Skip to main content
Glama

pubmed-mcp

单文件 PubMed MCP 服务(stdio),裸打 NCBI E-utilities,不经过 pubmed-client 之类的中间层。 现在也带 pip install 入口:装完直接敲 pubmed-mcp 就是服务。

当前版本为 1.4.0〔本项目自订版本号;来源:pyproject.toml 的 project.version〕,新增系统综述检索助手(check_recall/mesh/diff/export)与可选检索留痕,并修复 issue:引号短语开头误报警告。既有基础工具的默认行为保持兼容,验证范围见下方记录。源码发行包附带文档、测试及夹具;wheel 是运行安装包,不附带开发测试材料。

本轮演练修复与验收见 正畸与深度学习修复记录,包含测试结果、首测失败原因与未验证范围。发布前安装包验证另记于 发布检查〔版本来源:pyproject.toml;本项目自订文档命名〕。

它存在的唯一理由:把「查不到」和「没有」分开。 文献工具最常见的失败是静默——参数被吞掉、词被丢弃、编码不对、请求根本没跑完, 而输出看起来完全正常,于是你拿一个无意义的数字去写论文。本工具的做法是能拦就拦, 拦不住的在输出里把动过的手脚说出来。

代码注释里保留了大量 〔实测 日期〕、〔推算〕、〔本项目口径〕、【已作废+理由+日期】 标记。 读代码时请按那些标记理解证据强度,不要把带 推算/未核实 的行当事实引用。


快速开始(三条命令)

pip install git+https://github.com/rsvsv/pubmed-mcp.git
pubmed-mcp --check-key

--check-key 应返回 rc=0 并打印 key 形状/限速档/依赖版本。mcp 1.x 与 2.x 都支持;要是它报 拿不到 MCP 服务类,说明你环境里的 mcp 既不是一代也不是二代,pip install "mcp>=1.26,<3" 即可 (缘由见下面「版本要求」与 docs/mcp-sdk-v2.md)。

然后告诉 Claude Code 去哪儿找它 —— 在 ~/.claude.json 里加:

{
  "mcpServers": {
    "pubmed": { "command": "pubmed-mcp", "args": [] }
  }
}

在 Claude Code 里跑 /mcp,确认 pubmed 那一行是连上的,不是 ✘。

上面那段 "command": "pubmed-mcp" 只在「命令真能在 PATH 里被找到」时成立。 〔本会话 2026-11-11 在作者机器实测〕分三种情况:

  • 装进虚拟环境但没激活 → 裸命令找不到(实测 command -v pubmed-mcp 无输出)。Claude Code 不会替你先激活 venv,所以配置里必须写绝对路径: Windows <venv>\Scripts\pubmed-mcp.exe,类 Unix <venv>/bin/pubmed-mcp。 不知道落在哪就跑 python -c "import sys;print(sys.executable)" 看你在哪个解释器里装的。

  • 装进系统 Python(非 --user) → 作者机器上那个 Scripts 目录确实在 PATH 里 (实测 PATH 第 20 项),所以裸命令可用。你的机器不一定,自己确认: where pubmed-mcp(cmd)或 command -v pubmed-mcp(bash)。

  • pip install --user → 落点是 %APPDATA%\Python\Python<XY>\Scripts, 这个目录默认在不在 PATH 里,本仓库未核实(作者机器上该目录不存在,测不了)。 别照抄这一种,要么用上面两种,要么先用 where pubmed-mcp 确认命令敲得到。

零安装路线(下面那节)不受这个影响,因为配置里写的就是绝对路径。

不想装包也能用(零安装,直接跑文件):

git clone https://github.com/rsvsv/pubmed-mcp.git
cd pubmed-mcp
pip install -r requirements.txt
python pubmed_mcp.py --check-key

配置里就写绝对路径:

{
  "mcpServers": {
    "pubmed": { "command": "python", "args": ["-I", "/ABSOLUTE/PATH/TO/pubmed_mcp.py"], "env": {} }
  }
}

⚠️ 装依赖前先看清用的是哪个解释器

-I 是 Python 的隔离模式,等价于 -E -s:忽略 PYTHONPATH 与「用户」site-packages (也就是 pip install --user 的落点),但照常读 venv 与系统 site-packages。 〔本会话实测 2026-11-10:作者机器上 python -I -c "import sys;print(sys.path)" 的 sys.path 里确实没有 AppData\Roaming\Python\Python313\site-packages;而 -I 仍能 import mcp, 因为那份 mcp 装在系统 site-packages。〕

后果:依赖必须装进「配置里那个 command 所指向的解释器」里。用 pip install --user 装、 再配 "command": "python", "args": ["-I", ...],服务会在 Claude Code 里静默起不来。 虚拟环境里请去掉 -I,或者用 venv 内那个 python 的绝对路径。

也可以用命令行加(这条本仓库未在本机验证过:作者机器上 claude 不在 PATH 里, 跑不了 claude mcp add --help;参数形状随版本变过,动手前先自己 --help 对一下):

claude mcp add pubmed -- pubmed-mcp

Related MCP server: PubMed MCP Server

版本要求

后续更新:已加入 自动回归配置,下面“本仓库没有 CI”为历史状态,现已作废。矩阵是测试目标,实际通过情况以对应提交的 Actions 结果为准;本地运行不能代替远端运行。

requires-python = ">=3.10"。〔本项目口径:源码用了 bool | str 联合类型标注,3.10 以下在 运行时求值会失败。但作者机器只有 3.13,本仓库没有 CI,所以这条下限错了也不会有人发现—— 〔推算〕,别当已验证事实。〕

依赖:Python 标准库 + mcp(FastMCP 随它一起装)+ anyio。HTTP 走 stdlib urllib, 当前还直接使用 pydantic 的严格类型(由 MCP 依赖安装)。旧句“除这两个之外没有别的第三方依赖”已作废:源码后来增加了严格参数校验〔修订记录:2026-11-11;依据:pubmed_mcp.py 的 pydantic import〕。

mcp 的区间是 >=1.26,<3:1.x 和 2.x 都实测支持,3.x 没验过所以挡住。 下界是量出来的,不是拍的:〔实测 2026-11-11,三个干净 venv 配当前 pydantic 2.14.3〕mcp 1.2.0 与 1.21.0 都在 import 阶段就炸(cannot import name 'eval_type_backport' from 'pydantic._internal._typing_extra'),1.26.0 才 IMPORT_OK。原先写 >=1.2 等于承诺了一个 跑不起来的下界——那种装法看着成功、一跑就 traceback。 〔实测 2026-11-10,干净 venv〕原先只写 >=1.2 时,pip install git+https://… 会解析到 mcp 2.3.0,而 2.x 里 mcp.server.fastmcp 这个模块名已经没了 —— 装完第一次运行就 ModuleNotFoundError: No module named 'mcp.server.fastmcp'。作者本机是 1.29.0, 这类坑在作者机器上永远复现不出来,所以本仓库现在的验收一律用不带系统 site-packages 的 干净 venv 跑 pip install。

源码里因此加了一层 SDK 兼容层(1.x 拿 FastMCP,2.x 拿 MCPServer),两条通路各跑过完整 --probe:两代都是 0 失败〔实测 2026-11-11,mcp 1.30.0 与 2.3.0 各一轮,串行跑、中间隔 8 秒, 避免两轮在限速上互相干扰。〕 这里故意不写断言条数,也故意不写请求数:两个数都是「每加一条断言就变」那种,写死过一次就注定过期 (下面「自检」一节同此口径)。这句自己就过期过一回:此处原先写着「请求数仍是 89 次」, 后来又加了联网的冒烟断言(文档示例能不能真查到东西,光离线测不出来),89 已经不是实际值—— 同一段文字里一边说「不写死条数」、一边写死另一个数,正是本 README 批评过的形状。 现在的条数、请求数与它们的变化链记在 docs/release-delta.md 的验收表里。 其中四条专门走 SDK 的工具包装层(search / count / fetch_abstracts / links 各一条)。 为什么值得为它们各写一条:2.x 会把非 ToolError 异常的文本剥掉,这条通路一旦退化,四个工具的 「为什么被拦」会同时缩成一句没有信息的 Error executing tool xxx,而探针其余断言都直调协程、 结构上看不见这一层。〔实测依据见 docs/mcp-sdk-v2.md〕

【已作废 2026-11-11,本会话 A/B 实测推翻】这一段原先写「v2 变了的那些(客户端字段改 snake_case、serverInfo.version 变空串、多 structuredContent)都在客户端侧,本服务不读, 所以不影响」。它漏了服务端这一手:2.x 会把非 ToolError 异常的文本从返回结果里剥掉。 同一个 sort="journal" 拦截,1.30.0 下调用方拿到 323 字符的完整解释,未修的 2.3.0 只拿到 27 字符的 Error executing tool search —— 本仓库的主承诺「失败绝不静默」就在新用户默认走的那条 路上被打穿了。现在 NcbiError 继承当前那代 SDK 的 ToolError,两代拿到的文本逐字相同; --probe 里补了一条走包装层的断言当回归锁(其余断言都直调协程,结构上看不见这一层)。 原话留着不删,是因为「我不读那个字段,所以那个改动与我无关」这种推理会再犯第二次。 细节与逐字签名见 docs/mcp-sdk-v2.md。

新环境里 pip install 会拿范围内的最高版(眼下是 mcp 2.3.0)。想固定走 1.x: pip install "mcp<2"。两代本仓库都跑过全量 --probe,但你的其它 MCP 应用如果要求 mcp<2,pip 会照它的约束留手——这也是上界写成 <3 而不是钉死某一版的原因。

作者开发时实测 2026-11-08 的版本是 mcp 1.29.0 / anyio 4.14.2 / pydantic 2.13.4〔实测,本机 importlib.metadata;未在跨版本环境复核〕。

NCBI API key(可选)

不设 key 也能跑,只是限速低一档。读取顺序:

  1. 环境变量 NCBI_API_KEY

  2. 文件 ~/.ncbi_api_key

  3. 文件 ~/.ncbi_api_key.txt

  4. 都没有 → 匿名档

限速:有 key 10 次/秒,无 key 3 次/秒〔本项目口径:这是 NCBI 公布的档位, 作者没有逐字核对过官方页面,代码里也没做过计时测量,所以标口径不标实测〕。

key 文件的编码不用你操心。Windows 上 people 建这个文件默认拿到的往往是 PowerShell 5.1 的 UTF-16LE + BOM 或记事本的 UTF-8 带 BOM,两者都会让早期版本 抛裸 UnicodeDecodeError,或者让  混进 key( 不是空白,.strip() 剥不掉, 于是 NCBI 判 key 无效、而错误文本里看不出是编码的锅)。现在按 BOM 判编码、再兜一层 utf-8-sig、最后 latin-1 保命。本仓库不含任何 key,~/.ncbi_api_key* 也被 .gitignore 挡着。

用 --check-key 自检(它不发任何网络请求——但它是跑在这个文件里的:文件顶部要先 import 到 MCP 服务类,所以 mcp 没装齐时你会先看到兼容层那句 ImportError(那句里直接给了该跑的安装命令), 看不到 key 报告。这不是 bug,是「连依赖都没装对」时唯一有用的那句话):

python pubmed_mcp.py --check-key

它会报告 5 组信息:key 的形状(只说长度/有没有混进文字,不打印值)、限速档位、 它实际读到的 key 文件绝对路径与该文件的编码、NCBI_EMAIL、以及 mcp/anyio/pydantic 版本。 把「放错位置的人只会看到 (无)」这个坑堵上了——注意输出里那行路径带你自己的用户名, 贴到 issue 前先知道这件事。

NCBI_EMAIL(可选):NCBI 建议请求里带联系邮箱,设了就会随每个请求发出〔NCBI 的 courtesy 建议,作者未逐字核对原文页面——〔未核实〕〕。

工具

八个 @mcp.tool()〔本 README 逐字对照源码装饰的定义数出,2026-11-11〕:

工具

作用

要点

search

检索,返回命中数 + 每条的 PMID/日期/期刊卷页/标题/作者/DOI/PMC

term 支持 PubMed 语法:字段标签(写法与「引号只包短语、别把 [Tag] 包进去」的说明见 search 的工具说明)、A AND B、截词 resorption*、范围 2024:2026[dp];一次一个概念、靠字段标签收窄

count

只问「这个主题有多少篇」,不取记录

最省请求;查询被改写时印出「NCBI 实际执行」

fetch_abstracts

按 PMID 取摘要原文

内部每 50 个一批并发;报「要几条/实取几条/缺哪些」

links

查这些 PMID 在别的数据库里的对应记录(elink)

to=pmc 查询 PMC 关联,不保证开放许可或当前可下载;可选 pmc/nucleotide/gene/pubmed

check_recall

已知文献找回测试:一批已知相关 PMID 哪些被 term 检回

分批 esearch 交集判定 found/missing(每批 50,避免 URL 超长 414);缺失项附标题与存在状态(present/unavailable/unknown);term 被 NCBI 忽略时显著告警;只证明已知集找回,不代表查全率

mesh

查 MeSH 主题词表

描述符、入口词(同义词)、树号、下位词、范围注;无描述符命中不等于主题无文献

diff

对比两个查询的结果集

新增/丢失/共同 PMID;两查询都须在 9999 窗口内;集合差不判断相关性

export

取全某查询的 PMID 并写文件

超 9999 窗口自动按发表日期切片;pmids/csv/medline 三种格式;只回摘要+sha256;不覆盖已有文件

旧说明“判断有没有免费全文可下”已作废,原因:数据库关联不能证明开放许可或此刻下载可用〔修订记录:2026-11-11;依据:links 当前工具说明〕。

按需精简检索结果

search 新增可选 detail,默认 full。已有调用不传此参数时维持完整输出;as_json 仍独立控制输出格式。

detail

返回内容

保留的功能与限制

full

原有完整题录字段

默认行为及 JSON 字段保持兼容

brief

PMID、日期、完整标题、全部文献类型

仍读取元数据;不删除撤稿、勘误类型;省略的作者、期刊、DOI/PMC 不表示来源缺失

ids

按 esearch 返回顺序给 PMID

跳过 esummary;未获取元数据、未检查撤稿等类型;JSON 的 returned 按 PMID 计,esummary_missing 为 null

各档均保留实际执行式、查询警告、零结果解释与检索窗口上限提示。文本中的执行式沿用原有截断规则,完整执行式始终可从 JSON 的 querytranslation 取得。ids 不适合直接据此判断文献质量或引用细节。

调用示例(本项目自订使用示例):

search('"root resorption"[tiab]', detail="brief")
search('"root resorption"[tiab]', detail="ids", as_json=True)

精简不保证每次输出更短:少量短题录可能因必要说明而抵消节省。尚未测量实际模型 token 或费用收益。

系统综述检索助手(1.4.0 新增)

四个新工具加可选留痕,支撑系统综述的检索环节。设计依据与实测前提见 docs/systematic-review-plan.md,方法学工作流见 docs/systematic-review-workflow.md(亦作为 /systematic-review skill 随仓库分发)。

分工〔本项目自订〕:工具只做机械可复现的事(检索、集合运算、导出、留痕);拆概念、选同义词、判断相关性、定纳入排除由人与 LLM 按预设标准做。工具不声称查全率/查准率,已知集找回只证明这批已知文献被检回。

  • check_recall(term, pmids):分批 esearch 交集判定 found/missing;present 表示记录存在但本次实际执行式未检回,unavailable/unknown 表示存在性未确认。任一批仅剩 UID 条件时置 term_ignored;部分概念消失、解析警告或原式语法失真时置 term_degraded。空执行式归为信息不足,不能直接断言 term 被忽略。JSON 的 querytranslations 保存各批执行式;这些标记是保守诊断,仍须核对原式,不能把全部 found 当真实查全率。

  • mesh(term):esearch/esummary db=mesh,给入口词、树号、上下位词、历史前身词(previous indexing)、范围注与引入年份。本次返回候选中的字面精确项自动置顶;关联名称缺失时保留 UID 并告警。〔来源:源码 mesh;验证见演练修复记录〕

  • diff(term_a, term_b):两查询各取全窗口内 ID,本地集合差给新增/丢失/共同。任一超窗拒绝并提示改用 export。

  • export(term, path, format):超检索窗口按发表日期递归二分,切片计数与总数核对、按 PMID 去重。每次使用唯一临时文件;Windows 用不覆盖的 rename,其他系统用硬链接原子发布,文件系统不支持则报错。清理失败会警告;path 不得已存在。CSV 不含摘要,MEDLINE 保留来源已有字段。安全上限为十万条〔本项目自订;源码 EXPORT_MAX〕。

  • 检索留痕:设环境变量 PUBMED_AUDIT_DIR,工具在完成路径追加 JSONL 到 searches.jsonl。search/count 区分 input_params 与实际 request_params;记录实际返回数、执行式、警告和运行源码版本,search 元数据失败另记 error。fetch_abstracts/links 记录请求 PMID;check_recall 记录各批执行式。留痕默认关闭;写失败报 stderr。参数校验失败、网络中断等并非所有失败路径都有日志,不能当完整请求流水账。

  • 引文补查:links(to="refs") / links(to="citedin") 给参考文献/施引文献;有展示上限并显示截断,只限 PubMed 已录入关系。

实测注意〔2026-11-11 live,verify_sr_live.py〕:大题目切片计数和可能大于总数——同一记录带多个发表日期时会落进多个年份切片,去重后与总数一致;警告会如实说明,这不是错误。例:dental implant 命中 73612,切片计数和 78474,去重后 73612〔实测;重复数 4862 为推算 DV-SR-DEDUP〕。

验收:离线 84 项(mcp 1.30.0 与 2.3.0 各 84 通过)+默认行为 A/B 49 组逐字一致+真实联网验收 PASS+对抗性探针找坑并修复 3 处+真实题目端到端演练〔实测 2026-11-11,详见 docs/sr-tools-validation.md〕。尚未测量新工具的实际 token 开销;工具描述总字符由 1325 增至 2328〔实测 list_tools〕,描述体积回归上限相应由 2000 上调到 2600〔本项目自订〕。

自动回归

regression.yml 在推送、拉取请求和手动触发时安装项目,检查依赖,执行离线回归,并验证已安装 CLI 与新 stdio 进程。需要把配置推送至 GitHub 才会触发远端运行。

  • Python 3.10 / 3.13、MCP 一代 / 二代组合为本项目自订验证矩阵(来源:regression.yml);每个区间由 pip 选择兼容版本,不代表全部版本或最低 SDK 均已验证。

  • 日常测试不查询 NCBI;离线运行器拦截本进程的外部 socket 连接,保留事件循环需要的本机回环连接。依赖安装仍需联网,安装烟测不作全系统断网保证。

  • 完整联网 --probe 单独手动运行,不将外部网络故障混入普通提交检查。

  • Actions 红灯不会自动禁止合并;强制通过后才允许合并需要仓库分支保护规则,本配置不会改动该设置。

本地执行同一套离线检查:

python -I tests/run_offline.py

Behavior contract —— 它到底替你拦了什么

下面每条都在源码里有实测锚点或断言覆盖(本仓库的 --probe 会替你复验,包括第 1 条那个 200 + HTML 分支——它已落成一条离线断言,不再只是防御性假设)。

  1. 失败绝不静默。 请求失败抛 NcbiError 并带回 NCBI 原文;HTTP 200 + 一段 HTML、 或 200 + {"ERROR": ...} 都算失败,不会被说成「NCBI 里没有这篇」。 〔实测 2026-11-11:这条曾在 mcp 2.x 上被打穿过——SDK 把非 ToolError 的异常文本剥掉,调用方 只剩一句 Error executing tool <name>。现在的基类写法与那条走包装层的回归断言见 docs/mcp-sdk-v2.md。〕

  2. 0 条必须说清是哪一种 0。 真的没有匹配 / 词被当停用词忽略 / 整个引号短语在索引里不存在 / 两段同字段日期不相交 / retstart 越页 / retmax=0 且命中>0(只要计数、没要记录)——这几种各说各的话, 不统一兜底成「PubMed 里没有匹配」。

  3. field= 走白名单,宁拦勿吞。 实测 NCBI 对认不出的 field 静默忽略(拼错一个字母=限定被吃掉、 且没有任何提示)。keywords/PMC Number/ISSN 实测被整条忽略,MeSH Terms/Publication Type 实测让 esearch 不返回 count——这五个都直接报错并给改写建议。

  4. sort= 只收 pub_date / relevance / author〔实测 2026-11-10 本机 idlist 两两对照〕。 journal/relevancy/keyword 实测顺序与不传时逐字相同,所以放进黑名单而不是白名单。 best match 会被改写成 relevance 下发,并且输出里明说这次改写。

  5. 单边日期补哨兵,并声明补了什么。 实测 NCBI 对只给一端的 mindate/maxdate 整条忽略。 补的是不可能生效的哨兵 0001-01-01 / 2999-12-31,不是「今天」或「收录起点」—— 后者是真边界,本机日历与 NCBI 服务器日历差一天时会静默切掉那一天的文献。

  6. reldate 原样下发,本工具不做日历换算。 「近 N 天」由 NCBI 按它自己的服务器日历算。

  7. 摘要按 ^PMID: 行计数,不拿请求数冒充返回数。不存在的 PMID 会回「要 N 条 / 实取 M 条」, 并点名取不到的那个号;"实取"按 efetch 正文里的 PMID 行计,所以没有摘要的社论照样算实取 〔实测 2026-11-11:99999999 / 9999999999 → 要 1 条 / 实取 0 条〕。

  8. PMID 解析不猜。 1,234,567 这种带千位分隔符的形(从 Excel 复制一列号很常见)直接拦—— 旧写法会切成 3 个真实存在的 PMID,抓回三篇不相干文献、条数还看着正常。

  9. async 工具 + 网络调用出事件循环。 mcp 1.x 对非 async 工具是裸 return fn(**kwargs)、 没有 threadpool,一次 40s 的 efetch 能把整个 server 冻住〔依据:作者读的 mcp/server/fastmcp/utilities/func_metadata.py〕。 〔实测 2026-11-10:这一条只在 1.x 成立 —— 2.3.0 把该文件挪到 mcp/server/mcpserver/utilities/func_metadata.py,非 async 分支改成 await anyio.to_thread.run_sync(functools.partial(fn, **kwargs)),也就是 SDK 自己开始卸载了。 本服务全部工具均为 async def;装饰后协程属性和包装层透传由离线测试与源码 stdio 烟测覆盖。 〔这条后半句此前没有断言钉住——而它才是承重的部分:装饰之后的名字一旦不再是协程函数, SDK 就走同步分支。现在有一条离线断言专门问【装饰之后】那四个名字,两代各测一次都仍是协程函数 〔实测 2026-11-11〕。〕

  10. key 一个字符都不外泄。 错误文本里只报 key 长度不报片段;_mask 无条件整串替换成定长掩码 (旧写法既留前 4 位、又只在长度 > 8 时才掩)。〔已知边界:key 以 URL 百分号编码形态出现在 报错文本里时仍替换不到——过度设计,记着当边界,别当已修好。〕

自检

python pubmed_mcp.py --check-key      # 零网络请求,先看 key/限速/依赖装对没
python pubmed_mcp.py --probe          # 完整回归断言,需要联网,见下方警告
python pubmed_mcp.py --selftest "tooth resorption"
python pubmed_mcp.py --concurrent "tooth resorption"

⚠️ --probe 不是健康检查,是一轮重流量回归。它自己会在末行报数: 「N 通过 / M 失败 —— 本轮 K 次 HTTP 请求(含退避重试的每一次)」。 本 README 故意不写死任何条数——写死过一次就注定过期(这份代码里有一条真实的过期记录)。 按量级估:一轮要按几十秒到几分钟算,还要看你在 10 次/秒还是 3 次/秒档。

怎么确认它真的跑完了:看末行有没有那句「N 通过 / M 失败」,并看退出码 (非 0 即有 FAIL)。这条不是形式主义——作者踩过一次「探针中途崩掉、日志却显示 28 通过 / 0 失败」, 崩掉的探针看起来像通过,比一条 FAIL 危险得多。

复现编码相关的 bug 时别加 -I:隔离模式会忽略 PYTHONIOENCODING,stdout 直接落回 utf-8, 于是旧版也不会报错,你会得出「旧版也没问题」的假结论。

Limits(诚实清单)

  • 查询以实际执行式为准。 中文片段可能消失,混合查询仍可能命中剩余英文概念;不能把命中数当成完整原查询结果。 【已作废,修订日期:2026-11-12】旧“只索引英文”与“空执行式等于没解析出条件”结论过强;缺少执行式只能说明解析信息不足。

  • esearch 最多取回前 9,999 条,retstart 上限 9998(NCBI 硬墙,越界本工具直接报错)。 1.4.0 的 export 通过按发表日期切片取全超过此窗口的结果(history 服务器同样受此限制〔实测 2026-11-11〕);search/diff 仍受窗口约束。

  • retmax 上限 1000 是本工具自订的,不是 NCBI 的限制;要一次多拿就改那个常量, 或按年份/字段把查询切小分批取。夹过都会在输出里说明是本工具夹的。

  • PubMed 没有「按期刊影响力排序」这个概念,sort 里不存在这种值。本仓库也不含这类脚本 ——要那种排序得自己接外部期刊指标数据源。

  • 默认 datetype="pdat"(发表日期)。不带 datetype 时 NCBI 按入库日期算,两者结果不同〔实测〕。

  • 分批大小(esummary 100、efetch 50)与超时(25s/40s)是本项目口径/推算值, 不是量出来的最优点;它们挂在「实测」标题下的段落里容易被误读,源码里已就地标注。

为什么不用现成的包

作者初版对比的是 pubmedmcp 0.1.4 + pubmed-client 0.2.0,结论是那两个包不读 API key、不设 timeout、 出错时把异常打成空字符串。

⚠️【已不可就地复核,2026-11-08 作者自查】:那几条对比是当时看过源码得出的,但复核时本机 pip show 两个包均 not found、无可执行文件、无 pipx,现在无法重跑验证。 别当事实引用;要用就重装那两个包再看。

这份发布版与作者开发版的关系

公开仓库里的 pubmed_mcp.py 不是作者机器上正在跑那份的逐字节副本:它带着若干处发布专用改动 (_mask 收口、--selftest 不再打印 key 前缀、工具说明补上 author、journal-rank 指路改成不指向 本仓库没有的文件,以及三条新增离线断言)。逐处理由与依据见 docs/release-delta.md。

License

MIT — 见 LICENSE。

源码注释里的 〔实测〕/〔推算〕/【已作废+理由+日期】 标记请一并保留: 作废的推断不删除、只标注,是因为删掉之后人会重新踩同一个坑。

Available Tools

8 tools
check_recallA

已知文献找回测试:一批已知相关 PMID 里哪些被 term 检回。pmids 逗号/空格分隔,去重后最多 200 个。 分批 esearch 交集判定 found/missing(每批 50 个,避免 GET URL 超长被 NCBI 414);缺失项附标题与存在状态。 只证明这批已知集的找回,不代表整体查全率;金标准集本身可能有偏。 逐块诊断用 count("概念块 AND pmid[uid]")。查询警告原样透传;term 被忽略或部分词未生效时显著告警。

Inputs: term (required), pmids (required), as_json. Returns: result

countA

只取 PubMed 命中数,不取题录;需要题录直接用 search,避免重复检索。

term、field、日期参数规则同 search:英文词,大写 AND/OR/NOT,日期按发表日期。 返回实际执行式及 ⚠️;丢词/短语改写后的计数不能当原查询计数。0 条不证明主题无文献, 有命中也不证明原短语存在;确认短语须读取题录或摘要。完整解析可用 search(retmax=0, as_json=True)。

Inputs: term (required), field, maxdate, mindate, +1 more. Returns: result

diffA

对比两个 PubMed 查询的结果集:b 相对 a 新增、丢失了哪些 PMID。 检索式迭代前后核对增减;两查询都须在 9999 窗口内,超窗报错(先缩小或改用 export)。 max_show 默认 20、上限 200,文本档每侧只展示部分;as_json=True 给完整列表。 集合差只描述增减,不判断相关性;命中更多不等于更好。两次查询间数据库可能更新。

Inputs: term_a (required), term_b (required), as_json, max_show. Returns: result

exportA

取全某查询的 PMID 并写文件;超 9999 窗口自动按发表日期二分切片。 format: pmids(纯 PMID 列表)/ csv(核心题录字段,不含摘要)/ medline(.nbib,保留来源中已有的摘要与主题词)。 只回摘要(总数/片数/去重/路径/sha256),不回记录本身。path 显式给出且不得已存在(不覆盖)。 切片计数与总数核对,不一致如实报告;检索期间数据库可能更新,结果以导出时点为准。 自订安全上限 10 万条。筛选工具导入兼容性以对方文档为准;不保证与 PubMed 网页导出逐字一致。

Inputs: path (required), term (required), format, as_json. Returns: result

fetch_abstractsA

按逗号/空格分隔的 PMID 取 NCBI 原排版摘要;保留结构化段落、作者信息和声明。

自动去重、归一补零号、分批。建议先筛选题录,再只取需要的摘要以节省输出。 返回请求数、实际记录数和缺失号;有记录不等于有摘要,社论可能只有引文。 网络失败报错,不冒充无记录。文献数值引用仍须核对原文位置。

Inputs: pmids (required). Returns: result

meshA

查 MeSH 主题词表:描述符、入口词(同义词)、树号、上下位词、历史前身词(previous indexing)、范围注、引入年份。 词表以查询时点 NCBI 返回为准;retmax 默认 5、上限 20(本批候选内精确匹配置顶)。 历史前身词供扩展旧标引词,不保证补齐;下位词(最多展 10 个)供决定是否展开。 无描述符命中不等于主题无文献;NCBI 报 phrasesnotfound 时告警。

Inputs: term (required), retmax, as_json. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 8 tools

    Disambiguation5/5

    Each tool has a distinct role: record search, count-only, abstract retrieval, link/citation traversal, recall testing, MeSH lookup, query diffing, and bulk export. Overlaps such as search versus count and search versus fetch_abstracts are explicitly clarified by output scope and intended use.

    Naming Consistency3/5

    Multiword names use snake_case, but the set mixes verb-first names (fetch_abstracts, check_recall), bare verbs (search, count, export), and bare nouns (links, mesh, diff). It is readable, but there is no single predictable naming convention.

    Tool Count5/5

    Eight tools is well scoped for a PubMed research workflow and each tool supports a distinct part of literature retrieval or analysis. The count tool is somewhat redundant with search but is a reasonable lightweight convenience rather than bloat.

    Completeness4/5

    The surface covers search, counts, abstracts, related records/citations, MeSH vocabulary, recall checks, set comparison, and bulk export. Minor gaps remain around full-text/PMC retrieval and citation-manager export formats such as RIS or BibTeX.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables searching PubMed's biomedical literature database and retrieving article metadata, abstracts, and full content through the E-utilities API. Supports advanced queries, batch operations, and multiple output formats with automatic rate limiting.
      2
      -
    • A
      license
      A
      quality
      D
      maintenance
      An MCP server that provides direct access to PubMed and PubMed Central via the NCBI E-utilities API. It enables AI models to search biomedical literature, retrieve detailed article metadata, and download open-access full texts.
      5
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Exposes NCBI PubMed as MCP tools for searching literature, fetching abstracts, exploring citation graphs, and finding author publications without requiring an API key.
      4
      MIT