Skip to main content
Glama

Pubmed Fetch Fulltext

pubmed_fetch_fulltext
Read-only

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.

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault
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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed10 schema 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. Changed1 schema 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."
  3. Changed4 schema 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"
      +  }
      +]
  4. Changed11 schema 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"
      +]
  5. Changed8 schema 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"
      +}
  6. Changed1 schema 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"
      +  }
      +]
  7. Changed9 schema 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"
      +}
  8. Changed7 schema 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"
      -]
  9. Changed1 schema 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"
      +  }
      +]
  10. Changed5 schema 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"
      +}
  11. Changed7 schema 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"
      +]
  12. Changed1 schema field changed
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "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.",
      +  "type": "string"
      +}
  13. Changed1 schema field 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`. Covers preprints and EPMC-only OA records that lack PMID/PMCID. Chain: Europe PMC search-by-DOI → fullTextXML → Unpaywall."New 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."
  14. Changed1 schema field changed
    • addedInput schema / properties / pmcids / items / pattern
      Added value: +"^(?:PMC)?\\d+$"
  15. Changed16 schema fields changed
    • addedInput schema / properties / dois
      Added value: +{
      +  "description": "DOIs to resolve (e.g. [\"10.21203/rs.3.rs-9010375/v1\"]). Provide exactly one of `pmcids`, `pmids`, or `dois`. Covers preprints and EPMC-only OA records that lack PMID/PMCID. Chain: Europe PMC search-by-DOI → fullTextXML → Unpaywall.",
      +  "items": {
      +    "minLength": 3,
      +    "type": "string"
      +  },
      +  "maxItems": 10,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / pmcids / description
      Previous value: -"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide exactly one of `pmcids` or `pmids`."New value: +"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide exactly one of `pmcids`, `pmids`, or `dois`."
    • changedInput schema / properties / pmids / description
      Previous value: -"PubMed IDs. Provide exactly one of `pmcids` or `pmids`. Articles in PMC are returned as structured JATS; articles not in PMC are retrieved from Unpaywall when UNPAYWALL_EMAIL is set and a DOI is available."New value: +"PubMed 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."
    • changedOutput schema / properties / articles / items / description
      Previous value: -"Full-text article; shape depends on `source` (pmc = structured, unpaywall = best-effort)"New value: +"Full-text article; shape depends on `source` (pmc = structured JATS, unpaywall = best-effort)"
    • changedOutput schema / properties / articles / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "Structured PMC full-text article — reliable section/reference structure",
      -    "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"
      -      },
      -      "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",
      -        "type": "string"
      -      },
      -      "pmcUrl": {
      -        "description": "PMC URL",
      -        "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": "Content came from PubMed Central as structured JATS XML",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "Article title",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "source",
      -      "pmcId",
      -      "pmcUrl",
      -      "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 the article was resolved from",
      -        "type": "string"
      -      },
      -      "pubmedUrl": {
      -        "description": "PubMed URL",
      -        "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"
      -      },
      -      "wordCount": {
      -        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "source",
      -      "contentFormat",
      -      "pmid",
      -      "pubmedUrl",
      -      "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"
      +      },
      +      "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"
      +  }
      +]
    • changedOutput schema / properties / unavailable / description
      Previous value: -"Per-PMID explanations for any requested PMIDs with no returnable full text"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."
    • changedOutput schema / properties / unavailable / items / description
      Previous value: -"One PMID that could not be returned with an explanation of why"New value: +"One identifier that could not be returned, with the full chain it traversed"
    • removedOutput schema / properties / unavailable / items / properties / detail
      Removed value: -{
      -  "description": "Additional context when available",
      -  "type": "string"
      -}
    • addedOutput schema / properties / unavailable / items / properties / id
      Added value: +{
      +  "description": "Identifier the chain could not resolve — PMID, PMCID, or DOI per `idType`",
      +  "type": "string"
      +}
    • addedOutput schema / properties / unavailable / items / properties / idType
      Added value: +{
      +  "description": "Which input branch the id came from",
      +  "enum": [
      +    "pmid",
      +    "pmcid",
      +    "doi"
      +  ],
      +  "type": "string"
      +}
    • removedOutput schema / properties / unavailable / items / properties / pmid
      Removed value: -{
      -  "description": "PMID full text could not be returned for",
      -  "type": "string"
      -}
    • changedOutput schema / properties / unavailable / items / properties / reason / description
      Previous value: -"Why the PMID has no full text. no-pmc-fallback-disabled: not in PMC and UNPAYWALL_EMAIL is unset so the Unpaywall fallback is off. no-doi: not in PMC and the ID Converter returned no DOI to try Unpaywall with. no-oa: DOI exists but Unpaywall has no open-access copy indexed. fetch-failed: OA location found but the content could not be downloaded. parse-failed: content was downloaded but text extraction produced nothing usable. service-error: Unpaywall or an upstream host returned a server error."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-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: -[
      -  "no-pmc-fallback-disabled",
      -  "no-doi",
      -  "no-oa",
      -  "fetch-failed",
      -  "parse-failed",
      -  "service-error"
      -]New value: +[
      +  "not-found",
      +  "no-pmc-fallback-disabled",
      +  "no-epmc-fulltext",
      +  "no-doi",
      +  "no-oa",
      +  "fetch-failed",
      +  "parse-failed",
      +  "service-error"
      +]
    • addedOutput schema / properties / unavailable / items / properties / triedTiers
      Added value: +{
      +  "description": "Per-tier outcomes the chain produced for this id, in execution order. Covers `pmc`, `europepmc`, and `unpaywall` — the same tiers the tool description references. Tiers that the chain skipped appear as `outcome: not-attempted` with a `detail` explaining why.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One tier the resolution chain attempted, with its outcome",
      +    "properties": {
      +      "detail": {
      +        "description": "Tier-specific context when available",
      +        "type": "string"
      +      },
      +      "outcome": {
      +        "description": "Per-tier outcome. not-attempted: tier was skipped. miss: tier returned no record. no-fulltext: EPMC indexed the record but publishes no fullTextXML. no-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.",
      +        "enum": [
      +          "not-attempted",
      +          "miss",
      +          "no-fulltext",
      +          "no-doi",
      +          "no-oa",
      +          "fetch-failed",
      +          "parse-failed",
      +          "service-error"
      +        ],
      +        "type": "string"
      +      },
      +      "tier": {
      +        "description": "Which tier in the resolution chain",
      +        "enum": [
      +          "pmc",
      +          "europepmc",
      +          "unpaywall"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tier",
      +      "outcome"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / unavailable / items / required
      Previous value: -[
      -  "pmid",
      -  "reason"
      -]New value: +[
      +  "id",
      +  "idType",
      +  "reason",
      +  "triedTiers"
      +]
    • removedOutput schema / properties / unavailablePmcIds
      Removed value: -{
      -  "description": "PMC IDs that returned no data, whether requested directly via `pmcids` or resolved from `pmids` via the PMC ID Converter",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
  16. Changed3 schema fields changed
    • changedInput schema / properties / pmcids / description
      Previous value: -"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide this OR pmids, not both."New value: +"PMC IDs to fetch (e.g. [\"PMC9575052\"]). Provide exactly one of `pmcids` or `pmids`."
    • changedInput schema / properties / pmids / description
      Previous value: -"PubMed IDs. Articles in PMC are returned as structured JATS. Articles not in PMC are retrieved from Unpaywall when UNPAYWALL_EMAIL is set and a DOI is available. Provide this OR pmcids, not both."New value: +"PubMed IDs. Provide exactly one of `pmcids` or `pmids`. Articles in PMC are returned as structured JATS; articles not in PMC are retrieved from Unpaywall when UNPAYWALL_EMAIL is set and a DOI is available."
    • changedOutput schema / properties / unavailablePmcIds / description
      Previous value: -"PMC IDs requested directly that returned no data"New value: +"PMC IDs that returned no data, whether requested directly via `pmcids` or resolved from `pmids` via the PMC ID Converter"
  17. Changed13 schema fields changed
    • changedInput schema / properties / includeReferences / description
      Previous value: -"Include reference list"New value: +"Include reference list. Applies to `source=pmc` results only."
    • changedInput schema / properties / maxSections / description
      Previous value: -"Maximum top-level body sections"New value: +"Maximum top-level body sections. Applies to `source=pmc` results only."
    • changedInput schema / properties / pmids / description
      Previous value: -"PubMed IDs to resolve to PMC full text. Provide this OR pmcids, not both. Only works for open-access articles available in PMC."New value: +"PubMed IDs. Articles in PMC are returned as structured JATS. Articles not in PMC are retrieved from Unpaywall when UNPAYWALL_EMAIL is set and a DOI is available. Provide this OR pmcids, not both."
    • changedInput schema / properties / sections / description
      Previous value: -"Filter to specific sections by title, case-insensitive (e.g. [\"Introduction\", \"Methods\", \"Results\", \"Discussion\"])"New value: +"Filter to specific sections by title, case-insensitive (e.g. [\"Introduction\", \"Methods\", \"Results\", \"Discussion\"]). Applies to `source=pmc` results only."
    • removedOutput schema / properties / articles / items / additionalProperties
      Removed value: -false
    • changedOutput schema / properties / articles / items / description
      Previous value: -"Full-text PMC article"New value: +"Full-text article; shape depends on `source` (pmc = structured, unpaywall = best-effort)"
    • addedOutput schema / properties / articles / items / oneOf
      Added value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "Structured PMC full-text article — reliable section/reference structure",
      +    "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"
      +      },
      +      "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",
      +        "type": "string"
      +      },
      +      "pmcUrl": {
      +        "description": "PMC URL",
      +        "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": "Content came from PubMed Central as structured JATS XML",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "Article title",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "source",
      +      "pmcId",
      +      "pmcUrl",
      +      "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 the article was resolved from",
      +        "type": "string"
      +      },
      +      "pubmedUrl": {
      +        "description": "PubMed URL",
      +        "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"
      +      },
      +      "wordCount": {
      +        "description": "Approximate word count reported by the HTML extractor; absent for PDFs",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "source",
      +      "contentFormat",
      +      "pmid",
      +      "pubmedUrl",
      +      "doi",
      +      "sourceUrl",
      +      "content"
      +    ],
      +    "type": "object"
      +  }
      +]
    • removedOutput schema / properties / articles / items / properties
      Removed value: -{
      -  "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"
      -  },
      -  "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",
      -    "type": "string"
      -  },
      -  "pmcUrl": {
      -    "description": "PMC URL",
      -    "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"
      -  },
      -  "title": {
      -    "description": "Article title",
      -    "type": "string"
      -  }
      -}
    • removedOutput schema / properties / articles / items / required
      Removed value: -[
      -  "pmcId",
      -  "pmcUrl",
      -  "sections"
      -]
    • removedOutput schema / properties / articles / items / type
      Removed value: -"object"
    • addedOutput schema / properties / unavailable
      Added value: +{
      +  "description": "Per-PMID explanations for any requested PMIDs with no returnable full text",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One PMID that could not be returned with an explanation of why",
      +    "properties": {
      +      "detail": {
      +        "description": "Additional context when available",
      +        "type": "string"
      +      },
      +      "pmid": {
      +        "description": "PMID full text could not be returned for",
      +        "type": "string"
      +      },
      +      "reason": {
      +        "description": "Why the PMID has no full text. no-pmc-fallback-disabled: not in PMC and UNPAYWALL_EMAIL is unset so the Unpaywall fallback is off. no-doi: not in PMC and the ID Converter returned no DOI to try Unpaywall with. no-oa: DOI exists but Unpaywall has no open-access copy indexed. fetch-failed: OA location found but the content could not be downloaded. parse-failed: content was downloaded but text extraction produced nothing usable. service-error: Unpaywall or an upstream host returned a server error.",
      +        "enum": [
      +          "no-pmc-fallback-disabled",
      +          "no-doi",
      +          "no-oa",
      +          "fetch-failed",
      +          "parse-failed",
      +          "service-error"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "pmid",
      +      "reason"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / unavailablePmcIds / description
      Previous value: -"PMC IDs that returned no data"New value: +"PMC IDs requested directly that returned no data"
    • removedOutput schema / properties / unavailablePmids
      Removed value: -{
      -  "description": "PMIDs not available in PMC",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
  18. Changed5 schema fields changed
    • addedOutput schema / properties / articles / items / description
      Added value: +"Full-text PMC article"
    • addedOutput schema / properties / articles / items / properties / authors / items / description
      Added value: +"Author entry"
    • addedOutput schema / properties / articles / items / properties / references / items / description
      Added value: +"Reference entry"
    • addedOutput schema / properties / articles / items / properties / sections / items / description
      Added value: +"Article body section"
    • addedOutput schema / properties / articles / items / properties / sections / items / properties / subsections / items / description
      Added value: +"Article subsection"
  19. First observed

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.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.