@cyanheads/pubmed-mcp-server 2.9.9 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/AGENTS.md +2 -2
  2. package/CLAUDE.md +2 -2
  3. package/README.md +19 -4
  4. package/dist/index.js +3 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp-server/tools/definitions/_text.d.ts +22 -0
  7. package/dist/mcp-server/tools/definitions/_text.d.ts.map +1 -0
  8. package/dist/mcp-server/tools/definitions/_text.js +32 -0
  9. package/dist/mcp-server/tools/definitions/_text.js.map +1 -0
  10. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts +35 -0
  11. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts.map +1 -1
  12. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js +634 -123
  13. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js.map +1 -1
  14. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts +87 -0
  15. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts.map +1 -0
  16. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js +195 -0
  17. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js.map +1 -0
  18. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts +1 -0
  19. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js +29 -8
  21. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js.map +1 -1
  22. package/dist/services/europe-pmc/api-client.d.ts +14 -1
  23. package/dist/services/europe-pmc/api-client.d.ts.map +1 -1
  24. package/dist/services/europe-pmc/api-client.js +21 -25
  25. package/dist/services/europe-pmc/api-client.js.map +1 -1
  26. package/dist/services/europe-pmc/europe-pmc-service.d.ts +21 -7
  27. package/dist/services/europe-pmc/europe-pmc-service.d.ts.map +1 -1
  28. package/dist/services/europe-pmc/europe-pmc-service.js +39 -6
  29. package/dist/services/europe-pmc/europe-pmc-service.js.map +1 -1
  30. package/dist/services/europe-pmc/types.d.ts +9 -0
  31. package/dist/services/europe-pmc/types.d.ts.map +1 -1
  32. package/dist/services/openalex/api-client.d.ts +15 -1
  33. package/dist/services/openalex/api-client.d.ts.map +1 -1
  34. package/dist/services/openalex/api-client.js +21 -24
  35. package/dist/services/openalex/api-client.js.map +1 -1
  36. package/package.json +1 -1
  37. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** @cyanheads/pubmed-mcp-server
4
- **Version:** 2.9.9
4
+ **Version:** 2.10.0
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
 
@@ -246,7 +246,7 @@ src/
246
246
  parsing/ # XML parsers (article, esummary, PMC)
247
247
  formatting/ # Citation formatter (APA, MLA, BibTeX, RIS)
248
248
  mcp-server/
249
- tools/definitions/ # 9 tool definitions (*.tool.ts)
249
+ tools/definitions/ # 11 tool definitions (*.tool.ts)
250
250
  resources/definitions/ # database-info.resource.ts
251
251
  prompts/definitions/ # research-plan.prompt.ts
252
252
  ```
package/CLAUDE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** @cyanheads/pubmed-mcp-server
4
- **Version:** 2.9.9
4
+ **Version:** 2.10.0
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
 
@@ -246,7 +246,7 @@ src/
246
246
  parsing/ # XML parsers (article, esummary, PMC)
247
247
  formatting/ # Citation formatter (APA, MLA, BibTeX, RIS)
248
248
  mcp-server/
249
- tools/definitions/ # 9 tool definitions (*.tool.ts)
249
+ tools/definitions/ # 11 tool definitions (*.tool.ts)
250
250
  resources/definitions/ # database-info.resource.ts
251
251
  prompts/definitions/ # research-plan.prompt.ts
252
252
  ```
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
2
  <h1>@cyanheads/pubmed-mcp-server</h1>
3
3
  <p><b>Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms via MCP. STDIO or Streamable HTTP.</b>
4
- <div>10 Tools • 1 Resource • 1 Prompt</div>
4
+ <div>11 Tools • 1 Resource • 1 Prompt</div>
5
5
  </p>
6
6
  </div>
7
7
 
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- [![Version](https://img.shields.io/badge/Version-2.9.9-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/pubmed-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/pubmed-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pubmed-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.14-blueviolet.svg?style=flat-square)](https://bun.sh/)
12
+ [![Version](https://img.shields.io/badge/Version-2.10.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/pubmed-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/pubmed-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pubmed-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.14-blueviolet.svg?style=flat-square)](https://bun.sh/)
13
13
 
14
14
  </div>
15
15
 
@@ -31,12 +31,13 @@
31
31
 
32
32
  ## Tools
33
33
 
34
- 10 tools for working with PubMed, PubMed Central, and Europe PMC data:
34
+ 11 tools for working with PubMed, PubMed Central, and Europe PMC data:
35
35
 
36
36
  | Tool | Description |
37
37
  |:---|:---|
38
38
  | `pubmed_search_articles` | Search PubMed with full query syntax, field-specific filters, date ranges, pagination, and optional brief summaries |
39
39
  | `pubmed_europepmc_search` | Search Europe PMC for preprints, patents, Agricola, and EPMC-only OA records that don't surface in PubMed. Cursor-based pagination. |
40
+ | `pubmed_europepmc_fetch` | Fetch complete Europe PMC records — including the untruncated abstract — by `source` + `epmcId`, the only identifier many preprint, patent, and Agricola records carry |
40
41
  | `pubmed_fetch_articles` | Fetch full article metadata by PMIDs — abstract, authors, journal, MeSH terms, grants |
41
42
  | `pubmed_fetch_fulltext` | Fetch full-text articles via a chain: NCBI PMC EFetch → Europe PMC `fullTextXML` → Unpaywall. Accepts PMIDs, PMCIDs, or DOIs. |
42
43
  | `pubmed_format_citations` | Generate formatted citations in APA 7th, MLA 9th, BibTeX, RIS, or Vancouver (ICMJE/NLM) |
@@ -86,6 +87,7 @@ Fetch full-text articles via a three-stage chain: NCBI PMC EFetch → Europe PMC
86
87
  - Structured unavailable reasons (`not-found`, `no-pmc-fallback-disabled`, `no-epmc-fulltext`, `no-doi`, `no-oa`, `fetch-failed`, `parse-failed`, `service-error`) so callers can retry or explain to users without parsing text
87
88
  - Each `unavailable` entry carries `idType` (`pmid` / `pmcid` / `doi`) and `triedTiers` — per-tier outcomes (`not-attempted`, `miss`, `no-fulltext`, `service-error`, …) in execution order, so callers can see which stage failed and why
88
89
  - Section filtering by title (case-insensitive match, e.g. `["methods", "results"]`) and configurable max sections apply to PMC output
90
+ - Character budgets keep context size predictable: `maxCharacters` caps body text per article (PMC sections and subsections, or the Unpaywall body), `maxCharactersPerSection` caps a single PMC section, and `overflowMode` picks between `truncate` (fill sections in document order) and `outline` (split the budget evenly so every heading survives with an excerpt). Budgets run after the semantic filters, and a `truncation` object reports per-article and per-section character counts whenever anything was shortened
89
91
  - Up to 10 articles per request
90
92
 
91
93
  ---
@@ -98,6 +100,19 @@ Search Europe PMC (EBI/EMBL-EBI), a broader open-access biomedical corpus than P
98
100
  - Default sources `["MED", "PMC", "PPR"]`; pass `sources` to include `PAT` / `AGR`
99
101
  - Cursor-based pagination via `cursorMark` (unlike `pubmed_search_articles`, which uses offset) — `*` for the first page, return `nextCursorMark` for the next
100
102
  - Output discriminator on `source` plus optional `pmid` / `pmcId` / `doi` cross-walking
103
+ - `abstractSnippet` is capped at 400 characters to keep a page bounded; `abstractTruncated` says whether it was cut, and `pubmed_europepmc_fetch` returns the whole abstract for the records worth reading in full
104
+ - Disabled when `EUROPEPMC_ENABLED=false`; tool is not registered in that case
105
+
106
+ ---
107
+
108
+ ### `pubmed_europepmc_fetch`
109
+
110
+ Fetch complete Europe PMC records by `source` + `epmcId`, the detail counterpart to `pubmed_europepmc_search`.
111
+
112
+ - Returns the full, untruncated abstract as display-ready plain text — markup stripped, HTML entities decoded
113
+ - Addressed by the `source` and `epmcId` of a search hit, the only identifier preprint (`PPR`), patent (`PAT`), and Agricola (`AGR`) records reliably carry — `pubmed_fetch_articles` needs a PMID and `pubmed_fetch_fulltext` needs a PMCID, PMID, or DOI
114
+ - Up to 25 records per call, resolved in a single Europe PMC request
115
+ - Pairs unresolved requests back to the caller in `notFound` instead of failing the batch
101
116
  - Disabled when `EUROPEPMC_ENABLED=false`; tool is not registered in that case
102
117
 
103
118
  ---
@@ -355,7 +370,7 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
355
370
 
356
371
  | Directory | Purpose |
357
372
  |:---|:---|
358
- | `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Ten tools across PubMed, PMC, and Europe PMC. |
373
+ | `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Eleven tools across PubMed, PMC, and Europe PMC. |
359
374
  | `src/mcp-server/resources` | Resource definitions. Database info resource. |
360
375
  | `src/mcp-server/prompts` | Prompt definitions. Research plan prompt. |
361
376
  | `src/services/ncbi` | NCBI E-utilities service layer — API client, queue, parser, formatter. |
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import { findRelatedTool } from './mcp-server/tools/definitions/find-related.too
14
14
  import { formatCitationsTool } from './mcp-server/tools/definitions/format-citations.tool.js';
15
15
  import { lookupCitationTool } from './mcp-server/tools/definitions/lookup-citation.tool.js';
16
16
  import { lookupMeshTool } from './mcp-server/tools/definitions/lookup-mesh.tool.js';
17
+ import { pubmedEuropepmcFetchTool } from './mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js';
17
18
  import { pubmedEuropepmcSearchTool } from './mcp-server/tools/definitions/pubmed-europepmc-search.tool.js';
18
19
  import { searchArticlesTool } from './mcp-server/tools/definitions/search-articles.tool.js';
19
20
  import { spellCheckTool } from './mcp-server/tools/definitions/spell-check.tool.js';
@@ -32,7 +33,7 @@ const tools = [
32
33
  lookupMeshTool,
33
34
  lookupCitationTool,
34
35
  convertIdsTool,
35
- ...(config.europepmcEnabled ? [pubmedEuropepmcSearchTool] : []),
36
+ ...(config.europepmcEnabled ? [pubmedEuropepmcSearchTool, pubmedEuropepmcFetchTool] : []),
36
37
  ];
37
38
  await createApp({
38
39
  name: 'pubmed-mcp-server',
@@ -40,7 +41,7 @@ await createApp({
40
41
  tools,
41
42
  resources: [databaseInfoResource],
42
43
  prompts: [researchPlanPrompt],
43
- instructions: "Use the pubmed_* tools to search PubMed and PubMed Central, fetch article metadata and full text, format citations, and find related articles via NCBI's E-utilities. Articles are keyed by PMID (integer); PMC full text by PMCID (`PMC` prefix); most also carry a DOI. Typical flow: `pubmed_search_articles` → `pubmed_fetch_articles` → `pubmed_fetch_fulltext`. When PubMed itself comes up empty (preprints, EPMC-only OA), broaden via `pubmed_europepmc_search`. Prefer deterministic resolvers when inputs are structured: `pubmed_lookup_citation` for partial references, `pubmed_convert_ids` to crosswalk IDs. Refine queries with `pubmed_lookup_mesh` and `pubmed_spell_check`.",
44
+ instructions: "Use the pubmed_* tools to search PubMed and PubMed Central, fetch article metadata and full text, format citations, and find related articles via NCBI's E-utilities. Articles are keyed by PMID (integer); PMC full text by PMCID (`PMC` prefix); most also carry a DOI. Typical flow: `pubmed_search_articles` → `pubmed_fetch_articles` → `pubmed_fetch_fulltext`. When PubMed itself comes up empty (preprints, EPMC-only OA), broaden via `pubmed_europepmc_search`, then `pubmed_europepmc_fetch` with a hit's `source` + `epmcId` for its complete abstract. Prefer deterministic resolvers when inputs are structured: `pubmed_lookup_citation` for partial references, `pubmed_convert_ids` to crosswalk IDs. Refine queries with `pubmed_lookup_mesh` and `pubmed_spell_check`.",
44
45
  landing: {
45
46
  requireAuth: false,
46
47
  tagline: 'Search PubMed, fetch articles, generate citations, explore MeSH terms, and discover related research.',
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0DAA0D,CAAC;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yDAAyD,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;AACjC,MAAM,KAAK,GAAG;IACZ,kBAAkB;IAClB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,eAAe;IACf,cAAc;IACd,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;CAChE,CAAC;AAEF,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,mBAAmB;IAC1B,KAAK;IACL,SAAS,EAAE,CAAC,oBAAoB,CAAC;IACjC,OAAO,EAAE,CAAC,kBAAkB,CAAC;IAC7B,YAAY,EACV,iqBAAiqB;IACnqB,OAAO,EAAE;QACP,WAAW,EAAE,KAAK;QAClB,OAAO,EACL,uGAAuG;QACzG,QAAQ,EAAE,gDAAgD;QAC1D,KAAK,EAAE;YACL,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,kCAAkC,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC7E;gBACE,KAAK,EAAE,kBAAkB;gBACzB,IAAI,EAAE,8CAA8C;gBACpD,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,KAAK,EAAE,qBAAqB;gBAC5B,IAAI,EAAE,gDAAgD;gBACtD,QAAQ,EAAE,IAAI;aACf;YACD,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,4BAA4B,EAAE,QAAQ,EAAE,IAAI,EAAE;SAC9E;QACD,UAAU,EAAE;YACV,YAAY,EAAE,mBAAmB;YACjC,gBAAgB,EAAE,iBAAiB;YACnC,eAAe,EAAE,iBAAiB;SACnC;KACF;IACD,KAAK;QACH,eAAe,EAAE,CAAC;QAClB,oBAAoB,EAAE,CAAC;QACvB,oBAAoB,EAAE,CAAC;QACvB,mBAAmB,EAAE,CAAC;IACxB,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0DAA0D,CAAC;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yDAAyD,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;AACjC,MAAM,KAAK,GAAG;IACZ,kBAAkB;IAClB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,eAAe;IACf,cAAc;IACd,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,yBAAyB,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1F,CAAC;AAEF,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,mBAAmB;IAC1B,KAAK;IACL,SAAS,EAAE,CAAC,oBAAoB,CAAC;IACjC,OAAO,EAAE,CAAC,kBAAkB,CAAC;IAC7B,YAAY,EACV,2vBAA2vB;IAC7vB,OAAO,EAAE;QACP,WAAW,EAAE,KAAK;QAClB,OAAO,EACL,uGAAuG;QACzG,QAAQ,EAAE,gDAAgD;QAC1D,KAAK,EAAE;YACL,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,kCAAkC,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC7E;gBACE,KAAK,EAAE,kBAAkB;gBACzB,IAAI,EAAE,8CAA8C;gBACpD,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,KAAK,EAAE,qBAAqB;gBAC5B,IAAI,EAAE,gDAAgD;gBACtD,QAAQ,EAAE,IAAI;aACf;YACD,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,4BAA4B,EAAE,QAAQ,EAAE,IAAI,EAAE;SAC9E;QACD,UAAU,EAAE;YACV,YAAY,EAAE,mBAAmB;YACjC,gBAAgB,EAAE,iBAAiB;YACnC,eAAe,EAAE,iBAAiB;SACnC;KACF;IACD,KAAK;QACH,eAAe,EAAE,CAAC;QAClB,oBAAoB,EAAE,CAAC;QACvB,oBAAoB,EAAE,CAAC;QACvB,mBAAmB,EAAE,CAAC;IACxB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @fileoverview Text-cutting helper shared by the tool definitions that bound
3
+ * returned text to a character budget.
4
+ * @module src/mcp-server/tools/definitions/_text
5
+ */
6
+ /**
7
+ * Take at most `limit` UTF-16 code units from `text` without splitting a
8
+ * surrogate pair.
9
+ *
10
+ * `String.prototype.slice` cuts on a code-unit boundary, so a cut landing
11
+ * between the high and low half of an astral character — emoji, mathematical
12
+ * alphanumerics, CJK extensions — leaves a lone surrogate. It survives
13
+ * `JSON.stringify` as `\ud83e` and transports fine, then renders as U+FFFD once
14
+ * a client decodes it, and the string fails `String.prototype.isWellFormed()`.
15
+ *
16
+ * `limit` stays a ceiling: when the boundary would land mid-pair it backs off by
17
+ * one code unit, so the result can come back one unit short of the allowance.
18
+ * Callers that report character counts must measure the returned string rather
19
+ * than assume the allowance was spent exactly. (#93)
20
+ */
21
+ export declare function sliceCodeUnits(text: string, limit: number): string;
22
+ //# sourceMappingURL=_text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_text.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview Text-cutting helper shared by the tool definitions that bound
3
+ * returned text to a character budget.
4
+ * @module src/mcp-server/tools/definitions/_text
5
+ */
6
+ const HIGH_SURROGATE_FIRST = 0xd800;
7
+ const HIGH_SURROGATE_LAST = 0xdbff;
8
+ /**
9
+ * Take at most `limit` UTF-16 code units from `text` without splitting a
10
+ * surrogate pair.
11
+ *
12
+ * `String.prototype.slice` cuts on a code-unit boundary, so a cut landing
13
+ * between the high and low half of an astral character — emoji, mathematical
14
+ * alphanumerics, CJK extensions — leaves a lone surrogate. It survives
15
+ * `JSON.stringify` as `\ud83e` and transports fine, then renders as U+FFFD once
16
+ * a client decodes it, and the string fails `String.prototype.isWellFormed()`.
17
+ *
18
+ * `limit` stays a ceiling: when the boundary would land mid-pair it backs off by
19
+ * one code unit, so the result can come back one unit short of the allowance.
20
+ * Callers that report character counts must measure the returned string rather
21
+ * than assume the allowance was spent exactly. (#93)
22
+ */
23
+ export function sliceCodeUnits(text, limit) {
24
+ if (limit <= 0)
25
+ return '';
26
+ if (limit >= text.length)
27
+ return text;
28
+ const last = text.charCodeAt(limit - 1);
29
+ const splitsPair = last >= HIGH_SURROGATE_FIRST && last <= HIGH_SURROGATE_LAST;
30
+ return text.slice(0, splitsPair ? limit - 1 : limit);
31
+ }
32
+ //# sourceMappingURL=_text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_text.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEnC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa;IACxD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1B,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,IAAI,oBAAoB,IAAI,IAAI,IAAI,mBAAmB,CAAC;IAC/E,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACvD,CAAC"}
@@ -36,6 +36,12 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
36
36
  includeReferences: z.ZodDefault<z.ZodBoolean>;
37
37
  maxSections: z.ZodOptional<z.ZodNumber>;
38
38
  sections: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ maxCharacters: z.ZodOptional<z.ZodNumber>;
40
+ maxCharactersPerSection: z.ZodOptional<z.ZodNumber>;
41
+ overflowMode: z.ZodDefault<z.ZodEnum<{
42
+ outline: "outline";
43
+ truncate: "truncate";
44
+ }>>;
39
45
  }, z.core.$strip>, z.ZodObject<{
40
46
  articles: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
41
47
  source: z.ZodLiteral<"pmc">;
@@ -94,6 +100,7 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
94
100
  "html-markdown": "html-markdown";
95
101
  "pdf-text": "pdf-text";
96
102
  }>;
103
+ pmcId: z.ZodOptional<z.ZodString>;
97
104
  pmid: z.ZodOptional<z.ZodString>;
98
105
  pubmedUrl: z.ZodOptional<z.ZodString>;
99
106
  doi: z.ZodString;
@@ -116,6 +123,7 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
116
123
  }>;
117
124
  reason: z.ZodEnum<{
118
125
  "fetch-failed": "fetch-failed";
126
+ "no-body": "no-body";
119
127
  "no-doi": "no-doi";
120
128
  "no-epmc-fulltext": "no-epmc-fulltext";
121
129
  "no-oa": "no-oa";
@@ -133,6 +141,7 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
133
141
  outcome: z.ZodEnum<{
134
142
  "fetch-failed": "fetch-failed";
135
143
  miss: "miss";
144
+ "no-body": "no-body";
136
145
  "no-doi": "no-doi";
137
146
  "no-fulltext": "no-fulltext";
138
147
  "no-oa": "no-oa";
@@ -143,6 +152,32 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
143
152
  detail: z.ZodOptional<z.ZodString>;
144
153
  }, z.core.$strip>>;
145
154
  }, z.core.$strip>>>;
155
+ truncation: z.ZodOptional<z.ZodObject<{
156
+ mode: z.ZodEnum<{
157
+ outline: "outline";
158
+ truncate: "truncate";
159
+ }>;
160
+ maxCharacters: z.ZodOptional<z.ZodNumber>;
161
+ maxCharactersPerSection: z.ZodOptional<z.ZodNumber>;
162
+ originalCharacters: z.ZodNumber;
163
+ returnedCharacters: z.ZodNumber;
164
+ omittedSections: z.ZodNumber;
165
+ articles: z.ZodArray<z.ZodObject<{
166
+ id: z.ZodString;
167
+ source: z.ZodEnum<{
168
+ pmc: "pmc";
169
+ unpaywall: "unpaywall";
170
+ }>;
171
+ originalCharacters: z.ZodNumber;
172
+ returnedCharacters: z.ZodNumber;
173
+ sections: z.ZodOptional<z.ZodArray<z.ZodObject<{
174
+ title: z.ZodOptional<z.ZodString>;
175
+ originalCharacters: z.ZodNumber;
176
+ returnedCharacters: z.ZodNumber;
177
+ truncated: z.ZodBoolean;
178
+ }, z.core.$strip>>>;
179
+ }, z.core.$strip>>;
180
+ }, z.core.$strip>>;
146
181
  }, z.core.$strip>, readonly [{
147
182
  readonly reason: 'queue_full';
148
183
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.RateLimited;
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-fulltext.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fetch-fulltext.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AA8T/D;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CA+BT;AAID,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuhB5B,CAAC"}
1
+ {"version":3,"file":"fetch-fulltext.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fetch-fulltext.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAmoB/D;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CA+BT;AAID,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2rB5B,CAAC"}