Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Search PubMed and retrieve structured biomedical literature with PMID lists, abstracts, MeSH terms, publication types, and PMC IDs for full-text access. Use this skill whenever the user mentions PubMed, PMID, MeSH terms, Clinical Queries, NCBI, E-utilities, or needs evidence for systematic reviews, RCT searches, drug-disease research, mechanism mapping, market research, or clinical evidence gathering. Make sure to use at the START of any medical evidence pipeline (diagnostic queries, prognosis,
.claude/skills/ethanyoq-pubmed-eutils/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 110% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 109% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 246% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 197% | 0% |
把 NCBI E-utilities (esearch / efetch / esummary / elink) 封装成医学证据检索流水线里唯一的 PubMed 召回入口。只负责"把 PMID 列表 + 结构化元数据拿回来",不做相关性重排、不抽全文、不评证据等级。
bioc-fulltext-fetch 取全文)medical-evidence-grading 排序、给 pubtator-entity-search 实体标注)bioc-fulltext-fetch(PMC OAI / BioC API)europepmc-search(互补召回)clinical-trials-v2 + aact-bulk-trialspubtator-entity-searchmedical-evidence-gradingmedical-evidence-grading 或 reranker 处理 ┌─ pubmed-eutils(本 skill · 召回主力 · PMID + 元数据)
│
召回层 (recall) ───┼─ europepmc-search(互补 · preprint / 欧洲文献)
│
└─ clinical-trials-v2 / aact-bulk-trials(试验注册)
│
▼ PMID list
全文层 (fulltext) ─── bioc-fulltext-fetch(PMC 全文 JATS / BioC)
│
▼ entity-rich text
标注层 (annotate) ─── pubtator-entity-search(gene/disease/drug NER)
│
▼
排序层 (rank) ─── medical-evidence-grading(GRADE / RoB / 证据等级)
│
▼
终下游 ─── evidence-appendix-sync(市场调研附录 C 同步)显式 skill 引用路径(同 ~/.claude/skills/ 下):
~/.claude/skills/europepmc-search/SKILL.md — 互补召回(preprint / 欧洲灰文献)~/.claude/skills/bioc-fulltext-fetch/SKILL.md — 下游全文获取(PMID/PMCID → JATS/BioC)~/.claude/skills/pubtator-entity-search/SKILL.md — 互补实体级关系挖掘(疾病-药物-基因)~/.claude/skills/medical-evidence-grading/SKILL.md — 上层证据排序(GRADE / OCEBM / RoB)~/.claude/skills/evidence-appendix-sync/SKILL.md — 终下游附录 C 同步~/.claude/skills/clinical-trials-v2/SKILL.md — 试验注册(非文献)互补协作规则:本 skill 永远先跑,输出 PMID + 摘要 + MeSH,让下游 skill 决策"取哪些做全文 / 哪些进证据矩阵"。
pythonfrom typing import Literal from dataclasses import dataclass @dataclass class PubMedRecord: pmid: str title: str abstract: str | None authors_first: str | None authors_count: int journal: str | None year: int | None mesh_terms: list[str] publication_types: list[str] doi: str | None = None pmcid: str | None = None cited_count: int | None = None # 通过 elink pubmed_pubmed_citedin 获取,可选 # 1) 检索 → PMID 列表 def esearch_pubmed( query: str, max_results: int = 200, filters: dict | None = None, # {"pubdate_from": "2020/01/01", "pubdate_to": "2025/12/31", # "pub_types": ["Randomized Controlled Trial"], # "species": "humans", "language": "english"} sort: Literal["relevance", "pub_date", "first_author", "journal"] = "relevance", ) -> list[str]: ... # 2) 批量取摘要 + MeSH(XML 解析) def efetch_abstracts(pmid_list: list[str]) -> list[PubMedRecord]: ... # 3) 简表(标题 + 第一作者 + 年份 + 期刊,比 efetch 快 5-10x) def esummary_pubmed(pmid_list: list[str]) -> list[dict]: ... # 4) PMID → PMCID 映射(给 bioc-fulltext-fetch 用) def elink_pubmed_to_pmc(pmid_list: list[str]) -> dict[str, str]: """返回 {pmid: pmcid} · 没有全文的 PMID 不出现在结果里""" ... # 5) Clinical Queries 内置过滤器 def pubmed_clinical_queries( query: str, category: Literal[ "therapy", "diagnosis", "etiology", "prognosis", "clinical_prediction_guides", "systematic_reviews" ], scope: Literal["narrow", "broad"] = "narrow", max_results: int = 200, ) -> list[str]: ...
pythondef load_ncbi_config() -> dict: # 1. 项目本地(最高优先级) project_yaml = Path.cwd() / ".config" / "ncbi.local.yaml" if project_yaml.exists(): return yaml.safe_load(project_yaml.read_text()) # 2. 用户全局 user_yaml = Path.home() / ".config" / "ncbi.yaml" if user_yaml.exists(): return yaml.safe_load(user_yaml.read_text()) # 3. 环境变量 if os.getenv("NCBI_API_KEY"): return { "api_key": os.environ["NCBI_API_KEY"], "email": os.getenv("NCBI_EMAIL", "anonymous@example.com"), "tool": os.getenv("NCBI_TOOL", "claude-code-pubmed-eutils"), } # 4. 降级:无 key 模式(NCBI 允许 3 RPS) return {"api_key": None, "email": "anonymous@example.com", "tool": "claude-code-pubmed-eutils", "rps": 3}
配置文件示例 ~/.config/ncbi.yaml:
yamlapi_key: "your_36char_ncbi_api_key" email: "you@example.com" # 必传,NCBI 礼貌要求 tool: "your-project-name" # 必传,便于 NCBI 联系 rps: 10 # 有 key 上限 10
> 关键:每次请求都要带 email + tool + api_key(如有),否则 NCBI 可能 ban IP。
7 个 ready-to-use 医学场景检索式(系统综述 / RCT / Clinical Queries / 流行病学 / RWE / 中国人群 / 指南)和疾病迁移指引详见参考文件,以保持主文件精简:
→ references/query-templates.md(同目录 ~/.claude/skills/pubmed-eutils/references/query-templates.md)
完整 endpoint 表 / dbfrom-db 组合 / 速率限制详见:
→ references/endpoint-table.md
主文件保留要点:
| 模式 | RPS | 单批 PMID 上限 | 超时 | | --------- | --- | -------------- | ---- | | 有 API key | 10 | 200 | 30s | | 无 key | 3 | 200 | 30s |
实现要求:令牌桶限流 + 429/503 指数退避(1s→2s→4s,3 次) + 单批超 200 自动切片 + 长 query (>2000 字符) 切 POST。
| # | 失败模式 | 根因 | 修复 | |---|---------------------------|-------------------------------------------|-------------------------------------------------------------------| | 1 | 无 key 限速被 ban | HTTP 429 持续 / 缺 email+tool | 检查是否传 email + tool + api_key;申请 API key(免费) | | 2 | 429 / 5xx 暂时性错误 | 限速触发 / NCBI 服务器抖动 | 指数退避重试 3 次(1s→2s→4s);仍失败抛 EUtilsTransientError | | 3 | XML 解析错误 | <ERROR>...</ERROR> 节点 | 单条 PMID 失效 → 跳过该条 + log warning,不 raise 中断整批 | | 4 | PMID 不存在 / 已撤稿(404) | efetch 返回空 <PubmedArticle> | 在 PubMedRecord.title 标 [RETRACTED] 或 [NOT FOUND] | | 5 | MeSH term 不规范返 0 结果 | preferred term 拼写 / 已被合并 | 用 einfo 查 MeSH 树;退化为 [tiab] 自由词 + 同义词扩展 | | 6 | email 未传被 NCBI 警告 | 请求缺 email 参数 | 强制配置加载层校验 email,缺失则用 anonymous@example.com 兜底 | | 7 | 网络超时 | httpx.ReadTimeout | 退避重试 3 次仍失败 → 抛 EUtilsTimeout(上游可降级到 europepmc) | | 8 | 长 query GET 414 | URL too long | 自动切到 POST(E-utilities 支持) | | 9 | 日期格式错 | NCBI 返回 <ERROR>Empty term</ERROR> | 强制 YYYY/MM/DD;过滤器 builder 入口校验 | | 10| WebEnv 失效 | history server 过期(8h) | 重新 esearch 而非缓存 history |
本 skill 只给原始召回结果,不做证据等级判断。证据等级排序由 medical-evidence-grading 完成,依据:
elink pubmed_pubmed_citedin 选配输出 cited_count)bioc-fulltext-fetch 取全文后正则抽取)输出 PubMedRecord 时保留 publication_types 原始列表,让下游 skill 自行映射 GRADE / OCEBM / 牛津等级。
| 平台 | 触发方式 | 备注 | | ------------ | --------------------------------- | --------------------------------------------------- | | Claude Code | 自动 (description 包含触发词) | SKILL.md frontmatter 已优化 | | Codex CLI | codex skill use pubmed-eutils | 全部函数签名是纯 Python type hint,可直接 import | | Gemini CLI | /skill pubmed-eutils <query> | description 用关键词 + 自然语言双语,通用触发 |
实现层兼容要求:
anthropic / openai / google.genai)httpx / lxml(XML 解析)/ pydantic 或 dataclasses / pyyaml / aiolimiteresearch_pubmed + aesearch_pubmed),让 agent 编排器自由选用项目内 references(progressive disclosure):
~/.claude/skills/pubmed-eutils/references/query-templates.md — 7 个医学场景检索式 + 跨疾病移植清单~/.claude/skills/pubmed-eutils/references/endpoint-table.md — endpoint 速查 / dbfrom-db 组合 / 速率限制详情外部官方文档:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 11,301 | 10,946 | -3% | 1 | 1 | 0% | 2,209 | 5,954 | +170% | 0 | 0 | — |
case-02 | fail→pass | 12,485 | 5,946 | -52% | 1 | 1 | 0% | 2,309 | 4,846 | +110% | 0 | 0 | — |
case-03 | pass→pass | 10,367 | 3,853 | -63% | 1 | 1 | 0% | 1,610 | 4,222 | +162% | 0 | 0 | — |
case-04 | fail→pass | 13,731 | 9,747 | -29% | 1 | 1 | 0% | 2,808 | 5,444 | +94% | 0 | 0 | — |
case-05 | fail→pass | 12,679 | 5,018 | -60% | 1 | 1 | 0% | 2,194 | 4,579 | +109% | 0 | 0 | — |
case-06 | fail→fail | 14,807 | 11,132 | -25% | 1 | 1 | 0% | 2,652 | 5,728 | +116% | 0 | 0 | — |
case-07 | fail→pass | 7,130 | 4,251 | -40% | 1 | 1 | 0% | 1,304 | 4,515 | +246% | 0 | 0 | — |
case-08 | fail→pass | 8,785 | 6,155 | -30% | 1 | 1 | 0% | 1,613 | 4,790 | +197% | 0 | 0 | — |
case-09 | fail→pass | 8,275 | 3,077 | -63% | 1 | 1 | 0% | 1,445 | 4,060 | +181% | 0 | 0 | — |
case-10 | fail→fail | 6,768 | 2,019 | -70% | 1 | 1 | 0% | 1,229 | 3,877 | +215% | 0 | 0 | — |
case-11 | fail→fail | 13,621 | 15,375 | +13% | 1 | 1 | 0% | 3,039 | 6,891 | +127% | 0 | 0 | — |
case-12 | pass→pass | 10,667 | 7,306 | -32% | 1 | 1 | 0% | 2,431 | 5,232 | +115% | 0 | 0 | — |
case-13 | fail→pass | 5,106 | 3,425 | -33% | 1 | 1 | 0% | 1,148 | 4,250 | +270% | 0 | 0 | — |
case-14 | pass→pass | 11,036 | 5,491 | -50% | 1 | 1 | 0% | 2,137 | 4,788 | +124% | 0 | 0 | — |
case-15 | fail→pass | 12,752 | 10,285 | -19% | 1 | 1 | 0% | 2,916 | 5,885 | +102% | 0 | 0 | — |
case-16 | fail→fail | 13,976 | 10,546 | -25% | 1 | 1 | 0% | 2,692 | 5,845 | +117% | 0 | 0 | — |
case-17 | pass→pass | 6,564 | 4,299 | -35% | 1 | 1 | 0% | 1,556 | 4,588 | +195% | 0 | 0 | — |
case-18 | pass→pass | 3,804 | 5,943 | +56% | 1 | 1 | 0% | 742 | 4,908 | +561% | 0 | 0 | — |
case-19 | pass→pass | 14,674 | 11,512 | -22% | 1 | 1 | 0% | 3,436 | 6,319 | +84% | 0 | 0 | — |
case-20 | pass→pass | 4,242 | 4,086 | -4% | 1 | 1 | 0% | 884 | 4,603 | +421% | 0 | 0 | — |
case-21 | pass→pass | 12,496 | 7,183 | -43% | 1 | 1 | 0% | 2,526 | 5,042 | +100% | 0 | 0 | — |
case-22 | pass→pass | 8,149 | 3,394 | -58% | 1 | 1 | 0% | 1,651 | 4,349 | +163% | 0 | 0 | — |
case-23 | fail→pass | 13,358 | 9,752 | -27% | 1 | 1 | 0% | 3,026 | 5,786 | +91% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +39 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.