Skip to main content
Glama

Server Details

Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms.

If you are the author of this connector, you can claim ownership with GitHub, an HTTP challenge, or a DNS record. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
99.9% over 40 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
cyanheads/pubmed-mcp-server
GitHub Stars
149
Server Listing
pubmed-mcp-server

TDQS

A4.1/5.0

Scored across 11 tools

Disambiguation5/5

Each tool targets a distinct operation: search, spellcheck, metadata fetch, full-text fetch, ID conversion, citation lookup, MeSH lookup, related articles, and citation formatting. The two Europe PMC tools are explicitly paired and clearly differentiated from PubMed-only tools by source and ID type.

Naming Consistency4/5

All tools share a clear pubmed_ prefix and mostly follow verb_noun naming such as fetch_articles and search_articles. The europepmc_fetch and europepmc_search pair inverts the verb position, which is a minor deviation from an otherwise consistent pattern.

Tool Count5/5

Eleven tools is well-scoped for a biomedical literature server: search, identifier conversion, full-text retrieval, citation formatting, MeSH lookup, and related-article navigation are each represented without obvious redundancy.

Completeness4/5

The tool surface covers the main PubMed and Europe PMC workflows thoroughly, including search, retrieval, full-text access, related articles, and citation formatting. Minor gaps remain, such as the PMC-only limitation on batch ID conversion and no direct metadata-by-DOI endpoint, though both have workarounds via search.

Available Tools

11 tools
pubmed_convert_idsPubmed Convert IdsA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYesArticle 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.
idTypeYesThe type of IDs being submitted. Required so the API can unambiguously resolve them.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
recordsNoConversion results, one per input ID
totalConvertedNoNumber of IDs successfully converted
totalSubmittedNoNumber of IDs submitted

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the description is not burdened with safety disclosure. It adds meaningful behavioral context beyond the schema by naming the PMC-only resolution scope and the 50-ID single-type limit, which are useful for call planning.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences of dense, useful information with zero filler. The core action is stated first, followed by limits and an actionable alternative, making it easy to scan and use.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With full parameter documentation in the schema and a present output schema, the description covers everything else needed: the operation, constraints, scope limitation, and sibling alternative. An agent can select and invoke this tool correctly with no additional inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents each parameter thoroughly, including validation examples and rejection rules. The description does not need to repeat parameter details, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Convert') and names the exact resource (article identifiers DOI, PMID, PMCID), plus a concrete constraint (up to 50 IDs, single type). This clearly distinguishes it from sibling tools like pubmed_search_articles or pubmed_fetch_articles.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool and provides a direct alternative: only resolves articles in PubMed Central, so for non-PMC articles use pubmed_search_articles instead. This gives the agent clear routing guidance with no ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_europepmc_fetchPubmed Europepmc FetchA
Read-only
Inspect

Fetch complete Europe PMC records — including the full, untruncated abstract — for records addressed by source plus epmcId. Pairs with pubmed_europepmc_search, which returns bounded abstractSnippet values and flags cut ones with abstractTruncated: true; pass those hits' source and epmcId 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
recordsYesRecords to retrieve, each addressed by the `source` and `epmcId` of a `pubmed_europepmc_search` hit. The whole batch resolves in one Europe PMC request.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when one or more requested records could not be resolved. Absent when every record came back.
recordsNoResolved records, in the order Europe PMC returned them
notFoundNoRequested `source` + `epmcId` pairs Europe PMC returned no record for

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare `readOnlyHint` and `openWorldHint`, so the read-only nature is covered. The description adds meaningful behavior beyond that: it returns complete untruncated abstracts, resolves up to 25 records per call, and acts as the retrieval path for sources without PMID/DOI. This gives an agent a richer model of what the call will and will not return. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a dense but efficient paragraph where every sentence contributes: purpose, truncated-snippet context, sibling-tool boundaries, and the batch limit are all included. The main purpose is front-loaded in the first sentence, and there is no filler or repetition of structured metadata.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with detailed schema descriptions and an output schema present, the description covers everything an agent needs: what to pass, where to obtain the values, when this tool is necessary, why siblings fail, and the maximum batch size. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already explains `source` and `epmcId` in detail, so the baseline is 3. The description adds value by linking the parameters directly to search hits, explaining that the pair should be copied from `pubmed_europepmc_search`, and clarifying that these addresses are needed because other fetch tools cannot handle some sources. That goes beyond the schema's field-level documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Fetch') and the resource ('complete Europe PMC records') and emphasizes the full, untruncated abstract as the defining feature. It distinguishes this tool from `pubmed_europepmc_search` and from the sibling fetch tools by naming the record types only this tool can address. An agent can immediately tell what this tool does and why it exists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to use this tool when `pubmed_europepmc_search` returns truncated abstracts, and it names the concrete conditions that make sibling tools unsuitable: preprint, patent, and Agricola records often lack PMID and DOI. It also gives the practical pairing pattern: take `source` and `epmcId` from search hits. This is strong, actionable usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_fetch_articlesPubmed Fetch ArticlesA
Read-only
Inspect

Fetch full article metadata by PubMed IDs. Returns detailed article information including abstract, authors, journal, MeSH terms. Set maxResponseCharacters to bound the whole response: articles past the ceiling are deferred whole and listed in deferred.ids for a follow-up call.

ParametersJSON Schema
NameRequiredDescriptionDefault
pmidsYesPubMed IDs to fetch
includeMeshNoInclude MeSH terms
includeGrantsNoInclude grant information
maxResponseCharactersNoOpt-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.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoOptional 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.
articlesNoParsed articles
deferredNoContinuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.
truncatedNoTrue when `maxResponseCharacters` withheld at least one resolved article. Absent when the response carries every article that resolved. The continuation state is in `deferred`.
totalReturnedNoNumber of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest.
unavailablePmidsNoPMIDs 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.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses a non-obvious behavior: articles past the maxResponseCharacters ceiling are deferred whole and listed in deferred.ids for follow-up calls. This helps the agent understand response-boundary semantics. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The core purpose is front-loaded, and the key response-bounding caveat is stated directly. Every sentence adds meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description plus the rich schema and output schema cover what the agent needs: input IDs, optional flags, and the notable response-deferral behavior. It does not need to explain return values because an output schema exists. Minor context such as unavailable PMID handling is left to the schema/output, which is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents pmids, includeMesh, includeGrants, and maxResponseCharacters in detail. The description adds only a reiteration of the maxResponseCharacters deferral behavior, which is useful but mostly redundant with the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb (Fetch), the resource (full article metadata), and the input type (PubMed IDs), listing the kinds of data returned. It does not explicitly name a sibling tool, but the phrase 'full article metadata' distinguishes it from pubmed_fetch_fulltext and 'by PubMed IDs' distinguishes it from search/convert tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: use this tool when you have PubMed IDs and want detailed article metadata. It does not explicitly list exclusions or name alternatives, but the purpose statement is specific enough for an agent to decide when to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_fetch_fulltextPubmed Fetch FulltextA
Read-only
Inspect

Fetch full-text articles from PubMed Central with structured sections, tables, and references. When PMC misses, transparently falls back to Europe PMC fullTextXML (structured JATS for records with a PMC counterpart), then to Unpaywall — publisher-hosted or institutional open-access copies as HTML-as-Markdown or PDF-as-text. Provide exactly one of pmcids (PMC IDs directly), pmids (PubMed IDs, auto-resolved), or dois (DOIs, auto-resolved to PMC via the ID Converter; preprints and EPMC-only OA fall through to the Europe PMC and Unpaywall layers). 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
doisNoDOIs to resolve (e.g. ["10.21203/rs.3.rs-9010375/v1"]), one per element. Provide exactly one of `pmcids`, `pmids`, or `dois`. 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.
pmidsNoPubMed IDs. Provide exactly one of `pmcids`, `pmids`, or `dois`. 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.
pmcidsNoPMC IDs to fetch (e.g. ["PMC9575052"]). Provide exactly one of `pmcids`, `pmids`, or `dois`. PMC IDs with no retrievable full text fall through to Europe PMC, then to Unpaywall on the DOI the chain resolves for them.
sectionsNoFilter 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". 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. Applies to `source=pmc` results only.
maxSectionsNoMaximum top-level body sections. Applies to `source=pmc` results only.
overflowModeNoHow 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: split the budget evenly so every section and subsection keeps its heading, and an excerpt as far as the budget reaches — a heading the budget left empty is marked as such in the rendered text. 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.truncate
includeAssetsNoInclude 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.
includeTablesNoInclude 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.
maxCharactersNoPer-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, 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. 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. Sections are served first, then tables, then assets, each spending what is left, in document order — 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`. 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.
includeReferencesNoInclude reference list. Applies to `source=pmc` results only.
maxResponseCharactersNoOpt-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, body 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 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, `unavailable`, `truncation`, `deferred` itself — are not counted. Omit to return every resolved article.
maxCharactersPerSectionNoBudget for a single top-level body 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.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoOptional 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 response-wide budget that deferred articles names the ids to re-request. Absent when none of those applies.
articlesNoFull-text articles
deferredNoContinuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.
truncatedNoTrue when a character budget shortened at least one returned body, or withheld a whole article. Absent when every resolved article is present with its full post-filter body. The per-article body accounting is in `truncation`; the withheld ids are in `deferred`.
truncationNoCharacter 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.
unavailableNoPer-identifier explanations for any requested PMIDs, PMCIDs, or DOIs with no returnable full text. `idType` discriminates which branch the id came from. Distinct from `deferred`: nothing here is retrievable by re-calling, and an id never appears in both.
totalReturnedNoNumber of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and openWorldHint=true, but the description goes far beyond them, disclosing transparent fallbacks, character budget behaviors, deferral of oversized responses, truncation logic, and section filtering rules. It explains exactly what happens when budget limits are hit and how deferred articles are listed. No contradiction with annotations; instead it adds rich behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely long—several paragraphs of dense prose covering every parameter and behavior. While it is well-structured and front-loaded with the core purpose, it is far from concise. Each sentence carries information, but the sheer volume overwhelms an agent trying to quickly parse the essentials. A more condensed summary with pointers to schema details would improve usability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 12 parameters, an output schema, and multiple fallback layers, the description covers every aspect an agent needs: which ID to provide, how fallbacks work, how budgets are applied, what gets deferred, and how sections/tables/assets are filtered. It even clarifies interaction with other parameters and the response envelope. The presence of an output schema reduces the need to describe return values, and the description does not neglect any operational detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers all 12 parameters with detailed descriptions (100% coverage), so the baseline is 3. The tool description adds value by explaining the interplay between parameters, such as the ordering of filters (sections, maxSections, then maxCharacters) and the distinction between per-article and response-wide budgets. It also clarifies the fallback chain for each ID type, which is beyond the schema's per-parameter notes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Fetch full-text articles from PubMed Central with structured sections, tables, and references.' It also names fallback layers (Europe PMC, Unpaywall) and distinguishes from the sibling pubmed_fetch_articles by emphasizing structured full text and multi-source coverage. The purpose is unambiguous and differentiates from related tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage constraints: 'Provide exactly one of `pmcids`, `pmids`, or `dois`' and explains fallback behavior when a source misses. It does not explicitly name alternative tools or state when not to use this one, but the detailed parameter guidance and the implied contrast with simpler fetch tools give strong context. A slight gap is the absence of explicit 'use X instead when' statements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_format_citationsPubmed Format CitationsB
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pmidsYesPubMed IDs to cite
formatNoCitation format(s) to generate — single style as a string or multiple as an array. Allowed values: apa, mla, bibtex, ris, vancouver.apa

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoOptional guidance when no citations were produced — points to discovery tools. Absent when at least one citation was produced.
citationsNoCitations per article
totalFormattedNoNumber of PMIDs successfully formatted
totalSubmittedNoNumber of PMIDs submitted for citation formatting
unavailablePmidsNoPMIDs 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.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the description does not need to re-state that this is a safe read operation. The description adds the format flexibility (string or array), but that is also present in the schema. No additional behavioral details like authentication or rate limits are given, matching the baseline for annotation-covered tools.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The first sentence front-loads the core action and supported formats; the second explains the parameter usage pattern. Every word earns its place, and the description is appropriately sized for a simple, two-parameter tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter read-only tool with an output schema, the description adequately covers the core purpose and how to specify formats. It does not mention that format defaults to 'apa' or that it is optional, but the schema already carries that information. Overall it provides enough context for correct invocation, with only minor redundancy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both pmids and format having descriptive text and full enum explanations in the schema. The description's phrase 'Pass a single format as a string or multiple as an array' merely restates the schema's anyOf structure, adding no new semantic value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Get'), a clear resource ('formatted citations for PubMed articles'), and lists the exact supported formats (apa, mla, bibtex, ris, vancouver). This clearly distinguishes it from article fetching or searching, but it does not explicitly contrast with sibling tools like pubmed_lookup_citation, so it falls short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to choose this tool over alternatives such as pubmed_lookup_citation or pubmed_fetch_articles. It only explains how to pass formats, not when this tool is appropriate or when another should be used. No exclusions or alternative routing are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_lookup_citationPubmed Lookup CitationA
Read-only
Inspect

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

ParametersJSON Schema
NameRequiredDescriptionDefault
citationsYesCitations to look up — an array of up to 25, or a single citation object. More fields = better match accuracy.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
resultsNoMatch results, one per input citation
totalMatchedNoNumber of citations with PMID matches
totalWarningsNoNumber of matched citations that carry at least one warning
totalSubmittedNoNumber of citations submitted

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the operation as read-only and open-world, and the description adds meaningful behavioral detail beyond that: it explains ECitMatch primary-key behavior, states that author-only or volume-only inputs guarantee no match, and notes that more fields improve accuracy. This gives the agent a realistic model of how matching behaves.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose, when to use, and matching constraints. The core action is front-loaded and there is no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the single parameter, rich input schema, output schema presence, and read-only/open-world annotations, the description covers what the tool does, when to use it, and the key matching constraints an agent needs to invoke it correctly. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema thoroughly documents the 'citations' parameter, so the baseline is 3. The description adds practical value on top by framing the input as 'partial bibliographic citations' and emphasizing that more fields improve match accuracy, which helps the agent decide how much information to include.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Look up PubMed IDs from partial bibliographic citations.' It also signals how this differs from free-text search by emphasizing deterministic citation matching, though it never names a sibling tool explicitly, so it stops just short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states when the tool is useful: when you have structured reference data and need a PMID. It also compares favorably against free-text search for structured references, but does not explicitly explain when NOT to use it or name the alternative tool, so the guidance is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_lookup_meshPubmed Lookup MeshA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesMeSH descriptor name or free-text term to look up. Must carry a term: a blank or whitespace-only value is rejected rather than searched.
offsetNoResult 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.
maxResultsNoMaximum results
includeDetailsNoFetch full MeSH records (scope notes, tree numbers, entry terms)

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
queryNoOriginal search query
noticeNoOptional guidance when no descriptors matched or the offset overshot the result set — suggests spell-check, free-text search, or resetting the offset. Absent on successful result pages.
offsetNoResult offset this page was read from
resultsNoMatching MeSH records
nextOffsetNoOffset to request for the next page. Omitted when this is the last page, so its absence is the end-of-results signal.
totalCountNoTotal MeSH descriptors matching the query upstream, before the maxResults cap

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the description doesn't need to repeat that. The description adds value by explaining the pagination mechanism (offset for paging past maxResults cap) and the fact that the exact-descriptor match is pinned to the first page. This goes beyond the annotation and gives useful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The main purpose is front-loaded, followed by output details and pagination. Every sentence adds value and it is concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema, the description does not need to detail return values. It covers the core purpose, pagination behavior, and the maxResults cap. It is complete for an agent to decide when to invoke it and understand its basic operation, though it could mention any prerequisites or special cases, but none are apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all parameters are well-documented in the schema. The description mentions pagination and maxResults cap but adds minimal new meaning beyond the schema's parameter descriptions. Baseline 3 is appropriate since the schema carries the parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: searching and exploring the MeSH controlled vocabulary, and specifies the output (descriptor records with tree numbers, scope notes, entry terms) and pagination. It distinguishes itself from sibling tools like pubmed_search_articles by focusing on MeSH vocabulary rather than article search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for MeSH lookups but does not explicitly state when to use it versus alternatives, nor does it provide exclusions. It is clear from context that this is for controlled vocabulary exploration, but there is no explicit routing or comparison to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_search_articlesPubmed Search ArticlesA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
sortNoSort order: relevance (default), pub_date (newest first), author, or journalrelevance
queryYesPubMed search query (supports full NCBI syntax). Must carry a search term: a value that is blank once markup, bracketed field tags (`[pdat]`), and parentheses are removed is rejected rather than sent to PubMed as an empty term.
authorNoFilter by author name (e.g. "Smith J")
offsetNoResult 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.
journalNoFilter by journal name
speciesNoFilter by species
languageNoFilter by language (e.g. "english")
dateRangeNoFilter by date range. The filter is applied only when both `minDate` and `maxDate` are non-empty; either one empty disables the entire date range.
meshTermsNoFilter by MeSH terms. Multiple terms are AND'd — all must match.
maxResultsNoMaximum results to return
hasAbstractNoOnly include articles with abstracts
freeFullTextNoOnly include free full text articles
summaryCountNoFetch brief summaries for top N results (0 = PMIDs only). Above the 50 cap, pass the remaining PMIDs to pubmed_fetch_articles.
publicationTypesNoFilter by publication type (e.g. "Review", "Clinical Trial", "Meta-Analysis"). Multiple values are OR'd — any match qualifies.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
pmidsNoPubMed IDs
queryNoOriginal query
noticeNoOptional 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, or paging past the end. Absent when nothing applies.
offsetNoResult offset used
searchUrlNoPubMed search URL
summariesNoBrief summaries (empty array when summaryCount is 0)
totalCountNoTotal matching articles
appliedFiltersNoNormalized filter values that were applied to the PubMed query
effectiveQueryNoSanitized query sent to PubMed after applying all active filters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds valuable behavioral context beyond the annotations. It discloses that the tool 'Returns PMIDs and optional brief summaries,' explains the offset cap ('PubMed serves at most the first 9999 records'), and clarifies the dateRange behavior ('the filter is applied only when both minDate and maxDate are non-empty'). These are not present in the annotations (readOnlyHint and openWorldHint) and help the agent understand side effects and limitations. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the primary purpose, and uses compact but informative language. It covers the main capabilities without redundancy, and each phrase adds value (e.g., 'full query syntax', 'optional brief summaries', 'pagination'). It is well-structured and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 14 parameters and an output schema, the description is reasonably complete. It summarizes key features (filters, pagination, summaries) but does not enumerate all parameter types; however, the schema provides full details. It also explains critical limits (offset cap, summaryCount cap) that an agent needs to know. The presence of an output schema reduces the need to describe return values, so a 4 is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the baseline is 3. The tool description mostly restates what the schema already documents (e.g., 'pagination via offset' aligns with the offset parameter's description). It does not add new meaning to parameters; the only added value is the summaryCount routing note, which is already in the schema. Therefore, it does not exceed the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Search PubMed with full query syntax, filters, and date ranges.' It specifies the resource (PubMed), the action (search), and the scope (full query syntax, filters, date ranges), and distinguishes itself from sibling tools like pubmed_fetch_articles by focusing on search and returning PMIDs/summaries rather than full articles. The mention of 'field-specific filters' and 'pagination' further clarifies its role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus siblings, but it implies its role as a search tool through the phrase 'Search PubMed.' It does provide a specific routing hint in the summaryCount parameter description: 'Above the 50 cap, pass the remaining PMIDs to pubmed_fetch_articles.' However, there is no explicit statement of exclusions or alternatives for the overall search task, so it falls short of a perfect 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pubmed_spell_checkPubmed Spell CheckA
Read-only
Inspect

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 — every misspelled token is corrected in one call (alzhiemer diseese treatmnt outcomse → alzheimer disease treatment outcomes), and hasSuggestion is false when NCBI has no change to offer. Re-run the search with corrected.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesPubMed search query to spell-check. Must carry a term: a blank or whitespace-only value is rejected rather than sent to ESpell.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
originalNoOriginal query
correctedNoCorrected query (same as original if no suggestion)
hasSuggestionNoWhether NCBI suggested a correction

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and openWorldHint=true, and the description does not contradict them. It adds behavioral context: corrects all misspelled tokens in one call, hasSuggestion indicates whether NCBI offered a change, and gives an example transformation. This is useful beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single focused paragraph that front-loads purpose, then gives usage guidance and an example, all without waste. It earns its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with an output schema, the description provides adequate context: purpose, usage triggers, expected behavior, and an example. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'query' is fully documented in the schema (100% coverage), including the requirement to carry a term. The description does not add additional parameter semantics beyond the schema, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb 'Spell-check' against NCBI ESpell, and clarifies it returns the corrected query. It also differentiates from siblings by explicitly positioning it as a follow-up to pubmed_search_articles when results are thin or misspellings suspected.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: after a zero-hit or thin pubmed_search_articles result, or when a drug/gene/disease/author may be misspelled. This guides the agent to invoke it in the right context and implies it's not for well-formed queries.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 1 tool update
    • Changedpubmed_fetch_fulltext10 fields changed
      • changedInput schema / properties / maxCharacters / description
        Previous value: -"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, and references are never counted or shortened. 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. Sections are served first, then tables, then assets, each spending what is left, in document order — 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`. 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."New value: +"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, 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. 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. Sections are served first, then tables, then assets, each spending what is left, in document order — 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`. 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."
      • changedInput schema / properties / overflowMode / description
        Previous value: -"How to spend `maxCharacters` across an article that exceeds it. truncate: fill sections in document order, so early sections stay whole and sections past the budget are dropped (counted in `truncation.omittedSections`). outline: split the budget evenly so every section keeps its heading, and an excerpt as far as the budget reaches — 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."New value: +"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: split the budget evenly so every section and subsection keeps its heading, and an excerpt as far as the budget reaches — a heading the budget left empty is marked as such in the rendered text. 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."
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "assets": {
        -        "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 the body 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.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "One figure or supplementary-material item, with its caption, pointer, and section",
        -          "properties": {
        -            "assetType": {
        -              "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit",
        -              "enum": [
        -                "figure",
        -                "supplementary-material"
        -              ],
        -              "type": "string"
        -            },
        -            "caption": {
        -              "description": "Caption text, with the label excluded",
        -              "type": "string"
        -            },
        -            "href": {
        -              "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.",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "JATS `id` attribute — the target body-text cross-references point at",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Display label as printed, e.g. `Fig. 1`",
        -              "type": "string"
        -            },
        -            "sectionTitle": {
        -              "description": "Title of the innermost section enclosing the asset, wherever that section sits — body, `<back>` matter, or an appendix all count. Absent for an asset inside no section at all, such as a `<floats-group>` deposit.",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "assetType"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "elocationId": {
        -            "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.",
        -            "type": "string"
        -          },
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "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.",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "tables": {
        -        "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.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "One table from the article, with its cells, caption, and owning section",
        -          "properties": {
        -            "caption": {
        -              "description": "Caption text, with the label excluded",
        -              "type": "string"
        -            },
        -            "footnotes": {
        -              "description": "`<table-wrap-foot>` text, flattened to one string",
        -              "type": "string"
        -            },
        -            "headerRowCount": {
        -              "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.",
        -              "type": "number"
        -            },
        -            "id": {
        -              "description": "JATS `id` attribute — the target body-text cross-references point at",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Table label as printed, e.g. `TABLE 1`",
        -              "type": "string"
        -            },
        -            "rows": {
        -              "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. Empty when `unextractableReason` is set.",
        -              "items": {
        -                "description": "One row, as cell text by grid column",
        -                "items": {
        -                  "type": "string"
        -                },
        -                "type": "array"
        -              },
        -              "type": "array"
        -            },
        -            "sectionTitle": {
        -              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        -              "type": "string"
        -            },
        -            "unextractableReason": {
        -              "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.",
        -              "enum": [
        -                "cals-tgroup",
        -                "graphic-only",
        -                "no-rows"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "headerRowCount",
        -            "rows"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "assets": {
        +        "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 the body 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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One figure or supplementary-material item, with its caption, pointer, and section",
        +          "properties": {
        +            "assetType": {
        +              "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit",
        +              "enum": [
        +                "figure",
        +                "supplementary-material"
        +              ],
        +              "type": "string"
        +            },
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "href": {
        +              "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.",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Display label as printed, e.g. `Fig. 1`",
        +              "type": "string"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the asset, wherever that section sits — body, `<back>` matter, or an appendix all count. Absent for an asset inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "assetType"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "elocationId": {
        +            "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.",
        +            "type": "string"
        +          },
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "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.",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "tables": {
        +        "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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One table from the article, with its cells, caption, and owning section",
        +          "properties": {
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "footnotes": {
        +              "description": "`<table-wrap-foot>` text, flattened to one string",
        +              "type": "string"
        +            },
        +            "headerRowCount": {
        +              "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.",
        +              "type": "number"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Table label as printed, e.g. `TABLE 1`",
        +              "type": "string"
        +            },
        +            "rows": {
        +              "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. Empty when `unextractableReason` is set.",
        +              "items": {
        +                "description": "One row, as cell text by grid column",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "type": "array"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            },
        +            "unextractableReason": {
        +              "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.",
        +              "enum": [
        +                "cals-tgroup",
        +                "graphic-only",
        +                "no-rows"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "headerRowCount",
        +            "rows"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "journalName": {
        +        "description": "Journal or repository name from Unpaywall's record for the DOI (e.g. `medRxiv` for a medRxiv preprint). Absent when Unpaywall has none.",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      },
        +      "year": {
        +        "description": "Publication year from Unpaywall's record for the DOI. Absent when Unpaywall has none.",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `unpaywall_unreachable`: Unpaywall was unreachable when resolving a DOI or fetching content. `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 such as an empty query, an empty response to a sort with an undocumented field or no asc/desc direction, or an empty response to a pagination cursor on every attempt. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found",
        -  "unpaywall_unreachable",
        -  "europepmc_unreachable",
        -  "europepmc_invalid_response",
        -  "europepmc_invalid_input"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found"
        +]
      • changedOutput schema / properties / truncation / properties / articles / items / properties / sections / description
        Previous value: -"Per-section accounting for `source: pmc` articles, in document order, including sections dropped for budget. Absent for `source: unpaywall`, whose body has no section structure."New value: +"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."
      • addedOutput schema / properties / truncation / properties / articles / items / properties / sections / items / properties / label
        Added value: +{
        +  "description": "Section label as printed (e.g. `2`), when the section carries one",
        +  "type": "string"
        +}
      • changedOutput schema / properties / truncation / properties / articles / items / properties / sections / items / properties / returnedCharacters / description
        Previous value: -"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."New value: +"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."
      • addedOutput schema / properties / truncation / properties / articles / items / properties / sections / items / properties / subsections
        Added value: +{
        +  "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.",
        +  "items": {
        +    "additionalProperties": false,
        +    "description": "Character accounting for one subsection of a shortened section",
        +    "properties": {
        +      "label": {
        +        "description": "Subsection label as printed (e.g. `2.1`), when the subsection carries one",
        +        "type": "string"
        +      },
        +      "originalCharacters": {
        +        "description": "Body characters this subsection carried before the budget pass",
        +        "type": "number"
        +      },
        +      "returnedCharacters": {
        +        "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.",
        +        "type": "number"
        +      },
        +      "title": {
        +        "description": "Subsection heading, when the subsection carries one",
        +        "type": "string"
        +      },
        +      "truncated": {
        +        "description": "True when the subsection returned fewer characters than it originally carried",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "originalCharacters",
        +      "returnedCharacters",
        +      "truncated"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / truncation / properties / omittedSections / description
        Previous value: -"Body sections dropped entirely because an article budget was exhausted before reaching them. Always 0 in `outline` mode, which keeps every heading."New value: +"Body sections and subsections dropped entirely because an article budget was exhausted before reaching them. A dropped section counts once, together with its subsections. Always 0 in `outline` mode, which keeps every heading."
  2. 5 tool updates
    • Changedpubmed_europepmc_search2 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"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 combined with `AND SRC:` must be unquoted — the quoted form matches nothing. Free text is matched broadly across abstract/title/keywords."New value: +"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."
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "hits",
        -      "cursorMark",
        -      "searchUrl",
        -      "query",
        -      "totalCount",
        -      "appliedSources"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "hits",
        +      "cursorMark",
        +      "searchUrl",
        +      "totalCount",
        +      "query",
        +      "appliedSources"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
    • Changedpubmed_lookup_citation6 fields changed
      • addedInput schema / properties / citations / anyOf
        Added value: +[
        +  {
        +    "description": "Up to 25 citations, each matched independently.",
        +    "items": {
        +      "description": "Citation to match against PubMed. Must include at least journal or year — ECitMatch primary-keys on journal+volume+page, so author-only or volume-only inputs guarantee no match.",
        +      "properties": {
        +        "authorName": {
        +          "description": "Author name, typically \"lastname initials\" (e.g., \"mann bj\"). Cannot contain a pipe (\"|\") or a line break.",
        +          "pattern": "^[^|\\r\\n]*$",
        +          "type": "string"
        +        },
        +        "firstPage": {
        +          "description": "First page number. Cannot contain a pipe (\"|\") or a line break.",
        +          "pattern": "^[^|\\r\\n]*$",
        +          "type": "string"
        +        },
        +        "journal": {
        +          "description": "Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\"). Cannot contain a pipe (\"|\") or a line break.",
        +          "pattern": "^[^|\\r\\n]*$",
        +          "type": "string"
        +        },
        +        "key": {
        +          "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.",
        +          "type": "string"
        +        },
        +        "volume": {
        +          "description": "Volume number. Cannot contain a pipe (\"|\") or a line break.",
        +          "pattern": "^[^|\\r\\n]*$",
        +          "type": "string"
        +        },
        +        "year": {
        +          "description": "Publication year (e.g., \"1991\"). Cannot contain a pipe (\"|\") or a line break.",
        +          "pattern": "^[^|\\r\\n]*$",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "maxItems": 25,
        +    "minItems": 1,
        +    "type": "array"
        +  },
        +  {
        +    "description": "Citation to match against PubMed. Must include at least journal or year — ECitMatch primary-keys on journal+volume+page, so author-only or volume-only inputs guarantee no match.",
        +    "properties": {
        +      "authorName": {
        +        "description": "Author name, typically \"lastname initials\" (e.g., \"mann bj\"). Cannot contain a pipe (\"|\") or a line break.",
        +        "pattern": "^[^|\\r\\n]*$",
        +        "type": "string"
        +      },
        +      "firstPage": {
        +        "description": "First page number. Cannot contain a pipe (\"|\") or a line break.",
        +        "pattern": "^[^|\\r\\n]*$",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "description": "Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\"). Cannot contain a pipe (\"|\") or a line break.",
        +        "pattern": "^[^|\\r\\n]*$",
        +        "type": "string"
        +      },
        +      "key": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "volume": {
        +        "description": "Volume number. Cannot contain a pipe (\"|\") or a line break.",
        +        "pattern": "^[^|\\r\\n]*$",
        +        "type": "string"
        +      },
        +      "year": {
        +        "description": "Publication year (e.g., \"1991\"). Cannot contain a pipe (\"|\") or a line break.",
        +        "pattern": "^[^|\\r\\n]*$",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / citations / description
        Previous value: -"Citations to look up. More fields = better match accuracy."New value: +"Citations to look up — an array of up to 25, or a single citation object. More fields = better match accuracy."
      • removedInput schema / properties / citations / items
        Removed value: -{
        -  "description": "Citation to match against PubMed. Must include at least journal or year — ECitMatch primary-keys on journal+volume+page, so author-only or volume-only inputs guarantee no match.",
        -  "properties": {
        -    "authorName": {
        -      "description": "Author name, typically \"lastname initials\" (e.g., \"mann bj\"). Cannot contain a pipe (\"|\") or a line break.",
        -      "pattern": "^[^|\\r\\n]*$",
        -      "type": "string"
        -    },
        -    "firstPage": {
        -      "description": "First page number. Cannot contain a pipe (\"|\") or a line break.",
        -      "pattern": "^[^|\\r\\n]*$",
        -      "type": "string"
        -    },
        -    "journal": {
        -      "description": "Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\"). Cannot contain a pipe (\"|\") or a line break.",
        -      "pattern": "^[^|\\r\\n]*$",
        -      "type": "string"
        -    },
        -    "key": {
        -      "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.",
        -      "type": "string"
        -    },
        -    "volume": {
        -      "description": "Volume number. Cannot contain a pipe (\"|\") or a line break.",
        -      "pattern": "^[^|\\r\\n]*$",
        -      "type": "string"
        -    },
        -    "year": {
        -      "description": "Publication year (e.g., \"1991\"). Cannot contain a pipe (\"|\") or a line break.",
        -      "pattern": "^[^|\\r\\n]*$",
        -      "type": "string"
        -    }
        -  },
        -  "type": "object"
        -}
      • removedInput schema / properties / citations / maxItems
        Removed value: -25
      • removedInput schema / properties / citations / minItems
        Removed value: -1
      • removedInput schema / properties / citations / type
        Removed value: -"array"
    • Changedpubmed_lookup_mesh1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and anything the tool strips before searching, are removed — so NCBI would receive a blank term. pubmed_search_articles strips markup, bracketed field tags, and parentheses, so a bare field tag such as `[pdat]` or empty parentheses `()` count as blank there. Other values are possible when a failure originates below the handler."
    • Changedpubmed_search_articles3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"PubMed search query (supports full NCBI syntax). Must carry a search term: a value that is blank once markup is stripped is rejected rather than sent to PubMed as an empty term."New value: +"PubMed search query (supports full NCBI syntax). Must carry a search term: a value that is blank once markup, bracketed field tags (`[pdat]`), and parentheses are removed is rejected rather than sent to PubMed as an empty term."
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "query",
        -      "offset",
        -      "pmids",
        -      "summaries",
        -      "searchUrl",
        -      "effectiveQuery",
        -      "totalCount",
        -      "appliedFilters"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "query",
        +      "offset",
        +      "pmids",
        +      "summaries",
        +      "searchUrl",
        +      "totalCount",
        +      "effectiveQuery",
        +      "appliedFilters"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and anything the tool strips before searching, are removed — so NCBI would receive a blank term. pubmed_search_articles strips markup, bracketed field tags, and parentheses, so a bare field tag such as `[pdat]` or empty parentheses `()` count as blank there. Other values are possible when a failure originates below the handler."
    • Changedpubmed_spell_check1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and anything the tool strips before searching, are removed — so NCBI would receive a blank term. pubmed_search_articles strips markup, bracketed field tags, and parentheses, so a bare field tag such as `[pdat]` or empty parentheses `()` count as blank there. Other values are possible when a failure originates below the handler."
  3. 11 tool updates
    • Changedpubmed_convert_ids1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
    • Changedpubmed_europepmc_fetch1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."New value: +"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 such as an empty query, an empty response to a sort with an undocumented field or no asc/desc direction, or an empty response to a pagination cursor on every attempt. `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."
    • Changedpubmed_europepmc_search2 fields changed
      • changedInput schema / properties / sort / description
        Previous value: -"Optional EPMC sort: `<field> asc|desc`. Documented sortable fields: `P_PDATE_D` (publication date), `CITED` (citation count), `AUTH_FIRST` (first author surname), `PUB_YEAR` (publication year). Examples: `P_PDATE_D desc` (newest first), `CITED desc` (most cited). Omit for relevance ranking. Fields outside the documented set are rejected by EPMC. Note: `P_PDATE_D` is ignored for preprint-only (`sources: [\"PPR\"]`) result sets — preprints have no populated publication date, so use `PUB_YEAR` to order preprints by date."New value: +"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). Examples: `P_PDATE_D desc` (newest first), `CITED desc` (most cited). Omit for relevance ranking. Field and direction match case-insensitively. A field outside the documented set may be honored, silently ignored, or rejected, and a sort using one — or a key without `asc`/`desc` — can fail with `europepmc_invalid_input` naming it, 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` to order preprints by date."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."New value: +"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 such as an empty query, an empty response to a sort with an undocumented field or no asc/desc direction, or an empty response to a pagination cursor on every attempt. `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler."
    • Changedpubmed_fetch_articles1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
    • Changedpubmed_fetch_fulltext1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `unpaywall_unreachable`: Unpaywall was unreachable when resolving a DOI or fetching content. `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `unpaywall_unreachable`: Unpaywall was unreachable when resolving a DOI or fetching content. `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 such as an empty query, an empty response to a sort with an undocumented field or no asc/desc direction, or an empty response to a pagination cursor on every attempt. Other values are possible when a failure originates below the handler."
    • Changedpubmed_find_related2 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `openalex_unreachable`: OpenAlex was unreachable after all retry attempts. `openalex_invalid_response`: OpenAlex returned a body that could not be parsed (invalid JSON). `all_providers_failed`: Every provider eligible for the requested relationship failed; none answered. Other values are possible when a failure originates below the handler."New value: +"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."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found",
        -  "europepmc_unreachable",
        -  "europepmc_invalid_response",
        -  "europepmc_invalid_input",
        -  "openalex_unreachable",
        -  "openalex_invalid_response",
        -  "all_providers_failed"
        -]New value: +[
        +  "all_providers_failed"
        +]
    • Changedpubmed_format_citations1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
    • Changedpubmed_lookup_citation1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
    • Changedpubmed_lookup_mesh1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
    • Changedpubmed_search_articles1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
    • Changedpubmed_spell_check1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."New value: +"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 is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
  4. 7 tool updates
    • Changedpubmed_convert_ids3 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Article identifiers to convert. All IDs must be the same type. DOIs: \"10.1093/nar/gks1195\", PMIDs: \"23193287\", PMCIDs: \"PMC3531190\" (the \"PMC\" prefix is optional — bare digits like \"3531190\" are also accepted)."New value: +"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."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found",
        +  "malformed_id"
        +]
    • Changedpubmed_fetch_articles9 fields changed
      • changedOutput schema / properties / articles / items / properties / authors / description
        Previous value: -"Author list"New value: +"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."
      • addedOutput schema / properties / articles / items / properties / book
        Added value: +{
        +  "additionalProperties": false,
        +  "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`.",
        +  "properties": {
        +    "accession": {
        +      "description": "NCBI Bookshelf accession from `ArticleIdList` (`bookaccession`), e.g. \"NBK1247\". The record is readable at `https://www.ncbi.nlm.nih.gov/books/<accession>/`.",
        +      "type": "string"
        +    },
        +    "beginningDate": {
        +      "description": "First year of a continuously-updated book, from `Book/BeginningDate` (GeneReviews runs from 1993). Absent on a book published once.",
        +      "type": "string"
        +    },
        +    "collectionTitle": {
        +      "description": "Series the book belongs to, from `Book/CollectionTitle` (e.g. \"ADA Clinical Compendia Series\"). Absent for a book outside a series.",
        +      "type": "string"
        +    },
        +    "doi": {
        +      "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.",
        +      "type": "string"
        +    },
        +    "edition": {
        +      "description": "Edition statement from `Book/Edition`. Rare on Bookshelf titles — absent unless NCBI supplies one.",
        +      "type": "string"
        +    },
        +    "editors": {
        +      "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.",
        +      "items": {
        +        "additionalProperties": false,
        +        "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.",
        +        "properties": {
        +          "collectiveName": {
        +            "description": "Group or committee credited as editor, when the entry names an organization rather than a person. Mutually exclusive with the name-part fields.",
        +            "type": "string"
        +          },
        +          "firstName": {
        +            "description": "Editor given name as NCBI supplies it (`ForeName`, often \"Margaret P\"). Absent when NCBI carries initials only, or on a group editor.",
        +            "type": "string"
        +          },
        +          "initials": {
        +            "description": "Editor initials with no separators (e.g. \"MP\"). Absent when NCBI supplies none, or on a group editor.",
        +            "type": "string"
        +          },
        +          "lastName": {
        +            "description": "Editor surname, from the book's `Book/AuthorList Type=\"editors\"` entry. Absent on a group editor, which carries `collectiveName` instead.",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "endingDate": {
        +      "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.",
        +      "type": "string"
        +    },
        +    "isbns": {
        +      "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.",
        +      "items": {
        +        "description": "One ISBN, verbatim as NCBI reports it — leading zeros intact",
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "medium": {
        +      "description": "Medium the book is published in, from `Book/Medium` — \"Internet\" wherever NCBI supplies it. Absent when NCBI supplies none; it is never defaulted.",
        +      "type": "string"
        +    },
        +    "pubDate": {
        +      "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.",
        +      "type": "string"
        +    },
        +    "publisher": {
        +      "description": "Publisher of the book, from `Book/Publisher/PublisherName`.",
        +      "type": "string"
        +    },
        +    "publisherLocation": {
        +      "description": "Place of publication, from `Book/Publisher/PublisherLocation` (e.g. \"Seattle (WA)\"). Absent when NCBI supplies no place.",
        +      "type": "string"
        +    },
        +    "title": {
        +      "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`.",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / articles / items / properties / journalInfo / description
        Previous value: -"Journal information"New value: +"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)"
      • addedOutput schema / properties / articles / items / properties / journalInfo / properties / elocationId
        Added value: +{
        +  "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.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / articles / items / properties / journalInfo / properties / elocationIdType
        Added value: +{
        +  "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.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / articles / items / properties / recordType
        Added value: +{
        +  "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.",
        +  "enum": [
        +    "journal-article",
        +    "book-chapter",
        +    "book"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / articles / items / properties / title / description
        Previous value: -"Article title"New value: +"Article title — the chapter title on a `book-chapter`, and the book title on a `book` record, where it repeats `book.title`."
      • addedOutput schema / properties / articles / items / required
        Added value: +[
        +  "recordType"
        +]
      • changedOutput schema / properties / unavailablePmids / description
        Previous value: -"PMIDs that returned no article data. Reported in full regardless of where a `maxResponseCharacters` cutoff lands — these are misses, not deferrals, and re-requesting them returns nothing."New value: +"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."
    • Changedpubmed_fetch_fulltext4 fields changed
      • changedInput schema / properties / dois / description
        Previous value: -"DOIs to resolve (e.g. [\"10.21203/rs.3.rs-9010375/v1\"]). Provide exactly one of `pmcids`, `pmids`, or `dois`. 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."New value: +"DOIs to resolve (e.g. [\"10.21203/rs.3.rs-9010375/v1\"]), one per element. Provide exactly one of `pmcids`, `pmids`, or `dois`. 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."
      • removedInput schema / properties / dois / items / minLength
        Removed value: -3
      • addedInput schema / properties / dois / items / pattern
        Added value: +"^10\\.[^\\s,]+\\/[^\\s,]+$"
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "assets": {
        -        "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 the body 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.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "One figure or supplementary-material item, with its caption, pointer, and section",
        -          "properties": {
        -            "assetType": {
        -              "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit",
        -              "enum": [
        -                "figure",
        -                "supplementary-material"
        -              ],
        -              "type": "string"
        -            },
        -            "caption": {
        -              "description": "Caption text, with the label excluded",
        -              "type": "string"
        -            },
        -            "href": {
        -              "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.",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "JATS `id` attribute — the target body-text cross-references point at",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Display label as printed, e.g. `Fig. 1`",
        -              "type": "string"
        -            },
        -            "sectionTitle": {
        -              "description": "Title of the innermost section enclosing the asset, wherever that section sits — body, `<back>` matter, or an appendix all count. Absent for an asset inside no section at all, such as a `<floats-group>` deposit.",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "assetType"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "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.",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "tables": {
        -        "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.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "One table from the article, with its cells, caption, and owning section",
        -          "properties": {
        -            "caption": {
        -              "description": "Caption text, with the label excluded",
        -              "type": "string"
        -            },
        -            "footnotes": {
        -              "description": "`<table-wrap-foot>` text, flattened to one string",
        -              "type": "string"
        -            },
        -            "headerRowCount": {
        -              "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.",
        -              "type": "number"
        -            },
        -            "id": {
        -              "description": "JATS `id` attribute — the target body-text cross-references point at",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Table label as printed, e.g. `TABLE 1`",
        -              "type": "string"
        -            },
        -            "rows": {
        -              "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. Empty when `unextractableReason` is set.",
        -              "items": {
        -                "description": "One row, as cell text by grid column",
        -                "items": {
        -                  "type": "string"
        -                },
        -                "type": "array"
        -              },
        -              "type": "array"
        -            },
        -            "sectionTitle": {
        -              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        -              "type": "string"
        -            },
        -            "unextractableReason": {
        -              "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.",
        -              "enum": [
        -                "cals-tgroup",
        -                "graphic-only",
        -                "no-rows"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "headerRowCount",
        -            "rows"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "assets": {
        +        "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 the body 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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One figure or supplementary-material item, with its caption, pointer, and section",
        +          "properties": {
        +            "assetType": {
        +              "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit",
        +              "enum": [
        +                "figure",
        +                "supplementary-material"
        +              ],
        +              "type": "string"
        +            },
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "href": {
        +              "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.",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Display label as printed, e.g. `Fig. 1`",
        +              "type": "string"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the asset, wherever that section sits — body, `<back>` matter, or an appendix all count. Absent for an asset inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "assetType"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "elocationId": {
        +            "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.",
        +            "type": "string"
        +          },
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "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.",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "tables": {
        +        "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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One table from the article, with its cells, caption, and owning section",
        +          "properties": {
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "footnotes": {
        +              "description": "`<table-wrap-foot>` text, flattened to one string",
        +              "type": "string"
        +            },
        +            "headerRowCount": {
        +              "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.",
        +              "type": "number"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Table label as printed, e.g. `TABLE 1`",
        +              "type": "string"
        +            },
        +            "rows": {
        +              "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. Empty when `unextractableReason` is set.",
        +              "items": {
        +                "description": "One row, as cell text by grid column",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "type": "array"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            },
        +            "unextractableReason": {
        +              "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.",
        +              "enum": [
        +                "cals-tgroup",
        +                "graphic-only",
        +                "no-rows"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "headerRowCount",
        +            "rows"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedpubmed_find_related6 fields changed
      • changedOutput schema / properties / articles / items / properties / authors / description
        Previous value: -"Author string"New value: +"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`."
      • addedOutput schema / properties / articles / items / properties / bookTitle
        Added value: +{
        +  "description": "Title of the book an NCBI Bookshelf record belongs to. Present instead of `source` on a book record; absent on a journal article.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / articles / items / properties / docType
        Added value: +{
        +  "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.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / articles / items / properties / editors
        Added value: +{
        +  "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.",
        +  "items": {
        +    "description": "One editor, \"Surname Initials\" as ESummary renders it",
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / articles / items / properties / publisherName
        Added value: +{
        +  "description": "Publisher of the book an NCBI Bookshelf record belongs to. Present only on a book record; absent on a journal article.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / articles / items / properties / source / description
        Previous value: -"Journal source"New value: +"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."
    • Changedpubmed_format_citations1 field changed
      • changedOutput schema / properties / unavailablePmids / description
        Previous value: -"Requested PMIDs that did not return article metadata"New value: +"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."
    • Changedpubmed_lookup_citation11 fields changed
      • changedInput schema / properties / citations / items / properties / authorName / description
        Previous value: -"Author name, typically \"lastname initials\" (e.g., \"mann bj\")"New value: +"Author name, typically \"lastname initials\" (e.g., \"mann bj\"). Cannot contain a pipe (\"|\") or a line break."
      • addedInput schema / properties / citations / items / properties / authorName / pattern
        Added value: +"^[^|\\r\\n]*$"
      • changedInput schema / properties / citations / items / properties / firstPage / description
        Previous value: -"First page number"New value: +"First page number. Cannot contain a pipe (\"|\") or a line break."
      • addedInput schema / properties / citations / items / properties / firstPage / pattern
        Added value: +"^[^|\\r\\n]*$"
      • changedInput schema / properties / citations / items / properties / journal / description
        Previous value: -"Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\")"New value: +"Journal title or ISO abbreviation (e.g., \"proc natl acad sci u s a\"). Cannot contain a pipe (\"|\") or a line break."
      • addedInput schema / properties / citations / items / properties / journal / pattern
        Added value: +"^[^|\\r\\n]*$"
      • changedInput schema / properties / citations / items / properties / key / description
        Previous value: -"Arbitrary label to track this citation in results. Auto-assigned if omitted."New value: +"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."
      • changedInput schema / properties / citations / items / properties / volume / description
        Previous value: -"Volume number"New value: +"Volume number. Cannot contain a pipe (\"|\") or a line break."
      • addedInput schema / properties / citations / items / properties / volume / pattern
        Added value: +"^[^|\\r\\n]*$"
      • changedInput schema / properties / citations / items / properties / year / description
        Previous value: -"Publication year (e.g., \"1991\")"New value: +"Publication year (e.g., \"1991\"). Cannot contain a pipe (\"|\") or a line break."
      • addedInput schema / properties / citations / items / properties / year / pattern
        Added value: +"^[^|\\r\\n]*$"
    • Changedpubmed_search_articles6 fields changed
      • changedOutput schema / properties / summaries / items / properties / authors / description
        Previous value: -"Formatted author string"New value: +"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`."
      • addedOutput schema / properties / summaries / items / properties / bookTitle
        Added value: +{
        +  "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.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / summaries / items / properties / docType
        Added value: +{
        +  "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.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / summaries / items / properties / editors
        Added value: +{
        +  "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.",
        +  "items": {
        +    "description": "One editor, \"Surname Initials\" as ESummary renders it",
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / summaries / items / properties / publisherName
        Added value: +{
        +  "description": "Publisher of the book an NCBI Bookshelf record belongs to. Present only on a book record; absent on a journal article.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / summaries / items / properties / source / description
        Previous value: -"Journal source"New value: +"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."
  5. 5 tool updates
    • Changedpubmed_fetch_fulltext11 fields changed
      • addedInput schema / properties / includeAssets
        Added value: +{
        +  "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.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / maxCharacters / description
        Previous value: -"Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text plus table label, caption, cell and footnote text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. 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. Sections are served first and tables spend what is left, in document order — admission stops at the first table that does not fit, and every table from there on is dropped whole rather than cut mid-row, counted in `truncation.omittedTables` and named in `truncation.articles[].omittedTableNames`. Applied after `sections`, `maxSections`, `includeReferences`, and `includeTables`, 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."New value: +"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, and references are never counted or shortened. 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. Sections are served first, then tables, then assets, each spending what is left, in document order — 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`. 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."
      • changedInput schema / properties / sections / description
        Previous value: -"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\". 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 narrow with the filter: one whose section did not survive, or that names no section, is dropped. Applies to `source=pmc` results only."New value: +"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\". 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. Applies to `source=pmc` results only."
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "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.",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "tables": {
        -        "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.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "One table from the article, with its cells, caption, and owning section",
        -          "properties": {
        -            "caption": {
        -              "description": "Caption text, with the label excluded",
        -              "type": "string"
        -            },
        -            "footnotes": {
        -              "description": "`<table-wrap-foot>` text, flattened to one string",
        -              "type": "string"
        -            },
        -            "headerRowCount": {
        -              "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.",
        -              "type": "number"
        -            },
        -            "id": {
        -              "description": "JATS `id` attribute — the target body-text cross-references point at",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Table label as printed, e.g. `TABLE 1`",
        -              "type": "string"
        -            },
        -            "rows": {
        -              "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. Empty when `unextractableReason` is set.",
        -              "items": {
        -                "description": "One row, as cell text by grid column",
        -                "items": {
        -                  "type": "string"
        -                },
        -                "type": "array"
        -              },
        -              "type": "array"
        -            },
        -            "sectionTitle": {
        -              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        -              "type": "string"
        -            },
        -            "unextractableReason": {
        -              "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.",
        -              "enum": [
        -                "cals-tgroup",
        -                "graphic-only",
        -                "no-rows"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "headerRowCount",
        -            "rows"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "assets": {
        +        "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 the body 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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One figure or supplementary-material item, with its caption, pointer, and section",
        +          "properties": {
        +            "assetType": {
        +              "description": "Which captioned element this came from — `figure` for a `<fig>`, `supplementary-material` for a `<supplementary-material>` deposit",
        +              "enum": [
        +                "figure",
        +                "supplementary-material"
        +              ],
        +              "type": "string"
        +            },
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "href": {
        +              "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.",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Display label as printed, e.g. `Fig. 1`",
        +              "type": "string"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the asset, wherever that section sits — body, `<back>` matter, or an appendix all count. Absent for an asset inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "assetType"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "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.",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "tables": {
        +        "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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One table from the article, with its cells, caption, and owning section",
        +          "properties": {
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "footnotes": {
        +              "description": "`<table-wrap-foot>` text, flattened to one string",
        +              "type": "string"
        +            },
        +            "headerRowCount": {
        +              "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.",
        +              "type": "number"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Table label as printed, e.g. `TABLE 1`",
        +              "type": "string"
        +            },
        +            "rows": {
        +              "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. Empty when `unextractableReason` is set.",
        +              "items": {
        +                "description": "One row, as cell text by grid column",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "type": "array"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            },
        +            "unextractableReason": {
        +              "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.",
        +              "enum": [
        +                "cals-tgroup",
        +                "graphic-only",
        +                "no-rows"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "headerRowCount",
        +            "rows"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedOutput schema / properties / truncation / properties / articles / items / properties / omittedAssetNames
        Added value: +{
        +  "description": "The dropped assets by name, in document order — each asset's label, 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.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / truncation / properties / articles / items / properties / omittedAssets
        Added value: +{
        +  "description": "Figures and supplementary items this article dropped whole because the budget left no room once 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.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / truncation / properties / omittedAssets
        Added value: +{
        +  "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.",
        +  "type": "number"
        +}
      • changedOutput schema / properties / unavailable / items / properties / reason / description
        Previous value: -"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: no DOI to query Unpaywall. 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."New value: +"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."
      • changedOutput schema / properties / unavailable / items / properties / reason / enum
        Previous value: -[
        -  "not-found",
        -  "no-pmc-fallback-disabled",
        -  "no-epmc-fulltext",
        -  "no-body",
        -  "no-doi",
        -  "no-oa",
        -  "fetch-failed",
        -  "parse-failed",
        -  "service-error"
        -]New value: +[
        +  "not-found",
        +  "no-pmc-fallback-disabled",
        +  "no-epmc-fulltext",
        +  "no-body",
        +  "no-doi",
        +  "doi-lookup-failed",
        +  "no-oa",
        +  "fetch-failed",
        +  "parse-failed",
        +  "service-error"
        +]
      • changedOutput schema / properties / unavailable / items / properties / triedTiers / items / properties / outcome / description
        Previous value: -"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: no DOI to query Unpaywall. 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."New value: +"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."
      • changedOutput schema / properties / unavailable / items / properties / triedTiers / items / properties / outcome / enum
        Previous value: -[
        -  "not-attempted",
        -  "miss",
        -  "no-fulltext",
        -  "no-body",
        -  "no-doi",
        -  "no-oa",
        -  "fetch-failed",
        -  "parse-failed",
        -  "service-error"
        -]New value: +[
        +  "not-attempted",
        +  "miss",
        +  "no-fulltext",
        +  "no-body",
        +  "no-doi",
        +  "doi-lookup-failed",
        +  "no-oa",
        +  "fetch-failed",
        +  "parse-failed",
        +  "service-error"
        +]
    • Changedpubmed_find_related3 fields changed
      • addedOutput schema / properties / coverageFailures
        Added value: +{
        +  "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.",
        +  "items": {
        +    "additionalProperties": false,
        +    "description": "One coverage provider that could not be checked",
        +    "properties": {
        +      "provider": {
        +        "description": "Reference-coverage provider that failed",
        +        "enum": [
        +          "europepmc",
        +          "openalex"
        +        ],
        +        "type": "string"
        +      },
        +      "reason": {
        +        "description": "Declared failure reason, e.g. europepmc_unreachable or provider_disabled",
        +        "type": "string"
        +      },
        +      "retryable": {
        +        "description": "Whether a retry can reach this provider",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "provider",
        +      "reason",
        +      "retryable"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when results are empty, a fallback provider answered, offset overshot, or Europe PMC rows were excluded for carrying no PubMed PMID. Absent on a clean NCBI result page."New value: +"Guidance when results are empty, a fallback provider answered, offset overshot, a fallback provider could not be reached, or upstream rows were excluded for carrying no PubMed PMID. Absent on a clean NCBI result page."
      • changedOutput schema / properties / totalCount / description
        Previous value: -"Total related articles found before windowing. A Europe PMC 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."New value: +"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."
    • Changedpubmed_lookup_mesh3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"MeSH descriptor name or free-text term to look up"New value: +"MeSH descriptor name or free-text term to look up. Must carry a term: a blank or whitespace-only value is rejected rather than searched."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found",
        +  "blank_query"
        +]
    • Changedpubmed_search_articles3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"PubMed search query (supports full NCBI syntax)"New value: +"PubMed search query (supports full NCBI syntax). Must carry a search term: a value that is blank once markup is stripped is rejected rather than sent to PubMed as an empty term."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found",
        +  "blank_query"
        +]
    • Changedpubmed_spell_check3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"PubMed search query to spell-check"New value: +"PubMed search query to spell-check. Must carry a term: a blank or whitespace-only value is rejected rather than sent to ESpell."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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."New value: +"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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 holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found",
        +  "blank_query"
        +]
  6. 1 tool update
    • Changedpubmed_fetch_fulltext8 fields changed
      • addedInput schema / properties / includeTables
        Added value: +{
        +  "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.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / maxCharacters / description
        Previous value: -"Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. Applied after `sections`, `maxSections`, and `includeReferences`, 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."New value: +"Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text plus table label, caption, cell and footnote text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. 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. Sections are served first and tables spend what is left, in document order — admission stops at the first table that does not fit, and every table from there on is dropped whole rather than cut mid-row, counted in `truncation.omittedTables` and named in `truncation.articles[].omittedTableNames`. Applied after `sections`, `maxSections`, `includeReferences`, and `includeTables`, 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."
      • changedInput schema / properties / sections / description
        Previous value: -"Filter to specific sections by title, case-insensitive (e.g. [\"Introduction\", \"Methods\", \"Results\", \"Discussion\"]). Applies to `source=pmc` results only."New value: +"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\". 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 narrow with the filter: one whose section did not survive, or that names no section, is dropped. Applies to `source=pmc` results only."
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "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.",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "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.",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "tables": {
        +        "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.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "One table from the article, with its cells, caption, and owning section",
        +          "properties": {
        +            "caption": {
        +              "description": "Caption text, with the label excluded",
        +              "type": "string"
        +            },
        +            "footnotes": {
        +              "description": "`<table-wrap-foot>` text, flattened to one string",
        +              "type": "string"
        +            },
        +            "headerRowCount": {
        +              "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.",
        +              "type": "number"
        +            },
        +            "id": {
        +              "description": "JATS `id` attribute — the target body-text cross-references point at",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Table label as printed, e.g. `TABLE 1`",
        +              "type": "string"
        +            },
        +            "rows": {
        +              "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. Empty when `unextractableReason` is set.",
        +              "items": {
        +                "description": "One row, as cell text by grid column",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "type": "array"
        +            },
        +            "sectionTitle": {
        +              "description": "Title of the innermost section enclosing the table, wherever that section sits — body, `<back>` matter, or an appendix all count, and in back matter the section name is the only positional cue there is. Absent only for a table inside no section at all, such as a `<floats-group>` deposit.",
        +              "type": "string"
        +            },
        +            "unextractableReason": {
        +              "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.",
        +              "enum": [
        +                "cals-tgroup",
        +                "graphic-only",
        +                "no-rows"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "headerRowCount",
        +            "rows"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / properties / notice / description
        Previous value: -"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 budgeted response names the characters returned versus carried and points at `truncation`. A response-wide budget that deferred articles names the ids to re-request. Absent when none of those applies."New value: +"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 response-wide budget that deferred articles names the ids to re-request. Absent when none of those applies."
      • addedOutput schema / properties / truncation / properties / articles / items / properties / omittedTableNames
        Added value: +{
        +  "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.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / truncation / properties / articles / items / properties / omittedTables
        Added value: +{
        +  "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.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / truncation / properties / omittedTables
        Added value: +{
        +  "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.",
        +  "type": "number"
        +}
  7. 1 tool update
    • Changedpubmed_fetch_fulltext1 field changed
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "description": "Subsection body text",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "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.",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
  8. 2 tool updates
    • Changedpubmed_fetch_articles6 fields changed
      • addedInput schema / properties / maxResponseCharacters
        Added value: +{
        +  "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.",
        +  "maximum": 1000000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / deferred
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Continuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.",
        +  "properties": {
        +    "deferredCount": {
        +      "description": "Articles that resolved but were withheld to stay under the ceiling",
        +      "type": "number"
        +    },
        +    "ids": {
        +      "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`.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "maxResponseCharacters": {
        +      "description": "The `maxResponseCharacters` ceiling this response was budgeted against",
        +      "type": "number"
        +    },
        +    "nextDeferredCharacters": {
        +      "description": "Serialized size of the next deferred article — the first entry in `ids`, where the response stopped. Raise `maxResponseCharacters` to at least this to make progress; a smaller article further down `ids` cannot be reached until this one fits.",
        +      "type": "number"
        +    },
        +    "returnedCharacters": {
        +      "description": "Serialized characters the returned article records account for",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "maxResponseCharacters",
        +    "returnedCharacters",
        +    "deferredCount",
        +    "ids",
        +    "nextDeferredCharacters"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Optional guidance when no articles were returned — points to discovery tools. Absent on successful fetches."New value: +"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."
      • changedOutput schema / properties / totalReturned / description
        Previous value: -"Number of articles returned"New value: +"Number of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest."
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "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`.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / unavailablePmids / description
        Previous value: -"PMIDs that returned no article data"New value: +"PMIDs that returned no article data. Reported in full regardless of where a `maxResponseCharacters` cutoff lands — these are misses, not deferrals, and re-requesting them returns nothing."
    • Changedpubmed_fetch_fulltext9 fields changed
      • changedInput schema / properties / maxCharacters / description
        Previous value: -"Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. Applied after `sections`, `maxSections`, and `includeReferences`, so semantic filtering is unaffected. The response-wide ceiling is this value times the number of articles returned. Omit for the full body."New value: +"Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. Applied after `sections`, `maxSections`, and `includeReferences`, 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."
      • addedInput schema / properties / maxResponseCharacters
        Added value: +{
        +  "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, body 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 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, `unavailable`, `truncation`, `deferred` itself — are not counted. Omit to return every resolved article.",
        +  "maximum": 1000000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / deferred
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Continuation state for articles the whole-response budget withheld. Present only when `maxResponseCharacters` deferred at least one article.",
        +  "properties": {
        +    "deferredCount": {
        +      "description": "Articles the chain resolved but withheld to stay under the ceiling",
        +      "type": "number"
        +    },
        +    "idType": {
        +      "description": "Which input branch the deferred ids belong to — re-submit them as `pmids`, `pmcids`, or `dois` respectively. Matches the `idType` on `unavailable` entries.",
        +      "enum": [
        +        "pmid",
        +        "pmcid",
        +        "doi"
        +      ],
        +      "type": "string"
        +    },
        +    "ids": {
        +      "description": "Identifiers of the deferred articles, in response order, keyed as they were requested (PMC IDs in `PMC<digits>` form). Re-call `pubmed_fetch_fulltext` with these under the `idType` branch and the same other inputs. Never contains an id from `unavailable`.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "maxResponseCharacters": {
        +      "description": "The `maxResponseCharacters` ceiling this response was budgeted against",
        +      "type": "number"
        +    },
        +    "nextDeferredCharacters": {
        +      "description": "Serialized size of the next deferred article — the first entry in `ids`, where the response stopped. Raise `maxResponseCharacters` to at least this to make progress; a smaller article further down `ids` cannot be reached until this one fits.",
        +      "type": "number"
        +    },
        +    "returnedCharacters": {
        +      "description": "Serialized characters the returned article records account for",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "maxResponseCharacters",
        +    "returnedCharacters",
        +    "deferredCount",
        +    "idType",
        +    "ids",
        +    "nextDeferredCharacters"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"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 budgeted response names the characters returned versus carried and points at `truncation`. Absent when none of those applies."New value: +"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 budgeted response names the characters returned versus carried and points at `truncation`. A response-wide budget that deferred articles names the ids to re-request. Absent when none of those applies."
      • changedOutput schema / properties / totalReturned / description
        Previous value: -"Number of articles returned"New value: +"Number of articles in this response. Under a `maxResponseCharacters` budget this counts the kept articles only; `deferred.deferredCount` covers the rest."
      • changedOutput schema / properties / truncated / description
        Previous value: -"True when a character budget shortened at least one returned body. Absent when every returned article carries its full post-filter body. The per-article accounting is in `truncation`."New value: +"True when a character budget shortened at least one returned body, or withheld a whole article. Absent when every resolved article is present with its full post-filter body. The per-article body accounting is in `truncation`; the withheld ids are in `deferred`."
      • changedOutput schema / properties / unavailable / description
        Previous value: -"Per-identifier explanations for any requested PMIDs, PMCIDs, or DOIs with no returnable full text. `idType` discriminates which branch the id came from."New value: +"Per-identifier explanations for any requested PMIDs, PMCIDs, or DOIs with no returnable full text. `idType` discriminates which branch the id came from. Distinct from `deferred`: nothing here is retrievable by re-calling, and an id never appears in both."
      • changedOutput schema / properties / unavailable / items / properties / reason / description
        Previous value: -"Why no full text was returned. 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: no DOI to query Unpaywall. 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)."New value: +"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: no DOI to query Unpaywall. 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."
      • addedOutput schema / properties / unavailable / items / properties / unqueriedTiers
        Added value: +{
        +  "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.",
        +  "items": {
        +    "description": "A fallback tier this deployment has not configured",
        +    "enum": [
        +      "europepmc",
        +      "unpaywall"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  9. 3 tool updates
    • Changedpubmed_europepmc_fetch3 fields changed
      • changedOutput schema / properties / records / items / properties / authors / description
        Previous value: -"Formatted author string"New value: +"Formatted author string as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
      • changedOutput schema / properties / records / items / properties / journal / description
        Previous value: -"Journal title"New value: +"Journal title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
      • changedOutput schema / properties / records / items / properties / title / description
        Previous value: -"Record title"New value: +"Record title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
    • Changedpubmed_europepmc_search3 fields changed
      • changedOutput schema / properties / hits / items / properties / authors / description
        Previous value: -"Formatted author string"New value: +"Formatted author string as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
      • changedOutput schema / properties / hits / items / properties / journal / description
        Previous value: -"Journal title"New value: +"Journal title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
      • changedOutput schema / properties / hits / items / properties / title / description
        Previous value: -"Article title"New value: +"Article title as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded."
    • Changedpubmed_find_related4 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `openalex_unreachable`: OpenAlex was unreachable after all retry attempts. `openalex_invalid_response`: OpenAlex returned a body that could not be parsed (invalid JSON). Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `openalex_unreachable`: OpenAlex was unreachable after all retry attempts. `openalex_invalid_response`: OpenAlex returned a body that could not be parsed (invalid JSON). `all_providers_failed`: Every provider eligible for the requested relationship failed; none answered. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "queue_full",
        -  "ncbi_unreachable",
        -  "ncbi_deadline_exceeded",
        -  "ncbi_invalid_response",
        -  "ncbi_resource_not_found",
        -  "europepmc_unreachable",
        -  "europepmc_invalid_response",
        -  "europepmc_invalid_input",
        -  "openalex_unreachable",
        -  "openalex_invalid_response"
        -]New value: +[
        +  "queue_full",
        +  "ncbi_unreachable",
        +  "ncbi_deadline_exceeded",
        +  "ncbi_invalid_response",
        +  "ncbi_resource_not_found",
        +  "europepmc_unreachable",
        +  "europepmc_invalid_response",
        +  "europepmc_invalid_input",
        +  "openalex_unreachable",
        +  "openalex_invalid_response",
        +  "all_providers_failed"
        +]
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when results are empty, a fallback provider answered, or offset overshot. Absent on a clean NCBI result page."New value: +"Guidance when results are empty, a fallback provider answered, offset overshot, or Europe PMC rows were excluded for carrying no PubMed PMID. Absent on a clean NCBI result page."
      • changedOutput schema / properties / totalCount / description
        Previous value: -"Total related articles found before windowing"New value: +"Total related articles found before windowing. A Europe PMC 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."
  10. 11 tool updates
    • Changedpubmed_convert_ids6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "records",
        +      "totalConverted",
        +      "totalSubmitted"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "records",
        -  "totalConverted",
        -  "totalSubmitted"
        -]
    • Changedpubmed_europepmc_fetch6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "records"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "europepmc_unreachable",
        +            "europepmc_invalid_response",
        +            "europepmc_invalid_input",
        +            "europepmc_disabled"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "records"
        -]
    • Changedpubmed_europepmc_search6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "hits",
        +      "cursorMark",
        +      "searchUrl",
        +      "query",
        +      "totalCount",
        +      "appliedSources"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `europepmc_disabled`: Europe PMC service is disabled via EUROPEPMC_ENABLED=false. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "europepmc_unreachable",
        +            "europepmc_invalid_response",
        +            "europepmc_invalid_input",
        +            "europepmc_disabled"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "hits",
        -  "cursorMark",
        -  "searchUrl",
        -  "query",
        -  "totalCount",
        -  "appliedSources"
        -]
    • Changedpubmed_fetch_articles6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "articles",
        +      "totalReturned"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found",
        +            "invalid_efetch_response"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "articles",
        -  "totalReturned"
        -]
    • Changedpubmed_fetch_fulltext7 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "articles",
        +      "totalReturned"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `unpaywall_unreachable`: Unpaywall was unreachable when resolving a DOI or fetching content. `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found",
        +            "unpaywall_unreachable",
        +            "europepmc_unreachable",
        +            "europepmc_invalid_response",
        +            "europepmc_invalid_input"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "description": "True when a character budget shortened at least one returned body. Absent when every returned article carries its full post-filter body. The per-article accounting is in `truncation`.",
        +  "type": "boolean"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "articles",
        -  "totalReturned"
        -]
    • Changedpubmed_find_related6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "sourcePmid",
        +      "relationship",
        +      "offset",
        +      "articles",
        +      "totalCount",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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). `europepmc_unreachable`: Europe PMC was unreachable after all retry attempts. `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 (empty query, unknown sort field, malformed parameter). `openalex_unreachable`: OpenAlex was unreachable after all retry attempts. `openalex_invalid_response`: OpenAlex returned a body that could not be parsed (invalid JSON). Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found",
        +            "europepmc_unreachable",
        +            "europepmc_invalid_response",
        +            "europepmc_invalid_input",
        +            "openalex_unreachable",
        +            "openalex_invalid_response"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "sourcePmid",
        -  "relationship",
        -  "offset",
        -  "articles",
        -  "totalCount",
        -  "source"
        -]
    • Changedpubmed_format_citations6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "citations",
        +      "totalSubmitted",
        +      "totalFormatted"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "citations",
        -  "totalSubmitted",
        -  "totalFormatted"
        -]
    • Changedpubmed_lookup_citation6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "totalMatched",
        +      "totalSubmitted",
        +      "totalWarnings"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "totalMatched",
        -  "totalSubmitted",
        -  "totalWarnings"
        -]
    • Changedpubmed_lookup_mesh6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "query",
        +      "offset",
        +      "results",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "query",
        -  "offset",
        -  "results",
        -  "totalCount"
        -]
    • Changedpubmed_search_articles6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "query",
        +      "offset",
        +      "pmids",
        +      "summaries",
        +      "searchUrl",
        +      "effectiveQuery",
        +      "totalCount",
        +      "appliedFilters"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "query",
        -  "offset",
        -  "pmids",
        -  "summaries",
        -  "searchUrl",
        -  "effectiveQuery",
        -  "totalCount",
        -  "appliedFilters"
        -]
    • Changedpubmed_spell_check6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "original",
        +      "corrected",
        +      "hasSuggestion"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `queue_full`: Local NCBI request queue is at capacity. `ncbi_unreachable`: NCBI E-utilities is unreachable after all retry attempts. `ncbi_deadline_exceeded`: Total request deadline expired before NCBI returned a response. `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.",
        +          "examples": [
        +            "queue_full",
        +            "ncbi_unreachable",
        +            "ncbi_deadline_exceeded",
        +            "ncbi_invalid_response",
        +            "ncbi_resource_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "original",
        -  "corrected",
        -  "hasSuggestion"
        -]
  11. 6 tool updates
    • Changedpubmed_convert_ids1 field changed
      • changedOutput schema / properties / records / items / properties / doi / description
        Previous value: -"Digital Object Identifier; absent if no DOI is on record"New value: +"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."
    • Changedpubmed_europepmc_fetch3 fields changed
      • changedInput schema / properties / records / items / properties / source / description
        Previous value: -"Europe PMC source corpus — `MED` (PubMed), `PMC` (PubMed Central), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola). Copy it from the search hit's `source`."New value: +"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`."
      • changedOutput schema / properties / notFound / items / properties / source / description
        Previous value: -"Europe PMC source corpus — `MED` (PubMed), `PMC` (PubMed Central), `PPR` (preprint), `PAT` (patent), `AGR` (Agricola). Copy it from the search hit's `source`."New value: +"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`."
      • changedOutput schema / properties / records / items / properties / doi / description
        Previous value: -"DOI when present"New value: +"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."
    • Changedpubmed_europepmc_search1 field changed
      • changedOutput schema / properties / hits / items / properties / doi / description
        Previous value: -"DOI when present"New value: +"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."
    • Changedpubmed_fetch_articles1 field changed
      • changedOutput schema / properties / articles / items / properties / doi / description
        Previous value: -"DOI"New value: +"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."
    • Changedpubmed_fetch_fulltext1 field changed
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "description": "DOI",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "description": "Subsection body text",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmcId": {
        -        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "description": "Subsection body text",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedpubmed_search_articles5 fields changed
      • changedInput schema / properties / offset / description
        Previous value: -"Result offset for pagination (0-based)"New value: +"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."
      • changedInput schema / properties / offset / maximum
        Previous value: -9007199254740991New value: +9998
      • changedInput schema / properties / summaryCount / description
        Previous value: -"Fetch brief summaries for top N results (0 = PMIDs only)"New value: +"Fetch brief summaries for top N results (0 = PMIDs only). Above the 50 cap, pass the remaining PMIDs to pubmed_fetch_articles."
      • changedOutput schema / properties / notice / description
        Previous value: -"Optional guidance when results are empty or paging overshot — e.g. how to broaden filters or reset offset. Absent on successful result pages."New value: +"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, or paging past the end. Absent when nothing applies."
      • changedOutput schema / properties / summaries / items / properties / doi / description
        Previous value: -"DOI"New value: +"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."
  12. 3 tool updates
    • Addedpubmed_europepmc_fetch
    • Changedpubmed_europepmc_search3 fields changed
      • changedOutput schema / properties / hits / items / properties / abstractSnippet / description
        Previous value: -"First few hundred characters of the abstract as display-ready plain text — JATS/HTML markup stripped and HTML entities decoded — when `resultType: \"core\"` is requested"New value: +"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."
      • addedOutput schema / properties / hits / items / properties / abstractTruncated
        Added value: +{
        +  "description": "Whether `abstractSnippet` was cut short of the full abstract. Retrieve the complete text with `pubmed_europepmc_fetch` using this record’s `source` and `epmcId`. Present whenever `abstractSnippet` is; omitted when Europe PMC carries no abstract.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / hits / items / properties / epmcId / description
        Previous value: -"Europe PMC's internal record id; key for `fullTextXML` lookup"New value: +"Europe PMC's internal record id. Pass it with this hit's `source` to `pubmed_europepmc_fetch` for the complete record. Europe PMC's `fullTextXML` is keyed on `pmcId`, not on this id, so records without a PMC counterpart have no full text to fetch."
    • Changedpubmed_fetch_fulltext5 fields changed
      • addedInput schema / properties / maxCharacters
        Added value: +{
        +  "description": "Per-article budget for body text, in characters. Counts `source=pmc` section and subsection text, or the `source=unpaywall` `content` body; titles, abstracts, identifiers, and references are never counted or shortened. Applied after `sections`, `maxSections`, and `includeReferences`, so semantic filtering is unaffected. The response-wide ceiling is this value times the number of articles returned. Omit for the full body.",
        +  "maximum": 1000000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / maxCharactersPerSection
        Added value: +{
        +  "description": "Budget for a single top-level body 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.",
        +  "maximum": 1000000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / overflowMode
        Added value: +{
        +  "default": "truncate",
        +  "description": "How to spend `maxCharacters` across an article that exceeds it. truncate: fill sections in document order, so early sections stay whole and sections past the budget are dropped (counted in `truncation.omittedSections`). outline: split the budget evenly so every section keeps its heading, and an excerpt as far as the budget reaches — 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.",
        +  "enum": [
        +    "truncate",
        +    "outline"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Optional guidance for empty bodies. 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. Absent when neither case applies."New value: +"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 budgeted response names the characters returned versus carried and points at `truncation`. Absent when none of those applies."
      • addedOutput schema / properties / truncation
        Added value: +{
        +  "additionalProperties": false,
        +  "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.",
        +  "properties": {
        +    "articles": {
        +      "description": "Per-article accounting, covering only the articles the budget shortened",
        +      "items": {
        +        "additionalProperties": false,
        +        "description": "Character accounting for one article the budget shortened",
        +        "properties": {
        +          "id": {
        +            "description": "Identifier for the article — PMCID, PMID, DOI, or Europe PMC id, whichever the article carries first",
        +            "type": "string"
        +          },
        +          "originalCharacters": {
        +            "description": "Body characters this article carried before the budget pass",
        +            "type": "number"
        +          },
        +          "returnedCharacters": {
        +            "description": "Body characters this article carries in the response",
        +            "type": "number"
        +          },
        +          "sections": {
        +            "description": "Per-section accounting for `source: pmc` articles, in document order, including sections dropped for budget. Absent for `source: unpaywall`, whose body has no section structure.",
        +            "items": {
        +              "additionalProperties": false,
        +              "description": "Character accounting for one body section of a budgeted article",
        +              "properties": {
        +                "originalCharacters": {
        +                  "description": "Body characters this section carried before the budget pass",
        +                  "type": "number"
        +                },
        +                "returnedCharacters": {
        +                  "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.",
        +                  "type": "number"
        +                },
        +                "title": {
        +                  "description": "Section heading, when the section carries one",
        +                  "type": "string"
        +                },
        +                "truncated": {
        +                  "description": "True when the section returned fewer characters than it originally carried",
        +                  "type": "boolean"
        +                }
        +              },
        +              "required": [
        +                "originalCharacters",
        +                "returnedCharacters",
        +                "truncated"
        +              ],
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "description": "Which output shape was budgeted: `pmc` budgets body sections and subsections, `unpaywall` budgets the single `content` body",
        +            "enum": [
        +              "pmc",
        +              "unpaywall"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "source",
        +          "originalCharacters",
        +          "returnedCharacters"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "maxCharacters": {
        +      "description": "The `maxCharacters` budget applied, when set",
        +      "type": "number"
        +    },
        +    "maxCharactersPerSection": {
        +      "description": "The `maxCharactersPerSection` budget applied, when set",
        +      "type": "number"
        +    },
        +    "mode": {
        +      "description": "The `overflowMode` that produced these results",
        +      "enum": [
        +        "truncate",
        +        "outline"
        +      ],
        +      "type": "string"
        +    },
        +    "omittedSections": {
        +      "description": "Body sections dropped entirely because an article budget was exhausted before reaching them. Always 0 in `outline` mode, which keeps every heading.",
        +      "type": "number"
        +    },
        +    "originalCharacters": {
        +      "description": "Body characters the shortened articles carried before the budget pass",
        +      "type": "number"
        +    },
        +    "returnedCharacters": {
        +      "description": "Body characters the shortened articles carry in this response",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "mode",
        +    "originalCharacters",
        +    "returnedCharacters",
        +    "omittedSections",
        +    "articles"
        +  ],
        +  "type": "object"
        +}
  13. 2 tool updates
    • Changedpubmed_europepmc_search1 field changed
      • changedInput schema / properties / query / description
        Previous value: -"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`. Free text is matched broadly across abstract/title/keywords."New value: +"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 combined with `AND SRC:` must be unquoted — the quoted form matches nothing. Free text is matched broadly across abstract/title/keywords."
    • Changedpubmed_fetch_fulltext7 fields changed
      • changedInput schema / properties / pmcids / description
        Previous value: -"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide exactly one of `pmcids`, `pmids`, or `dois`."New value: +"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide exactly one of `pmcids`, `pmids`, or `dois`. PMC IDs with no retrievable full text fall through to Europe PMC, then to Unpaywall on the DOI the chain resolves for them."
      • changedOutput schema / properties / articles / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        -    "properties": {
        -      "abstract": {
        -        "description": "Abstract",
        -        "type": "string"
        -      },
        -      "affiliations": {
        -        "description": "Author affiliations",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "articleType": {
        -        "description": "Article type",
        -        "type": "string"
        -      },
        -      "authors": {
        -        "description": "Authors",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Author entry",
        -          "properties": {
        -            "collectiveName": {
        -              "description": "Group name",
        -              "type": "string"
        -            },
        -            "givenNames": {
        -              "description": "Given names",
        -              "type": "string"
        -            },
        -            "lastName": {
        -              "description": "Last name",
        -              "type": "string"
        -            }
        -          },
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "doi": {
        -        "description": "DOI",
        -        "type": "string"
        -      },
        -      "epmcId": {
        -        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        -        "type": "string"
        -      },
        -      "epmcSource": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "journal": {
        -        "additionalProperties": false,
        -        "description": "Journal information",
        -        "properties": {
        -          "issn": {
        -            "description": "ISSN",
        -            "type": "string"
        -          },
        -          "issue": {
        -            "description": "Issue number",
        -            "type": "string"
        -          },
        -          "pages": {
        -            "description": "Page range",
        -            "type": "string"
        -          },
        -          "title": {
        -            "description": "Journal title",
        -            "type": "string"
        -          },
        -          "volume": {
        -            "description": "Volume number",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "keywords": {
        -        "description": "Keywords",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "pmcId": {
        -        "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.",
        -        "type": "string"
        -      },
        -      "pmcUrl": {
        -        "description": "PMC URL — derived from `pmcId` when present",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID",
        -        "type": "string"
        -      },
        -      "publicationDate": {
        -        "additionalProperties": false,
        -        "description": "Publication date",
        -        "properties": {
        -          "day": {
        -            "description": "Publication day",
        -            "type": "string"
        -          },
        -          "month": {
        -            "description": "Publication month",
        -            "type": "string"
        -          },
        -          "year": {
        -            "description": "Publication year",
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL",
        -        "type": "string"
        -      },
        -      "references": {
        -        "description": "Reference list",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Reference entry",
        -          "properties": {
        -            "citation": {
        -              "description": "Citation text",
        -              "type": "string"
        -            },
        -            "id": {
        -              "description": "Reference ID",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Reference label",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "citation"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "sections": {
        -        "description": "Article body sections",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "Article body section",
        -          "properties": {
        -            "label": {
        -              "description": "Section label",
        -              "type": "string"
        -            },
        -            "subsections": {
        -              "description": "Nested subsections",
        -              "items": {
        -                "additionalProperties": false,
        -                "description": "Article subsection",
        -                "properties": {
        -                  "label": {
        -                    "description": "Subsection label",
        -                    "type": "string"
        -                  },
        -                  "text": {
        -                    "description": "Subsection body text",
        -                    "type": "string"
        -                  },
        -                  "title": {
        -                    "description": "Subsection heading",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "text"
        -                ],
        -                "type": "object"
        -              },
        -              "type": "array"
        -            },
        -            "text": {
        -              "description": "Section body text",
        -              "type": "string"
        -            },
        -            "title": {
        -              "description": "Section heading",
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "text"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "source": {
        -        "const": "pmc",
        -        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Article title",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "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.",
        -        "enum": [
        -          "pmc",
        -          "europepmc"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "sections"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Best-effort full text from an open-access copy",
        -    "properties": {
        -      "content": {
        -        "description": "Full article text — Markdown or plain text per `contentFormat`",
        -        "type": "string"
        -      },
        -      "contentFormat": {
        -        "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.",
        -        "enum": [
        -          "html-markdown",
        -          "pdf-text"
        -        ],
        -        "type": "string"
        -      },
        -      "doi": {
        -        "description": "DOI used to locate the open-access copy",
        -        "type": "string"
        -      },
        -      "hostType": {
        -        "description": "`publisher` or `repository` — where the OA copy is hosted",
        -        "type": "string"
        -      },
        -      "license": {
        -        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        -        "type": "string"
        -      },
        -      "pmid": {
        -        "description": "PubMed ID when input was `pmids`; absent for `dois` input",
        -        "type": "string"
        -      },
        -      "pubmedUrl": {
        -        "description": "PubMed URL — present when `pmid` is set",
        -        "type": "string"
        -      },
        -      "source": {
        -        "const": "unpaywall",
        -        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        -        "type": "string"
        -      },
        -      "sourceUrl": {
        -        "description": "URL the content was fetched from",
        -        "type": "string"
        -      },
        -      "title": {
        -        "description": "Detected article title when present",
        -        "type": "string"
        -      },
        -      "totalPages": {
        -        "description": "Page count reported by the PDF extractor; absent for HTML",
        -        "type": "number"
        -      },
        -      "version": {
        -        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        -        "type": "string"
        -      },
        -      "viaSource": {
        -        "const": "unpaywall",
        -        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        -        "type": "string"
        -      },
        -      "wordCount": {
        -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "source",
        -      "viaSource",
        -      "contentFormat",
        -      "doi",
        -      "sourceUrl",
        -      "content"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Structured JATS full-text article. `viaSource` records whether the JATS came from NCBI PMC or Europe PMC.",
        +    "properties": {
        +      "abstract": {
        +        "description": "Abstract",
        +        "type": "string"
        +      },
        +      "affiliations": {
        +        "description": "Author affiliations",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "articleType": {
        +        "description": "Article type",
        +        "type": "string"
        +      },
        +      "authors": {
        +        "description": "Authors",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Author entry",
        +          "properties": {
        +            "collectiveName": {
        +              "description": "Group name",
        +              "type": "string"
        +            },
        +            "givenNames": {
        +              "description": "Given names",
        +              "type": "string"
        +            },
        +            "lastName": {
        +              "description": "Last name",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "doi": {
        +        "description": "DOI",
        +        "type": "string"
        +      },
        +      "epmcId": {
        +        "description": "Europe PMC record id — present when `viaSource` is `europepmc`",
        +        "type": "string"
        +      },
        +      "epmcSource": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "journal": {
        +        "additionalProperties": false,
        +        "description": "Journal information",
        +        "properties": {
        +          "issn": {
        +            "description": "ISSN",
        +            "type": "string"
        +          },
        +          "issue": {
        +            "description": "Issue number",
        +            "type": "string"
        +          },
        +          "pages": {
        +            "description": "Page range",
        +            "type": "string"
        +          },
        +          "title": {
        +            "description": "Journal title",
        +            "type": "string"
        +          },
        +          "volume": {
        +            "description": "Volume number",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "keywords": {
        +        "description": "Keywords",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "pmcId": {
        +        "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.",
        +        "type": "string"
        +      },
        +      "pmcUrl": {
        +        "description": "PMC URL — derived from `pmcId` when present",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID",
        +        "type": "string"
        +      },
        +      "publicationDate": {
        +        "additionalProperties": false,
        +        "description": "Publication date",
        +        "properties": {
        +          "day": {
        +            "description": "Publication day",
        +            "type": "string"
        +          },
        +          "month": {
        +            "description": "Publication month",
        +            "type": "string"
        +          },
        +          "year": {
        +            "description": "Publication year",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL",
        +        "type": "string"
        +      },
        +      "references": {
        +        "description": "Reference list",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Reference entry",
        +          "properties": {
        +            "citation": {
        +              "description": "Citation text",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Reference ID",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Reference label",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "citation"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "sections": {
        +        "description": "Article body sections",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "Article body section",
        +          "properties": {
        +            "label": {
        +              "description": "Section label",
        +              "type": "string"
        +            },
        +            "subsections": {
        +              "description": "Nested subsections",
        +              "items": {
        +                "additionalProperties": false,
        +                "description": "Article subsection",
        +                "properties": {
        +                  "label": {
        +                    "description": "Subsection label",
        +                    "type": "string"
        +                  },
        +                  "text": {
        +                    "description": "Subsection body text",
        +                    "type": "string"
        +                  },
        +                  "title": {
        +                    "description": "Subsection heading",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "text"
        +                ],
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "text": {
        +              "description": "Section body text",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Section heading",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "text"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "source": {
        +        "const": "pmc",
        +        "description": "Structured JATS — same DTD whether sourced from NCBI PMC or Europe PMC",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Article title",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "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.",
        +        "enum": [
        +          "pmc",
        +          "europepmc"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "sections"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Best-effort full text from an open-access copy",
        +    "properties": {
        +      "content": {
        +        "description": "Full article text — Markdown or plain text per `contentFormat`",
        +        "type": "string"
        +      },
        +      "contentFormat": {
        +        "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.",
        +        "enum": [
        +          "html-markdown",
        +          "pdf-text"
        +        ],
        +        "type": "string"
        +      },
        +      "doi": {
        +        "description": "DOI used to locate the open-access copy",
        +        "type": "string"
        +      },
        +      "hostType": {
        +        "description": "`publisher` or `repository` — where the OA copy is hosted",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "License identifier from Unpaywall (e.g. cc-by, cc0)",
        +        "type": "string"
        +      },
        +      "pmcId": {
        +        "description": "PMC ID this article was requested under, in `PMC<digits>` form — present for `pmcids` input, absent for `pmids` and `dois` input. Ties the article back to the requested identifier, which `unavailable[]` keys on for the ids that found nothing.",
        +        "type": "string"
        +      },
        +      "pmid": {
        +        "description": "PubMed ID when input was `pmids`; absent for `pmcids` and `dois` input",
        +        "type": "string"
        +      },
        +      "pubmedUrl": {
        +        "description": "PubMed URL — present when `pmid` is set",
        +        "type": "string"
        +      },
        +      "source": {
        +        "const": "unpaywall",
        +        "description": "Content fetched from an open-access copy indexed by Unpaywall. Best-effort — structural fidelity depends on `contentFormat`.",
        +        "type": "string"
        +      },
        +      "sourceUrl": {
        +        "description": "URL the content was fetched from",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Detected article title when present",
        +        "type": "string"
        +      },
        +      "totalPages": {
        +        "description": "Page count reported by the PDF extractor; absent for HTML",
        +        "type": "number"
        +      },
        +      "version": {
        +        "description": "OA version: submittedVersion | acceptedVersion | publishedVersion",
        +        "type": "string"
        +      },
        +      "viaSource": {
        +        "const": "unpaywall",
        +        "description": "Layer that produced this article. Constant `unpaywall` for this branch.",
        +        "type": "string"
        +      },
        +      "wordCount": {
        +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "source",
        +      "viaSource",
        +      "contentFormat",
        +      "doi",
        +      "sourceUrl",
        +      "content"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / properties / notice / description
        Previous value: -"Optional guidance when a `sections` filter removed every body section — names the requested section terms and the affected article id(s), and suggests retrying without `sections` or using broader headings. Absent when no section filter was applied or sections matched."New value: +"Optional guidance for empty bodies. 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. Absent when neither case applies."
      • changedOutput schema / properties / unavailable / items / properties / reason / description
        Previous value: -"Why no full text was returned. 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-doi: no DOI to query Unpaywall. 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)."New value: +"Why no full text was returned. 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: no DOI to query Unpaywall. 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)."
      • changedOutput schema / properties / unavailable / items / properties / reason / enum
        Previous value: -[
        -  "not-found",
        -  "no-pmc-fallback-disabled",
        -  "no-epmc-fulltext",
        -  "no-doi",
        -  "no-oa",
        -  "fetch-failed",
        -  "parse-failed",
        -  "service-error"
        -]New value: +[
        +  "not-found",
        +  "no-pmc-fallback-disabled",
        +  "no-epmc-fulltext",
        +  "no-body",
        +  "no-doi",
        +  "no-oa",
        +  "fetch-failed",
        +  "parse-failed",
        +  "service-error"
        +]
      • changedOutput schema / properties / unavailable / items / properties / triedTiers / items / properties / outcome / description
        Previous value: -"Per-tier outcome. not-attempted: tier was skipped. miss: tier returned no record. no-fulltext: EPMC indexed the record but publishes no fullTextXML. no-doi: no DOI to query Unpaywall. 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."New value: +"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: no DOI to query Unpaywall. 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."
      • changedOutput schema / properties / unavailable / items / properties / triedTiers / items / properties / outcome / enum
        Previous value: -[
        -  "not-attempted",
        -  "miss",
        -  "no-fulltext",
        -  "no-doi",
        -  "no-oa",
        -  "fetch-failed",
        -  "parse-failed",
        -  "service-error"
        -]New value: +[
        +  "not-attempted",
        +  "miss",
        +  "no-fulltext",
        +  "no-body",
        +  "no-doi",
        +  "no-oa",
        +  "fetch-failed",
        +  "parse-failed",
        +  "service-error"
        +]
  14. 1 tool update
    • Changedpubmed_lookup_mesh6 fields changed
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 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.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / nextOffset
        Added value: +{
        +  "description": "Offset to request for the next page. Omitted when this is the last page, so its absence is the end-of-results signal.",
        +  "type": "number"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Optional guidance when no descriptors matched — suggests spell-check or free-text search. Absent on successful results."New value: +"Optional guidance when no descriptors matched or the offset overshot the result set — suggests spell-check, free-text search, or resetting the offset. Absent on successful result pages."
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Result offset this page was read from",
        +  "type": "number"
        +}
      • changedOutput schema / properties / totalCount / description
        Previous value: -"Total matching MeSH descriptors"New value: +"Total MeSH descriptors matching the query upstream, before the maxResults cap"
      • changedOutput schema / required
        Previous value: -[
        -  "query",
        -  "results",
        -  "totalCount"
        -]New value: +[
        +  "query",
        +  "offset",
        +  "results",
        +  "totalCount"
        +]

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.