Skip to main content
Glama
README.md
# CNR MCP

让 Claude Code、GitHub Copilot、Cursor 等 Agent 检索、阅读和引用中国知网论文。
支持校内 IP 直接识别与校外统一身份认证(Shibboleth / CARSI)两种机构访问方式。

**机构适配是自动的**:登录后从页面读取机构名,不依赖硬编码名单,任何学校都能识别。
另外内置了 40 所院校的 SSO 入口(北京、沈阳、大连的主要高校),
这些学校在校外可以直接跳转到本校认证页,无需手动查找。

## 访问方式

本项目支持两种知网机构访问方式,无需切换代码:

| 场景 | 需要做什么 |
|---|---|
| **校内 Wi-Fi / 校园网** | 知网按 IP 自动识别机构,**不需要登录**,直接检索即可 |
| **校外** | 跑一次 `--login`,在专用 Chrome 窗口里点「机构登录 → 校外访问」,选择你的学校并完成统一认证 |

登录状态保存在独立 Chrome 档案中(默认 `~/CNKIResearchMCP/browser-profile`),
不会影响你日常使用的 Chrome。会话过期后重跑 `--login` 即可。

> 校外访问能否成功取决于学校当前是否开通 CARSI 或校外访问服务,
> 以及学校是否订阅了对应文献。本工具不提供任何绕过订阅或访问控制的能力。

## 安装

需要:Python 3.10+、Google Chrome。

```bash
cd ~/cnr-mcp
uv venv --python 3.11
uv pip install -e .
```

本项目使用你本机已安装的 Chrome(`CNKI_BROWSER_CHANNEL` 默认 `chrome`),
**不需要**另外下载 Playwright 的 Chromium。

## 登录(仅校外需要)

```bash
.venv/bin/python -m cnki_mcp_server --login
```

会打开一个专用 Chrome 窗口:

1. 在知网首页点「机构登录」→「校外访问」;
2. 机构选择你的学校;
3. 在学校统一认证页面完成登录;
4. 回到终端按回车确认。

校内 IP 用户可以跳过这一步,直接接入 Agent。

## 学校适配

机构身份不需要预先配置,代码里也没有「支持哪些学校」的白名单。

### 机构识别:从页面读,不靠名单

登录(校内 IP 或校外 SSO)之后,知网首页头部会显示
`中央财经大学图书馆` 这样的文字,工具从 `div.ecp_header_unitName`
直接读取并去掉「图书馆」后缀,得到学校名。

这样任何学校都能识别,包括没有列进任何名单的。识别结果用于:

- `get_login_status` 返回的 `institution_visible`
- 自动记忆到 `~/CNKIResearchMCP/institutions.json`,下次校外登录直接复用

### 校外 SSO:内置 40 所院校入口

校外访问知网要走学校的统一身份认证(Shibboleth / CARSI)。
每次登录都去知网机构目录里查一遍很慢,所以内置了一批常用院校的 `entityID`:

| 地区 | 数量 | 学校 |
|---|---|---|
| 北京 | 24 | 清华、北大、人大、北航、北理、中国农大、北师大、中央民大、北交大、北工大、北科大、北化工、北邮、北林、北中医、中国传媒、中央财经、对外经贸、中央音乐、中国政法、华北电力、中国矿大(北京)、中国石油(北京)、中国地质(北京) |
| 沈阳 | 8 | 东北大学、辽宁大学、中国医科大学、沈阳农大、沈阳工大、沈阳航空航天、沈阳理工、沈阳药科 |
| 大连 | 8 | 大连理工、大连海事、大连医科、大连外国语、大连海洋、大连交通、东北财经、辽宁师范 |
| **合计** | **40** | |

以代码里的 `KNOWN_SSO_ENTITY_IDS` 为准。

**不在表里的学校也能用**,只是需要现场查一次目录:

1. 已内置 → 直接拼出 SSO 地址跳转,无需查询目录
2. 本地学过(之前登录成功过)→ 用缓存的地址
3. 都没有 → 实时检索 `fsso.cnki.net` 的机构目录,查到后自动记忆

三种路径都会**验证落地页是真登录页**(有密码框、正文不是 XML 元数据),
验证不通过才继续下一条,避免停在 Shibboleth 元数据文档上。

### 加一所新学校

如果某所学校常用,想免去现场查询,加一行即可:

```python
KNOWN_SSO_ENTITY_IDS = {
    ...
    "某某大学": "https://idp.xxx.edu.cn/idp/shibboleth",
}
```

`entityID` 可以从知网 [校外访问系统](https://fsso.cnki.net/) 输入校名后
的自动补全链接里拿到(`entityID=` 后面的部分)。

两个注意点:

- **存 entityID,不要存完整 URL**。`https://idp.xxx.edu.cn/idp/shibboleth`
  直接打开是 XML 元数据,不是登录页;必须由代码包成
  `fsso.cnki.net/Shibboleth.sso/Login?entityID=...` 才能跳转。
- **少数学校的 IdP 只支持 http**,https 会被浏览器直接拒绝。这类学校加进
  `INSTITUTIONS_HTTP_ONLY` 集合即可(目前只有大连交通大学)。

### 未接入知网 FSSO 的学校

有些学校在 CARSI 里但没进知网的机构目录(如北京外国语大学、北京体育大学、
大连工业大学)。这类学校无法自动跳转,工具会停在机构列表页让你手动选择。
如果确认该校有 CARSI、只是知网目录没收录,可以按上面的方法手工补一个 entityID。

## 接入 Claude Code

**用户级**(所有项目可用):

```bash
claude mcp add --transport stdio --scope user cnki -- ~/cnr-mcp/.venv/bin/python -m cnki_mcp_server
```

或手动写进 `~/.claude.json`:

```json
{
  "mcpServers": {
    "cnki": {
      "command": "/path/to/cnr-mcp/.venv/bin/python",
      "args": ["-m", "cnki_mcp_server"]
    }
  }
}
```

重启 Claude Code,用 `/mcp` 查看 `cnki` 是否已连接。

## 接入其他 Agent

本工具是标准的 stdio MCP server(FastMCP 4.x),任何支持 MCP 的客户端都能接,
换的只是配置文件位置,工具名和行为完全一致。

### GitHub Copilot(VS Code)

VS Code 1.102+ 内置 MCP 支持。在**工作区**建 `.vscode/mcp.json`
(或从命令面板 `MCP: Open User Configuration` 打开用户级配置):

```json
{
  "servers": {
    "cnki": {
      "type": "stdio",
      "command": "/path/to/cnr-mcp/.venv/bin/python",
      "args": ["-m", "cnki_mcp_server"]
    }
  }
}
```

在 Copilot Chat 里把对话模式切到 **Agent**,工具选择器里勾选 `cnki` 即可。
注意 `command` 要写**绝对路径** —— Copilot 启动子进程时的 `PATH`
未必包含项目虚拟环境。

### Cursor

`~/.cursor/mcp.json`(全局)或项目根目录 `.cursor/mcp.json`(单项目):

```json
{
  "mcpServers": {
    "cnki": {
      "command": "/path/to/cnr-mcp/.venv/bin/python",
      "args": ["-m", "cnki_mcp_server"]
    }
  }
}
```

在 `Cursor Settings → MCP` 里确认 `cnki` 显示为绿色(已连接)。

### WorkBuddy / 其他 MCP 客户端

WorkBuddy 这类客户端大多在设置界面提供「添加 MCP Server」的表单,
或允许直接导入 JSON。需要填的字段只有三个:

| 字段 | 填什么 |
|---|---|
| 类型 / Transport | `stdio` |
| 启动命令 | `/path/to/cnr-mcp/.venv/bin/python` |
| 启动参数 | `-m cnki_mcp_server`(即 `args: ["-m", "cnki_mcp_server"]`) |

如果客户端只支持 HTTP 传输(或你想让多个 Agent 共用一个实例),
用 HTTP 模式启动:

```bash
CNKI_MCP_PORT=8000 ~/cnr-mcp/.venv/bin/python -m cnki_mcp_server --http
```

然后在客户端里添加远程 MCP,地址填 `http://127.0.0.1:8000/mcp`。
服务默认只监听 `127.0.0.1`,**不要改成 `0.0.0.0`** —— 它带着你的知网机构权限。

### 通用要点

- **命令写绝对路径**:Agent 拉起的子进程往往拿不到你的 shell 配置,找不到 `python`
- **同时只能跑一个实例**:专用 Chrome 档案有文件锁,两个实例抢同一个 profile 会失败。
  多个 Agent 要共用,就都连同一个 HTTP 模式实例
- **首次连接会拉起 Chrome**:在配置里加 `"env": {"CNKI_SHOW_BROWSER": "false"}`
  可保持后台运行(默认已是后台)
- **验证仍需要人**:遇到滑块时窗口会跳到前台等你操作,
  在 Agent 客户端里看起来就是「工具调用卡住」,属正常现象,时限由
  `CNKI_CAPTCHA_TIMEOUT` 控制(默认 300 秒)
- **不需要为每个 Agent 重新登录**:会话存在 Chrome 档案里,所有 Agent 共用

## 可配置环境变量

| 变量 | 默认值 | 说明 |
|---|---|---|
| `CNKI_INSTITUTIONS` | 空 | 可选的补充机构名(逗号分隔)。机构名默认从页面自动读取,一般不需要设置;仅当页面结构变化导致读不到时才用于兜底匹配 |
| `CNKI_DATA_DIR` | `~/CNKIResearchMCP` | 数据目录 |
| `CNKI_PROFILE_DIR` | `$CNKI_DATA_DIR/browser-profile` | 专用 Chrome 档案 |
| `CNKI_HEADLESS` | `true` | 后台运行浏览器;调试时可设为 `false` |
| `CNKI_BROWSER_CHANNEL` | `chrome` | 可改成 `msedge` |
| `CNKI_DIRECT` | `true` | 专用浏览器是否绕过系统代理直连知网 |
| `CNKI_MCP_PORT` | `8000` | `--http` 模式端口 |
| `CNKI_CAPTCHA_TIMEOUT` | `300` | 等待人工完成验证的秒数 |
| `CNKI_IDLE_TIMEOUT` | `1800` | 常驻浏览器空闲多久后自动关闭(秒) |
| `CNKI_ZOTERO_DIR` | `~/Zotero` | 本地 Zotero 数据目录,用于读取已有 PDF |
| `CNKI_CDP_URL` | 空 | 设置后连接你本机已开启调试端口的 Chrome,而不是启动独立 profile |
| `CNKI_SHOW_BROWSER` | `false` | 为 `true` 时把工作标签页切到前台(调试用);默认后台运行 |

也可以在 `~/CNKIResearchMCP/settings.json` 里写 `{"show_browser": true}`,
**改完立即生效、不用重启**(优先级高于环境变量):

```bash
echo '{"show_browser": true}'  > ~/CNKIResearchMCP/settings.json   # 调试可见
echo '{"show_browser": false}' > ~/CNKIResearchMCP/settings.json   # 默认后台
```
| `CNKI_USER_AGENT` | 空 | 一般不要设。默认让 Chrome 报告真实 UA |
| `CNKI_HEADLESS` | `false` | 设为 `true` 则不显示窗口;此时遇到验证请求会直接报错,因为没有窗口可操作 |

## 可用工具

| 工具 | 用途 |
|---|---|
| `search_cnki` | 多字段检索、作者/期刊筛选、多页和排序 |
| `get_paper_detail` | 获取完整题录、摘要和可用权限入口 |
| `read_paper_fulltext` | 分段读取机构授权的在线正文(HTML 阅读器) |
| `read_pdf_text` | 读取本地 PDF 的正文,**纯本地、不联网、不触发验证** |
| `read_papers_batch` | **批量**读取多篇正文(1–20 篇),一次调用完成;缓存的走本地进程池 |
| `download_papers_batch` | **批量**下载 PDF,已缓存的自动跳过 |
| `list_cached_papers` | 列出本地已有的论文(CNKI 缓存 + Zotero 书库),**纯离线** |
| `get_paper_citations` | 参考文献(本文引用了谁)/ 引证文献(谁引用了本文) |
| `download_paper_pdf` | 下载机构授权 PDF |
| `find_best_match` | 根据标题核验并匹配文献 |
| `get_login_status` | 检查会话状态,不返回认证秘密 |
| `renew_session` | 重新登录知网(先开窗口,完成后调 `confirmed=true`) |

## 会话过期怎么判断

知网**不会提示 Cookie 过期**,页面看起来一切正常,实际只表现为下载失败或提示「机构没有额度」。
知网也没有公开 Cookie 有效期,公开的只有机构漫游时限(非假期 15 天、假期 60 天、
全球学术快报授权 3 天),且校内 IP 认证根本不依赖 Cookie。

因此本项目不设固定时长,而是用两条可验证的信号:

1. **本地检查**:每次任务开始前读取浏览器里知网 Cookie 的 `expires`。
   只有「持有的 Cookie 全部过期」才判定会话失效——空 Cookie 不算失败,因为 IP 认证不需要它。
2. **失败时验证**:下载按钮没出现时,先加载一次知网检查机构身份,再决定是报「文献无 PDF」
   还是报「会话已过期」。

判定过期后不会再反复重试,而是要求你调用 `renew_session` 手动恢复:

```
renew_session()                    # 打开知网窗口
# 校内直接访问即可;校外点「机构登录 → 校外访问」
renew_session(confirmed=True)      # 验证并记录
```

## 效率:几处关键取舍

### 检索

- **直达结果页**:用 `korder` + `kw` + `crossids` 直接打开结果列表,跳过首页加载、逐字输入和联想框。
- **排序按控件状态决定**,不靠猜。知网结果页打开时**默认就是「被引降序」**,无条件再点一次会翻成升序——这正是曾经"按被引排序却返回零被引文献"的原因。现在读取控件的 `cur` / `ASC` / `DESC` 类,只在方向不对时点击。
- **结果表一次取出**:整张表用一次 `page.evaluate` 取回,而不是逐行、逐字段读 DOM。

### 读取

- **优先 `read_paper_pdf`**(下载 + 本地解析)。HTML 阅读器是独立的高风控入口,同一篇文献在线阅读容易弹滑块,下载则不会。
- **缓存按论文身份定位**:归一化标题 + 第一作者 + 年份。知网摘要页 URL 带易变的 `v=` 参数,同一篇每次检索都会得到不同标签,按标签缓存等于永远不命中。
- **解析结果存旁车**(`.txt` + `.meta.json`),用 size 和 mtime 校验;只对缓存目录内的文件写旁车,不碰 Zotero 书库。
- **已缓存的读取完全不启动浏览器**,不触发 Cookie 预检。

### 批量

- `read_papers_batch` **默认并发 1**。提高并发更容易触发点选验证,保持串行更稳妥。
- 已缓存部分用**进程池**并行解析:pypdf 是 CPU 密集型,线程受 GIL 限制,进程池能真正并行。
- 整批正文按 `total_char_budget` 分配(默认 2 万字),超出的条目改为返回 `text_path`,避免结果被静默截断。

### 来源类别(核心期刊)筛选

`search_cnki` 的 `source_category` 参数可以按核心期刊目录筛选:

```
query='ESG', source_category='北大核心,CSSCI'
```

**为什么这个能力要单独做**:知网专业检索的字段下拉里只有 16 个字段
(主题、篇关摘、关键词、篇名、全文、作者、第一作者、通讯作者、作者单位、
基金、摘要、小标题、参考文献、分类号、文献来源、DOI),**没有来源类别**,
所以表达式写不出这个条件,只能走结果页侧栏的 `dl[groupid="LYBSM"]` 分组。

**实现优先级**:能用表达式表达的一律走表达式(稳健、一次生效);只有表达式
表达不了的才走侧栏。侧栏是点击驱动的 JS 状态,URL 里不体现,比表达式脆弱。

**其他注意事项**:

- 可选标签:北大核心 / CSSCI / AMI / WJCI / CSCD / EI / SCI(不同检索下可用项不同)
- 多选是**并集(OR)不是交集**,与点选顺序无关。
  想要「既是北大核心又是 CSSCI」做不到 —— 侧栏同一分面内只能 OR。
- 选中后会**重新加载结果列表并折叠分组**,所以每次选择前都要先重新展开
- 侧栏分组**只对前 4 万条记录生效**,超出时计数不完整
- 整本期刊下载时不需要这个参数 —— 刊名定了,来源类别就固定了
- 返回结果里的 `source_category` 字段会带 `applied` / `missing` / `counts` / `total`,便于核对

### 批量下载:先建清单表,再整轮执行

只要一次要下载的文献超过一小批(整本期刊某一年、某主题的全部论文、某作者的全部成果、
若干条件组合的检索结果),都走同一条流程。核心是**先把清单表格定稿,再按表机械执行**,
不要边搜边下。

1. **确定检索条件** —— 用户给的所有条件都落到 `search_cnki` 参数上:
   `journal`、`author`、`query`、`search_type`、`sort`、`pages`。
   只有刊名没有主题时 `query='*'` 通配;按期号归档用 `sort='发表时间'`;
   `pages` 拉满,翻页直到超出目标范围。
2. **核对总量** —— 看 `total_papers` 与用户说的范围比对,结果里常混有邻近年份或
   相关度不足的条目,先按条件筛掉。
3. **建清单表** —— 全部条目一次性整理成表(分组键 / 标题 / 作者 / 标签),存成 TSV。
   表格定稿后整轮往下跑,中途不再重新检索。
4. **按分组分目录** —— 文件夹按分组键命名(`2026-01`、`2026-02` …),
   `save_dir` 指向当期。
5. **先问清非论文条目** —— 「导读与推荐」「重点选题指引」「招生简章」默认剔除,需要时先问。
6. **警惕同名缓存跳过** —— 不同期次的同名条目命中缓存后 `skipped=true`,
   文件不会落到当期目录,不能当已下载。
7. **按表核对** —— 逐组统计「应有 / 已有」,缺失项列成 retry 清单再补。
   **一批超时不要立刻重试** —— 多为风控或机构配额触发,应停下等冷却。

## 先查本地,再联网

**查文献前先调 `list_cached_papers`。** 它把两个来源合在一起,全部离线:

| 来源 | 位置 | 读取方式 |
|---|---|---|
| CNKI 缓存 | `~/CNKIResearchMCP/pdf-cache/` | `read_paper_pdf`(按标签) |
| Zotero 书库 | `~/Zotero/storage/` | `read_pdf_text`(按 `file_path`) |

`search_cnki` 的每条结果也会带两个字段:

- `cached`:CNKI 缓存里已经下载过
- `in_zotero`:Zotero 书库里已有这篇(按标题模糊匹配)

命中任意一个就直接读本地,不联网、不触发验证。

Zotero 库路径可用 `CNKI_ZOTERO_DIR` 覆盖,默认 `~/Zotero`。读取是只读的,
Zotero 正在运行时也能用,不会修改你的书库。

## 批量读文献:先下 PDF 再本地读

在线 HTML 阅读器是知网管控最严的入口,最容易触发验证。如果一次要读十几二十篇,
推荐这条路径:

```
download_paper_pdf  →  read_pdf_text
```

1. `download_paper_pdf` 把 PDF 存到本地
2. `read_pdf_text`(或 `read_paper_pdf`,下载+解析一步到位)在本地抽文本,分段返回

**下载也会触发验证**——详情页点下载按钮同样可能弹滑块。
但两条路径的验证次数差别很大:

| 路径 | 每篇文献的联网请求 | 验证机会 |
|---|---|---|
| 在线阅读 | 打开阅读器 + 章节接口 + 每次重读都要再来一遍 | 多 |
| 下载 + 本地读 | 只有下载那一次 | 一次 |

所以真正的收益是:**一篇文献只撞一次验证门,之后读多少遍都不联网**。
读十几二十篇时差距很明显。

其他好处:

- PDF 留在本地,反复引用不用重新联网
- `read_paper_pdf` 按标签缓存,同一篇第二次读是瞬时的

注意:扫描版 PDF 没有文本层,会明确报错,需要另外做 OCR。

## 用你自己的 Chrome(推荐,可显著减少风控)

独立 profile 没有浏览历史、cookie 和扩展,在知网眼里是"陌生设备",容易触发风控。
把你的日常 Chrome 档案**复制**一份交给本工具用,就能带上真实的信任状态。

> Chrome 136+ 出于安全考虑,**禁止在默认档案上开启调试端口**(即使显式写出默认路径)。
> 所以必须使用复制出来的独立目录。

### 一次性准备(首次启动自动执行)

MCP 会**自己启动**带调试端口的 Chrome,不需要手动跑脚本。唯一需要准备的是档案副本,
而这件事**在服务首次启动时会自动尝试完成**,不需要你主动发起。

#### 自动执行的过程

1. 服务第一次加载时,自动把日常 Chrome 档案复制到 `~/.cnki-chrome-profile`
2. 如果 Chrome 正开着,复制会失败 —— 这是唯一需要你配合的地方
3. Agent 会从 `get_login_status` 的 `profile_bootstrap` 字段看到失败原因,
   提示你退出 Chrome,然后重试

成功之后 `profile_bootstrap.status` 为 `prepared` 或 `already_prepared`,无需再管。

#### 为什么不用你动手

独立档案没有浏览历史、Cookie 和扩展,在知网眼里是"陌生设备",更容易弹验证。
复制一份日常档案过来就能带上真实的信任状态。这件事做得越早,后面遇到的验证越少,
所以默认让它自动完成,而不是留给你去记。

#### 想自己来做

```bash
cnr-prepare
```

不在 PATH 里就用完整路径,例如 `~/cnr-mcp/.venv/bin/cnr-prepare`。
等价写法:`<安装目录>/.venv/bin/python -m cnki_mcp_server --prepare-chrome`。

执行前需要先完全退出 Chrome(⌘Q)。重做时加 `--force`。

也可以对 Agent 说「准备一下浏览器档案」,它会调用 `prepare_browser_profile` 工具代跑。

#### 结果

日常档案会被复制到 `~/.cnki-chrome-profile`(约 300 MB,排除缓存)。
**只需做一次**;之后重启电脑、重启 Chrome 都不必重复。不需要 sudo——只写用户主目录。

没有成功也不影响使用:MCP 会自动回退到独立档案,只是更容易触发验证。

### 让 MCP 使用它

`~/.claude.json` 的 `cnki` 项加 `env`:

```json
"env": { "CNKI_CDP_URL": "http://127.0.0.1:9222" }
```

重启 Claude Code 生效。之后:

- 调试端口的 Chrome 没开 → MCP 自动启动它
- 已经在运行 → 直接复用
- 找不到 Chrome 或档案副本 → 自动回退到独立档案,并打印原因

### 这个模式下的行为差异

- 用复制档案里的 cookie / 历史 / 扩展,指纹与日常浏览器一致
- **不会**动你已有的标签页;工具只操作自己新开的标签
- **不会**关闭这个 Chrome;断开时只断开连接
- 工具会**新开一个**状态标签页(`home.html`),显示当前在做什么和运行日志;
  断开时只关闭这个标签页,你的标签一个不动
- 自动启动时会直接打开状态页,不会多出空白页
- 调试端口只监听 `127.0.0.1`,但**本机任何程序都能通过它控制这个 Chrome**,不用时关掉即可

### 什么时候需要重新复制档案

日常 Chrome 里重新登录知网、或 cookie 过期后,复制档案不会自动同步。
届时重新执行第 1 步(先关掉调试实例)即可。

## 验证与常驻窗口

知网会对自动化访问弹出两类验证:**滑块**(向右拖动)和**点选图形**(依次点击图中文字)。
本工具**不会自动破解**,只负责把窗口送到你面前。

### 一个窗口,全程复用

浏览器是**常驻**的:第一次请求打开一个 Chrome 窗口,之后所有检索、读正文、下载都在这同一个窗口里开标签页,
不会每次开关。验证通过一次,整个会话内都有效。

空闲时窗口会停在 `~/CNKIResearchMCP/home.html`,上面写着「这是 MCP 常驻窗口,无需操作」,
不会出现空白的 `about:blank`。可以自己改这个文件,但下次启动 MCP 时会覆盖回默认内容。

空闲 30 分钟后自动关闭(可用 `CNKI_IDLE_TIMEOUT` 秒数调整)。手动关掉窗口也没关系,下次请求会重新打开。

### 遇到验证时

工具只在**真的做不成事**的时候才报告验证,不会因为页面上残留验证文案就提前退出。
检测到验证会**立即返回**,不会卡在那里等:

1. 返回 `captcha: true` 和提示,验证所在标签页**保留**在窗口里
2. 你手动完成滑块或点选图形
3. 重新调用刚才的工具即可——验证状态在整个会话内有效

验证页不会在你操作途中被关掉。完成后再调一次,通常就直接通过了。

### 状态与日志

实际工作跑在**后台标签页**里,所以常驻窗口的首页会实时显示当前在做什么:

> 正在检索知网(ESG)/ 正在阅读文献(某某标题)/ 正在下载并解析 PDF(某某标题)/ 等待你完成验证 / 空闲

默认情况下,真正干活的标签页**留在后台**,前台始终是这一页,不会看到标签页反复开合。
调试时把 `CNKI_SHOW_BROWSER` 设为 `true` 即可看到实际操作过程。

页面下方有「运行日志」,**默认折叠**,点开可看带时间戳的历史记录(最多 200 条),
用来回溯刚才跑过什么。

也可以主动打开验证窗口(推荐在批量读文献前先做一次):

> 调用 `open_verification_window` 工具

它会在常驻窗口里打开知网首页并置顶,你完成验证后再发请求,后续都不会再被打断。

| 工具 | 用途 |
|---|---|
| `open_verification_window` | 打开可见验证窗口,手动完成滑块/点选 |

## 试一句

> 检查我的知网登录状态,然后检索近五年关于「公司金融」的中文论文,按被引量排序。

## 登录与安全

MCP 没有读取或设置 Cookie 的工具,也不会把 Cookie、令牌、账号或密码返回给模型。
所有网页导航均限制为 HTTPS 的 `*.cnki.net` 域名。使用 HTTP 模式时服务默认只监听
`127.0.0.1`,请勿改成 `0.0.0.0`。

## 许可

MIT 许可证,详见 [LICENSE](LICENSE)。

请遵守学校、数据库和版权方的使用规则,避免高频批量下载。

TDQS

A3.5/5.0

Scored across 17 tools

Disambiguation3/5

Three overlapping reading tools (read_paper_fulltext for online, read_paper_pdf for download-and-parse, read_pdf_text for already-cached PDFs) require careful reading of the descriptions to distinguish, and find_best_match vs search_cnki overlap for retrieval. The descriptions do spell out the distinctions and the network side effects, but an agent can easily pick the wrong reader on first pass.

Naming Consistency4/5

All tools are snake_case with a leading verb (get_, search_, read_, download_, list_, export_, renew_), which is predictable. Minor deviations exist: the noun for the same concept varies (paper_fulltext vs paper_pdf vs pdf_text) and find_best_match/get_login_status are less self-describing than the rest.

Tool Count4/5

17 tools is slightly heavy but each covers a distinct lifecycle step: discovery, reading, batch fetching, session/auth recovery, and export. The inclusion of browser-session hygiene tools (renew_session, prepare_browser_profile, open_verification_window) is justified by the CNKI anti-bot domain.

Completeness4/5

The surface covers search, detail lookup, citations, fulltext (online and PDF), batch read/download, BibTeX export, and session/auth recovery — a full retrieval lifecycle. Gaps are minor: no metadata/field-filtered export besides BibTeX, and Zotero is only surfaced through list_cached_papers rather than dedicated library tools.

Maintenance

ActivityMaintained
ResponsivenessNo issues