关于 PubMed MCP Server
PubMed MCP Server 面向生物医学研究者及文献工作流,提供 PubMed、Europe PMC 等来源的检索、文章与全文获取及引文处理。它同时支持本地运行和公共托管端点,并以来源信息和结构化结果呈现数据。
主要功能
- 01检索 PubMed 与 Europe PMC
- 02获取文章元数据和全文
- 03格式化及解析引文
- 04查询 MeSH 术语与引用指标
- 05转换 PMID、PMCID 和 DOI
- 06提供来源标注与部分失败结果
适用场景
- 01查找特定主题的生物医学文献
- 02获取文章全文及其元数据
- 03整理并转换参考文献格式
- 04制定结构化生物医学研究计划
MCP 相关
向 MCP 客户端提供 12 个工具、1 个资源和 1 个提示词,涵盖文献检索、文章获取、引文和 MeSH 查询等。支持 stdio、本地 Streamable HTTP 和公共托管端点。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://pubmed.caseyjhand.com/mcpclaude mcp add --transport http pubmed https://pubmed.caseyjhand.com/mcp{"mcpServers":{"pubmed":{"type":"http","url":"https://pubmed.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"pubmed":{"type":"http","url":"https://pubmed.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"pubmed":{"type":"http","url":"https://pubmed.caseyjhand.com/mcp"}}}{"mcpServers":{"pubmed":{"serverUrl":"https://pubmed.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
11| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| query | string | 是 | PubMed 搜索查询(支持完整的 NCBI 语法) |
| maxResults | integer | 否 | 要返回的最大结果数 |
| offset | integer | 否 | 用于分页的结果偏移量(从 0 开始)。PubMed 对一个结果集最多提供前 9999 条记录,因此此值上限为 9998;如需获取更多记录,请缩小查询范围或添加筛选条件。 |
| sort | enum | 否 | 排序方式:relevance(默认)、pub_date(最新优先)、author 或 journalrelevance | pub_date | author | journal |
| dateRange | object | 否 | 按日期范围筛选。仅当 `minDate` 和 `maxDate` 均非空时才应用筛选;任一为空都会禁用整个日期范围筛选。 |
| dateRange.minDate | string | 是 | 开始日期(YYYY/MM/DD、YYYY/MM 或 YYYY);空字符串表示不设此边界 |
| dateRange.maxDate | string | 是 | 结束日期(YYYY/MM/DD、YYYY/MM 或 YYYY);空字符串表示不设此边界 |
| dateRange.dateType | enum | 否 | 日期类型:pdat(出版)、mdat(修改)、edat(Entrez)pdat | mdat | edat |
| publicationTypes | array | 否 | 按出版类型筛选(例如 "Review"、"Clinical Trial"、"Meta-Analysis")。多个值按 OR 处理,任意值匹配即可。 |
| author | string | 否 | 按作者姓名筛选(例如 "Smith J") |
| journal | string | 否 | 按期刊名称筛选 |
| meshTerms | array | 否 | 按 MeSH 术语筛选。多个术语按 AND 处理,必须全部匹配。 |
| language | string | 否 | 按语言筛选(例如 "english") |
| hasAbstract | boolean | 否 | 仅包含带摘要的文章 |
| freeFullText | boolean | 否 | 仅包含可免费获取全文的文章 |
| species | enum | 否 | 按物种筛选humans | animals |
| summaryCount | integer | 否 | 获取前 N 条结果的简要摘要(0 = 仅返回 PMID)。超过 50 条上限时,将剩余的 PMID 传递给 pubmed_fetch_articles。 |
README 原文English
来自项目 READMEREADME 暂无中文译文,以下为英文原文;中文介绍见上方。
@cyanheads/pubmed-mcp-server
Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://pubmed.caseyjhand.com/mcp
Overview
Biomedical literature from PubMed, PubMed Central, and Europe PMC. Search it, fetch metadata and full text, resolve identifiers and partial citations, format references, and ground queries in MeSH vocabulary. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|---|---|
pubmed_search_articles | Search PubMed with full query syntax, structured filters, date ranges, and optional summaries |
pubmed_fetch_articles | Fetch article metadata by PMID: abstract, authors, journal, MeSH terms, databank accessions such as trial registration IDs, grants, a collective author's investigators on request, linked retraction and correction notices |
pubmed_fetch_fulltext | Fetch full text by PMID, PMCID, or DOI, falling back from PMC to Europe PMC to Unpaywall |
pubmed_europepmc_search | Search Europe PMC for preprints, patents, Agricola, and open-access records PubMed doesn't carry |
pubmed_europepmc_fetch | Fetch complete Europe PMC records, including the untruncated abstract, as records: [{ source, epmcId }] |
pubmed_fetch_citation_metrics | Fetch NIH iCite citation metrics by PMID: Relative Citation Ratio, NIH percentile, citation counts and rates |
pubmed_format_citations | Format citations in APA 7th, MLA 9th, BibTeX, RIS, or Vancouver (ICMJE/NLM), with linked retraction and correction notices |
pubmed_find_related | Find similar articles, citing articles, or references for a PMID |
pubmed_spell_check | Correct a misspelled PubMed query via NCBI ESpell |
pubmed_lookup_mesh | Look up MeSH headings with tree numbers, scope notes, and entry terms |
pubmed_lookup_citation | Resolve partial references, up to 25 at a time, to PMIDs via ECitMatch |
pubmed_convert_ids | Convert between DOI, PMID, and PMCID via the PMC ID Converter |
Resources
| Resource | Description |
|---|---|
pubmed://database/info | PubMed database metadata via EInfo (field list, record count, last update) |
Prompts
| Prompt | Description |
|---|---|
research_plan | Generate a structured four-phase biomedical research plan |
Capability reference
pubmed_search_articles tool
- Full PubMed query syntax plus filters (author, journal, MeSH, publication type, language, species, abstract, free full text) and publication/modification/Entrez date ranges
- Up to 1,000 results per page and offsets up to 9,998, or
maxResults: 0for the match count alone;summaryCountadds briefs for up to 50 hits - Reports
totalCount, theeffectiveQueryPubMed ran, and theappliedFilters - Rejects blank filter values, impossible dates, and reversed date ranges before PubMed is called
pubmed_fetch_articles tool
- Up to 200 PMIDs per call; misses are listed in
unavailablePmids - Abstract, authors, journal, DOI, publication types, linked retraction/erratum/comment notices, and links; MeSH terms on by default, grants via
includeGrants, and the members of a collective author (itsInvestigatorList, thousands on some consortium trials) viaincludeInvestigators - A retracted, corrected, or questioned article opens with the same notice block as
pubmed_format_citations, directly under its title dataBankslists the record's trial registrations and data deposits (ClinicalTrials.gov NCT IDs, GenBank and PDB accessions, Dryad DOIs) verbatim; searchpubmed_search_articlesfor<accession>[si]to find other records citing onerecordTypeseparates journal articles from Bookshelf chapters and books; opt-inmaxResponseCharactersdefers overflow todeferred.ids
pubmed_fetch_fulltext tool
pmcids,pmids, anddoisin any mix, up to 50 distinct identifiers per call: the first 10 are fetched and the rest returned inoverLimitfor a follow-up call. Each is tried against PMC, then Europe PMC, then Unpaywall (needsUNPAYWALL_EMAIL); an article several of them name is fetched and returned once, andviaSourcenames the tier that answeredsource: "pmc"returns sections (the body, then back matter such as acknowledgments, declarations, and appendices), tables, and figures;source: "unpaywall"returns a best-effort HTML or PDF text body- Europe PMC full text is fetched for records Europe PMC marks open access, preprints included; articles carry the
licensestheir PMC JATS states - Misses carry a typed
reasonandtriedTiers;sections,maxSections,maxCharacters,overflowMode, andmaxResponseCharactersbound the response,truncationreports what was cut, andsectionCapnames the sectionsmaxSectionscut
pubmed_europepmc_search tool
- Adds preprints (
PPR), patents (PAT), and Agricola (AGR) toMEDandPMC; defaults toMED,PMC,PPR - Cursor pagination via
cursorMark/nextCursorMark, up to 100 per page; abstracts arrive as 400-character snippets - Optional
sortof comma-separated<field> asc|desckeys;relevanceis the default order, and a sort Europe PMC cannot use fails aseuropepmc_invalid_input - Hits carry
licenseandhasFullTextXml - Not registered when
EUROPEPMC_ENABLED=false
pubmed_europepmc_fetch tool
- Up to 25 records per call as
records: [{ source, epmcId }], each pair copied from a search hit, with the full abstract,license, andhasFullTextXml; unresolved ids land innotFound; opt-inmaxResponseCharactersdefers overflow todeferred.records - Not registered when
EUROPEPMC_ENABLED=false
pubmed_fetch_citation_metrics tool
- Up to 1,000 PMIDs per call; the first 200 distinct are fetched and the rest returned in
overLimit, PMIDs NIH iCite has no record for inunavailablePmids - Relative Citation Ratio (with a provisional flag), NIH percentile, citation count and rates, Approximate Potential to Translate, MeSH category shares, and clinical citations
- iCite does not flag retractions; check
pubmed_fetch_articlesfor notices - Source: NIH iCite
pubmed_format_citations tool
- Up to 50 PMIDs per call, in any mix of
apa,mla,bibtex,ris, andvancouver - Bookshelf records cite as edited books, each chapter dated by its own last revision or contribution date; PMIDs that can't be fetched are reported as unavailable
- Vancouver writes page ranges in elided Citing Medicine form (
1637-1645→1637-45); BibTeXissnand RISSNcarry the journal's linking ISSN, and RISTIdrops its trailing period - Retractions, errata, and expressions of concern NCBI links to an article come back as
noticesand are shown ahead of its citations; Vancouver adds aRetraction in:/Erratum in:note and APA a retraction parenthetical
pubmed_find_related tool
similar,cited_by, orreferences, up to 50 per page with offset pagination- Falls back to Europe PMC, then OpenAlex, and names the provider that answered; fails as
all_providers_failedif none can
pubmed_spell_check tool
- Returns
original,corrected, andhasSuggestion; corrections land in place, so field tags, operators, spacing, and gene symbols stay as written, and a single letter such as an author initial is never swapped for another - Values of indexed field tags (
aged[mh],zhang y[au],free full text[sb]) are kept as written; free-text fields ([tiab],[ti],[tw]) are still corrected - Run it after a zero-hit or thin search, then retry
pubmed_search_articleswithcorrected
pubmed_lookup_mesh tool
- Descriptors by name or free-text term, with an exact heading match pinned first (the descriptor, for a drug-class heading); up to 50 per page, continued via
nextOffset - Records carry their MeSH unique ID (
meshId, e.g.D000072657) beside the Entrez UID;includeDetails(default on) adds tree numbers, scope notes, and entry terms
pubmed_lookup_citation tool
- Up to 25 partial citations per call; a journal or a four-digit year is required, and volume, first page, and author sharpen the match
- Each is matched independently and comes back
matched,not_found, orambiguous, with recovery detail
pubmed_convert_ids tool
- Up to 50 ids per call, all of one declared
idType(doi,pmid,pmcid); only PMC-indexed articles resolve - One success or error row per id, in order, so a partial batch never fails
pubmed://database/info resource
- Live EInfo call for the
pubmeddatabase, returned asapplication/json count,lastUpdate, andfields[], whose names are the search tagspubmed_search_articlesaccepts
research_plan prompt
- Arguments:
title,goal, andkeywordsrequired;organismandincludeAgentPromptsoptional - Returns a four-phase research plan;
includeAgentPrompts: "true"adds an agent-guidance block under each of its nine sub-steps, two of which point at tools: the literature review namespubmed_search_articlesandpubmed_lookup_mesh, and the interpretation step namespubmed_search_articles
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
PubMed-specific:
- NCBI E-utilities (ESearch, EFetch, ESummary, ELink, ESpell, EInfo, ECitMatch) and the PMC ID Converter, with Europe PMC, OpenAlex, and Unpaywall filling the gaps
- Shared NCBI request queue: paced request starts, capped concurrency, a cooldown that holds every caller after an NCBI 429, and one deadline covering queue wait and retries
- XML parsing built for PubMed's inconsistent records: structured abstracts, missing fields, varying date formats
- Forgiving identifiers: a zero-padded PMID resolves as the PMID it spells in every tool that takes one;
pubmed_fetch_fulltextalso matches DOIs case-insensitively and PMC IDs with or without thePMCprefix - Hand-rolled citation formatters (APA, MLA, BibTeX, RIS, Vancouver) with no dependencies
Agent-friendly output:
- Provenance in responses: source labels, license fields on full-text and Europe PMC results, best-effort warnings on Unpaywall results, and effective-query echo on searches, so agents can judge what to trust
- Graceful partial failure: batch tools return per-item success/error rows instead of failing the request, with structured status codes and actionable next-step text
- Discriminated output contracts:
source: "pmc" | "unpaywall", typedunavailablereasons,viaSourceandtriedTiersfields, so callers branch on data, not string parsing
Getting started
Connect to the hosted instance, no install:
claude mcp add --transport http pubmed-mcp-server https://pubmed.caseyjhand.com/mcp
Or run it locally:
claude mcp add pubmed-mcp-server -- npx -y @cyanheads/pubmed-mcp-server
For other clients, add this to the MCP config file:
{
"mcpServers": {
"pubmed-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/pubmed-mcp-server"]
}
}
}
An NCBI API key in NCBI_API_KEY raises the rate limit from 3 to 10 requests per second (-e NCBI_API_KEY=your-key, or an env entry). For Docker or a source build, see Running the server.
Configuration
| Variable | Description | Default |
|---|---|---|
NCBI_API_KEY | NCBI API key; raises the rate limit from 3 to 10 req/s. | none |
NCBI_ADMIN_EMAIL | Contact email sent with NCBI requests, as NCBI recommends. | none |
NCBI_REQUEST_DELAY_MS | Minimum gap between NCBI request starts, in ms. | 400 (100 with a key) |
NCBI_MAX_CONCURRENT | Max concurrent in-flight NCBI requests. | 8 |
NCBI_MAX_RETRIES | Retry attempts for failed NCBI requests. | 6 |
NCBI_TIMEOUT_MS | Per-request HTTP timeout, in ms. | 30000 |
NCBI_TOTAL_DEADLINE_MS | Deadline for one NCBI call across queue wait, retries, and backoff, in ms. A call that can't start in time is rejected at once. | 60000 |
UNPAYWALL_EMAIL | Contact email for Unpaywall. Setting it enables the Unpaywall tier of pubmed_fetch_fulltext for non-PMC DOIs. | none |
UNPAYWALL_TIMEOUT_MS | Per-request timeout for Unpaywall lookups and content fetches, in ms. | 20000 |
EUROPEPMC_ENABLED | Set false to disable every Europe PMC call: both Europe PMC tools go unregistered, pubmed_fetch_fulltext skips that tier, and pubmed_find_related skips that fallback. | true |
EUROPEPMC_EMAIL | Optional contact email sent with Europe PMC requests. | none |
EUROPEPMC_REQUEST_DELAY_MS | Minimum gap between Europe PMC request starts, in ms. | 200 |
EUROPEPMC_MAX_RETRIES | Retry attempts for failed Europe PMC requests. | 3 |
EUROPEPMC_TIMEOUT_MS | Per-request timeout for Europe PMC calls, in ms. | 20000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for every server setting and the common framework overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
-
Clone and install:
git clone https://github.com/cyanheads/pubmed-mcp-server.git cd pubmed-mcp-server && bun install cp .env.example .env # set NCBI_API_KEY, NCBI_ADMIN_EMAIL, and UNPAYWALL_EMAIL as needed -
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Docker
docker run --rm -p 3010:3010 ghcr.io/cyanheads/pubmed-mcp-server:latest
The image defaults to HTTP transport, stateless session mode, and logs to /var/log/pubmed-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/pubmed-mcp-server:latest"]. To build locally, docker build -t pubmed-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/mcp-server/tools | Tool definitions (*.tool.ts). Twelve tools across PubMed, PMC, Europe PMC, and NIH iCite. |
src/mcp-server/resources | Resource definitions. Database info resource. |
src/mcp-server/prompts | Prompt definitions. Research plan prompt. |
src/services/ncbi | NCBI E-utilities service layer — API client, queue, parser, formatter. |
src/services/europe-pmc | Europe PMC service — search + fullTextXML JATS retrieval. Reuses the NCBI JATS parser. |
src/services/unpaywall | Unpaywall service — DOI → OA location resolution and content fetch (HTML/PDF). |
src/services/openalex | OpenAlex service — last-resort provider for pubmed_find_related. |
src/config | Server-specific environment variable parsing and validation with Zod. |
tests/ | Unit and integration tests, mirroring the src/ structure. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools and resources in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。