UNPKG

@cyanheads/pubmed-mcp-server

Version:

Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms via MCP. STDIO or Streamable HTTP.

190 lines 9.16 kB
/** * @fileoverview Full-text fetch tool. Resolves full-text articles through a * three-stage chain: NCBI PMC EFetch Europe PMC `fullTextXML` Unpaywall. * Accepts three mutually-exclusive input shapes: * * - `pmcids` fetch directly by PMC ID. Articles not in PMC fall through to * EPMC by PMC ID, then to Unpaywall when the DOI is available. * - `pmids` resolve PMID PMCID via PMC ID Converter, then run the chain. * - `dois` skip PMC EFetch (no PMCID); resolve via EPMC search-by-DOI * fullTextXML, then Unpaywall. Covers EPMC-only OA and preprints with no * PubMed presence. * * Output uses a discriminated union on `source` (`pmc` | `unpaywall`) with an * extra `viaSource` discriminator that records which layer produced the * content. EPMC's JATS reuses the `pmc` schema shape because it's the same * DTD; `viaSource: 'europepmc'` distinguishes it from PMC EFetch output. * * @module src/mcp-server/tools/definitions/fetch-fulltext.tool */ import { z } from '@cyanheads/mcp-ts-core'; export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{ pmcids: z.ZodOptional<z.ZodArray<z.ZodString>>; pmids: z.ZodOptional<z.ZodArray<z.ZodString>>; dois: z.ZodOptional<z.ZodArray<z.ZodString>>; includeReferences: z.ZodDefault<z.ZodBoolean>; maxSections: z.ZodOptional<z.ZodNumber>; sections: z.ZodOptional<z.ZodArray<z.ZodString>>; }, z.core.$strip>, z.ZodObject<{ articles: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{ source: z.ZodLiteral<"pmc">; viaSource: z.ZodEnum<{ pmc: "pmc"; europepmc: "europepmc"; }>; pmcId: z.ZodOptional<z.ZodString>; pmcUrl: z.ZodOptional<z.ZodString>; pmid: z.ZodOptional<z.ZodString>; pubmedUrl: z.ZodOptional<z.ZodString>; doi: z.ZodOptional<z.ZodString>; title: z.ZodOptional<z.ZodString>; abstract: z.ZodOptional<z.ZodString>; authors: z.ZodOptional<z.ZodArray<z.ZodObject<{ collectiveName: z.ZodOptional<z.ZodString>; givenNames: z.ZodOptional<z.ZodString>; lastName: z.ZodOptional<z.ZodString>; }, z.core.$strip>>>; affiliations: z.ZodOptional<z.ZodArray<z.ZodString>>; journal: z.ZodOptional<z.ZodObject<{ title: z.ZodOptional<z.ZodString>; issn: z.ZodOptional<z.ZodString>; volume: z.ZodOptional<z.ZodString>; issue: z.ZodOptional<z.ZodString>; pages: z.ZodOptional<z.ZodString>; }, z.core.$strip>>; keywords: z.ZodOptional<z.ZodArray<z.ZodString>>; articleType: z.ZodOptional<z.ZodString>; publicationDate: z.ZodOptional<z.ZodObject<{ year: z.ZodOptional<z.ZodString>; month: z.ZodOptional<z.ZodString>; day: z.ZodOptional<z.ZodString>; }, z.core.$strip>>; sections: z.ZodArray<z.ZodObject<{ title: z.ZodOptional<z.ZodString>; label: z.ZodOptional<z.ZodString>; text: z.ZodString; subsections: z.ZodOptional<z.ZodArray<z.ZodObject<{ title: z.ZodOptional<z.ZodString>; label: z.ZodOptional<z.ZodString>; text: z.ZodString; }, z.core.$strip>>>; }, z.core.$strip>>; references: z.ZodOptional<z.ZodArray<z.ZodObject<{ citation: z.ZodString; id: z.ZodOptional<z.ZodString>; label: z.ZodOptional<z.ZodString>; }, z.core.$strip>>>; epmcId: z.ZodOptional<z.ZodString>; epmcSource: z.ZodOptional<z.ZodString>; }, z.core.$strip>, z.ZodObject<{ source: z.ZodLiteral<"unpaywall">; viaSource: z.ZodLiteral<"unpaywall">; contentFormat: z.ZodEnum<{ "html-markdown": "html-markdown"; "pdf-text": "pdf-text"; }>; pmid: z.ZodOptional<z.ZodString>; pubmedUrl: z.ZodOptional<z.ZodString>; doi: z.ZodString; sourceUrl: z.ZodString; title: z.ZodOptional<z.ZodString>; content: z.ZodString; wordCount: z.ZodOptional<z.ZodNumber>; totalPages: z.ZodOptional<z.ZodNumber>; license: z.ZodOptional<z.ZodString>; hostType: z.ZodOptional<z.ZodString>; version: z.ZodOptional<z.ZodString>; }, z.core.$strip>], "source">>; totalReturned: z.ZodNumber; unavailable: z.ZodOptional<z.ZodArray<z.ZodObject<{ id: z.ZodString; idType: z.ZodEnum<{ pmid: "pmid"; pmcid: "pmcid"; doi: "doi"; }>; reason: z.ZodEnum<{ "no-oa": "no-oa"; "not-found": "not-found"; "no-pmc-fallback-disabled": "no-pmc-fallback-disabled"; "no-epmc-fulltext": "no-epmc-fulltext"; "no-doi": "no-doi"; "fetch-failed": "fetch-failed"; "parse-failed": "parse-failed"; "service-error": "service-error"; }>; triedTiers: z.ZodArray<z.ZodObject<{ tier: z.ZodEnum<{ pmc: "pmc"; europepmc: "europepmc"; unpaywall: "unpaywall"; }>; outcome: z.ZodEnum<{ "no-oa": "no-oa"; "no-doi": "no-doi"; "fetch-failed": "fetch-failed"; "parse-failed": "parse-failed"; "service-error": "service-error"; "not-attempted": "not-attempted"; miss: "miss"; "no-fulltext": "no-fulltext"; }>; detail: z.ZodOptional<z.ZodString>; }, z.core.$strip>>; }, z.core.$strip>>>; }, z.core.$strip>, readonly [{ readonly reason: "queue_full"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.RateLimited; readonly when: "Local NCBI request queue is at capacity."; readonly recovery: "Retry after 1-2 seconds; the request queue hit the NCBI rate limit."; readonly retryable: true; }, { readonly reason: "ncbi_unreachable"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable; readonly when: "NCBI E-utilities is unreachable after all retry attempts."; readonly recovery: "Retry after a brief delay; NCBI was unreachable across all retry attempts."; readonly retryable: true; }, { readonly reason: "ncbi_deadline_exceeded"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Timeout; readonly when: "Total request deadline expired before NCBI returned a response."; readonly recovery: "Reduce batch size or retry; NCBI may be under temporary load."; readonly retryable: true; }, { readonly reason: "ncbi_invalid_response"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.SerializationError; readonly when: "NCBI returned a body that could not be parsed (invalid XML/JSON)."; readonly recovery: "Retry the request; NCBI returned a malformed response that could not be parsed."; readonly retryable: true; }, { readonly reason: "ncbi_resource_not_found"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound; readonly when: "NCBI returned a structured \"not found\" error for the requested ID(s)."; readonly recovery: "Verify the ID exists in PubMed; the resource was not found in NCBI and retrying will not help."; readonly retryable: false; }, { readonly reason: "unpaywall_unreachable"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable; readonly when: "Unpaywall was unreachable when resolving a DOI or fetching content."; readonly recovery: "Retry after a brief delay; Unpaywall was unreachable. The PMC source remains the primary path."; readonly retryable: true; }, { readonly reason: "europepmc_unreachable"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable; readonly when: "Europe PMC was unreachable after all retry attempts."; readonly recovery: "Retry after a brief delay; Europe PMC was unreachable. NCBI PMC and Unpaywall remain available."; readonly retryable: true; }, { readonly reason: "europepmc_invalid_response"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.SerializationError; readonly when: "Europe PMC returned a body that could not be parsed (invalid JSON or XML)."; readonly recovery: "Retry the request; Europe PMC returned a malformed response that could not be parsed."; readonly retryable: true; }, { readonly reason: "europepmc_invalid_input"; readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError; readonly when: "Europe PMC rejected the request input (empty query, unknown sort field, malformed parameter)."; readonly recovery: "Adjust the input — usually the query or sort field — before retrying; the same input will be rejected again."; readonly retryable: false; }]>; //# sourceMappingURL=fetch-fulltext.tool.d.ts.map