
Connects Claude to PubMed, PubMed Central, and Europe PMC through ten tools covering search, metadata retrieval, and full-text access. The search tools handle both standard PubMed queries and Europe PMC's broader corpus including preprints and patents. Article fetching returns structured metadata with MeSH terms and affiliations, while the full-text chain attempts NCBI PMC first, falls back to Europe PMC, then tries Unpaywall for open access PDFs. Citation formatting covers APA, MLA, BibTeX, and RIS. ID conversion moves between PMID, PMCID, and DOI. Reach for this when building research workflows that need programmatic access to biomedical literature beyond simple web searches, especially when you need structured article data or need to locate full text across multiple repositories.
claude mcp add --transport http pubmed https://pubmed.caseyjhand.com/mcpRun in your terminal. Add --scope user to make it available in every project.
Review the command, arguments, and environment values before installing — MCP servers run with your local permissions.
Verified live against the running server on Jun 10, 2026.
pubmed_search_articlesSearch PubMed with full query syntax, filters, and date ranges. Returns PMIDs and optional brief summaries. Supports field-specific filters (author, journal, MeSH terms), common filters (language, species, free full text), and pagination via offset for paging through large res...14 paramsSearch PubMed with full query syntax, filters, and date ranges. Returns PMIDs and optional brief summaries. Supports field-specific filters (author, journal, MeSH terms), common filters (language, species, free full text), and pagination via offset for paging through large res...
authorstringdateRangeobjectfreeFullTextbooleanhasAbstractbooleanjournalstringlanguagestringmaxResultsintegermeshTermsarrayoffsetintegerpublicationTypesarrayquery*stringsortstringrelevance · pub_date · author · journaldefault: relevancespeciesstringhumans · animalssummaryCountintegerpubmed_fetch_articlesFetch full article metadata by PubMed IDs. Returns detailed article information including abstract, authors, journal, MeSH terms.3 paramsFetch full article metadata by PubMed IDs. Returns detailed article information including abstract, authors, journal, MeSH terms.
includeGrantsbooleanincludeMeshbooleanpmids*arraypubmed_fetch_fulltextFetch full-text articles from PubMed Central with structured sections and references. When PMC misses, transparently falls back to Europe PMC `fullTextXML` (structured JATS for records with a PMC counterpart), then to Unpaywall — publisher-hosted or institutional open-access c...6 paramsFetch full-text articles from PubMed Central with structured sections and references. When PMC misses, transparently falls back to Europe PMC `fullTextXML` (structured JATS for records with a PMC counterpart), then to Unpaywall — publisher-hosted or institutional open-access c...
doisarrayincludeReferencesbooleanmaxSectionsintegerpmcidsarraypmidsarraysectionsarraypubmed_format_citationsGet formatted citations for PubMed articles in one or more styles (apa, mla, bibtex, ris, vancouver). Pass a single style as a string or multiple as an array.2 paramsGet formatted citations for PubMed articles in one or more styles (apa, mla, bibtex, ris, vancouver). Pass a single style as a string or multiple as an array.
formatvaluepmids*arraypubmed_find_relatedFind articles related to a source article — similar content (similar), articles citing this one (cited_by), or articles this one cites (references). Uses NCBI ELink as the primary source; falls back to Europe PMC then OpenAlex when NCBI is unavailable.4 paramsFind articles related to a source article — similar content (similar), articles citing this one (cited_by), or articles this one cites (references). Uses NCBI ELink as the primary source; falls back to Europe PMC then OpenAlex when NCBI is unavailable.
maxResultsintegeroffsetintegerpmid*stringrelationshipstringsimilar · cited_by · referencesdefault: similarpubmed_spell_checkSpell-check a query and get NCBI's suggested correction. Useful for refining search queries.1 paramsSpell-check a query and get NCBI's suggested correction. Useful for refining search queries.
query*stringpubmed_lookup_meshSearch and explore the MeSH (Medical Subject Headings) controlled vocabulary. Returns descriptor records with tree numbers, scope notes, and entry terms.3 paramsSearch and explore the MeSH (Medical Subject Headings) controlled vocabulary. Returns descriptor records with tree numbers, scope notes, and entry terms.
includeDetailsbooleanmaxResultsintegerquery*stringpubmed_lookup_citationLook up PubMed IDs from partial bibliographic citations. Useful when you have a reference (journal, year, volume, page, author) and need the PMID — deterministic citation matching, more reliable than free-text search for structured references. Each citation must include at lea...1 paramsLook up PubMed IDs from partial bibliographic citations. Useful when you have a reference (journal, year, volume, page, author) and need the PMID — deterministic citation matching, more reliable than free-text search for structured references. Each citation must include at lea...
citations*arraypubmed_convert_idsConvert between article identifiers (DOI, PMID, PMCID). Accepts up to 50 IDs of a single type per request. Only resolves articles indexed in PubMed Central — for articles not in PMC, use pubmed_search_articles instead.2 paramsConvert between article identifiers (DOI, PMID, PMCID). Accepts up to 50 IDs of a single type per request. Only resolves articles indexed in PubMed Central — for articles not in PMC, use pubmed_search_articles instead.
idType*stringpmcid · pmid · doiids*arraypubmed_europepmc_searchSearch Europe PMC, a broad open-access biomedical corpus. Surfaces preprints (`source: PPR`), patents (`source: PAT`), Agricola (`source: AGR`), plus everything in PubMed (`MED`) and PMC. Use when additional coverage is needed — preprints and EPMC-only OA records are the typic...6 paramsSearch Europe PMC, a broad open-access biomedical corpus. Surfaces preprints (`source: PPR`), patents (`source: PAT`), Agricola (`source: AGR`), plus everything in PubMed (`MED`) and PMC. Use when additional coverage is needed — preprints and EPMC-only OA records are the typic...
cursorMarkstringpageSizeintegerquery*stringresultTypestringcore · litedefault: coresortstringsourcesarraySearch 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
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.
| 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, 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_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 |
| Resource | Description |
|---|---|
pubmed://database/info | PubMed database metadata via EInfo (field list, record count, last update) |
| Prompt | Description |
|---|---|
research_plan | Generate a structured four-phase biomedical research plan |
pubmed_search_articles toolmaxResults: 0 for the match count alone; summaryCount adds briefs for up to 50 hitstotalCount, the effectiveQuery PubMed ran, and the appliedFilterspubmed_fetch_articles toolunavailablePmidsincludeGrants, and the members of a collective author (its InvestigatorList, thousands on some consortium trials) via includeInvestigatorspubmed_format_citations, directly under its titlerecordType separates journal articles from Bookshelf chapters and books; opt-in maxResponseCharacters defers overflow to deferred.idspubmed_fetch_fulltext toolpmcids, pmids, and dois in any mix, up to 50 distinct identifiers per call: the first 10 are fetched and the rest returned in overLimit for a follow-up call. Each is tried against PMC, then Europe PMC, then Unpaywall (needs UNPAYWALL_EMAIL); an article several of them name is fetched and returned once, and viaSource names 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 bodyreason and triedTiers; sections, maxCharacters, overflowMode, and maxResponseCharacters bound the response, and truncation reports what was cutpubmed_europepmc_search toolPPR), patents (PAT), and Agricola (AGR) to MED and PMC; defaults to MED, PMC, PPRcursorMark / nextCursorMark, up to 100 per page; abstracts arrive as 400-character snippetssort of comma-separated <field> asc|desc keys; relevance is the default order, and a sort Europe PMC cannot use fails as europepmc_invalid_inputEUROPEPMC_ENABLED=falsepubmed_europepmc_fetch toolrecords: [{ source, epmcId }], each pair copied from a search hit, with the full abstract; unresolved ids land in notFound; opt-in maxResponseCharacters defers overflow to deferred.recordsEUROPEPMC_ENABLED=falsepubmed_format_citations toolapa, mla, bibtex, ris, and vancouvernotices and are shown ahead of its citations; Vancouver adds a Retraction in: / Erratum in: note and APA a retraction parentheticalpubmed_find_related toolsimilar, cited_by, or references, up to 50 per page with offset paginationall_providers_failed if none canpubmed_spell_check tooloriginal, corrected, and hasSuggestion; corrections land in place, so field tags, operators, spacing, and gene symbols stay as writtenpubmed_search_articles with correctedpubmed_lookup_mesh toolnextOffsetmeshId, e.g. D000072657) beside the Entrez UID; includeDetails (default on) adds tree numbers, scope notes, and entry termspubmed_lookup_citation toolmatched, not_found, or ambiguous, with recovery detailpubmed_convert_ids toolidType (doi, pmid, pmcid); only PMC-indexed articles resolvepubmed://database/info resourcepubmed database, returned as application/jsoncount, lastUpdate, and fields[], whose names are the search tags pubmed_search_articles acceptsresearch_plan prompttitle, goal, and keywords required; organism and includeAgentPrompts optionalincludeAgentPrompts: "true" adds an agent-guidance block under each of its nine sub-steps, two of which point at tools: the literature review names pubmed_search_articles and pubmed_lookup_mesh, and the interpretation step names pubmed_search_articlesBuilt 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:
pubmed_fetch_fulltext also matches DOIs case-insensitively and PMC IDs with or without the PMC prefixAgent-friendly output:
source: "pmc" | "unpaywall", typed unavailable reasons, viaSource and triedTiers fields, so callers branch on data, not string parsingA public instance is available at https://pubmed.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"pubmed-mcp-server": {
"type": "streamable-http",
"url": "https://pubmed.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"pubmed-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/pubmed-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"NCBI_API_KEY": "your-key-here"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"pubmed-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/pubmed-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"NCBI_API_KEY": "your-key-here"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"pubmed-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/pubmed-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/pubmed-mcp-server.git
cd pubmed-mcp-server
bun install
cp .env.example .env
# edit .env and set NCBI_API_KEY, NCBI_ADMIN_EMAIL, and UNPAYWALL_EMAIL as needed
| 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.
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
| Directory | Purpose |
|---|---|
src/mcp-server/tools | Tool definitions (*.tool.ts). Eleven tools across PubMed, PMC, and Europe PMC. |
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. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for logging, ctx.state for storagecreateApp() arrays in src/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
NCBI_API_KEYNCBI API key for higher rate limits (10 req/s vs 3 req/s).
NCBI_ADMIN_EMAILContact email sent with NCBI requests (recommended by NCBI).
UNPAYWALL_EMAILContact email for Unpaywall. When set, pubmed_fetch_fulltext falls back to Unpaywall open-access copies for DOIs not in PMC.
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_PUBLIC_URLPublic origin override for deployments behind a TLS-terminating reverse proxy (e.g. https://mcp.example.com).
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.