Koskamo

pubmed-mcp-server

An MCP server that enables agents to search PubMed and Europe PMC, fetch article metadata and full text, retrieve citation metrics, format references, and explore MeSH terms for biomedical research.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

pubmed-mcp-server logo, by cyanheadsCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-06Published by cyanheads
MCP endpoint (Streamable HTTP)
https://pubmed.caseyjhand.com/mcp
Vendor documentation

What its tools do

12 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

12 of 12 have a description · 12 of 12 declare behavior hints · 12 of 12 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Search PubMed with full query syntax and filters
  • Fetch article metadata and full text from PMC or Unpaywall
  • Format citations in APA, MLA, BibTeX, or Vancouver styles
  • Find related articles or citation metrics by PMID

Source and maintenance

Community listingRegistry 2.12.0
Maintenance checked

Protocol and capabilities

Server
pubmed-mcp-server 2.12.0
MCP protocol negotiated in check
2025-11-25
Tools
12 advertised
Resources
2 advertised
Resource templates
1 advertised
Prompts
1 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "logging": {},
  "prompts": {
    "listChanged": true
  },
  "resources": {
    "subscribe": true,
    "listChanged": true
  },
  "extensions": {
    "io.modelcontextprotocol/skills": {
      "directoryRead": true
    }
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Use the pubmed_* tools to search PubMed and PubMed Central, fetch article metadata and full text, format citations, and find related articles via NCBI's E-utilities. Articles are keyed by PMID (integer); PMC full text by PMCID (`PMC` prefix); most also carry a DOI. Typical flow: `pubmed_search_articles` → `pubmed_fetch_articles` → `pubmed_fetch_fulltext`. When PubMed itself comes up empty (preprints, EPMC-only OA), broaden via `pubmed_europepmc_search`, then `pubmed_europepmc_fetch` with `records: [{ source, epmcId }]` copied from a hit for its complete abstract. Prefer deterministic resolvers when inputs are structured: `pubmed_lookup_citation` for partial references, `pubmed_convert_ids` to crosswalk IDs. Refine queries with `pubmed_lookup_mesh` and `pubmed_spell_check`. For an article's citation influence, `pubmed_fetch_citation_metrics` returns its Relative Citation Ratio, NIH percentile, and citation counts (Source: NIH iCite, https://icite.od.nih.gov/). The pubmed-guide skill (skill://pubmed-guide/SKILL.md) carries the gates for MeSH and query syntax, DOI-to-PMID routes outside PMC, resolving reference lists, citation counts, and full-text availability.

Tools

12 advertised

pubmed_search_articles — Pubmed Search Articles
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search 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 result sets.

pubmed_search_articles input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "sort": {
      "enum": [
        "relevance",
        "pub_date",
        "author",
        "journal"
      ],
      "type": "string",
      "default": "relevance",
      "description": "Sort order: relevance (default), pub_date (newest first), author, or journal"
    },
    "query": {
      "type": "string",
      "description": "PubMed search query (supports full NCBI syntax), sent as written apart from inline formatting tags such as `<i>`, which are removed. Omit it or pass an empty string to search on the filters alone, which needs `author`, `journal`, `meshTerms`, or `publicationTypes`; `all[sb]` selects the whole database for a slice by the other filters. A query given must carry a search term: a value that is blank once markup, bracketed field tags (`[pdat]`), parentheses, and invisible characters such as a zero-width space are disregarded is rejected rather than sent to PubMed."
    },
    "author": {
      "type": "string",
      "description": "Filter by author name (e.g. \"Smith J\"). An empty string applies no filter; a value of only whitespace, invisible characters, markup, parentheses, brackets, or double quotes is rejected."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9998,
      "minimum": 0,
      "description": "Result offset for pagination (0-based). PubMed serves at most the first 9999 records of a result set, so this caps at 9998; narrow the query or add filters to reach anything beyond it."
    },
    "journal": {
      "type": "string",
      "description": "Filter by journal name. An empty string applies no filter; a value of only whitespace, invisible characters, markup, parentheses, brackets, or double quotes is rejected."
    },
    "species": {
      "enum": [
        "humans",
        "animals"
      ],
      "type": "string",
      "description": "Filter by species: `humans` adds `humans[MeSH Terms]`, `animals` adds `\"animals\"[mh:noexp]` (animals other than humans; a record indexed for both stays in). Both match only records with MEDLINE species indexing, which preprints and ahead-of-print citations lack."
    },
    "language": {
      "type": "string",
      "description": "Filter by language (e.g. \"english\"). An empty string applies no filter; a value of only whitespace, invisible characters, markup, parentheses, brackets, or double quotes is rejected."
    },
    "dateRange": {
      "type": "object",
      "required": [
        "minDate",
        "maxDate"
      ],
      "properties": {
        "maxDate": {
          "type": "string",
          "pattern": "^$|^\\d{4}([/\\-.]\\d{1,2}([/\\-.]\\d{1,2})?)?$",
          "description": "End date (YYYY/MM/DD, YYYY/MM, or YYYY). Must be a real calendar date — `2023/02/29` is rejected. Leaving it empty drops the whole date range, not just this bound; for no upper bound pass a wide sentinel such as `3000`."
        },
        "minDate": {
          "type": "string",
          "pattern": "^$|^\\d{4}([/\\-.]\\d{1,2}([/\\-.]\\d{1,2})?)?$",
          "description": "Start date (YYYY/MM/DD, YYYY/MM, or YYYY). Must be a real calendar date — `2023/02/29` is rejected. Leaving it empty drops the whole date range, not just this bound; for no lower bound pass a wide sentinel such as `1000`."
        },
        "dateType": {
          "enum": [
            "pdat",
            "mdat",
            "edat"
          ],
          "type": "string",
          "default": "pdat",
          "description": "Date type: pdat (publication), mdat (modification), edat (entrez)"
        }
      },
      "description": "Filter by date range. The filter is applied only when both `minDate` and `maxDate` are non-empty; either one empty disables the entire date range. A partial date covers its whole year or month, and a range whose `minDate` falls after its `maxDate` is rejected: `2024/06` to `2024` is valid, `2024/07` to `2024/06/30` is not."
    },
    "meshTerms": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Filter by MeSH terms. Multiple terms are AND'd — all must match. Empty strings are skipped; an element of only whitespace, invisible characters, markup, parentheses, brackets, or double quotes is rejected."
    },
    "maxResults": {
      "type": "integer",
      "default": 20,
      "maximum": 10000,
      "minimum": 0,
      "description": "Maximum results to return, up to 1000 per call; a larger value returns 1000 with a notice naming the next `offset`. 0 returns only `totalCount`."
    },
    "hasAbstract": {
      "type": "boolean",
      "description": "Only include articles with abstracts"
    },
    "freeFullText": {
      "type": "boolean",
      "description": "Only include free full text articles"
    },
    "summaryCount": {
      "type": "integer",
      "default": 0,
      "maximum": 500,
      "minimum": 0,
      "description": "Fetch brief summaries for the top N results (0 = PMIDs only), up to 50 per call; a larger value fetches 50 with a notice. Pass the PMIDs past the cap to pubmed_fetch_articles."
    },
    "publicationTypes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Filter by publication type (e.g. \"Review\", \"Clinical Trial\", \"Meta-Analysis\"). Multiple values are OR'd — any match qualifies. Empty strings are skipped; an element of only whitespace, invisible characters, markup, parentheses, brackets, or double quotes is rejected."
    }
  },
  "additionalProperties": false
}
pubmed_search_articles output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "query",
        "offset",
        "pmids",
        "summaries",
        "searchUrl",
        "totalCount",
        "effectiveQuery",
        "appliedFilters"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "blank_query",
                "invalid_date_range",
                "blank_filter",
                "no_search_term"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `blank_query`: The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`. On pubmed_search_articles an exactly-empty `query` is not blank: it means no query, and the search runs on its filters. `invalid_date_range`: A `dateRange` bound is not a real calendar date — a month outside 01–12, day 00, or a day past the end of its month such as `2023/02/29` — or `minDate` falls after `maxDate` once PubMed expands each partial date: `minDate` from the start of its year or month, `maxDate` to the end. `blank_filter`: An `author`, `journal`, or `language` value, or a `publicationTypes` or `meshTerms` element, holds no term once markup is removed and HTML entities are decoded — only whitespace, invisible characters such as a zero-width space, parentheses, brackets, or double quotes are left, as in `()` or `\"\"` — so its field clause would carry no term. An exactly-empty string is not blank here; it sets no filter. `no_search_term`: No `query` is given — it is omitted or an empty string — and no subject filter (`author`, `journal`, `meshTerms`, or `publicationTypes`) carries a term. `dateRange`, `language`, `species`, `hasAbstract`, and `freeFullText` narrow a search without saying what it is for, so they cannot run one alone. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "pmids": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "PubMed IDs"
    },
    "query": {
      "type": "string",
      "description": "Original query; empty when the search ran on the filters alone"
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance when the result set does not reflect what was asked for — a field tag PubMed ignored, a phrase it matched nothing for, a dateRange dropped for having one bound, no matches at all, paging past the end, or a `maxResults` or `summaryCount` past its per-call cap, served at the cap. Absent when nothing applies."
    },
    "offset": {
      "type": "number",
      "description": "Result offset used"
    },
    "searchUrl": {
      "type": "string",
      "description": "PubMed search URL"
    },
    "summaries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "pmid"
        ],
        "properties": {
          "doi": {
            "type": "string",
            "description": "DOI, cased as NCBI reports it. DOIs are case-insensitive by spec and no case normalization is applied here, so casing can differ from a Europe PMC-sourced `doi` — compare the two case-insensitively."
          },
          "pmid": {
            "type": "string",
            "description": "PubMed ID"
          },
          "pmcId": {
            "type": "string",
            "description": "PMC ID"
          },
          "title": {
            "type": "string",
            "description": "Article title"
          },
          "pmcUrl": {
            "type": "string",
            "description": "PMC URL"
          },
          "source": {
            "type": "string",
            "description": "Journal the article appeared in. Absent on an NCBI Bookshelf record, which has no journal — its venue is in `bookTitle` and `publisherName` instead, and `docType` says which kind of record it is."
          },
          "authors": {
            "type": "string",
            "description": "Formatted author string — the first three of the record's own authors, then \"et al.\". On an NCBI Bookshelf chapter these are the chapter's authors; the book's editors are reported separately in `editors`."
          },
          "docType": {
            "type": "string",
            "description": "What PubMed classifies this record as: \"chapter\" or \"book\" for an NCBI Bookshelf record, \"citation\" for an ordinary journal article. Absent when PubMed supplies none."
          },
          "editors": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "One editor, \"Surname Initials\" as ESummary renders it"
            },
            "description": "Editors of the containing book, kept out of `authors` so they cannot displace the record's own authors. Absent on a journal article and on a book that credits no editors."
          },
          "pubDate": {
            "type": "string",
            "description": "Publication date as YYYY-MM-DD; a month- or year-only date reads as the first day of that month or year. On an NCBI Bookshelf chapter (`docType` \"chapter\") it is the chapter's own date — its last revision, otherwise its contribution — not the year its book began."
          },
          "bookTitle": {
            "type": "string",
            "description": "Title of the book an NCBI Bookshelf record belongs to, e.g. \"GeneReviews(®)\". Present instead of `source` on a book record; absent on a journal article."
          },
          "pubmedUrl": {
            "type": "string",
            "description": "PubMed URL"
          },
          "publisherName": {
            "type": "string",
            "description": "Publisher of the book an NCBI Bookshelf record belongs to. Present only on a book record; absent on a journal article."
          }
        },
        "description": "Brief article summary",
        "additionalProperties": false
      },
      "description": "Brief summaries (empty array when summaryCount is 0)"
    },
    "totalCount": {
      "type": "number",
      "description": "Total matching articles"
    },
    "appliedFilters": {
      "type": "object",
      "properties": {
        "author": {
          "type": "string",
          "description": "Author filter applied to the search"
        },
        "journal": {
          "type": "string",
          "description": "Journal filter applied to the search"
        },
        "species": {
          "enum": [
            "humans",
            "animals"
          ],
          "type": "string",
          "description": "Species filter applied to the search: `humans` as `humans[MeSH Terms]`, `animals` as `\"animals\"[mh:noexp]`"
        },
        "language": {
          "type": "string",
          "description": "Language filter applied to the search"
        },
        "dateRange": {
          "type": "object",
          "required": [
            "minDate",
            "maxDate",
            "dateType"
          ],
          "properties": {
            "maxDate": {
              "type": "string",
              "description": "Applied maximum date"
            },
            "minDate": {
              "type": "string",
              "description": "Applied minimum date"
            },
            "dateType": {
              "enum": [
                "pdat",
                "mdat",
                "edat"
              ],
              "type": "string",
              "description": "Applied date field used for the range filter"
            }
          },
          "description": "Date range filter applied to the search",
          "additionalProperties": false
        },
        "meshTerms": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "MeSH term filters applied to the search"
        },
        "hasAbstract": {
          "type": "boolean",
          "description": "Whether results were restricted to articles with abstracts"
        },
        "freeFullText": {
          "type": "boolean",
          "description": "Whether results were restricted to free full-text articles"
        },
        "publicationTypes": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Publication type filters applied to the search"
        }
      },
      "description": "Filter values applied to the PubMed query, as sent: each text value as written, formatting tags removed, and dates in YYYY/MM/DD form",
      "additionalProperties": false
    },
    "effectiveQuery": {
      "type": "string",
      "description": "The term sent to PubMed: the query as written, with a clause appended for each active filter, or the filter clauses alone, joined by AND, when no query was given. Only inline formatting tags with no attributes (`<i>`, `<b>`, `<em>`, `<strong>`, `<u>` and their closers) are removed; `&`, `<`, and `>` are sent as written."
    }
  },
  "additionalProperties": false
}
pubmed_search_articles annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_fetch_articles — Pubmed Fetch Articles
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch full article metadata by PubMed IDs. Returns detailed article information including abstract, authors, journal, MeSH terms, linked retraction, erratum, and comment notices, and databank accessions such as trial registration IDs; grants and the members of a collective author are opt-in (`includeGrants`, `includeInvestigators`). Set `maxResponseCharacters` to bound the whole response: articles past the ceiling are deferred whole and listed in `deferred.ids` for a follow-up call.

pubmed_fetch_articles input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "pmids"
  ],
  "properties": {
    "pmids": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\d+$"
      },
      "maxItems": 200,
      "minItems": 1,
      "description": "PubMed IDs to fetch"
    },
    "includeMesh": {
      "type": "boolean",
      "default": true,
      "description": "Include MeSH terms"
    },
    "includeGrants": {
      "type": "boolean",
      "default": false,
      "description": "Include grant information"
    },
    "includeInvestigators": {
      "type": "boolean",
      "default": false,
      "description": "Include `investigators`: the members NCBI lists for a collective author such as \"TGU Investigators\". Off by default because the list is unbounded: consortium trials name thousands, at about 60 characters of JSON each — PMID 33933206 lists 6,349, adding about 372,000 characters to its record. Under `maxResponseCharacters` they count toward the size of their article, which is deferred whole when it no longer fits."
    },
    "maxResponseCharacters": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Opt-in ceiling for the whole response, in characters. Each article is measured as the JSON record it is returned as — title, abstract, authors, journal, MeSH terms, grants, identifiers, every field it carries. Articles are kept in response order until the next one would cross the ceiling; that article and the rest are deferred whole (never partially populated) and listed in `deferred.ids`. Response envelope fields — counts, `unavailablePmids`, `deferred` itself — are not counted. Omit to return every resolved article."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_articles output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "articles",
        "totalReturned"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "invalid_efetch_response"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `invalid_efetch_response`: NCBI EFetch returned a payload missing the PubmedArticleSet wrapper. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance when no articles were returned — points to discovery tools — or when `maxResponseCharacters` deferred articles, naming how to retrieve them. Absent on successful unbudgeted fetches."
    },
    "articles": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "recordType"
        ],
        "properties": {
          "doi": {
            "type": "string",
            "description": "DOI, cased as NCBI reports it (usually the publisher's mixed case). DOIs are case-insensitive by spec and no case normalization is applied here, so the same DOI can arrive in a different case from `pubmed_europepmc_search` and `pubmed_europepmc_fetch` (NCBI `10.1056/NEJMoa2212948`, Europe PMC `10.1056/nejmoa2212948`) — a byte-for-byte comparison across the two reports a false mismatch."
          },
          "book": {
            "type": "object",
            "properties": {
              "doi": {
                "type": "string",
                "description": "The book's own DOI, from `Book/ELocationID` with `EIdType=\"doi\"`. Distinct from the record-level `doi`, which is the chapter's: a chapter does not inherit this one."
              },
              "isbns": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "One ISBN, verbatim as NCBI reports it — leading zeros intact"
                },
                "description": "Every `Book/Isbn` on the record. A book commonly carries a print and an electronic ISBN, so this is a list. Absent for a Bookshelf title with no ISBN, which is most of them."
              },
              "title": {
                "type": "string",
                "description": "Title of the containing book, from `Book/BookTitle` (e.g. \"GeneReviews®\"). On a `book` record this is the same value as the record's own `title`."
              },
              "medium": {
                "type": "string",
                "description": "Medium the book is published in, from `Book/Medium` — \"Internet\" wherever NCBI supplies it. Absent when NCBI supplies none; it is never defaulted."
              },
              "edition": {
                "type": "string",
                "description": "Edition statement from `Book/Edition`. Rare on Bookshelf titles — absent unless NCBI supplies one."
              },
              "editors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "suffix": {
                      "type": "string",
                      "description": "Editor generational name suffix verbatim from NCBI `Suffix` (e.g. \"Jr\"). Absent when NCBI supplies none, or on a group editor."
                    },
                    "initials": {
                      "type": "string",
                      "description": "Editor initials with no separators (e.g. \"MP\"). Absent when NCBI supplies none, or on a group editor."
                    },
                    "lastName": {
                      "type": "string",
                      "description": "Editor surname, from the book's `Book/AuthorList Type=\"editors\"` entry. Absent on a group editor, which carries `collectiveName` instead."
                    },
                    "firstName": {
                      "type": "string",
                      "description": "Editor given name as NCBI supplies it (`ForeName`, often \"Margaret P\"). Absent when NCBI carries initials only, or on a group editor."
                    },
                    "collectiveName": {
                      "type": "string",
                      "description": "Group or committee credited as editor, when the entry names an organization rather than a person. Mutually exclusive with the name-part fields."
                    }
                  },
                  "description": "One editor of the containing book. Name parts only — editors are a citation credit, not a contributor record, so no affiliations or ORCID are reported for them.",
                  "additionalProperties": false
                },
                "description": "Editors of the containing book, from `Book/AuthorList` marked `Type=\"editors\"`. Kept out of `authors`, which carries the chapter's own writers. Absent when the book credits no editors."
              },
              "pubDate": {
                "type": "string",
                "description": "Publication year from `Book/PubDate`. Year only — NCBI's month and day are not reported, since no citation style uses them for a book."
              },
              "accession": {
                "type": "string",
                "description": "NCBI Bookshelf accession from `ArticleIdList` (`bookaccession`), e.g. \"NBK1247\". The record is readable at `https://www.ncbi.nlm.nih.gov/books/<accession>/`."
              },
              "publisher": {
                "type": "string",
                "description": "Publisher of the book, from `Book/Publisher/PublisherName`."
              },
              "endingDate": {
                "type": "string",
                "description": "Last year of a closed date range, from `Book/EndingDate`. Absent while a book is still being updated, which leaves the range open-ended."
              },
              "beginningDate": {
                "type": "string",
                "description": "First year of a continuously-updated book, from `Book/BeginningDate` (GeneReviews runs from 1993). Absent on a book published once."
              },
              "collectionTitle": {
                "type": "string",
                "description": "Series the book belongs to, from `Book/CollectionTitle` (e.g. \"ADA Clinical Compendia Series\"). Absent for a book outside a series."
              },
              "publisherLocation": {
                "type": "string",
                "description": "Place of publication, from `Book/Publisher/PublisherLocation` (e.g. \"Seattle (WA)\"). Absent when NCBI supplies no place."
              }
            },
            "description": "The containing book of a `book-chapter`, or the book itself on a `book` record. Present only on those two record types, and never a stand-in for `journalInfo`.",
            "additionalProperties": false
          },
          "pmid": {
            "type": "string",
            "description": "PubMed ID"
          },
          "pmcId": {
            "type": "string",
            "description": "PMC ID"
          },
          "title": {
            "type": "string",
            "description": "Article title — the chapter title on a `book-chapter`, and the book title on a `book` record, where it repeats `book.title`."
          },
          "pmcUrl": {
            "type": "string",
            "description": "PMC full text URL"
          },
          "authors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "orcid": {
                  "type": "string",
                  "description": "ORCID identifier"
                },
                "suffix": {
                  "type": "string",
                  "description": "Generational name suffix verbatim from NCBI `Suffix` (e.g. \"Jr\", \"2nd\", \"3rd\"), never normalized. Absent when NCBI gives none."
                },
                "initials": {
                  "type": "string",
                  "description": "Author initials"
                },
                "lastName": {
                  "type": "string",
                  "description": "Last name"
                },
                "firstName": {
                  "type": "string",
                  "description": "First/given name"
                },
                "collectiveName": {
                  "type": "string",
                  "description": "Group/collective author name. NCBI may list the members of the group separately; set `includeInvestigators` to return them as `investigators`."
                },
                "affiliationIndices": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "description": "Indices into the top-level affiliations array"
                }
              },
              "description": "Author record",
              "additionalProperties": false
            },
            "description": "Author list. On a `book-chapter` these are the chapter's own authors, never the book's editors, which are in `book.editors`. Empty on a Bookshelf record that credits neither."
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Keywords"
          },
          "dataBanks": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Databank or registry name, verbatim from NCBI `DataBankName` (e.g. \"ClinicalTrials.gov\", \"GENBANK\", \"PDB\", \"Dryad\", \"OMIM\")."
                },
                "accessionNumbers": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "description": "One accession as NCBI writes it — free text, an all-digit OMIM number or a DOI included (e.g. \"NCT03951753\", \"300460\", \"10.5061/dryad.8gtht7726\")"
                  },
                  "description": "The record's accessions in this bank, from `AccessionNumberList`, in NCBI's order and uncapped. Absent when NCBI lists the bank without one."
                }
              },
              "description": "One databank or registry the record links to, with its accessions there",
              "additionalProperties": false
            },
            "description": "Trial registrations and data deposits the record lists, from NCBI's `DataBankList`, in NCBI's order and uncapped — a ClinicalTrials.gov NCT ID, GenBank and PDB accessions, Dryad and figshare DOIs. To find other PubMed records citing an accession, search `pubmed_search_articles` for `<accession>[si]` (e.g. `NCT03951753[si]`). Counted with the rest of the record under `maxResponseCharacters`. Absent when the record lists none, and never set on `book-chapter` or `book` records."
          },
          "grantList": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "agency": {
                  "type": "string",
                  "description": "Funding agency"
                },
                "acronym": {
                  "type": "string",
                  "description": "Acronym of the funding institute or agency from `Grant/Acronym` (e.g. \"EY\" for the National Eye Institute) — it names the funder, never the grant, so it is no substitute for `grantId`."
                },
                "country": {
                  "type": "string",
                  "description": "Agency country"
                },
                "grantId": {
                  "type": "string",
                  "description": "Grant identifier"
                }
              },
              "description": "Grant record",
              "additionalProperties": false
            },
            "description": "Grant information"
          },
          "meshTerms": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "isMajorTopic"
              ],
              "properties": {
                "qualifiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "qualifierName",
                      "isMajorTopic"
                    ],
                    "properties": {
                      "qualifierUi": {
                        "type": "string",
                        "description": "Qualifier unique ID"
                      },
                      "isMajorTopic": {
                        "type": "boolean",
                        "description": "Whether this qualifier is a major topic"
                      },
                      "qualifierName": {
                        "type": "string",
                        "description": "Qualifier/subheading name"
                      }
                    },
                    "description": "MeSH qualifier/subheading",
                    "additionalProperties": false
                  },
                  "description": "MeSH qualifiers/subheadings"
                },
                "descriptorUi": {
                  "type": "string",
                  "description": "MeSH descriptor unique ID"
                },
                "isMajorTopic": {
                  "type": "boolean",
                  "description": "Whether this is a major topic of the article"
                },
                "descriptorName": {
                  "type": "string",
                  "description": "MeSH descriptor name"
                }
              },
              "description": "MeSH descriptor term",
              "additionalProperties": false
            },
            "description": "MeSH terms"
          },
          "pubmedUrl": {
            "type": "string",
            "description": "PubMed article URL"
          },
          "recordType": {
            "enum": [
              "journal-article",
              "book-chapter",
              "book"
            ],
            "type": "string",
            "description": "Which kind of PubMed record this is, set from the XML element it arrived in: `journal-article` for an ordinary article, `book-chapter` for an NCBI Bookshelf chapter, `book` for a whole Bookshelf book. Read this to tell the three apart — `publicationTypes` cannot, because PubMed labels a Bookshelf record \"Review\" or \"Study Guide\". `journalInfo` is present only on `journal-article`; `book` only on the other two."
          },
          "journalInfo": {
            "type": "object",
            "properties": {
              "issn": {
                "type": "string",
                "description": "Print ISSN"
              },
              "eIssn": {
                "type": "string",
                "description": "Electronic ISSN"
              },
              "issue": {
                "type": "string",
                "description": "Issue number"
              },
              "pages": {
                "type": "string",
                "description": "Page range (e.g. \"48-55\")"
              },
              "title": {
                "type": "string",
                "description": "Full journal title"
              },
              "volume": {
                "type": "string",
                "description": "Volume number"
              },
              "elocationId": {
                "type": "string",
                "description": "Electronic article locator from NCBI `ELocationID` — the publisher-assigned article number (e.g. \"2400512\"). Journals that assign article numbers instead of pages often omit pagination entirely, leaving this the only locator. Never a substitute for `pages`, and never the DOI: a DOI-typed `ELocationID` is reported in `doi` instead. Absent when the only locator NCBI supplies is marked invalid."
              },
              "elocationIdType": {
                "type": "string",
                "description": "Type of `elocationId`, from NCBI's `EIdType` attribute — \"pii\" in practice. Free-form: NCBI does not close the set, so treat an unfamiliar value as opaque."
              },
              "isoAbbreviation": {
                "type": "string",
                "description": "ISO journal abbreviation"
              },
              "publicationDate": {
                "type": "object",
                "properties": {
                  "day": {
                    "type": "string",
                    "description": "Publication day"
                  },
                  "year": {
                    "type": "string",
                    "description": "Publication year"
                  },
                  "month": {
                    "type": "string",
                    "description": "Publication month"
                  },
                  "medlineDate": {
                    "type": "string",
                    "description": "Non-standard date string (e.g. \"2000 Spring\")"
                  }
                },
                "description": "Journal publication date",
                "additionalProperties": false
              }
            },
            "description": "Journal information. Present on `journal-article` records only — absent on `book-chapter` and `book` records, because a Bookshelf record has no journal and its book title is never reported as one; read `book` for those. (#114)",
            "additionalProperties": false
          },
          "abstractText": {
            "type": "string",
            "description": "Abstract text"
          },
          "affiliations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Deduplicated affiliations, referenced by `affiliationIndices`: the authors' entries first, then any that only `investigators` carry"
          },
          "articleDates": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "description": "Day"
                },
                "year": {
                  "type": "string",
                  "description": "Year"
                },
                "month": {
                  "type": "string",
                  "description": "Month"
                },
                "dateType": {
                  "type": "string",
                  "description": "Date type"
                }
              },
              "description": "Dated article event",
              "additionalProperties": false
            },
            "description": "Dates of the record itself, each named by `dateType`. On a journal article, PubMed's `ArticleDate` entries (`Electronic` — the electronic publication date). On a Bookshelf record, its own `ContributionDate` (when the chapter was contributed) and `DateRevised` (when it was last updated), distinct from the containing book's dates in `book`; `pubmed_format_citations` cites a chapter by `DateRevised` when present, otherwise `ContributionDate`. Absent when NCBI supplies none."
          },
          "investigators": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "orcid": {
                  "type": "string",
                  "description": "ORCID identifier"
                },
                "suffix": {
                  "type": "string",
                  "description": "Generational name suffix verbatim from NCBI `Suffix` (e.g. \"Jr\", \"2nd\"). Absent when NCBI gives none."
                },
                "initials": {
                  "type": "string",
                  "description": "Initials"
                },
                "lastName": {
                  "type": "string",
                  "description": "Last name"
                },
                "firstName": {
                  "type": "string",
                  "description": "First/given name"
                },
                "affiliationIndices": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "description": "Indices into the top-level affiliations array, where an investigator's affiliations follow the authors'"
                }
              },
              "description": "One member of a collective author, from NCBI's `InvestigatorList`",
              "additionalProperties": false
            },
            "description": "Members of the article's collective author, from NCBI's `InvestigatorList`: every list flattened in NCBI's order, uncapped. They are not authors, and no citation style lists them. Present only when `includeInvestigators` is set and the record lists any; never on `book-chapter` or `book` records."
          },
          "publicationTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Publication types"
          },
          "commentsCorrections": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "refType",
                "refSource"
              ],
              "properties": {
                "note": {
                  "type": "string",
                  "description": "NCBI's note on the link, e.g. what an erratum corrected (\"Fuβer, Fabian [corrected to Fußer, Fabian]\"). Absent unless NCBI supplies one."
                },
                "pmid": {
                  "type": "string",
                  "description": "PMID of the linked record — pass it to `pubmed_fetch_articles` to read that record. Absent when the linked record has no PMID, as with many errata."
                },
                "refType": {
                  "type": "string",
                  "description": "Link type, verbatim from NCBI's `RefType` — e.g. \"RetractionIn\", \"RetractionOf\", \"ErratumIn\", \"ErratumFor\", \"ExpressionOfConcernIn\", \"CommentIn\", \"CommentOn\", \"UpdateIn\". The set is open: treat an unfamiliar value as opaque."
                },
                "refSource": {
                  "type": "string",
                  "description": "Citation of the linked record as NCBI writes it (e.g. \"Lancet. 2010 Feb 6;375(9713):445. doi: 10.1016/S0140-6736(10)60175-4.\")."
                }
              },
              "description": "One record NCBI links to this article and published separately from it — for example a retraction notice, erratum, expression of concern, comment, update, or republication.",
              "additionalProperties": false
            },
            "description": "Records NCBI links to this article — for example retraction notices, errata, expressions of concern, comments, and updates — from `CommentsCorrectionsList`, in NCBI's order and uncapped. `Cites` entries are excluded: they list a bibliography, which `pubmed_find_related` covers with its `references` relationship. Read this alongside `publicationTypes`, not in place of it: that field describes the record itself, and a corrected or questioned article often carries no matching type. Absent when NCBI links nothing other than `Cites` entries, and never set on `book-chapter` or `book` records."
          }
        },
        "description": "Parsed PubMed article",
        "additionalProperties": false
      },
      "description": "Parsed articles"
    },
    "deferred": {
      "type": "object",
      "required": [
        "maxResponseCharacters",
        "returnedCharacters",
        "deferredCount",
        "ids",
        "nextDeferredCharacters"
      ],
      "properties": {
        "ids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "PMIDs of the deferred articles, in response order. Re-call `pubmed_fetch_articles` with these as `pmids` and the same other inputs to retrieve them. Never contains a PMID from `unavailablePmids`."
        },
        "deferredCount": {
          "type": "number",
          "description": "Articles that resolved but were withheld to stay under the ceiling"
        },
        "returnedCharacters": {
          "type": "number",
          "description": "Serialized characters the returned article records account for"
        },
        "maxResponseCharacters": {
          "type": "number",
          "description": "The `maxResponseCharacters` ceiling this response was budgeted against"
        },
        "nextDeferredCharacters": {
          "type": "number",
          "description": "Serialized size of the next deferred article — the first entry in `ids`, where the response stopped — and the continuation ceiling: re-calling with the deferred PMIDs needs `maxResponseCharacters` ≥ this to return anything, and a smaller article further down `ids` cannot be reached until this one fits. Repeating this same call needs `maxResponseCharacters` ≥ `returnedCharacters` + this to return this article as well."
        }
      },
      "description": "Continuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.",
      "additionalProperties": false
    },
    "truncated": {
      "type": "boolean",
      "description": "True when `maxResponseCharacters` withheld at least one resolved article. Absent when the response carries every article that resolved. The continuation state is in `deferred`."
    },
    "totalReturned": {
      "type": "number",
      "description": "Number of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest."
    },
    "unavailablePmids": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "PMIDs PubMed returned no record for. That is all this reports: PubMed omits an unknown PMID silently, with no error and no reason, so the absence says nothing about whether the PMID exists. Reported in full regardless of where a `maxResponseCharacters` cutoff lands — these are misses, not deferrals. Use `pubmed_search_articles` to find PMIDs that do resolve."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_articles annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_fetch_fulltext — Pubmed Fetch Fulltext
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch full-text articles from PubMed Central as structured sections — the body, then back matter such as acknowledgments, declarations, and appendices — with tables and references. When PMC misses, transparently falls back to Europe PMC `fullTextXML` (structured JATS for its open-access subset, preprints included), then to Unpaywall — publisher-hosted or institutional open-access copies as HTML-as-Markdown or PDF-as-text. Name articles by `pmcids` (PMC IDs directly), `pmids` (PubMed IDs, auto-resolved), `dois` (DOIs, auto-resolved to PMC via the ID Converter; preprints and EPMC-only OA fall through to the Europe PMC and Unpaywall layers), or any mix of the three — up to 50 distinct identifiers; the first 10 are fetched per call, the rest returned in `overLimit`; an article several of them name is fetched and returned once. Two independent character controls: `maxCharacters` caps body text per article, `maxResponseCharacters` caps the whole response and defers articles past the ceiling whole, listing them in `deferred.ids` for a follow-up call.

pubmed_fetch_fulltext input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "dois": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^10\\.[^\\s,]+\\/[^\\s,]+$"
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "DOIs to resolve (e.g. [\"10.21203/rs.3.rs-9010375/v1\"]), one per element. Combinable with `pmcids` and `pmids` — up to 50 distinct identifiers across the three; the first 10 are fetched per call, the rest returned in `overLimit`. Resolved to a PMCID via the PMC ID Converter and returned as structured JATS when the article is in PMC; DOIs with no PMC counterpart (preprints, EPMC-only OA) fall through to Europe PMC, then Unpaywall, when those layers are enabled."
    },
    "pmids": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\d+$"
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "PubMed IDs. Combinable with `pmcids` and `dois` — up to 50 distinct identifiers across the three; the first 10 are fetched per call, the rest returned in `overLimit`. Articles in PMC are returned as structured JATS; articles not in PMC fall through to Europe PMC (when EPMC has a `fullTextXML`), then to Unpaywall when `UNPAYWALL_EMAIL` is set and a DOI is available."
    },
    "pmcids": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^(?:PMC)?\\d+$"
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "PMC IDs to fetch (e.g. [\"PMC9575052\"]). Combinable with `pmids` and `dois` — up to 50 distinct identifiers across the three; the first 10 are fetched per call, the rest returned in `overLimit`. PMC IDs with no retrievable full text fall through to Europe PMC, then to Unpaywall on the DOI the chain resolves for them."
    },
    "sections": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Filter to specific sections by title (e.g. [\"Introduction\", \"Methods\", \"Results\", \"Discussion\"]). A term matches a section or subsection title at any nesting depth, case-insensitively, as a substring — \"resul\" matches \"Results\". Back-matter sections match the same way: by their own titles, or by their kind when they carry neither a title nor a label — \"appendix\" matches a section titled \"Appendix A\", \"footnotes\" an untitled footnote group. A label is never matched, so an appendix labelled \"Appendix A\" under a title of its own matches only on that title. A section whose own title matches is returned whole; one kept only because a nested subsection matched keeps its heading as a breadcrumb, with its own text cleared and only the matching branch beneath it. Tables and assets narrow with the filter: one whose section did not survive, or that names no section, is dropped. Empty strings are skipped, so `[\"\"]` applies no filter; an element of only whitespace or invisible characters, such as a zero-width space, is rejected. Applies to `source=pmc` results only."
    },
    "maxSections": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Maximum top-level sections, counted after `sections`. Back-matter sections count and follow the body, so a cap drops them first. The sections it drops are named per article in `sectionCap`. Applies to `source=pmc` results only."
    },
    "overflowMode": {
      "enum": [
        "truncate",
        "outline"
      ],
      "type": "string",
      "default": "truncate",
      "description": "How to spend `maxCharacters` across an article that exceeds it. truncate: fill sections in document order, so early sections stay whole, the section the budget runs out in is cut, and every section or subsection past that point is dropped (counted in `truncation.omittedSections`). outline: every section and subsection keeps its heading, and the budget is split evenly at every level — across the top-level sections, then inside each one across its own text and each subsection — with what a short part does not need going to the rest. A part whose share would cut it to under 100 characters (or under `maxCharactersPerSection`, when that is lower) returns heading-only instead, its share going to the others, emptying the last such part first; a part that fits its share keeps all its text however short, and a cut excerpt ends at the last word boundary inside its share, so it can run somewhat under that floor. A heading the budget left empty is marked as such in the rendered text. In both modes the body sections spend the budget first and back-matter sections share what the body, tables, and assets leave. Use it to survey what an article contains before requesting specific `sections`. Ignored when no budget is set, and identical for `source=unpaywall` bodies, which have no headings to preserve."
    },
    "includeAssets": {
      "type": "boolean",
      "default": true,
      "description": "Include the article's figures and supplementary material — `assets[]`, each with its label, caption, enclosing section and deposit pointer. On by default because it is cheaper than tables: a median asset-bearing article grows about 10%, and the body prose already refers to these by label. Set false to omit them, which also removes the `[Figure: …]` / `[Supplementary: …]` markers from the section text, since without the array they point at nothing. Prose-shaped blocks — lists, definition lists, block quotes, boxed text, preformatted blocks, displayed formulae — are section text rather than assets and this switch never affects them. Applies to `source=pmc` results only."
    },
    "includeTables": {
      "type": "boolean",
      "default": true,
      "description": "Include the article's tables — cells, captions, labels and footnotes. On by default because a dropped table takes its numbers with it. Table-dense articles pay for it: rendered tables typically add 12–17% to an article record and can more than double it. Set false to omit them, or cap the cost with `maxCharacters`, which drops tables it cannot fit whole. Applies to `source=pmc` results only."
    },
    "maxCharacters": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text — which carries the inline blocks the parser renders in place, such as lists, definition lists, block quotes, boxed text, preformatted blocks and displayed formulae — plus table label, caption, cell and footnote text and asset label, caption and `href` text; or the `source=unpaywall` `content` body. Titles, abstracts, identifiers, licenses, and references are never counted or shortened. Shortened text ends at the last word boundary inside its allowance, so it can come back a few characters under it; a section or subsection whose allowance cannot hold its first word returns no text rather than part of that word, so it is dropped in `truncate` mode and heading-only in `outline` mode, while text that is one unbroken token, such as a sequence or URL, is cut at the allowance. The counted unit is that text alone — the Markdown grid `content[]` renders around the cells (pipes, padding, the divider row, headings) is scaffolding this budget does not measure, so a table renders longer than it costs here. Body sections are served first, then tables, then assets, then back-matter sections, each spending what is left, in document order. For tables and assets, admission stops at the first entry that does not fit, and every entry from there on is dropped whole rather than cut mid-row or returned with a shortened caption, counted in `truncation.omittedTables` / `truncation.omittedAssets` and named in `truncation.articles[].omittedTableNames` / `omittedAssetNames`. Back matter takes only what remains and is shortened or dropped as body sections are; `sections` still returns it after the body. Applied after `sections`, `maxSections`, `includeReferences`, `includeTables`, and `includeAssets`, so semantic filtering is unaffected. This knob alone bounds only bodies: the response-wide ceiling it implies is this value times the number of articles returned, plus every uncounted field. Use `maxResponseCharacters` for a true whole-response ceiling. Omit for the full body."
    },
    "includeReferences": {
      "type": "boolean",
      "default": false,
      "description": "Include reference list. Applies to `source=pmc` results only."
    },
    "maxResponseCharacters": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Opt-in ceiling for the whole response, in characters — the true response-wide counterpart to the per-article `maxCharacters`. Each article is measured as the JSON record it is returned as, after every filter and the per-article body budget: title, abstract, sections, references, identifiers, license and source metadata — every field it carries. One ledger covers all tiers, so PMC-, Europe PMC-, and Unpaywall-served articles spend the same budget. Articles are kept in the order `articles` lists them until the next one would cross the ceiling; that article and the rest are deferred whole (never partially populated) and listed in `deferred.ids`. Response envelope fields — counts, `unavailable`, `truncation`, `sectionCap`, `deferred` itself — are not counted. Omit to return every resolved article."
    },
    "maxCharactersPerSection": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Budget for a single top-level section, in characters, counting the section text plus its subsections. Combine with `maxCharacters` to cap both one section and the article; the tighter of the two wins. Applies to `source=pmc` results only."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_fulltext output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "articles",
        "totalReturned"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "blank_filter"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `blank_filter`: A `sections` element holds no visible character — only whitespace, or invisible characters such as a zero-width space — so it names no heading. An exactly-empty element is not blank here; it is skipped. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance for a partial or empty body. A `sections`-filter miss names the requested terms and affected article id(s) and suggests retrying without `sections` or using broader headings. A metadata-only record names the id(s) the chain could retrieve as front matter only and points at `pubmed_fetch_articles` for the abstract. A table returned with no cell values names the affected table(s), the article each came from, and why the cells cannot be recovered. A budgeted response names the characters returned versus carried and points at `truncation`. A `maxSections` cap that dropped sections names, per article, how many it kept of how many and the titles it left out, and points at `sections` or a larger cap. A response-wide budget that deferred articles names the ids to re-request. Identifiers past the per-call limit are named with the field to resend each under. Absent when none of those applies."
    },
    "articles": {
      "type": "array",
      "items": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "source",
              "viaSource",
              "sections"
            ],
            "properties": {
              "doi": {
                "type": "string",
                "description": "DOI, cased as the tier that served this record reports it (NCBI PMC, Europe PMC, or Unpaywall). DOIs are case-insensitive by spec and no case normalization is applied here, so casing can differ between tiers and from other tools — compare case-insensitively."
              },
              "pmid": {
                "type": "string",
                "description": "PubMed ID"
              },
              "pmcId": {
                "type": "string",
                "description": "PMC ID — present for NCBI PMC records and Europe PMC entries that have a PMC counterpart. Absent for EPMC-only records like preprints; use `epmcId` in that case."
              },
              "title": {
                "type": "string",
                "description": "Article title"
              },
              "assets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "assetType"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "JATS `id` attribute — the target body-text cross-references point at"
                    },
                    "href": {
                      "type": "string",
                      "description": "The `<graphic>`/`<media>` `@xlink:href` exactly as deposited — a pointer into the PMC deposit (`MOL2-20-1253-g001.jpg`), not a fetchable URL. No absolute form of it resolves; read the rendered article at `pmcUrl` instead. Absent when the deposit names no file."
                    },
                    "label": {
                      "type": "string",
                      "description": "Display label as printed, e.g. `Fig. 1`, less one trailing ` |`, `.` or `:` (`Figure 1.` reads `Figure 1`). Some supplements carry a bare number (`1`), kept as deposited here"
                    },
                    "caption": {
                      "type": "string",
                      "description": "Caption text, with the label excluded"
                    },
                    "assetType": {
                      "enum": [
                        "figure",
                        "supplementary-material"
                      ],
                      "type": "string",
                      "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit"
                    },
                    "sectionTitle": {
                      "type": "string",
                      "description": "Title of the innermost titled section enclosing the asset — a body section or a back-matter one such as an appendix — as that section is titled in `sections`, or, for a heading nested deeper than `sections` carries, as its heading line inside the text of the section that contains it. Absent for an asset inside no titled section, such as a `<floats-group>` deposit."
                    }
                  },
                  "description": "One figure or supplementary-material item, with its caption, pointer, and section",
                  "additionalProperties": false
                },
                "description": "Every `<fig>` and `<supplementary-material>` the article carries, in document order — from the body and from `<floats-group>`, `<back>` and appendices alike. Each one lifted from a section, body or back matter, leaves a `[Figure: <label>]` or `[Supplementary: <label>]` marker at its position in the section text, so reading order survives the lift. Absent when the article deposits none, when `includeAssets` is false, or when a `sections` filter left none standing."
              },
              "epmcId": {
                "type": "string",
                "description": "Europe PMC record id — present when `viaSource` is `europepmc`"
              },
              "pmcUrl": {
                "type": "string",
                "description": "PMC URL — derived from `pmcId` when present"
              },
              "source": {
                "type": "string",
                "const": "pmc",
                "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC"
              },
              "tables": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "headerRowCount",
                    "rows"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "JATS `id` attribute — the target body-text cross-references point at"
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "One row, as cell text by grid column"
                      },
                      "description": "Cell text by row, in document order, one entry per grid column. `colspan` and `rowspan` are expanded, so a cell covering several columns or rows repeats its text across each cell it covers and a well-formed table is rectangular — align on position from the left, and read a repeated value as one spanning cell rather than several measurements. A line break in a cell — a `<break/>`, a paragraph, or a list item in the source — is kept as `\\n`, so `1.08\\n2.44` is two values; superscripts and other inline markup are never spaced (`0.108a`). Empty when `unextractableReason` is set."
                    },
                    "label": {
                      "type": "string",
                      "description": "Table label as printed, e.g. `TABLE 1`, less one trailing ` |`, `.` or `:` (`Table 1.` reads `Table 1`)"
                    },
                    "caption": {
                      "type": "string",
                      "description": "Caption text, with the label excluded"
                    },
                    "footnotes": {
                      "type": "string",
                      "description": "`<table-wrap-foot>` text, one line per footnote or paragraph, joined by `\\n`. A footnote marker deposited as a `<label>` leads its line, followed by a space (`* No patient …`)."
                    },
                    "sectionTitle": {
                      "type": "string",
                      "description": "Title of the innermost titled section enclosing the table — a body section or a back-matter one such as an appendix — as that section is titled in `sections`, or, for a heading nested deeper than `sections` carries, as its heading line inside the text of the section that contains it. A `sections` filter keeps the table with that section. In back matter the section name is the only positional cue there is. Absent for a table inside no titled section, such as a `<floats-group>` deposit."
                    },
                    "headerRowCount": {
                      "type": "number",
                      "description": "How many leading `rows` entries are header rows — a `<thead>` block, or leading rows made entirely of `<th>`. 0 when the table declares none. Several header rows stack: read one column top to bottom for its full header path."
                    },
                    "unextractableReason": {
                      "enum": [
                        "cals-tgroup",
                        "graphic-only",
                        "no-rows"
                      ],
                      "type": "string",
                      "description": "Why `rows` is empty — set only then. graphic-only: the table was deposited as an image with no underlying markup. cals-tgroup: the table uses the CALS `<tgroup>` model, which this server does not extract (0 of 283 tables in an open-access survey used it). no-rows: the markup carried no rows. The label and caption are still returned, so a table that could not be read is visible rather than silently missing."
                    }
                  },
                  "description": "One table from the article, with its cells, caption, and owning section",
                  "additionalProperties": false
                },
                "description": "Every `<table-wrap>` the article carries, in document order — from the body and from `<floats-group>`, `<back>` and appendices alike. Absent when the article deposits none, when `includeTables` is false, or when a `sections` filter left none standing."
              },
              "authors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "suffix": {
                      "type": "string",
                      "description": "Generational name suffix verbatim from the JATS `<suffix>` (e.g. \"Jr\", \"IV\"), never normalized. Absent when the deposit gives none."
                    },
                    "lastName": {
                      "type": "string",
                      "description": "Last name"
                    },
                    "givenNames": {
                      "type": "string",
                      "description": "Given names"
                    },
                    "collectiveName": {
                      "type": "string",
                      "description": "Group or consortium name, as the group's own name only: members a deposit nests inside it are not listed here or in `authors`. `pubmed_fetch_articles` with `includeInvestigators` returns a collective author's members from PubMed."
                    }
                  },
                  "description": "Author entry",
                  "additionalProperties": false
                },
                "description": "Authors"
              },
              "journal": {
                "type": "object",
                "properties": {
                  "issn": {
                    "type": "string",
                    "description": "ISSN"
                  },
                  "issue": {
                    "type": "string",
                    "description": "Issue number"
                  },
                  "pages": {
                    "type": "string",
                    "description": "Page range"
                  },
                  "title": {
                    "type": "string",
                    "description": "Journal title"
                  },
                  "volume": {
                    "type": "string",
                    "description": "Volume number"
                  },
                  "elocationId": {
                    "type": "string",
                    "description": "Electronic article locator from JATS `<elocation-id>` — the publisher-assigned article number (e.g. \"e20542\"). Journals that assign article numbers deposit no `<fpage>`, so this is the only locator on roughly half of PMC records. Never a substitute for `pages`; JATS carries no type attribute, so there is no counterpart to the `elocationIdType` that `pubmed_fetch_articles` reports."
                  }
                },
                "description": "Journal information",
                "additionalProperties": false
              },
              "abstract": {
                "type": "string",
                "description": "Abstract"
              },
              "keywords": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Keywords"
              },
              "licenses": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "The license's `<license-p>` paragraphs as plain text, a blank line between paragraphs. Absent when the license deposits only a URL."
                    },
                    "urls": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The license's distinct `xlink:href`, then `ali:license_ref` values, as deposited. Absent when the license deposits only text."
                    }
                  },
                  "description": "One license statement the article deposits",
                  "additionalProperties": false
                },
                "description": "The reuse statements the article's JATS deposits, from NCBI PMC and Europe PMC alike: one entry per `<license>` in its article-meta `<permissions>`, in document order. Figure and table permissions are not included. Relayed as deposited, never interpreted. Absent when the article-meta carries no `<license>`."
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "text"
                  ],
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "Section body text"
                    },
                    "label": {
                      "type": "string",
                      "description": "Section label"
                    },
                    "title": {
                      "type": "string",
                      "description": "Section heading"
                    },
                    "subsections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "text"
                        ],
                        "properties": {
                          "text": {
                            "type": "string",
                            "description": "Subsection body text. Sections nested deeper than this level are folded in here in document order, each heading rendered on its own line above its text."
                          },
                          "label": {
                            "type": "string",
                            "description": "Subsection label"
                          },
                          "title": {
                            "type": "string",
                            "description": "Subsection heading"
                          }
                        },
                        "description": "Article subsection",
                        "additionalProperties": false
                      },
                      "description": "Nested subsections"
                    }
                  },
                  "description": "Article section, from the body or from the back matter after it",
                  "additionalProperties": false
                },
                "description": "Article sections in source order: the body, then the back matter — acknowledgments, notes and declarations, footnotes, glossary, appendices. A back-matter element with no heading of its own is titled by its kind, such as `Footnotes` or `Appendix`."
              },
              "pubmedUrl": {
                "type": "string",
                "description": "PubMed URL"
              },
              "viaSource": {
                "enum": [
                  "pmc",
                  "europepmc"
                ],
                "type": "string",
                "description": "Which layer produced the JATS: `pmc` for NCBI PMC EFetch (db=pmc), `europepmc` for Europe PMC `fullTextXML`. Both paths return the same JATS shape; the discriminator records origin for observability and license attribution."
              },
              "epmcSource": {
                "type": "string",
                "description": "Europe PMC source code when `viaSource` is `europepmc`. Common values: `MED` (PubMed-derived), `PMC` (PMC counterpart), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola), plus less common codes (`CTX`, `CBA`, `ETH`, `HIR`). Treat as opaque — EPMC may introduce new codes."
              },
              "references": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "citation"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Reference ID"
                    },
                    "label": {
                      "type": "string",
                      "description": "Reference label"
                    },
                    "citation": {
                      "type": "string",
                      "description": "Citation text"
                    }
                  },
                  "description": "Reference entry",
                  "additionalProperties": false
                },
                "description": "Reference list"
              },
              "articleType": {
                "type": "string",
                "description": "Article type"
              },
              "affiliations": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Author affiliations"
              },
              "publicationDate": {
                "type": "object",
                "properties": {
                  "day": {
                    "type": "string",
                    "description": "Publication day"
                  },
                  "year": {
                    "type": "string",
                    "description": "Publication year"
                  },
                  "month": {
                    "type": "string",
                    "description": "Publication month"
                  }
                },
                "description": "Publication date",
                "additionalProperties": false
              }
            },
            "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "source",
              "viaSource",
              "contentFormat",
              "doi",
              "sourceUrl",
              "content"
            ],
            "properties": {
              "doi": {
                "type": "string",
                "description": "DOI used to locate the open-access copy"
              },
              "pmid": {
                "type": "string",
                "description": "PubMed ID this article was requested under — present when it was requested under a `pmids` entry, absent when under a PMC ID or DOI (see `pmcId` for which identifier an article several of them name is requested under)"
              },
              "year": {
                "type": "number",
                "description": "Publication year from Unpaywall's record for the DOI. Absent when Unpaywall has none."
              },
              "pmcId": {
                "type": "string",
                "description": "PMC ID this article was requested under, in `PMC<digits>` form — present when a `pmcids` entry named it, absent when it was requested under a PMID or DOI. When several identifiers name one article, it is requested under the first to reach it: `pmcids`, then `pmids`, then `dois`. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing."
              },
              "title": {
                "type": "string",
                "description": "Article title, from the first source that carries one: Unpaywall's record for the DOI, then the Europe PMC record when the chain searched Europe PMC for this id, then — for `html-markdown` content only — the title detected on the page. Absent when none of them has a title."
              },
              "source": {
                "type": "string",
                "const": "unpaywall",
                "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`."
              },
              "content": {
                "type": "string",
                "description": "Full article text — Markdown or plain text per `contentFormat`"
              },
              "license": {
                "type": "string",
                "description": "License identifier from Unpaywall (e.g. cc-by, cc0)"
              },
              "version": {
                "type": "string",
                "description": "OA version: submittedVersion | acceptedVersion | publishedVersion"
              },
              "hostType": {
                "type": "string",
                "description": "`publisher` or `repository` — where the OA copy is hosted"
              },
              "pubmedUrl": {
                "type": "string",
                "description": "PubMed URL — present when `pmid` is set"
              },
              "sourceUrl": {
                "type": "string",
                "description": "URL the content was fetched from"
              },
              "viaSource": {
                "type": "string",
                "const": "unpaywall",
                "description": "Layer that produced this article. Constant `unpaywall` for this branch."
              },
              "wordCount": {
                "type": "number",
                "description": "Approximate word count reported by the HTML extractor; absent for PDFs"
              },
              "totalPages": {
                "type": "number",
                "description": "Page count reported by the PDF extractor; absent for HTML"
              },
              "journalName": {
                "type": "string",
                "description": "Journal or repository name from Unpaywall's record for the DOI (e.g. `medRxiv` for a medRxiv preprint). Absent when Unpaywall has none."
              },
              "contentFormat": {
                "enum": [
                  "html-markdown",
                  "pdf-text"
                ],
                "type": "string",
                "description": "How `content` was extracted. html-markdown: Defuddle extracted Markdown from an HTML landing page; light section structure may survive but is not guaranteed. pdf-text: unpdf extracted plain text from a PDF; no section, reference, or heading structure."
              }
            },
            "description": "Best-effort full text from an open-access copy",
            "additionalProperties": false
          }
        ],
        "description": "Full-text article; shape depends on `source` (pmc = structured JATS, unpaywall = best-effort)"
      },
      "description": "Full-text articles in routing order — `pmcids`, then `pmids`, then `dois`, request order within each — each at the position of the id it would be deferred under, whichever tier served it. An article several ids name appears once."
    },
    "deferred": {
      "type": "object",
      "required": [
        "maxResponseCharacters",
        "returnedCharacters",
        "deferredCount",
        "ids",
        "nextDeferredCharacters"
      ],
      "properties": {
        "ids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Identifiers of the deferred articles, in routing order — `pmcids`, then `pmids`, then `dois`, request order within each — keyed as they were requested (PMC IDs in `PMC<digits>` form). Re-call `pubmed_fetch_fulltext` with these under the `idType` field — or, when `idType` is absent, with the `pmcids` / `pmids` / `dois` lists below — and the same other inputs. Never contains an id from `unavailable`."
        },
        "dois": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The deferred ids sent as DOIs, in routing order — re-submit them as `dois`. Present only when the deferred ids came from more than one field (so `idType` is absent) and one of them was a DOI."
        },
        "pmids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The deferred ids sent as PMIDs, in routing order — re-submit them as `pmids`. Present only when the deferred ids came from more than one field (so `idType` is absent) and one of them was a PMID."
        },
        "idType": {
          "enum": [
            "pmid",
            "pmcid",
            "doi"
          ],
          "type": "string",
          "description": "The input field every deferred id was sent in — re-submit them as `pmids`, `pmcids`, or `dois` respectively. Matches the `idType` on `unavailable` entries. Absent when the deferred ids came from more than one field; `pmcids` / `pmids` / `dois` then group them."
        },
        "pmcids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The deferred ids sent as PMC IDs, in routing order — re-submit them as `pmcids`. Present only when the deferred ids came from more than one field (so `idType` is absent) and one of them was a PMC ID."
        },
        "deferredCount": {
          "type": "number",
          "description": "Articles the chain resolved but withheld to stay under the ceiling"
        },
        "returnedCharacters": {
          "type": "number",
          "description": "Serialized characters the returned article records account for"
        },
        "maxResponseCharacters": {
          "type": "number",
          "description": "The `maxResponseCharacters` ceiling this response was budgeted against"
        },
        "nextDeferredCharacters": {
          "type": "number",
          "description": "Serialized size of the next deferred article — the first entry in `ids`, where the response stopped — and the continuation ceiling: re-calling with the deferred ids needs `maxResponseCharacters` ≥ this to return anything, and a smaller article further down `ids` cannot be reached until this one fits. Repeating this same call needs `maxResponseCharacters` ≥ `returnedCharacters` + this to return this article as well."
        }
      },
      "description": "Continuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.",
      "additionalProperties": false
    },
    "overLimit": {
      "type": "object",
      "required": [
        "limit",
        "ids"
      ],
      "properties": {
        "ids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Identifiers past the per-call limit, none of them fetched, in routing order — each listed once, under the first spelling sent (PMC IDs in `PMC<digits>` form). Re-call `pubmed_fetch_fulltext` with these under the `idType` field — or, when `idType` is absent, with the `pmcids` / `pmids` / `dois` lists below — and the same other inputs, at most `limit` per call. Never contains an id from `unavailable` or `deferred`."
        },
        "dois": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The over-limit ids sent as DOIs, in routing order — re-submit them as `dois`. Present only when the over-limit ids came from more than one field (so `idType` is absent) and one of them was a DOI."
        },
        "limit": {
          "type": "number",
          "description": "Distinct identifiers one call fetches. The first this many, in routing order — `pmcids`, then `pmids`, then `dois`, request order within each — were fetched; the ids below were not."
        },
        "pmids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The over-limit ids sent as PMIDs, in routing order — re-submit them as `pmids`. Present only when the over-limit ids came from more than one field (so `idType` is absent) and one of them was a PMID."
        },
        "idType": {
          "enum": [
            "pmid",
            "pmcid",
            "doi"
          ],
          "type": "string",
          "description": "The input field every over-limit id was sent in — re-submit them as `pmids`, `pmcids`, or `dois` respectively. Absent when the over-limit ids came from more than one field; `pmcids` / `pmids` / `dois` then group them."
        },
        "pmcids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The over-limit ids sent as PMC IDs, in routing order — re-submit them as `pmcids`. Present only when the over-limit ids came from more than one field (so `idType` is absent) and one of them was a PMC ID."
        }
      },
      "description": "Identifiers the call named past the per-call fetch limit, returned unfetched for a follow-up call. Present only when the call named more than `limit` distinct identifiers. Separate from `deferred`, which lists articles that were fetched but withheld by `maxResponseCharacters`.",
      "additionalProperties": false
    },
    "truncated": {
      "type": "boolean",
      "description": "True when a character budget shortened at least one returned body or withheld a whole article, when `maxSections` dropped top-level sections from a returned article, or when the call named more distinct identifiers than one call fetches. Absent when every requested identifier was fetched and every resolved article is present with its full post-filter body. The per-article body accounting is in `truncation`; the sections the cap dropped are in `sectionCap`; the withheld ids are in `deferred`; the unfetched ids are in `overLimit`."
    },
    "sectionCap": {
      "type": "object",
      "required": [
        "maxSections",
        "articles"
      ],
      "properties": {
        "articles": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "omittedSections"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Identifier for the article — PMCID, PMID, DOI, or Europe PMC id, whichever the article carries first; the id `truncation.articles[].id` uses"
              },
              "omittedSections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string",
                      "description": "Section label as printed (e.g. `2`), when the section carries one"
                    },
                    "title": {
                      "type": "string",
                      "description": "Section heading, when the section carries one"
                    }
                  },
                  "description": "One top-level section the cap left out",
                  "additionalProperties": false
                },
                "description": "The top-level sections past the cap, in document order, back matter included — counted after the `sections` filter, so a section the filter excluded is not here. The article returned the first `maxSections` top-level sections and had `maxSections` plus this many."
              }
            },
            "description": "The top-level sections one article lost to `maxSections`",
            "additionalProperties": false
          },
          "description": "Per-article lists, in the order `articles` lists the articles, covering only the returned articles the cap cut"
        },
        "maxSections": {
          "type": "number",
          "description": "The `maxSections` cap applied"
        }
      },
      "description": "The top-level sections `maxSections` left out of `source: pmc` articles, PMC- and Europe PMC-served alike. Present only when the cap dropped at least one section from a returned article. Separate from `truncation`, which accounts for characters a budget removed from the sections the cap kept: no section appears in both. Re-call with `sections` set to the titles you need, or with a larger `maxSections`, to receive them.",
      "additionalProperties": false
    },
    "truncation": {
      "type": "object",
      "required": [
        "mode",
        "originalCharacters",
        "returnedCharacters",
        "omittedSections",
        "articles"
      ],
      "properties": {
        "mode": {
          "enum": [
            "truncate",
            "outline"
          ],
          "type": "string",
          "description": "The `overflowMode` that produced these results"
        },
        "articles": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "source",
              "originalCharacters",
              "returnedCharacters"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Identifier for the article — PMCID, PMID, DOI, or Europe PMC id, whichever the article carries first"
              },
              "source": {
                "enum": [
                  "pmc",
                  "unpaywall"
                ],
                "type": "string",
                "description": "Which output shape was budgeted: `pmc` budgets sections and subsections, `unpaywall` budgets the single `content` body"
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "originalCharacters",
                    "returnedCharacters",
                    "truncated"
                  ],
                  "properties": {
                    "label": {
                      "type": "string",
                      "description": "Section label as printed (e.g. `2`), when the section carries one"
                    },
                    "title": {
                      "type": "string",
                      "description": "Section heading, when the section carries one"
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "True when the section returned fewer characters than it originally carried"
                    },
                    "subsections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "originalCharacters",
                          "returnedCharacters",
                          "truncated"
                        ],
                        "properties": {
                          "label": {
                            "type": "string",
                            "description": "Subsection label as printed (e.g. `2.1`), when the subsection carries one"
                          },
                          "title": {
                            "type": "string",
                            "description": "Subsection heading, when the subsection carries one"
                          },
                          "truncated": {
                            "type": "boolean",
                            "description": "True when the subsection returned fewer characters than it originally carried"
                          },
                          "originalCharacters": {
                            "type": "number",
                            "description": "Body characters this subsection carried before the budget pass"
                          },
                          "returnedCharacters": {
                            "type": "number",
                            "description": "Body characters this subsection carries in the response. Zero means it was dropped in `truncate` mode and counted in `omittedSections`, or kept as a heading-only entry in `outline` mode, marked as such in the rendered text."
                          }
                        },
                        "description": "Character accounting for one subsection of a shortened section",
                        "additionalProperties": false
                      },
                      "description": "Per-subsection accounting for a shortened section, in document order, including subsections dropped for budget — where inside the section the cut landed. Absent when the section was returned whole or carries no subsections."
                    },
                    "originalCharacters": {
                      "type": "number",
                      "description": "Body characters this section carried before the budget pass"
                    },
                    "returnedCharacters": {
                      "type": "number",
                      "description": "Body characters this section carries in the response. Zero means the section was dropped in `truncate` mode, or kept as a heading-only entry in `outline` mode, marked as such in the rendered text."
                    }
                  },
                  "description": "Character accounting for one section of a budgeted article",
                  "additionalProperties": false
                },
                "description": "Per-section accounting for `source: pmc` articles, in document order, including sections dropped for budget; a shortened section lists its subsections. Absent for `source: unpaywall`, whose body has no section structure."
              },
              "omittedAssets": {
                "type": "number",
                "description": "Figures and supplementary items this article dropped whole because the budget left no room once body sections and tables were served. An asset is never returned with a truncated caption, so it is either returned complete or counted here. Absent when none were dropped."
              },
              "omittedTables": {
                "type": "number",
                "description": "Tables this article dropped whole because the budget left no room for them. A table is never cut mid-row, so it is either returned complete or counted here. Absent when none were dropped."
              },
              "omittedAssetNames": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "The dropped assets by name, in document order — each asset's label (a bare-number label led by its type, `Supplementary material 1`), else its `id`, else `asset <n>` for its position in the article. Contiguous for the same reason `omittedTableNames` is: admission stops at the first asset that did not fit rather than skipping ahead to a smaller one. Absent when none were dropped."
              },
              "omittedTableNames": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "The dropped tables by name, in document order — each table's label, else its `id`, else `table <n>` for its position in the article. Names the tables a bare count only hints at, the way `deferred.ids` names deferred articles. Every table from the first that did not fit onward is here: admission stops at that table rather than skipping ahead to a smaller one, so these are contiguous. Absent when none were dropped."
              },
              "originalCharacters": {
                "type": "number",
                "description": "Body characters this article carried before the budget pass"
              },
              "returnedCharacters": {
                "type": "number",
                "description": "Body characters this article carries in the response"
              }
            },
            "description": "Character accounting for one article the budget shortened",
            "additionalProperties": false
          },
          "description": "Per-article accounting, covering only the articles the budget shortened"
        },
        "maxCharacters": {
          "type": "number",
          "description": "The `maxCharacters` budget applied, when set"
        },
        "omittedAssets": {
          "type": "number",
          "description": "Figures and supplementary items dropped whole across every budgeted article, because the budget left no room once body sections and tables were served. Absent when none were dropped. Re-request the affected articles with a higher `maxCharacters`, or with `sections` narrowed, to receive them."
        },
        "omittedTables": {
          "type": "number",
          "description": "Tables dropped whole across every budgeted article, because the budget left no room once body sections were served. Absent when none were dropped. Re-request the affected articles with a higher `maxCharacters`, or with `sections` narrowed, to receive them."
        },
        "omittedSections": {
          "type": "number",
          "description": "Sections and subsections, back matter included, dropped entirely because an article budget was exhausted before reaching them. Back matter is reached last, after tables and assets. A dropped section counts once, together with its subsections. Always 0 in `outline` mode, which keeps every heading."
        },
        "originalCharacters": {
          "type": "number",
          "description": "Body characters the shortened articles carried before the budget pass"
        },
        "returnedCharacters": {
          "type": "number",
          "description": "Body characters the shortened articles carry in this response"
        },
        "maxCharactersPerSection": {
          "type": "number",
          "description": "The `maxCharactersPerSection` budget applied, when set"
        }
      },
      "description": "Character accounting for full text the budget shortened. Present only when a budget actually removed characters — its absence means every returned article carries its full post-filter body.",
      "additionalProperties": false
    },
    "unavailable": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "idType",
          "reason",
          "triedTiers"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifier the chain could not resolve — PMID, PMCID, or DOI per `idType`"
          },
          "idType": {
            "enum": [
              "pmid",
              "pmcid",
              "doi"
            ],
            "type": "string",
            "description": "Which input field the id was sent in — `pmids`, `pmcids`, or `dois` respectively"
          },
          "reason": {
            "enum": [
              "not-found",
              "no-pmc-fallback-disabled",
              "no-epmc-fulltext",
              "no-body",
              "no-doi",
              "doi-lookup-failed",
              "no-oa",
              "fetch-failed",
              "parse-failed",
              "service-error"
            ],
            "type": "string",
            "description": "Why no full text was returned — the most specific signal any tier that answered reported. not-found: upstream returned no record for this ID. no-pmc-fallback-disabled: every tier was skipped (`triedTiers` is all `not-attempted`) — typically because EPMC (`EUROPEPMC_ENABLED`) and Unpaywall (`UNPAYWALL_EMAIL`) are not configured. no-epmc-fulltext: EPMC indexed the record but publishes no fullTextXML. no-body: the record was retrieved but carries front matter and abstract only, with no body sections — use `pubmed_fetch_articles` for the metadata. no-doi: the DOI lookup ran and this record has none, so Unpaywall could not be queried. doi-lookup-failed: the DOI lookup itself errored, so whether a DOI exists is unknown and Unpaywall was never reached — retry the request; unlike no-doi this is a transient failure, not a settled answer. no-oa: Unpaywall has no OA copy. fetch-failed: download failed. parse-failed: extraction empty. service-error: upstream server failure (threw, timed out, or returned malformed data). A reason never means the chain ran to completion — read `unqueriedTiers` for that."
          },
          "triedTiers": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "tier",
                "outcome"
              ],
              "properties": {
                "tier": {
                  "enum": [
                    "pmc",
                    "europepmc",
                    "unpaywall"
                  ],
                  "type": "string",
                  "description": "Which tier in the resolution chain"
                },
                "detail": {
                  "type": "string",
                  "description": "Tier-specific context when available"
                },
                "outcome": {
                  "enum": [
                    "not-attempted",
                    "miss",
                    "no-fulltext",
                    "no-body",
                    "no-doi",
                    "doi-lookup-failed",
                    "no-oa",
                    "fetch-failed",
                    "parse-failed",
                    "service-error"
                  ],
                  "type": "string",
                  "description": "Per-tier outcome. not-attempted: tier was skipped. miss: tier returned no record. no-fulltext: EPMC indexed the record but publishes no fullTextXML. no-body: the tier returned a record with front matter and abstract but no body sections, so the chain continued. no-doi: the DOI lookup ran and this record has none, so Unpaywall could not be queried. doi-lookup-failed: the DOI lookup itself errored, so whether a DOI exists is unknown and Unpaywall was never reached — retry the request. no-oa: Unpaywall reports no open-access copy. fetch-failed: OA copy download failed. parse-failed: extraction produced empty content. service-error: tier service threw."
                }
              },
              "description": "One tier the resolution chain attempted, with its outcome",
              "additionalProperties": false
            },
            "description": "Per-tier outcomes the chain produced for this id, in execution order. Covers `pmc`, `europepmc`, and `unpaywall` — the same tiers the tool description references. Tiers that the chain skipped appear as `outcome: not-attempted` with a `detail` explaining why."
          },
          "unqueriedTiers": {
            "type": "array",
            "items": {
              "enum": [
                "europepmc",
                "unpaywall"
              ],
              "type": "string",
              "description": "A fallback tier this deployment has not configured"
            },
            "description": "Tiers the chain skipped because this deployment has not configured them, and that could have served this id — the search was incomplete, and a deployment with these tiers configured may still resolve the id. `triedTiers` carries which environment variable each one is waiting on. Absent when every tier that could have served the id was actually queried; a tier skipped because it was inapplicable to this id (no DOI for Unpaywall) is never listed."
          }
        },
        "description": "One identifier that could not be returned, with the full chain it traversed",
        "additionalProperties": false
      },
      "description": "Per-identifier explanations for any requested PMIDs, PMCIDs, or DOIs with no returnable full text. `idType` names the field each id was sent in. Distinct from `deferred`: nothing here is retrievable by re-calling, and an id never appears in both. Ids past the per-call limit are listed in `overLimit`, never here."
    },
    "totalReturned": {
      "type": "number",
      "description": "Number of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_fulltext annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_format_citations — Pubmed Format Citations
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Get formatted citations for PubMed articles in one or more formats (apa, mla, bibtex, ris, vancouver). Pass a single format as a string or multiple as an array. Retractions, errata, and expressions of concern NCBI links to an article come back in `notices`; Vancouver and APA also cite a retraction in the reference itself.

pubmed_format_citations input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "pmids"
  ],
  "properties": {
    "pmids": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\d+$"
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "PubMed IDs to cite"
    },
    "format": {
      "anyOf": [
        {
          "enum": [
            "apa",
            "mla",
            "bibtex",
            "ris",
            "vancouver"
          ],
          "type": "string",
          "description": "Single citation style. One of: apa, mla, bibtex, ris, vancouver."
        },
        {
          "type": "array",
          "items": {
            "enum": [
              "apa",
              "mla",
              "bibtex",
              "ris",
              "vancouver"
            ],
            "type": "string"
          },
          "minItems": 1,
          "description": "Multiple citation styles to generate. Each entry: apa, mla, bibtex, ris, or vancouver."
        }
      ],
      "default": "apa",
      "description": "Citation format(s) to generate — single style as a string or multiple as an array. Allowed values: apa, mla, bibtex, ris, vancouver."
    }
  },
  "additionalProperties": false
}
pubmed_format_citations output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "citations",
        "totalSubmitted",
        "totalFormatted"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance when no citations were produced — points to discovery tools. Absent when at least one citation was produced."
    },
    "citations": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "pmid",
          "citations"
        ],
        "properties": {
          "pmid": {
            "type": "string",
            "description": "PubMed ID"
          },
          "title": {
            "type": "string",
            "description": "Article title"
          },
          "notices": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "refType",
                "refSource"
              ],
              "properties": {
                "note": {
                  "type": "string",
                  "description": "NCBI's note on the link, e.g. the correction an erratum makes. Absent when NCBI gives none."
                },
                "pmid": {
                  "type": "string",
                  "description": "PMID of the notice — pass it to `pubmed_fetch_articles` to read it. Absent when the notice has no PMID, as with many errata."
                },
                "refType": {
                  "enum": [
                    "RetractionIn",
                    "RetractedandRepublishedIn",
                    "ExpressionOfConcernIn",
                    "ErratumIn",
                    "CorrectedandRepublishedIn"
                  ],
                  "type": "string",
                  "description": "NCBI's `RefType` for the link: RetractionIn, RetractedandRepublishedIn, ExpressionOfConcernIn, ErratumIn, or CorrectedandRepublishedIn."
                },
                "refSource": {
                  "type": "string",
                  "description": "Citation of the notice as NCBI writes it (e.g. \"Lancet. 2010 Feb 6;375(9713):445. doi: 10.1016/S0140-6736(10)60175-4.\")."
                }
              },
              "description": "A linked notice that qualifies the cited article",
              "additionalProperties": false
            },
            "description": "Retraction, erratum, and expression-of-concern notices NCBI links to this article, in NCBI's order. Vancouver notes each `RetractionIn` and `ErratumIn` after the reference and APA each `RetractionIn`; the other types, and MLA, BibTeX, and RIS, carry none, so check this before citing. Absent when NCBI links none."
          },
          "citations": {
            "type": "object",
            "description": "Citations keyed by style. APA and MLA are Markdown — the journal, volume and book title in *italics*, every other character of the record escaped so it renders as written; BibTeX, RIS and Vancouver are plain text.",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "description": "Citations for a single article",
        "additionalProperties": false
      },
      "description": "Citations per article"
    },
    "totalFormatted": {
      "type": "number",
      "description": "Number of PMIDs successfully formatted"
    },
    "totalSubmitted": {
      "type": "number",
      "description": "Number of PMIDs submitted for citation formatting"
    },
    "unavailablePmids": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "PMIDs PubMed returned no record for, so nothing could be cited for them. That is all this reports: PubMed omits a PMID it does not recognize silently, with no error and no reason, so the absence says nothing about whether the PMID exists. Use `pubmed_search_articles` to find PMIDs that do resolve."
    }
  },
  "additionalProperties": false
}
pubmed_format_citations annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_find_related — Pubmed Find Related
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Find 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.

pubmed_find_related input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "pmid"
  ],
  "properties": {
    "pmid": {
      "type": "string",
      "pattern": "^\\d+$",
      "description": "Source PubMed ID"
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Result offset for pagination (0-based). For the next page, add the number of articles returned (at most 50) to this offset."
    },
    "maxResults": {
      "type": "integer",
      "default": 10,
      "maximum": 500,
      "minimum": 1,
      "description": "Maximum related articles per page, up to 50 per call. A larger value is served at 50, with a notice naming the next `offset` when more remain."
    },
    "relationship": {
      "enum": [
        "similar",
        "cited_by",
        "references"
      ],
      "type": "string",
      "default": "similar",
      "description": "Relationship type: similar (content-based), cited_by (articles citing this one), references (articles this one cites)"
    }
  },
  "additionalProperties": false
}
pubmed_find_related output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "sourcePmid",
        "relationship",
        "offset",
        "articles",
        "totalCount",
        "source"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "all_providers_failed"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `all_providers_failed`: Every provider eligible for the requested relationship failed; none answered. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance when results are empty, a fallback provider answered, offset overshot, a fallback provider could not be reached, upstream rows were excluded for carrying no PubMed PMID, or a `maxResults` past the per-call cap of 50 was served at 50. Absent on an NCBI result page that needs none of these."
    },
    "offset": {
      "type": "number",
      "description": "Result offset used"
    },
    "source": {
      "enum": [
        "ncbi",
        "europepmc",
        "openalex"
      ],
      "type": "string",
      "description": "Provider that answered this request"
    },
    "articles": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "pmid"
        ],
        "properties": {
          "pmid": {
            "type": "string",
            "description": "PubMed ID"
          },
          "title": {
            "type": "string",
            "description": "Article title"
          },
          "source": {
            "type": "string",
            "description": "Journal the article appeared in. Absent on an NCBI Bookshelf record, which has no journal — its venue is in `bookTitle` and `publisherName` instead, and `docType` says which kind of record it is."
          },
          "authors": {
            "type": "string",
            "description": "Author string — the first three of the record's own authors, then \"et al.\". On an NCBI Bookshelf chapter these are the chapter's authors; the book's editors are in `editors`."
          },
          "docType": {
            "type": "string",
            "description": "What PubMed classifies this record as: \"chapter\" or \"book\" for an NCBI Bookshelf record, \"citation\" for an ordinary journal article. Absent when PubMed supplies none."
          },
          "editors": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "One editor, \"Surname Initials\" as ESummary renders it"
            },
            "description": "Editors of the containing book, kept out of `authors` so they cannot displace the record's own authors. Absent on a journal article and on a book that credits no editors."
          },
          "pubDate": {
            "type": "string",
            "description": "Publication date as YYYY-MM-DD; a month- or year-only date reads as the first day of that month or year. On an NCBI Bookshelf chapter (`docType` \"chapter\") it is the chapter's own date — its last revision, otherwise its contribution — not the year its book began."
          },
          "bookTitle": {
            "type": "string",
            "description": "Title of the book an NCBI Bookshelf record belongs to. Present instead of `source` on a book record; absent on a journal article."
          },
          "publisherName": {
            "type": "string",
            "description": "Publisher of the book an NCBI Bookshelf record belongs to. Present only on a book record; absent on a journal article."
          }
        },
        "description": "Related article with enriched summary",
        "additionalProperties": false
      },
      "description": "Related articles"
    },
    "sourcePmid": {
      "type": "string",
      "description": "Source PubMed ID"
    },
    "totalCount": {
      "type": "number",
      "description": "Total related articles found before windowing. A Europe PMC or OpenAlex total may shrink to the PubMed-addressable count once a request window covers the whole upstream set, since rows without a PubMed PMID cannot be returned."
    },
    "relationship": {
      "enum": [
        "similar",
        "cited_by",
        "references"
      ],
      "type": "string",
      "description": "Relationship type used"
    },
    "coverageFailures": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "provider",
          "reason",
          "retryable"
        ],
        "properties": {
          "reason": {
            "type": "string",
            "description": "Declared failure reason, e.g. europepmc_unreachable or provider_disabled"
          },
          "provider": {
            "enum": [
              "europepmc",
              "openalex"
            ],
            "type": "string",
            "description": "Reference-coverage provider that failed"
          },
          "retryable": {
            "type": "boolean",
            "description": "Whether a retry can reach this provider"
          }
        },
        "description": "One coverage provider that could not be checked",
        "additionalProperties": false
      },
      "description": "Reference-coverage fallbacks that failed instead of answering, so the reference set is unverified rather than confirmed absent. Absent when every provider consulted answered."
    }
  },
  "additionalProperties": false
}
pubmed_find_related annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_spell_check — Pubmed Spell Check
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Spell-check a PubMed search query against NCBI ESpell and get the corrected query back. Use after a zero-hit or thin `pubmed_search_articles` result, or when a drug, gene, disease, or author name may be misspelled. Corrections are applied in place, so field tags, operators, spacing, and gene symbols stay as written (`alzhiemer diseese treatmnt outcomse` → `alzheimer disease treatment outcomes`). The value of an indexed field — MeSH, publication type, journal, author, language, subset, and the like (`aged[mh]`, `free full text[sb]`, `zhang y[au]`) — is kept as written, misspelled or not, since the ESpell dictionary is not the index that field searches; free-text fields such as `[tiab]`, `[ti]`, and `[tw]` are corrected. Words in all capitals, with digits or non-ASCII letters, or differing only in case are never changed, nor is a single letter swapped for another (`q fever`, the initial in `smith q`), words after a number or symbol ESpell skips are left as written, and `hasSuggestion` is false when no correction was applied. Re-run the search with `corrected`.

pubmed_spell_check input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "description": "PubMed search query to spell-check. Must carry a term: a value of only whitespace or invisible characters, such as a zero-width space, is rejected rather than sent to ESpell."
    }
  },
  "additionalProperties": false
}
pubmed_spell_check output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "original",
        "corrected",
        "hasSuggestion"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "blank_query"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `blank_query`: The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`. On pubmed_search_articles an exactly-empty `query` is not blank: it means no query, and the search runs on its filters. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "original": {
      "type": "string",
      "description": "Original query"
    },
    "corrected": {
      "type": "string",
      "description": "The query with ESpell's accepted corrections applied in place; field tags, the values of indexed fields such as `aged[mh]` and `zhang y[au]`, operators, spacing, words in capitals or with digits, and a single letter ESpell would swap for another are kept as written. Same as `original` when `hasSuggestion` is false."
    },
    "hasSuggestion": {
      "type": "boolean",
      "description": "Whether at least one correction was applied to `corrected`"
    }
  },
  "additionalProperties": false
}
pubmed_spell_check annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_lookup_mesh — Pubmed Lookup Mesh
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search and explore the MeSH (Medical Subject Headings) controlled vocabulary. Returns descriptor records with tree numbers, scope notes, and entry terms, plus pagination via offset for paging past the maxResults cap.

pubmed_lookup_mesh input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "MeSH descriptor name or free-text term to look up. Must carry a term: a value of only whitespace or invisible characters, such as a zero-width space, is rejected rather than searched."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Result offset for pagination (0-based). Pass the `nextOffset` from the previous response to get the following page; the exact-descriptor match is pinned to the first page only."
    },
    "maxResults": {
      "type": "integer",
      "default": 10,
      "maximum": 500,
      "minimum": 1,
      "description": "Maximum results per page, up to 50 per call. A larger value is served at 50, with a notice; continue from `nextOffset`."
    },
    "includeDetails": {
      "type": "boolean",
      "default": true,
      "description": "Fetch full MeSH records (scope notes, tree numbers, entry terms)"
    }
  },
  "additionalProperties": false
}
pubmed_lookup_mesh output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "query",
        "offset",
        "results",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "blank_query"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `blank_query`: The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`. On pubmed_search_articles an exactly-empty `query` is not blank: it means no query, and the search runs on its filters. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "query": {
      "type": "string",
      "description": "Original search query"
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance when no descriptors matched, the offset overshot the result set, or a `maxResults` past the per-call cap of 50 was served at 50 — suggests spell-check, free-text search, resetting the offset, or the `nextOffset` to continue from. Absent on a result page that needs none of these."
    },
    "offset": {
      "type": "number",
      "description": "Result offset this page was read from"
    },
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "entrezUid",
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Descriptor name"
          },
          "meshId": {
            "type": "string",
            "description": "Canonical MeSH unique identifier (e.g. \"D003924\", \"C000626284\", \"Q000009\") — resolves at the MeSH Browser and NLM linked data. A pharmacological-action record carries its descriptor's UI. Omitted only when eSummary returned no record for this UID."
          },
          "entrezUid": {
            "type": "string",
            "description": "NCBI Entrez UID for this record — the join key for E-utilities (eSummary/eFetch db=mesh)."
          },
          "scopeNote": {
            "type": "string",
            "description": "Scope note"
          },
          "entryTerms": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Synonyms / entry terms"
          },
          "treeNumbers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Navigable MeSH tree numbers (e.g. \"D02.078.370.141.450\"). Omitted for supplementary concept records (SCRs), which map to a heading rather than occupying a tree position, and for pharmacological-action records, whose descriptor carries the tree positions."
          }
        },
        "description": "Matching MeSH descriptor record",
        "additionalProperties": false
      },
      "description": "Matching MeSH records"
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset to request for the next page. Omitted when this is the last page, so its absence is the end-of-results signal."
    },
    "totalCount": {
      "type": "number",
      "description": "Total MeSH descriptors matching the query upstream, before the maxResults cap"
    }
  },
  "additionalProperties": false
}
pubmed_lookup_mesh annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_lookup_citation — Pubmed Lookup Citation
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Look 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 least journal or a four-digit year (ECitMatch primary-keys on journal+volume+page; author-only or volume-only inputs guarantee no match); more fields = better match accuracy.

pubmed_lookup_citation input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "citations"
  ],
  "properties": {
    "citations": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Arbitrary label to track this citation in results. Auto-assigned if omitted. Echoed back unchanged and never sent to NCBI, so any character is accepted here."
          },
          "year": {
            "type": "string",
            "pattern": "^[ \\t]*\\d{4}[ \\t]*$",
            "description": "Publication year as four digits (e.g., \"1991\")."
          },
          "volume": {
            "type": "string",
            "pattern": "^[^|\\r\\n]*$",
            "description": "Volume number. Must contain a visible character, and cannot contain a pipe (\"|\") or a line break."
          },
          "journal": {
            "type": "string",
            "pattern": "^[^|\\r\\n]*$",
            "description": "Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\"). Must contain a visible character, and cannot contain a pipe (\"|\") or a line break."
          },
          "firstPage": {
            "type": "string",
            "pattern": "^[^|\\r\\n]*$",
            "description": "First page number. Must contain a visible character, and cannot contain a pipe (\"|\") or a line break."
          },
          "authorName": {
            "type": "string",
            "pattern": "^[^|\\r\\n]*$",
            "description": "Author name, typically \"lastname initials\" (e.g., \"mann bj\"). Must contain a visible character, and cannot contain a pipe (\"|\") or a line break."
          }
        },
        "description": "Citation to match against PubMed. Must include at least journal or a four-digit year — ECitMatch primary-keys on journal+volume+page, so author-only or volume-only inputs guarantee no match."
      },
      "maxItems": 25,
      "minItems": 1,
      "description": "Citations to look up, 1–25, each matched independently. More fields = better match accuracy."
    }
  },
  "additionalProperties": false
}
pubmed_lookup_citation output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "results",
        "totalMatched",
        "totalSubmitted",
        "totalWarnings"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "key",
          "matched",
          "status"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Citation tracking key"
          },
          "pmid": {
            "type": "string",
            "description": "Matched PubMed ID"
          },
          "detail": {
            "type": "string",
            "description": "Additional detail returned by ECitMatch for non-exact matches"
          },
          "status": {
            "enum": [
              "matched",
              "not_found",
              "ambiguous"
            ],
            "type": "string",
            "description": "Lookup outcome classification for this citation"
          },
          "matched": {
            "type": "boolean",
            "description": "Whether a PMID was found"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "code",
                "message"
              ],
              "properties": {
                "code": {
                  "enum": [
                    "author_mismatch",
                    "year_mismatch"
                  ],
                  "type": "string",
                  "description": "Machine-readable warning code"
                },
                "message": {
                  "type": "string",
                  "description": "Human-readable description of the warning"
                }
              },
              "description": "Non-fatal warning about the match",
              "additionalProperties": false
            },
            "description": "Non-fatal warnings about this match. A PMID may be returned even when the queried author or year disagrees with the matched article — verify before treating the PMID as authoritative."
          },
          "candidatePmids": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "PMID"
            },
            "description": "Candidate PMIDs returned when the citation matched ambiguously. Add more bibliographic fields and retry to disambiguate, or fetch each candidate via pubmed_fetch_articles to pick the intended one."
          },
          "matchedFirstAuthor": {
            "type": "string",
            "description": "First author of the matched article (e.g., \"Husain M\"). Useful eyeball signal for verifying a match."
          }
        },
        "description": "Per-citation match result",
        "additionalProperties": false
      },
      "description": "Match results, one per input citation"
    },
    "totalMatched": {
      "type": "number",
      "description": "Number of citations with PMID matches"
    },
    "totalWarnings": {
      "type": "number",
      "description": "Number of matched citations that carry at least one warning"
    },
    "totalSubmitted": {
      "type": "number",
      "description": "Number of citations submitted"
    }
  },
  "additionalProperties": false
}
pubmed_lookup_citation annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_convert_ids — Pubmed Convert Ids
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Convert 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.

pubmed_convert_ids input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "ids",
    "idType"
  ],
  "properties": {
    "ids": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "maxItems": 50,
      "minItems": 1,
      "description": "Article identifiers to convert — one identifier per element, all of the same type. Each element is checked against `idType` before the request: `doi` starts with \"10.\" and carries a \"/\" (\"10.1093/nar/gks1195\"); `pmid` is digits (\"23193287\"); `pmcid` is digits with an optional \"PMC\" prefix (\"PMC3531190\" or \"3531190\"). No element may contain a comma or whitespace — a packed value like \"23193287,37952131\" is rejected, so split it across elements."
    },
    "idType": {
      "enum": [
        "pmcid",
        "pmid",
        "doi"
      ],
      "type": "string",
      "description": "The type of IDs being submitted. Required so the API can unambiguously resolve them."
    }
  },
  "additionalProperties": false
}
pubmed_convert_ids output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "records",
        "totalConverted",
        "totalSubmitted"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "queue_full",
                "ncbi_unreachable",
                "ncbi_rate_limited",
                "ncbi_deadline_exceeded",
                "ncbi_invalid_response",
                "ncbi_resource_not_found",
                "malformed_id"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: The local NCBI request queue shed the call — the queue is full, or the call cannot start before its total deadline (for example behind the cooldown that follows an NCBI 429). `ncbi_unreachable`: NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline. `ncbi_rate_limited`: NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap. `ncbi_deadline_exceeded`: The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff. `ncbi_invalid_response`: NCBI returned a body that could not be parsed (invalid XML/JSON). `ncbi_resource_not_found`: NCBI returned a structured \"not found\" error for the requested ID(s). `malformed_id`: An `ids` element does not match the declared `idType` — most often several identifiers packed into one element, which the comma-delimited upstream batch would split into extra records. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "records": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "requestedId"
        ],
        "properties": {
          "doi": {
            "type": "string",
            "description": "Digital Object Identifier, cased as the PMC ID Converter reports it; absent if no DOI is on record. DOIs are case-insensitive by spec and no case normalization is applied here, so casing can differ from a Europe PMC-sourced `doi` — compare the two case-insensitively."
          },
          "pmid": {
            "type": "string",
            "description": "PubMed ID; absent if no mapping was found"
          },
          "pmcid": {
            "type": "string",
            "description": "PubMed Central ID; absent if the article has no PMC copy"
          },
          "errmsg": {
            "type": "string",
            "description": "Error message if conversion failed. Presence of `errmsg` is the failure signal; absence means the conversion succeeded."
          },
          "requestedId": {
            "type": "string",
            "description": "The ID that was submitted"
          }
        },
        "description": "Per-ID conversion record",
        "additionalProperties": false
      },
      "description": "Conversion results, one per input ID"
    },
    "totalConverted": {
      "type": "number",
      "description": "Number of IDs successfully converted"
    },
    "totalSubmitted": {
      "type": "number",
      "description": "Number of IDs submitted"
    }
  },
  "additionalProperties": false
}
pubmed_convert_ids annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_fetch_citation_metrics — Pubmed Fetch Citation Metrics
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch NIH iCite citation metrics for PubMed articles: the Relative Citation Ratio (RCR), NIH percentile, citation count, citations per year, expected and field citation rates, the Approximate Potential to Translate (APT), the human, animal, and molecular/cellular shares of each article's MeSH terms, and how many clinical articles cite it. RCR is a field- and year-normalized citation rate benchmarked to NIH-funded papers, whose median RCR is 1.0; iCite computes none for the most recent papers and marks recent ones provisional. iCite does not flag retractions — a retracted article keeps its metrics — so check pubmed_fetch_articles for retraction notices before relying on a record. Up to 1000 PMIDs per call; the first 200 distinct PMIDs are fetched and the rest returned in `overLimit`. PMIDs iCite has no record for are listed in `unavailablePmids`.

pubmed_fetch_citation_metrics input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "pmids"
  ],
  "properties": {
    "pmids": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\d+$"
      },
      "maxItems": 1000,
      "minItems": 1,
      "description": "PubMed IDs to look up (e.g. [\"23456789\"]). The first 200 distinct PMIDs are fetched; the rest are returned in `overLimit`. Leading zeros are ignored, so \"00023456789\" and \"23456789\" name one article."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_citation_metrics output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "records"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "icite_unreachable",
                "icite_invalid_response",
                "icite_unrequested_record"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `icite_unreachable`: NIH iCite failed on every attempt the retry budget allowed — a network failure or an HTTP 5xx. `icite_invalid_response`: NIH iCite returned a body that is not its JSON record list on the last attempt the retry budget allowed. `icite_unrequested_record`: NIH iCite answered with a record for a PMID the call did not request, or one whose PMID is not a PMID — the answer it gives this PMID list every time. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Names the PMIDs iCite had no record for, records not yet scored, records with no RCR or a provisional one, and PMIDs past the per-call limit with how to fetch them. Absent when every record came back final and complete."
    },
    "records": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "pmid"
        ],
        "properties": {
          "apt": {
            "type": "number",
            "description": "Approximate Potential to Translate: iCite's estimate of the likelihood that a clinical article will cite this one, reported as 0.05, 0.25, 0.75, or 0.95."
          },
          "doi": {
            "type": "string",
            "description": "DOI when iCite carries one."
          },
          "pmid": {
            "type": "string",
            "description": "PubMed ID, without leading zeros."
          },
          "year": {
            "type": "number",
            "description": "iCite's publication year: the year of the published version, which can differ from PubMed's publication date."
          },
          "human": {
            "type": "number",
            "description": "Share (0–1) of the article's MeSH terms in the Human category."
          },
          "title": {
            "type": "string",
            "description": "Article title as display-ready plain text — markup stripped and HTML entities decoded. Absent when iCite carries none."
          },
          "animal": {
            "type": "number",
            "description": "Share (0–1) of the article's MeSH terms in the Animal category."
          },
          "journal": {
            "type": "string",
            "description": "Journal abbreviation as iCite reports it."
          },
          "isClinical": {
            "type": "boolean",
            "description": "Whether iCite classes the article as clinical research."
          },
          "citationCount": {
            "type": "number",
            "description": "Citations iCite counts for the article. Absent when the record is not yet scored."
          },
          "nihPercentile": {
            "type": "number",
            "description": "Percentile (0–100) of the article's RCR among NIH-funded papers. Absent when iCite reports none, as for papers before 1980 and for most-recent-year provisional RCRs."
          },
          "rcrProvisional": {
            "type": "boolean",
            "description": "True when iCite marks the RCR provisional: a recent paper whose RCR can change as citations accrue. Present only beside `relativeCitationRatio`."
          },
          "citationsPerYear": {
            "type": "number",
            "description": "Citations per year since publication, the numerator of the RCR."
          },
          "fieldCitationRate": {
            "type": "number",
            "description": "Citation rate of the article's co-citation network — the field benchmark the expected rate is derived from."
          },
          "isResearchArticle": {
            "type": "boolean",
            "description": "Whether iCite classes the record as a primary research article; reviews, editorials, letters, and errata are not."
          },
          "molecularCellular": {
            "type": "number",
            "description": "Share (0–1) of the article's MeSH terms in the Molecular/Cellular category."
          },
          "clinicalCitationCount": {
            "type": "number",
            "description": "Clinical articles citing this one: 0 when `citedByClinicalArticle` is false, absent when that flag is."
          },
          "relativeCitationRatio": {
            "type": "number",
            "description": "Relative Citation Ratio (RCR): the article's citations per year divided by the citations per year expected for its field, benchmarked so the median NIH-funded paper of the same year scores 1.0. Absent when iCite computes none — papers too recent to benchmark, and some older records."
          },
          "citedByClinicalArticle": {
            "type": "boolean",
            "description": "Whether at least one clinical article cites this one."
          },
          "expectedCitationsPerYear": {
            "type": "number",
            "description": "Citations per year expected for an article in this one's field and year, the denominator of the RCR."
          }
        },
        "description": "NIH iCite citation metrics for one PubMed article",
        "additionalProperties": false
      },
      "description": "One record per fetched PMID iCite knows, in request order."
    },
    "overLimit": {
      "type": "object",
      "required": [
        "limit",
        "pmids"
      ],
      "properties": {
        "limit": {
          "type": "number",
          "description": "Distinct PMIDs one call fetches. The first this many, in request order, were fetched; the PMIDs below were not."
        },
        "pmids": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "PMIDs past the per-call limit, none of them fetched, in request order — each listed once, under the first spelling sent. Re-call `pubmed_fetch_citation_metrics` with these as `pmids`, at most `limit` per call."
        }
      },
      "description": "PMIDs the call named past the per-call fetch limit. Present only when the call named more distinct PMIDs than one call fetches.",
      "additionalProperties": false
    },
    "unavailablePmids": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Requested PMIDs within the per-call limit that NIH iCite has no record for, in request order, under the spelling sent. iCite omits a PMID it has no record for without an error, so the absence says nothing about whether PubMed has the article; pubmed_fetch_articles confirms that."
    }
  },
  "additionalProperties": false
}
pubmed_fetch_citation_metrics annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_europepmc_search — Pubmed Europepmc Search
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search 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 typical recovery. Paginate via `cursorMark`. Defaults to `MED`, `PMC`, and `PPR`; pass `sources` to include `PAT` / `AGR`. Abstracts arrive as a bounded `abstractSnippet` with `abstractTruncated` marking the cut ones — pass a hit to `pubmed_europepmc_fetch` as `records: [{ source, epmcId }]` for the complete abstract.

pubmed_europepmc_search input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "sort": {
      "type": "string",
      "description": "Optional EPMC sort: `<field> asc|desc`, or several comma-separated keys applied in order (`PUB_YEAR desc, CITED desc`). Documented sortable fields: `P_PDATE_D` (publication date), `CITED` (citation count), `AUTH_FIRST` (first author surname), `PUB_YEAR` (publication year), `FIRST_IDATE_D` (date first indexed in Europe PMC). Examples: `P_PDATE_D desc` (newest first), `CITED desc` (most cited). Omit for relevance ranking; `relevance` or `relevance desc` is sent as no sort. Field and direction match case-insensitively. Each key must be one field plus `asc` or `desc`: a key without a direction, an empty key, or an extra word fails with `europepmc_invalid_input` before the request. A field outside the documented set may be honored, silently ignored, or refused — a sort Europe PMC refuses fails with `europepmc_invalid_input` naming it, and an empty Europe PMC response to a sort with an undocumented field fails the same way, even when Europe PMC honors the field. Note: `P_PDATE_D` is ignored for preprint-only (`sources: [\"PPR\"]`) result sets — preprints have no populated publication date, so use `PUB_YEAR desc` to order preprints by date."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Europe PMC search query. Supports field tokens like `AUTH:\"<name>\"`, `JOURNAL:\"<title>\"`, `TITLE:\"<words>\"`, `PUB_YEAR:[2020 TO 2024]`, `DOI:\"...\"`, `EXT_ID:<pmid> AND SRC:MED`, `PMCID:PMC<digits>`. Identifier tokens may be quoted or unquoted — this tool wraps every query with its `sources` filter, and Europe PMC honors a quoted identifier inside that wrapper. A PubMed-indexed article resolves under `SRC:MED`, not `SRC:PMC`, whichever identifier is used. Free text is matched broadly across abstract/title/keywords. A query with no search term — blank once HTML entities are decoded and markup, parentheses, and invisible characters are disregarded, such as `()` or `<b></b>` — is rejected; any other query is sent as written."
    },
    "sources": {
      "type": "array",
      "items": {
        "enum": [
          "MED",
          "PMC",
          "PPR",
          "PAT",
          "AGR"
        ],
        "type": "string"
      },
      "minItems": 1,
      "description": "Filter to specific EPMC sources. Defaults to MED, PMC, PPR when omitted. Pass an explicit array including PAT or AGR to broaden coverage. Allowed values: MED, PMC, PPR, PAT, AGR."
    },
    "pageSize": {
      "type": "integer",
      "default": 25,
      "maximum": 1000,
      "minimum": 1,
      "description": "Results per page, up to 100 per call (this server's cap; Europe PMC itself serves up to 1,000). A larger value is served at 100, with a notice; continue from `nextCursorMark`."
    },
    "cursorMark": {
      "type": "string",
      "default": "*",
      "description": "Pagination cursor. Use `*` (default) for the first page; pass the previous response's `nextCursorMark` verbatim for subsequent pages. Under relevance ranking (no `sort`), a record can reappear on the next page, so de-duplicate hits by `epmcId` across pages. A whitespace-only cursor, invisible characters included, is rejected before the request, and a cursor Europe PMC cannot read fails with `europepmc_invalid_input` once a retry of it fails again while the first page of the same query is served."
    },
    "resultType": {
      "enum": [
        "core",
        "lite"
      ],
      "type": "string",
      "default": "core",
      "description": "`core` returns abstract, IDs, dates, license; `lite` is a smaller payload with the same IDs, title, authors, journal, and dates, but no abstract or license."
    }
  },
  "additionalProperties": false
}
pubmed_europepmc_search output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "hits",
        "cursorMark",
        "searchUrl",
        "totalCount",
        "query",
        "appliedSources"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "hits": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "epmcId",
          "epmcUrl"
        ],
        "properties": {
          "doi": {
            "type": "string",
            "description": "DOI when present, cased as Europe PMC reports it. DOIs are case-insensitive by spec and no case normalization is applied here, so the same DOI can arrive in a different case from `pubmed_fetch_articles` (Europe PMC `10.1056/nejmoa2212948`, NCBI `10.1056/NEJMoa2212948`) — a byte-for-byte comparison across the two reports a false mismatch."
          },
          "pmid": {
            "type": "string",
            "description": "PMID when present in PubMed"
          },
          "pmcId": {
            "type": "string",
            "description": "PMC ID when present in PMC"
          },
          "title": {
            "type": "string",
            "description": "Article title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
          },
          "epmcId": {
            "type": "string",
            "description": "Europe PMC's internal record id. Pass it with this hit's `source` to `pubmed_europepmc_fetch` as `records: [{ source, epmcId }]` for the complete record. `pubmed_fetch_fulltext` takes this hit's `pmcId`, `pmid`, or `doi`, not this id."
          },
          "source": {
            "enum": [
              "MED",
              "PMC",
              "PPR",
              "PAT",
              "AGR"
            ],
            "type": "string",
            "description": "Europe PMC source — `MED` (PubMed), `PMC` (PubMed Central), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola)"
          },
          "authors": {
            "type": "string",
            "description": "Formatted author string as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
          },
          "epmcUrl": {
            "type": "string",
            "description": "Europe PMC article URL"
          },
          "journal": {
            "type": "string",
            "description": "Journal name as Europe PMC reports it — its MEDLINE abbreviation where it records one (e.g. `Otolaryngol Pol`), else the full journal title — the same for `resultType` `core` and `lite`. Display-ready plain text — JATS/HTML markup stripped and HTML entities decoded. Absent when Europe PMC carries no journal, as for preprints."
          },
          "license": {
            "type": "string",
            "description": "License Europe PMC records for this record, verbatim (e.g. `cc by`, `cc by-nc-nd`, `cc0`). Relayed as Europe PMC states it, never interpreted. Absent when Europe PMC supplies none, and on every `resultType: \"lite\"` result."
          },
          "pubYear": {
            "type": "string",
            "description": "Publication year"
          },
          "citedByCount": {
            "type": "number",
            "description": "Citation count reported by Europe PMC"
          },
          "isOpenAccess": {
            "type": "boolean",
            "description": "Whether EPMC reports the record as open access"
          },
          "hasFullTextXml": {
            "type": "boolean",
            "description": "Whether Europe PMC publishes a fullTextXML for this record: true when Europe PMC marks it open access and lists a full-text id for it, open-access preprints (`PPR`) included; false otherwise. Absent when Europe PMC reports no open-access status."
          },
          "abstractSnippet": {
            "type": "string",
            "description": "First 400 characters of the abstract as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded — when `resultType: \"core\"` is requested, with a trailing … appended when the abstract was cut. Check `abstractTruncated` before treating it as the whole abstract."
          },
          "abstractTruncated": {
            "type": "boolean",
            "description": "Whether `abstractSnippet` was cut short of the full abstract. Retrieve the complete text by passing this record to `pubmed_europepmc_fetch` as `records: [{ source, epmcId }]`. Present whenever `abstractSnippet` is; omitted when Europe PMC carries no abstract."
          },
          "firstPublicationDate": {
            "type": "string",
            "description": "First publication date (ISO YYYY-MM-DD)"
          }
        },
        "description": "Single Europe PMC record returned by the search",
        "additionalProperties": false
      },
      "description": "Matching Europe PMC records, in the order EPMC returned them"
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "europepmc_unreachable",
                "europepmc_invalid_response",
                "europepmc_invalid_input",
                "blank_query",
                "blank_cursor",
                "europepmc_disabled"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC failed on every retry attempt — unreachable, an HTTP 404 or 5xx other than a 504 timeout from its search endpoint, or an empty response with no results. `europepmc_invalid_response`: Europe PMC returned a body that could not be parsed (invalid JSON or XML). `europepmc_invalid_input`: Europe PMC rejected the request input — an error message in place of results; a sort it cannot use (one whose keys are not each a field plus asc/desc, rejected before any request; an empty response to a sort with an undocumented field; or a second HTTP 503 to a sorted search when the same query without the sort is served); or a pagination cursor it cannot read (an empty response on the last attempt the retry budget allows, or a second HTTP 503 when the first page of the same query is served). `blank_query`: The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`. On pubmed_search_articles an exactly-empty `query` is not blank: it means no query, and the search runs on its filters. `blank_cursor`: The `cursorMark` holds only whitespace or invisible characters such as a zero-width space. Europe PMC cannot read it and answers with the HTTP 503 it also uses for an outage. `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "query": {
      "type": "string",
      "description": "Effective query string echoed by Europe PMC"
    },
    "notice": {
      "type": "string",
      "description": "Optional guidance when results are empty, when a cursor is past the last result, when Europe PMC ignores a date sort on preprint-only results, or when a `pageSize` past the per-call cap of 100 was served at 100."
    },
    "searchUrl": {
      "type": "string",
      "description": "Europe PMC's website search URL for this query"
    },
    "cursorMark": {
      "type": "string",
      "description": "Cursor used for this response (echoed from the request)"
    },
    "totalCount": {
      "type": "number",
      "description": "Total matching records across all pages"
    },
    "appliedSources": {
      "type": "array",
      "items": {
        "enum": [
          "MED",
          "PMC",
          "PPR",
          "PAT",
          "AGR"
        ],
        "type": "string"
      },
      "description": "Sources the query was filtered against (defaults applied)"
    },
    "nextCursorMark": {
      "type": "string",
      "description": "Cursor to pass back as `cursorMark` for the next page. Absent on a page shorter than `pageSize`, which ends the result set. A full page that happens to end it still carries one, and the page it leads to comes back empty."
    }
  },
  "additionalProperties": false
}
pubmed_europepmc_search annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
pubmed_europepmc_fetch — Pubmed Europepmc Fetch
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch complete Europe PMC records — including the full, untruncated abstract — addressed as `records: [{ source, epmcId }]`, an array even for one record. Pairs with `pubmed_europepmc_search`, which returns bounded `abstractSnippet` values and flags cut ones with `abstractTruncated: true`; copy each hit's `source` and `epmcId` into `records` here to read the whole abstract. This is the retrieval path for preprint (`PPR`), patent (`PAT`), and Agricola (`AGR`) records, which frequently carry no PMID and no DOI, so `pubmed_fetch_articles` and `pubmed_fetch_fulltext` cannot address them. Up to 25 records per call. Set `maxResponseCharacters` to bound the whole response: records past the ceiling are deferred whole and listed in `deferred.records` for a follow-up call.

pubmed_europepmc_fetch input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "records"
  ],
  "properties": {
    "records": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "epmcId"
        ],
        "properties": {
          "epmcId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
            "maxLength": 64,
            "description": "Europe PMC's own record id within that source. Copy it from the search hit's `epmcId` — for `MED` records this is the PMID; for the other sources it is an EPMC-native accession."
          },
          "source": {
            "enum": [
              "MED",
              "PMC",
              "PPR",
              "PAT",
              "AGR"
            ],
            "type": "string",
            "description": "Europe PMC source corpus — `MED` (PubMed), `PMC` (PubMed Central), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola). Copy it from the search hit's `source`. `PMC` paired with a PMCID resolves whether or not the article is also indexed in PubMed, and a PubMed-indexed one comes back as its canonical `MED` record carrying that PMCID in `pmcId`."
          }
        },
        "description": "One record address: the Europe PMC source corpus plus its id within that corpus"
      },
      "maxItems": 25,
      "minItems": 1,
      "description": "Records to retrieve, each addressed by the `source` and `epmcId` of a `pubmed_europepmc_search` hit. The whole batch resolves in one Europe PMC request."
    },
    "maxResponseCharacters": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1,
      "description": "Opt-in ceiling for the whole response, in characters. Each record is measured as the JSON record it is returned as — title, authors, journal, abstract, identifiers, every field it carries. Records are kept in the order Europe PMC returned them until the next one would cross the ceiling; that record and the rest are deferred whole (never partially populated) and listed in `deferred.records`. Response envelope fields — `notFound`, `deferred` itself — are not counted. Omit to return every resolved record."
    }
  },
  "additionalProperties": false
}
pubmed_europepmc_fetch output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "records"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "europepmc_unreachable",
                "europepmc_invalid_response",
                "europepmc_invalid_input",
                "europepmc_disabled"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC failed on every retry attempt — unreachable, an HTTP 404 or 5xx other than a 504 timeout from its search endpoint, or an empty response with no results. `europepmc_invalid_response`: Europe PMC returned a body that could not be parsed (invalid JSON or XML). `europepmc_invalid_input`: Europe PMC rejected the request input — an error message in place of results; a sort it cannot use (one whose keys are not each a field plus asc/desc, rejected before any request; an empty response to a sort with an undocumented field; or a second HTTP 503 to a sorted search when the same query without the sort is served); or a pagination cursor it cannot read (an empty response on the last attempt the retry budget allows, or a second HTTP 503 when the first page of the same query is served). `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance when one or more requested records could not be resolved, or when `maxResponseCharacters` deferred records — naming how to retrieve them. Absent when every requested record came back."
    },
    "records": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "epmcId",
          "epmcUrl"
        ],
        "properties": {
          "doi": {
            "type": "string",
            "description": "DOI when present, cased as Europe PMC reports it. DOIs are case-insensitive by spec and no case normalization is applied here, so the same DOI can arrive in a different case from `pubmed_fetch_articles` (Europe PMC `10.1056/nejmoa2212948`, NCBI `10.1056/NEJMoa2212948`) — a byte-for-byte comparison across the two reports a false mismatch."
          },
          "pmid": {
            "type": "string",
            "description": "PMID when present in PubMed"
          },
          "pmcId": {
            "type": "string",
            "description": "PMC ID when present in PMC"
          },
          "title": {
            "type": "string",
            "description": "Record title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
          },
          "epmcId": {
            "type": "string",
            "description": "Europe PMC's internal record id"
          },
          "source": {
            "enum": [
              "MED",
              "PMC",
              "PPR",
              "PAT",
              "AGR"
            ],
            "type": "string",
            "description": "Europe PMC source the record was resolved from"
          },
          "authors": {
            "type": "string",
            "description": "Formatted author string as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
          },
          "epmcUrl": {
            "type": "string",
            "description": "Europe PMC article URL"
          },
          "journal": {
            "type": "string",
            "description": "Journal name as Europe PMC reports it — its MEDLINE abbreviation where it records one (e.g. `Otolaryngol Pol`), else the full journal title — the same name `pubmed_europepmc_search` returns for the record. Display-ready plain text — JATS/HTML markup stripped and HTML entities decoded. Absent when Europe PMC carries no journal, as for preprints."
          },
          "license": {
            "type": "string",
            "description": "License Europe PMC records for this record, verbatim (e.g. `cc by`, `cc by-nc-nd`, `cc0`). Relayed as Europe PMC states it, never interpreted. Absent when Europe PMC supplies none."
          },
          "pubYear": {
            "type": "string",
            "description": "Publication year"
          },
          "abstract": {
            "type": "string",
            "description": "Complete abstract as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded, never truncated. Omitted when Europe PMC carries no abstract for the record."
          },
          "citedByCount": {
            "type": "number",
            "description": "Citation count reported by Europe PMC"
          },
          "isOpenAccess": {
            "type": "boolean",
            "description": "Whether Europe PMC reports the record as open access"
          },
          "hasFullTextXml": {
            "type": "boolean",
            "description": "Whether Europe PMC publishes a fullTextXML for this record: true when Europe PMC marks it open access and lists a full-text id for it, open-access preprints (`PPR`) included; false otherwise. Absent when Europe PMC reports no open-access status."
          },
          "firstPublicationDate": {
            "type": "string",
            "description": "First publication date (ISO YYYY-MM-DD)"
          }
        },
        "description": "Complete Europe PMC record",
        "additionalProperties": false
      },
      "description": "Resolved records, in the order Europe PMC returned them. Under a `maxResponseCharacters` budget, only the leading records that fit; `deferred.records` lists the rest."
    },
    "deferred": {
      "type": "object",
      "required": [
        "maxResponseCharacters",
        "returnedCharacters",
        "deferredCount",
        "records",
        "nextDeferredCharacters"
      ],
      "properties": {
        "records": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "source",
              "epmcId"
            ],
            "properties": {
              "epmcId": {
                "type": "string",
                "description": "Europe PMC's internal record id"
              },
              "source": {
                "enum": [
                  "MED",
                  "PMC",
                  "PPR",
                  "PAT",
                  "AGR"
                ],
                "type": "string",
                "description": "Europe PMC source the record was resolved from"
              }
            },
            "description": "One deferred record, addressed by its own `source` + `epmcId`",
            "additionalProperties": false
          },
          "description": "The deferred records, in response order, each as the resolved record's own `source` + `epmcId` — a `PMC` request answered by its `MED` record is listed as that `MED` pair. Pass them back as `records` to retrieve them. Never contains a pair from `notFound`."
        },
        "deferredCount": {
          "type": "number",
          "description": "Records that resolved but were withheld to stay under the ceiling"
        },
        "returnedCharacters": {
          "type": "number",
          "description": "Serialized characters the returned records account for"
        },
        "maxResponseCharacters": {
          "type": "number",
          "description": "The `maxResponseCharacters` ceiling this response was budgeted against"
        },
        "nextDeferredCharacters": {
          "type": "number",
          "description": "Serialized size of the next deferred record — the first entry in `records`, where the response stopped — and the continuation ceiling: re-calling with the deferred pairs needs `maxResponseCharacters` ≥ this to return anything, and a smaller record further down `records` cannot be reached until this one fits. Repeating this same call needs `maxResponseCharacters` ≥ `returnedCharacters` + this to return this record as well."
        }
      },
      "description": "Continuation state for records the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one record.",
      "additionalProperties": false
    },
    "notFound": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "epmcId"
        ],
        "properties": {
          "epmcId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
            "maxLength": 64,
            "description": "Europe PMC's own record id within that source. Copy it from the search hit's `epmcId` — for `MED` records this is the PMID; for the other sources it is an EPMC-native accession."
          },
          "source": {
            "enum": [
              "MED",
              "PMC",
              "PPR",
              "PAT",
              "AGR"
            ],
            "type": "string",
            "description": "Europe PMC source corpus — `MED` (PubMed), `PMC` (PubMed Central), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola). Copy it from the search hit's `source`. `PMC` paired with a PMCID resolves whether or not the article is also indexed in PubMed, and a PubMed-indexed one comes back as its canonical `MED` record carrying that PMCID in `pmcId`."
          }
        },
        "description": "One record address: the Europe PMC source corpus plus its id within that corpus",
        "additionalProperties": false
      },
      "description": "Requested `source` + `epmcId` pairs Europe PMC returned no record for. Reported in full regardless of where a `maxResponseCharacters` cut lands — these are misses, not deferrals."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when `maxResponseCharacters` withheld at least one resolved record. Absent when the response carries every record that resolved. The continuation state is in `deferred`."
    }
  },
  "additionalProperties": false
}
pubmed_europepmc_fetch annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}

Prompts

1 advertised

research_plan

Advertised by the server during the last successful anonymous check.

Generate a structured research plan outline for a biomedical research project.

title
Project title (required)
goal
Primary research goal (required)
keywords
Research keywords (comma-separated) (required)
organism
Target organism
includeAgentPrompts
Include inline guidance blocks under each phase with execution-time hints ("true" or "false"; omitted = "false")

Resources

2 advertised

database-info — PubMed Database Info

Advertised by the server during the last successful anonymous check.

PubMed database metadata including field list, last update date, and record count.

database-info URI
pubmed://database/info

MIME type: application/json

pubmed-guide

Advertised by the server during the last successful anonymous check.

PubMed query syntax, identifier crosswalks, and gates for the pubmed_* tools over PubMed, PubMed Central, Europe PMC, and NIH iCite. Use when building a MeSH-based or systematic search, resolving a reference list or DOIs to PMIDs, judging how cited an article is, getting full text, or finding preprints and records PubMed lacks.

pubmed-guide URI
skill://pubmed-guide/SKILL.md

MIME type: text/markdown

io.modelcontextprotocol/skills

Advertised by the server during the last successful anonymous check.

io.modelcontextprotocol/skills URI template
skill://{+path}

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
655 ms
95th percentile latency
655 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 655 ms · metadata changed · 12 tool(s), 2 resource(s), 1 resource template(s), 1 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http pubmed-mcp-server-caseyjhand https://pubmed.caseyjhand.com/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add pubmed-mcp-server-caseyjhand --url https://pubmed.caseyjhand.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable pubmed-mcp-server-caseyjhand in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "pubmed-mcp-server-caseyjhand": {
      "url": "https://pubmed.caseyjhand.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "pubmed-mcp-server-caseyjhand": {
      "type": "streamableHttp",
      "url": "https://pubmed.caseyjhand.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start pubmed-mcp-server-caseyjhand and inspect its tools.
VS Code configuration
{
  "servers": {
    "pubmed-mcp-server-caseyjhand": {
      "type": "http",
      "url": "https://pubmed.caseyjhand.com/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http pubmed-mcp-server-caseyjhand https://pubmed.caseyjhand.com/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://pubmed.caseyjhand.com/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "pubmed-mcp-server-caseyjhand": {
      "serverUrl": "https://pubmed.caseyjhand.com/mcp"
    }
  }
}

Let your agent find its tools

Find servers like pubmed-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.