@cyanheads/pubmed-mcp-server 2.10.13 → 2.10.15

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 (154) hide show
  1. package/AGENTS.md +24 -6
  2. package/CLAUDE.md +24 -6
  3. package/README.md +7 -7
  4. package/changelog/2.0.x/2.0.0.md +32 -0
  5. package/changelog/2.0.x/2.0.1.md +32 -0
  6. package/changelog/2.1.x/2.1.0.md +17 -0
  7. package/changelog/2.1.x/2.1.1.md +29 -0
  8. package/changelog/2.1.x/2.1.2.md +18 -0
  9. package/changelog/2.1.x/2.1.3.md +10 -0
  10. package/changelog/2.1.x/2.1.4.md +12 -0
  11. package/changelog/2.1.x/2.1.5.md +18 -0
  12. package/changelog/2.1.x/2.1.6.md +15 -0
  13. package/changelog/2.10.x/2.10.0.md +17 -0
  14. package/changelog/2.10.x/2.10.1.md +14 -0
  15. package/changelog/2.10.x/2.10.10.md +22 -0
  16. package/changelog/2.10.x/2.10.11.md +21 -0
  17. package/changelog/2.10.x/2.10.12.md +14 -0
  18. package/changelog/2.10.x/2.10.13.md +28 -0
  19. package/changelog/2.10.x/2.10.14.md +29 -0
  20. package/changelog/2.10.x/2.10.15.md +28 -0
  21. package/changelog/2.10.x/2.10.2.md +13 -0
  22. package/changelog/2.10.x/2.10.3.md +26 -0
  23. package/changelog/2.10.x/2.10.4.md +11 -0
  24. package/changelog/2.10.x/2.10.5.md +31 -0
  25. package/changelog/2.10.x/2.10.6.md +30 -0
  26. package/changelog/2.10.x/2.10.7.md +17 -0
  27. package/changelog/2.10.x/2.10.8.md +22 -0
  28. package/changelog/2.10.x/2.10.9.md +15 -0
  29. package/changelog/2.2.x/2.2.0.md +67 -0
  30. package/changelog/2.2.x/2.2.1.md +10 -0
  31. package/changelog/2.2.x/2.2.2.md +20 -0
  32. package/changelog/2.2.x/2.2.3.md +17 -0
  33. package/changelog/2.2.x/2.2.4.md +34 -0
  34. package/changelog/2.2.x/2.2.5.md +10 -0
  35. package/changelog/2.2.x/2.2.6.md +17 -0
  36. package/changelog/2.3.x/2.3.0.md +27 -0
  37. package/changelog/2.3.x/2.3.1.md +15 -0
  38. package/changelog/2.3.x/2.3.10.md +20 -0
  39. package/changelog/2.3.x/2.3.11.md +21 -0
  40. package/changelog/2.3.x/2.3.2.md +27 -0
  41. package/changelog/2.3.x/2.3.3.md +38 -0
  42. package/changelog/2.3.x/2.3.4.md +21 -0
  43. package/changelog/2.3.x/2.3.5.md +24 -0
  44. package/changelog/2.3.x/2.3.6.md +26 -0
  45. package/changelog/2.3.x/2.3.7.md +31 -0
  46. package/changelog/2.3.x/2.3.8.md +19 -0
  47. package/changelog/2.3.x/2.3.9.md +22 -0
  48. package/changelog/2.4.x/2.4.0.md +34 -0
  49. package/changelog/2.4.x/2.4.1.md +32 -0
  50. package/changelog/2.5.x/2.5.0.md +35 -0
  51. package/changelog/2.5.x/2.5.1.md +32 -0
  52. package/changelog/2.5.x/2.5.2.md +23 -0
  53. package/changelog/2.5.x/2.5.3.md +22 -0
  54. package/changelog/2.5.x/2.5.5.md +52 -0
  55. package/changelog/2.5.x/2.5.6.md +33 -0
  56. package/changelog/2.6.x/2.6.0.md +32 -0
  57. package/changelog/2.6.x/2.6.1.md +26 -0
  58. package/changelog/2.6.x/2.6.10.md +16 -0
  59. package/changelog/2.6.x/2.6.11.md +24 -0
  60. package/changelog/2.6.x/2.6.12.md +29 -0
  61. package/changelog/2.6.x/2.6.2.md +23 -0
  62. package/changelog/2.6.x/2.6.3.md +17 -0
  63. package/changelog/2.6.x/2.6.4.md +21 -0
  64. package/changelog/2.6.x/2.6.5.md +30 -0
  65. package/changelog/2.6.x/2.6.6.md +25 -0
  66. package/changelog/2.6.x/2.6.7.md +37 -0
  67. package/changelog/2.6.x/2.6.8.md +15 -0
  68. package/changelog/2.6.x/2.6.9.md +36 -0
  69. package/changelog/2.7.x/2.7.0.md +41 -0
  70. package/changelog/2.7.x/2.7.1.md +21 -0
  71. package/changelog/2.7.x/2.7.10.md +13 -0
  72. package/changelog/2.7.x/2.7.11.md +15 -0
  73. package/changelog/2.7.x/2.7.2.md +22 -0
  74. package/changelog/2.7.x/2.7.3.md +18 -0
  75. package/changelog/2.7.x/2.7.4.md +15 -0
  76. package/changelog/2.7.x/2.7.5.md +34 -0
  77. package/changelog/2.7.x/2.7.6.md +14 -0
  78. package/changelog/2.7.x/2.7.7.md +14 -0
  79. package/changelog/2.7.x/2.7.8.md +18 -0
  80. package/changelog/2.7.x/2.7.9.md +16 -0
  81. package/changelog/2.8.x/2.8.0.md +23 -0
  82. package/changelog/2.9.x/2.9.0.md +21 -0
  83. package/changelog/2.9.x/2.9.1.md +12 -0
  84. package/changelog/2.9.x/2.9.10.md +15 -0
  85. package/changelog/2.9.x/2.9.2.md +21 -0
  86. package/changelog/2.9.x/2.9.3.md +11 -0
  87. package/changelog/2.9.x/2.9.4.md +24 -0
  88. package/changelog/2.9.x/2.9.5.md +20 -0
  89. package/changelog/2.9.x/2.9.6.md +22 -0
  90. package/changelog/2.9.x/2.9.7.md +26 -0
  91. package/changelog/2.9.x/2.9.8.md +15 -0
  92. package/changelog/2.9.x/2.9.9.md +35 -0
  93. package/changelog/template.md +151 -0
  94. package/dist/index.js +1 -0
  95. package/dist/index.js.map +1 -1
  96. package/dist/mcp-server/tools/definitions/convert-ids.tool.d.ts +7 -2
  97. package/dist/mcp-server/tools/definitions/convert-ids.tool.d.ts.map +1 -1
  98. package/dist/mcp-server/tools/definitions/fetch-articles.tool.d.ts +7 -2
  99. package/dist/mcp-server/tools/definitions/fetch-articles.tool.d.ts.map +1 -1
  100. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts +14 -5
  101. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts.map +1 -1
  102. package/dist/mcp-server/tools/definitions/find-related.tool.d.ts +0 -60
  103. package/dist/mcp-server/tools/definitions/find-related.tool.d.ts.map +1 -1
  104. package/dist/mcp-server/tools/definitions/find-related.tool.js +4 -4
  105. package/dist/mcp-server/tools/definitions/find-related.tool.js.map +1 -1
  106. package/dist/mcp-server/tools/definitions/format-citations.tool.d.ts +7 -2
  107. package/dist/mcp-server/tools/definitions/format-citations.tool.d.ts.map +1 -1
  108. package/dist/mcp-server/tools/definitions/lookup-citation.tool.d.ts +7 -2
  109. package/dist/mcp-server/tools/definitions/lookup-citation.tool.d.ts.map +1 -1
  110. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts +7 -2
  111. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts.map +1 -1
  112. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts +6 -3
  113. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts.map +1 -1
  114. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts +6 -3
  115. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts.map +1 -1
  116. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js +1 -1
  117. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js.map +1 -1
  118. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts +7 -2
  119. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts.map +1 -1
  120. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts +7 -2
  121. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts.map +1 -1
  122. package/dist/services/error-contracts.d.ts +30 -13
  123. package/dist/services/error-contracts.d.ts.map +1 -1
  124. package/dist/services/error-contracts.js +30 -13
  125. package/dist/services/error-contracts.js.map +1 -1
  126. package/dist/services/europe-pmc/api-client.d.ts +14 -2
  127. package/dist/services/europe-pmc/api-client.d.ts.map +1 -1
  128. package/dist/services/europe-pmc/api-client.js +30 -4
  129. package/dist/services/europe-pmc/api-client.js.map +1 -1
  130. package/dist/services/europe-pmc/europe-pmc-service.d.ts +20 -1
  131. package/dist/services/europe-pmc/europe-pmc-service.d.ts.map +1 -1
  132. package/dist/services/europe-pmc/europe-pmc-service.js +98 -50
  133. package/dist/services/europe-pmc/europe-pmc-service.js.map +1 -1
  134. package/dist/services/ncbi/ncbi-service.d.ts +18 -26
  135. package/dist/services/ncbi/ncbi-service.d.ts.map +1 -1
  136. package/dist/services/ncbi/ncbi-service.js +111 -127
  137. package/dist/services/ncbi/ncbi-service.js.map +1 -1
  138. package/dist/services/ncbi/request-queue.d.ts +22 -30
  139. package/dist/services/ncbi/request-queue.d.ts.map +1 -1
  140. package/dist/services/ncbi/request-queue.js +29 -128
  141. package/dist/services/ncbi/request-queue.js.map +1 -1
  142. package/dist/services/ncbi/response-handler.d.ts +14 -1
  143. package/dist/services/ncbi/response-handler.d.ts.map +1 -1
  144. package/dist/services/ncbi/response-handler.js +65 -9
  145. package/dist/services/ncbi/response-handler.js.map +1 -1
  146. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  147. package/dist/services/openalex/openalex-service.js +3 -10
  148. package/dist/services/openalex/openalex-service.js.map +1 -1
  149. package/package.json +20 -11
  150. package/server.json +3 -3
  151. package/dist/services/retry-policy.d.ts +0 -18
  152. package/dist/services/retry-policy.d.ts.map +0 -1
  153. package/dist/services/retry-policy.js +0 -21
  154. package/dist/services/retry-policy.js.map +0 -1
@@ -0,0 +1,15 @@
1
+ ---
2
+ summary: "pubmed_fetch_fulltext: EPMC/PMCID query builders fixed, front-matter-only records fall through the retrieval chain instead of being dropped, pmcids input reaches Unpaywall via a resolved DOI, and Unpaywall articles carry a pmcId backlink. Dead 404-handling branches removed from the Europe PMC and OpenAlex clients."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.10 — 2026-07-26
8
+
9
+ ## Fixed
10
+
11
+ - **`pubmed_europepmc_search` / `pubmed_fetch_fulltext` EPMC query builders** — `EXT_ID:"<pmid>" AND SRC:MED` and `PMCID:"PMC<digits>" AND SRC:PMC` matched zero records: Europe PMC requires identifier tokens combined with `AND SRC:` to be unquoted, and the canonical record for a PMCID lookup has `source: MED`, so `SRC:PMC` excluded the very record being sought. Query builders now emit `EXT_ID:<pmid> AND SRC:MED` and `PMCID:<PMC<digits>>` (the `SRC:PMC` filter dropped); `pubmed_europepmc_search`'s `query` `.describe()` updated to match. ([#85](https://github.com/cyanheads/pubmed-mcp-server/issues/85))
12
+ - **`pubmed_fetch_fulltext` front-matter-only PMC/EPMC records** — a PMC article with front matter and abstract but no `<body>` (publishers that block full-text XML download still return a populated `<front>`) was previously demoted like any other retrieved article. It's now detected pre-filter and routed through the fallback chain like a miss, so a later tier can still recover it. New `no-body` member on the `UnavailableReasonSchema` and `TierOutcomeSchema` output enums, plus an `enrichment.notice` naming the affected id(s) when no tier recovers a copy. ([#86](https://github.com/cyanheads/pubmed-mcp-server/issues/86))
13
+ - **`pubmed_fetch_fulltext` `pmcids` input skipped Unpaywall entirely** — PMC/EPMC misses on `pmcids` input never reached the Unpaywall fallback tier because the DOI needed to query it was never resolved. Now threads the DOI from the Europe PMC hit (when present) or the NCBI ID Converter through to Unpaywall. ([#88](https://github.com/cyanheads/pubmed-mcp-server/issues/88))
14
+ - **Unpaywall articles from `pmcids` input lacked a PMCID backlink** — `UnpaywallArticleSchema` gains an optional `pmcId` field so a batch's `articles[]` and `unavailable[]` key on the same identifier for `pmcids` input; `format()`'s heading and metadata block now surface the PMCID when present. ([#92](https://github.com/cyanheads/pubmed-mcp-server/issues/92))
15
+ - **Europe PMC / OpenAlex 404 handling** — `fetchWithTimeout` throws a status-mapped `McpError` for any non-2xx response rather than returning the failing `Response`, so the `response.status === 404` / `!response.ok` branches in `src/services/europe-pmc/api-client.ts` and `src/services/openalex/api-client.ts` (plus four sibling methods) were unreachable; a genuine 404 was rethrown as a generic error and surfaced as `service-error` instead of the documented `no-fulltext`/`null` outcome. Converted to catch-block classification on `error.code`, and corrected the test mocks that had resolved with a non-2xx `Response`. ([#90](https://github.com/cyanheads/pubmed-mcp-server/issues/90))
@@ -0,0 +1,21 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.10.5: ctx.enrich.total(), z.stringbool(), server identity fields; totalCount enrichment rename; .mcpbignore anchored"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.2 — 2026-06-11
8
+
9
+ ## Changed
10
+
11
+ - **`totalFound` enrichment key renamed to `totalCount`** across `pubmed_search_articles`, `pubmed_find_related`, `pubmed_lookup_mesh`, and `pubmed_europepmc_search`. Pagination overshoot notices updated to reference `totalCount`. This key appears in `structuredContent` enrichment blocks and is consumed by agents reading result-set metadata.
12
+ - **`PUBMED_EUROPEPMC_ENABLED` now uses `z.stringbool()` semantics.** Accepts `true/false/1/0/yes/no/on/off` (case-insensitive); `yes` and `on` now parse truthy. Unrecognized values fail at startup instead of silently coercing to `false`. Previously only `true`/`1` were truthy.
13
+ - **Server identity fields added to `createApp()`**: `name`, `title`, `websiteUrl`, and `description` are now set, surfaced in the `initialize` response and `/.well-known/mcp.json`.
14
+ - **`.mcpbignore` dev-dir patterns anchored to root**: `/.claude/`, `/.agents/`, `/skills/` now use leading `/` so they cannot strip nested `node_modules` runtime paths.
15
+ - **`ctx.enrich.total()` migration**: enrichment total counts are now set via the framework's `ctx.enrich.total()` helper rather than as inline `totalFound` fields in the `ctx.enrich()` call.
16
+
17
+ ## Dependencies
18
+
19
+ - `@cyanheads/mcp-ts-core` ^0.9.21 → ^0.10.5
20
+ - `sanitize-html` ^2.17.4 → ^2.17.5
21
+ - `@types/node` ^25.9.2 → ^25.9.3
@@ -0,0 +1,11 @@
1
+ ---
2
+ summary: "serverInfo title corrected to machine name pubmed-mcp-server"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.3 — 2026-06-11
8
+
9
+ ## Fixed
10
+
11
+ - **`createApp()` `title`** corrected to `pubmed-mcp-server` (was the Title Case display string `'PubMed MCP Server'` introduced in 2.9.2). MCP clients display `serverInfo.title` in their UI — this aligns the displayed name with the machine name convention.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.10.6: post-pack bundle cleaner, packaging identity checks; lint-packaging checks 8–9 synced; orchestrations skill v1.3"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.4 — 2026-06-11
8
+
9
+ ## Changed
10
+
11
+ - **`src/index.ts`** — removed `websiteUrl` and `description` from `createApp()` options; canonical source is `package.json` (framework derives description from it); identity pair `name`/`title` both set to `'pubmed-mcp-server'`.
12
+ - **`scripts/lint-packaging.ts`** — synced from mcp-ts-core 0.10.6 template: adds check 8 (post-bundle content guard: flags `node_modules/**` agent-doc entries in built `.mcpb`) and check 9 (entrypoint identity: `name`/`title` in `createApp()` / `createWorkerHandler()` and `manifest.json` `display_name` must equal the unscoped package name). `checkBundleContent` refactored to accept raw content string; `KNOWN_DEV_DIRS` / `CRITICAL_RUNTIME_PATHS` / `AGENT_DOC_ENTRY` exported for unit testing.
13
+ - **`package.json` `bundle` script** — appended `&& bun run scripts/clean-mcpb.ts dist/pubmed-mcp-server.mcpb` after `mcpb pack`; strips dependency-shipped agent docs from the bundle.
14
+ - **`skills/orchestrations` v1.3** — Phase 4 close-loop wording: one what-landed comment per shipped issue, then a bare close; bare "Fixed in v\<version\>" trailer replaced.
15
+ - **`skills/polish-docs-meta` v2.7** — adds `name`/`title` identity requirement and updated `bundle` description.
16
+ - **`CLAUDE.md` / `AGENTS.md`** — framework version `^0.10.5 → ^0.10.6`; identity example corrected; `bundle` description updated.
17
+
18
+ ## Added
19
+
20
+ - **`scripts/clean-mcpb.ts`** — post-pack bundle cleaner: runs `mcpb clean`, then strips `node_modules/**` agent-doc entries (`skills/`, `.claude/`, `.agents/` trees and `SKILL.md` files) that root-anchored `.mcpbignore` patterns cannot reach. Wired into the `bundle` script. (mcp-ts-core [#230](https://github.com/cyanheads/mcp-ts-core/issues/230))
21
+
22
+ ## Dependencies
23
+
24
+ - `@cyanheads/mcp-ts-core` ^0.10.5 → ^0.10.6
@@ -0,0 +1,20 @@
1
+ ---
2
+ summary: "Fixes: transient NCBI eutils 500s now reclassify to ServiceUnavailable and retry; pubmed_lookup_mesh returns the canonical MeSH DescriptorUI with a new entrezUid field"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.5 — 2026-06-13
8
+
9
+ ## Fixed
10
+
11
+ - **`NcbiApiClient` eutils 500 retry** — `getRequest`/`postRequest` now issue plain `fetch` (via a shared `buildTimeoutSignal` helper) instead of `fetchWithTimeout`, which threw on any non-2xx before the status could be read. The `if (!response.ok)` reclassification in `makeRequest` is now reachable, so NCBI's transient HTTP 500s map to `ServiceUnavailable` and are retried by `NcbiService.withRetry`; HTTP 501 stays `InternalError` (not transient). ([#70](https://github.com/cyanheads/pubmed-mcp-server/issues/70))
12
+ - **`pubmed_lookup_mesh` `meshId`** — now returns the canonical MeSH DescriptorUI (e.g. `D003924`) instead of NCBI's Entrez UID. `decodeMeshDescriptorUi` maps the 8-digit UID's two-digit prefix to its letter (`67→C`, `68→D`, `81→Q`); non-decodable UIDs (e.g. 7-digit supplementary-concept IDs) fall back to the raw value. ([#71](https://github.com/cyanheads/pubmed-mcp-server/issues/71))
13
+
14
+ ## Added
15
+
16
+ - **`pubmed_lookup_mesh` `entrezUid`** — new output field carrying the raw NCBI Entrez UID, the join key for E-utilities (`eSummary`/`eFetch` `db=mesh`); rendered in `format()` as **Entrez UID**. ([#71](https://github.com/cyanheads/pubmed-mcp-server/issues/71))
17
+
18
+ ## Dependencies
19
+
20
+ - `@biomejs/biome` ^2.4.16 → ^2.5.0
@@ -0,0 +1,22 @@
1
+ ---
2
+ summary: "Output cleanups: convert_ids accepts mixed PMC/bare-digit batches; europepmc_search and fetch_articles strip leaked markup and decode entities; europepmc_search splits its silent-rejection diagnosis from its recovery hint; lookup_mesh drops non-navigable SCR tree pointers"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.6 — 2026-06-18
8
+
9
+ ## Fixed
10
+
11
+ - **`pubmed_convert_ids` mixed PMCID batches** — `NcbiService.idConvert` now canonicalizes bare-digit PMCIDs to `PMC`+digits before the PMC ID Converter call, so a batch mixing `PMC3531190` and `3531190` resolves like a homogeneous one instead of being rejected wholesale (HTTP 400). The `pmcid` format hint (both `ID_CONVERT_FORMAT_HINTS` and the tool's `ids` `.describe()`) now states bare digits are accepted. ([#73](https://github.com/cyanheads/pubmed-mcp-server/issues/73))
12
+ - **`pubmed_europepmc_search` `abstractSnippet`** — normalized to display-ready plain text via a new `toDisplayText` helper: strips structural JATS/HTML tags, decodes HTML entities, and removes soft hyphens (U+00AD) before truncation, so the snippet budget holds text rather than markup and stray soft hyphens don't corrupt token matching. ([#74](https://github.com/cyanheads/pubmed-mcp-server/issues/74))
13
+ - **`pubmed_fetch_articles` `grantList`** — `extractGrants` now decodes the residual `&amp;` that NCBI's double-encoding leaves after the XML parser's single decode pass, so `grantId`/`acronym`/`agency`/`country` surface as `CSR&D` rather than `CSR&amp;D`. ([#74](https://github.com/cyanheads/pubmed-mcp-server/issues/74))
14
+ - **`pubmed_europepmc_search` silent-rejection error** — the version-only-envelope throw now passes a distinct diagnosis as the message and an actionable next step as `recovery.hint`, instead of the same string for both. Previously the framework rendered byte-identical `Error:`/`Recovery:` blocks. ([#75](https://github.com/cyanheads/pubmed-mcp-server/issues/75))
15
+ - **`pubmed_lookup_mesh` `treeNumbers`** — `extractTreeNumbers` now drops `@`-prefixed values, which supplementary concept records (SCRs) surface in the `TreeNum` field as non-navigable mapped-heading pointers (e.g. `@218176`). `treeNumbers` now holds only real tree numbers and is omitted for SCRs; its `.describe()` documents this. ([#76](https://github.com/cyanheads/pubmed-mcp-server/issues/76))
16
+
17
+ ## Dependencies
18
+
19
+ - `defuddle` ^0.18.1 → ^0.19.0
20
+ - `fast-xml-parser` ^5.8.0 → ^5.9.2
21
+ - `vitest` ^4.1.8 → ^4.1.9
22
+ - `@vitest/coverage-istanbul` ^4.1.8 → ^4.1.9
@@ -0,0 +1,26 @@
1
+ ---
2
+ summary: "Adopt mcp-ts-core 0.10.9: devcheck gains a Dependency Specifiers guard (floating latest/*/dist-tags) and plugin-manifest checks in lint:packaging; fresh-scaffold git guards; 14 skills re-synced; dependency refresh"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.7 — 2026-06-20
8
+
9
+ ## Added
10
+
11
+ - **`Dependency Specifiers` devcheck step** — new `scripts/check-dependency-specifiers.ts` (flag `--no-dep-specifiers`) hard-fails on floating specifiers (`latest`, `*`, `next`/`beta`/`canary`/`rc`) in `package.json`'s dependency sections and `bun.lock`'s `workspaces` map, catching the case where `bun update --latest` writes a literal `latest` dist-tag into the lock and lets the next `bun install` re-resolve past the manifest range. Static and local — runs in the default and `--fast` passes. ([mcp-ts-core#246](https://github.com/cyanheads/mcp-ts-core/issues/246))
12
+ - **Plugin marketplace manifest checks in `lint:packaging`** — `scripts/lint-packaging.ts` check 10 validates `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and `.codex-plugin/mcp.json`: non-empty descriptions, display fields carrying the unscoped machine name, and the `npx -y` install arg carrying the full scoped package name. Gated by the new `devcheck.config.json` `packaging.pluginManifests` flag (default on; set here). ([mcp-ts-core#240](https://github.com/cyanheads/mcp-ts-core/issues/240))
13
+
14
+ ## Changed
15
+
16
+ - **14 `skills/<name>/SKILL.md` re-synced** from mcp-ts-core 0.10.7–0.10.9 — `metadata.version` bumps and body drift: `add-tool` 2.14→2.15, `api-auth` 1.1→1.2, `api-canvas` 1.6→1.7, `api-config` 1.7→1.8, `api-context` 1.8→1.9, `api-errors` 1.6→1.7, `api-services` 1.3→1.4, `api-telemetry` 1.0→1.2, `field-test` 2.5→2.6, `git-wrapup` 1.2→1.4, `orchestrations` 1.3→1.4, `polish-docs-meta` 2.7→2.9, `report-issue-local` 1.5→1.6, `tool-defs-analysis` 1.2→1.3.
17
+
18
+ ## Fixed
19
+
20
+ - **Fresh-scaffold devcheck guards** — `devcheck.ts` (TODOs/FIXMEs, Tracked Secrets, Framework Antipatterns), `check-framework-antipatterns.ts`, and `build-changelog.ts --check` now skip cleanly when `.git` is absent, and `check-skill-versions.ts` skips a `SKILL.md` deleted from the worktree, instead of exiting 128 / crashing with ENOENT. ([mcp-ts-core#242](https://github.com/cyanheads/mcp-ts-core/issues/242), [#243](https://github.com/cyanheads/mcp-ts-core/issues/243), [#237](https://github.com/cyanheads/mcp-ts-core/issues/237))
21
+
22
+ ## Dependencies
23
+
24
+ - `@cyanheads/mcp-ts-core` ^0.10.6 → ^0.10.9
25
+ - `fast-xml-parser` ^5.9.2 → ^5.9.3
26
+ - `@types/node` ^25.9.3 → ^26.0.0
@@ -0,0 +1,15 @@
1
+ ---
2
+ summary: "pubmed_fetch_fulltext surfaces a recovery notice when a sections filter removes every body section from an article that had one — naming the requested terms and affected article ids, still returning the article; detected on both the PMC and Europe PMC paths. Adopts mcp-ts-core 0.10.10."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.8 — 2026-06-30
8
+
9
+ ## Added
10
+
11
+ - **`pubmed_fetch_fulltext` section-filter-miss notice** — when a `sections` filter removes every body section from an article that had sections upstream, the tool surfaces a recovery notice via a new `enrichment.notice` block (emitted through `ctx.enrich.notice`) instead of silently returning an empty body. The notice names the requested section terms and the affected article id(s), distinguishes a filtered-empty body from one absent upstream, and suggests retrying without `sections` or filtering on broader headings (Introduction, Methods, Results, Discussion). The article is still returned with its empty body — not an error — and the miss is detected on both the PMC EFetch and Europe PMC paths. ([#80](https://github.com/cyanheads/pubmed-mcp-server/issues/80))
12
+
13
+ ## Dependencies
14
+
15
+ - `@cyanheads/mcp-ts-core` ^0.10.9 → ^0.10.10 (framework js-yaml v4→v5 migration and biome 2.5.1; no consumer change — this server installs no js-yaml directly)
@@ -0,0 +1,35 @@
1
+ ---
2
+ summary: "pubmed_lookup_mesh gets true upstream totalCount plus offset/nextOffset pagination; pubmed_lookup_citation stops false-flagging authors ranked 4th or later; pubmed_spell_check threads ctx.signal into ESpell. Adopts mcp-ts-core 0.11.0."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 2.9.9 — 2026-07-26
8
+
9
+ ## Added
10
+
11
+ - **`pubmed_lookup_mesh` offset pagination** — new `offset` input (default `0`) and `nextOffset` output let callers page past the `maxResults` cap; `nextOffset` is omitted on the last page as the end-of-results signal. ([#84](https://github.com/cyanheads/pubmed-mcp-server/issues/84))
12
+
13
+ ## Changed
14
+
15
+ - **`pubmed_lookup_mesh` `totalCount`** now reports the true upstream match count from `eSearch`'s `count` field instead of the number of records returned on the page. ([#82](https://github.com/cyanheads/pubmed-mcp-server/issues/82))
16
+
17
+ ## Fixed
18
+
19
+ - **`pubmed_lookup_mesh` pinned exact-match double-serve** — the exact-descriptor match is now held back on every page it ranks into, not just the first; a page consisting solely of the already-served pinned match returns an explanatory `enrichment.notice` instead of an empty or duplicated result. ([#91](https://github.com/cyanheads/pubmed-mcp-server/issues/91))
20
+ - **`pubmed_lookup_citation` false `author_mismatch` warning** — the mismatch check now verifies the queried author against the full author roster (`authorNames`) instead of the `authors` display string, which truncates to three names plus "et al." and was flagging genuine fourth-or-later authors as mismatches. `ESummaryDocumentSummary` parsing and `ParsedBriefSummary` gain an `authorNames: string[]` field alongside the existing `authors` display string. ([#87](https://github.com/cyanheads/pubmed-mcp-server/issues/87))
21
+ - **`pubmed_spell_check` dropped `ctx.signal`** — the handler now passes `{ signal: ctx.signal }` into `eSpell`, so request cancellation reaches the NCBI ESpell call. Also fixes a stale `pubmed_spell` log message to `pubmed_spell_check`. ([#89](https://github.com/cyanheads/pubmed-mcp-server/issues/89))
22
+ - **`pubmed_format_citations` description** — replaced "styles"/"style" with "formats"/"format" for accuracy.
23
+ - **Noisy error-path telemetry on expected 404s** — `expectedStatuses` added to the `fetchWithTimeout` call sites in `src/services/europe-pmc/api-client.ts` (404), `src/services/openalex/api-client.ts` (404), and `src/services/unpaywall/unpaywall-service.ts` (404, 422), so upstream responses these services already treat as expected "not found" outcomes no longer classify as errors.
24
+
25
+ ## Dependencies
26
+
27
+ - `@cyanheads/mcp-ts-core` ^0.10.10 → ^0.11.0
28
+ - `typescript` ^6.0.3 → ^7.0.2
29
+ - `bun` (packageManager) 1.3.2 → 1.3.14; `engines.bun` floor relaxed `>=1.3.2` → `>=1.3.0`
30
+ - `@biomejs/biome` ^2.5.0 → ^2.5.5, `@types/node` ^26.0.0 → ^26.1.1, `@vitest/coverage-istanbul`/`vitest` ^4.1.9 → ^4.1.10, `fast-check` ^4.8.0 → ^4.9.0, `ignore` ^7.0.5 → ^7.0.6, `tsc-alias` ^1.8.17 → ^1.9.1
31
+ - `defuddle` ^0.19.0 → ^0.19.2, `fast-xml-parser` ^5.9.3 → ^5.10.1, `linkedom` ^0.18.12 → ^0.18.13, `sanitize-html` ^2.17.5 → ^2.17.6
32
+ - Added `@socketsecurity/bun-security-scanner` ^1.1.2 as a dev dependency, wired as the `bunfig.toml` `[install.security]` scanner and a `devcheck.config.json` known-dep entry
33
+ - New `package.json` `overrides` block pins nested transitive copies: `@hono/node-server` ^2.0.11, `brace-expansion` ^2.1.2, `fast-uri` ^3.1.4, `postcss` ^8.5.22
34
+ - `Dockerfile` — `oven/bun:1.3` → `oven/bun:1.3.14` (build and production stages), `bun install` steps gain `--ignore-scripts` and a BuildKit cache mount on `/root/.bun/install/cache`
35
+ - `bunfig.toml` — `install.minimumReleaseAge` set to 259200s (3 days), excluding `@cyanheads/mcp-ts-core`
@@ -0,0 +1,151 @@
1
+ ---
2
+ # FORMAT REFERENCE — do not edit. Copy this file to
3
+ # `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.8.x/0.8.6.md`)
4
+ # to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
5
+ # with a concrete date.
6
+
7
+ # Required. One-line GitHub Release-style headline. 350 character cap — a
8
+ # ceiling, not a target. Default short and scannable. Don't pad, don't stitch
9
+ # unrelated changes with commas/semicolons into an inventory — pick the one
10
+ # headline the release is about. Quotes required: unquoted YAML treats
11
+ # `: ` inside the value as a key separator and fails GitHub's strict parser.
12
+ summary: ""
13
+
14
+ # Set `true` when consumers must change code to upgrade: API removals,
15
+ # signature changes, config renames, behavior changes that break existing
16
+ # usage. Flagged as `Breaking` in the rollup.
17
+ breaking: false
18
+
19
+ # Set `true` ONLY for a security fix in THIS project's own source code — a
20
+ # vulnerability or hardening in code you ship. A dependency or transitive CVE
21
+ # bump is routine maintenance, NOT a security release: record it under
22
+ # `## Dependencies` (with the advisory ID) and leave this `false`. When true,
23
+ # pairs with the `## Security` section below and flags `Security` in the rollup.
24
+ security: false
25
+
26
+ # Optional free-form notes for maintenance agents processing this release.
27
+ # Not rendered in CHANGELOG — consumed by agents running `maintenance` on
28
+ # downstream servers. ADOPTION STEPS ONLY — new files to create, fields to
29
+ # populate, one-time migration steps. Never a second rendering of the body:
30
+ # if a body bullet already says it, name the bullet's symbol instead of
31
+ # re-explaining. Omit the field entirely when there's nothing to say.
32
+ # agent-notes: |
33
+ # <instructions for downstream maintenance agents>
34
+ ---
35
+
36
+ # <version> — YYYY-MM-DD
37
+
38
+ <!--
39
+ AUTHORING GUIDE — applies to the new per-version file you create from this
40
+ template.
41
+
42
+ Audience: someone scanning release notes to decide what affects them. Lead
43
+ each bullet with the symbol or concept name in **bold** so they can skip
44
+ what's irrelevant and zoom in on what's not.
45
+
46
+ Tone: terse, fact-dense, not verbose. Bullet shape: **symbol** + what
47
+ changed + at most one consumer-facing caveat. One sentence by default, two
48
+ when the second carries weight — a bullet past ~40 words or three sentences
49
+ is wrong. The depth lives one hop away: the linked issue carries the why,
50
+ the commit diff carries the how. The changelog names what changed and what
51
+ a consumer does about it; a reader who wants mechanism opens the link.
52
+
53
+ Model length on THIS guide, never on the previous entry — entries modeled
54
+ on entries compound.
55
+
56
+ Cut (each has shipped as a wall of text; these are the cruft):
57
+ - History/justification narration — how the bug worked, why the old
58
+ behavior was wrong. One short clause at most; the issue carries the story.
59
+ - Design-rationale defense — "chosen over Y because…", "guarding the
60
+ getter is not enough…". That is the author arguing with a reviewer;
61
+ reviewers read the PR, not the changelog.
62
+ - Defensive unchanged-clauses — "X is unchanged", "byte-identical to
63
+ <prev>". Keep one only where its absence would cause a real misread,
64
+ as a short parenthetical.
65
+ - Edge-case inventories — marker lists, not-flagged lists, escape tables.
66
+ Tests and the issue carry those.
67
+ - Mechanism walkthroughs (JSDoc, CLAUDE.md/AGENTS.md, or the relevant
68
+ skill own those), ceremonial framings ("This release introduces…"),
69
+ backwards-compat paragraphs, file-by-file test enumerations. Prefer
70
+ code/symbol names over English re-explanations.
71
+
72
+ Verified ≠ included: the every-claim-verified-from-the-diff rule bounds
73
+ the TRUTH of what you write, never the AMOUNT.
74
+
75
+ Example — same fact, right size:
76
+
77
+ TOO LONG: **`fetchWithTimeout`'s `timeoutMs` bounds the whole exchange**
78
+ (#341). `fetch` resolves once headers arrive and the deadline was
79
+ cleared as the helper returned, so a peer that answered promptly and
80
+ then stalled the stream held the request open indefinitely. A 2xx
81
+ carrying a body now comes back as a passthrough wrapper that disarms
82
+ the deadline when the body closes, errors, or is cancelled; …
83
+ [+90 more words of mechanism and edge cases]
84
+
85
+ RIGHT: **`fetchWithTimeout`'s `timeoutMs` now bounds the whole
86
+ exchange, not just the headers** (#341). A stalled body aborts with
87
+ the same `Timeout` error; the returned `Response` is a wrapper, so
88
+ identity assertions (`toBe(response)`) no longer hold.
89
+
90
+ Narrative intro: skip by default. Add one short sentence only when the
91
+ release theme genuinely needs framing the bullets can't carry. When many
92
+ bullets share one upgrade consequence, state it ONCE — intro line or
93
+ agent-notes — never per bullet.
94
+
95
+ Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
96
+ Fixed, Security. Include only sections with entries; delete the rest
97
+ (including the commented-out scaffolding below). Don't ship empty headers.
98
+
99
+ Include: every distinct fact a reader needs to adopt or audit the release —
100
+ new exports, signatures, lint rule IDs, env vars, breaking changes, version
101
+ bumps on shipped skills. Nothing more.
102
+
103
+ Links: link issues, PRs, docs, or skills where they help a reader jump to
104
+ context. Once per item per entry — don't re-link the same issue in summary,
105
+ narrative, and bullet. Skip links for inline symbol names; code spans speak
106
+ for themselves.
107
+
108
+ Issue/PR URLs: use full URLs. GitHub's bare `#NN` auto-link only resolves
109
+ inside its own UI, not in npm reads or local editors.
110
+
111
+ [#38](https://github.com/cyanheads/mcp-ts-core/issues/38) ← issue
112
+ [#42](https://github.com/cyanheads/mcp-ts-core/pull/42) ← PR
113
+
114
+ Verify numbers exist before linking (`gh issue view NN`, `gh pr view NN`).
115
+ Never speculate on a future number — `#42` for an upcoming PR silently
116
+ resolves to whatever real item already owns 42, and timeline previews pull
117
+ in that unrelated item's metadata.
118
+
119
+ TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): a short subject line without the
123
+ version, flat headline bullets — no Keep-a-Changelog section headers, no
124
+ gates line — at most one deps line, issue backlinks, and the changelog link
125
+ last. In release-PR mode the `git-wrapup` skill authors those bullets as the
126
+ PR body's `## Changes` and the tag copies them.
127
+ -->
128
+
129
+ ## Added
130
+
131
+ -
132
+
133
+ ## Changed
134
+
135
+ -
136
+
137
+ <!-- ## Deprecated
138
+
139
+ - -->
140
+
141
+ <!-- ## Removed
142
+
143
+ - -->
144
+
145
+ ## Fixed
146
+
147
+ -
148
+
149
+ <!-- ## Security
150
+
151
+ - -->
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ const tools = [
38
38
  await createApp({
39
39
  name: 'pubmed-mcp-server',
40
40
  title: 'pubmed-mcp-server',
41
+ sessionMode: 'stateless',
41
42
  tools,
42
43
  resources: [databaseInfoResource],
43
44
  prompts: [researchPlanPrompt],
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,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"}
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,WAAW,EAAE,WAAW;IACxB,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"}
@@ -24,33 +24,38 @@ export declare const convertIdsTool: import("@cyanheads/mcp-ts-core").ToolDefini
24
24
  }, z.core.$strip>, readonly [{
25
25
  readonly reason: 'queue_full';
26
26
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.RateLimited;
27
- readonly when: 'Local NCBI request queue is at capacity.';
28
- readonly recovery: 'Retry after 1-2 seconds; the request queue hit the NCBI rate limit.';
27
+ readonly when: '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).';
28
+ readonly recovery: 'Wait the number of seconds in `retryAfter`, then retry; the NCBI request queue is saturated or cooling down after a rate limit.';
29
29
  readonly retryable: true;
30
+ readonly thrownBy: 'service';
30
31
  }, {
31
32
  readonly reason: 'ncbi_unreachable';
32
33
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable;
33
34
  readonly when: 'NCBI E-utilities is unreachable after all retry attempts.';
34
35
  readonly recovery: 'Retry after a brief delay; NCBI was unreachable across all retry attempts.';
35
36
  readonly retryable: true;
37
+ readonly thrownBy: 'service';
36
38
  }, {
37
39
  readonly reason: 'ncbi_deadline_exceeded';
38
40
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Timeout;
39
41
  readonly when: 'Total request deadline expired before NCBI returned a response.';
40
42
  readonly recovery: 'Reduce batch size or retry; NCBI may be under temporary load.';
41
43
  readonly retryable: true;
44
+ readonly thrownBy: 'service';
42
45
  }, {
43
46
  readonly reason: 'ncbi_invalid_response';
44
47
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.SerializationError;
45
48
  readonly when: 'NCBI returned a body that could not be parsed (invalid XML/JSON).';
46
49
  readonly recovery: 'Retry the request; NCBI returned a malformed response that could not be parsed.';
47
50
  readonly retryable: true;
51
+ readonly thrownBy: 'service';
48
52
  }, {
49
53
  readonly reason: 'ncbi_resource_not_found';
50
54
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
51
55
  readonly when: 'NCBI returned a structured "not found" error for the requested ID(s).';
52
56
  readonly recovery: 'Verify the ID exists in PubMed; the resource was not found in NCBI and retrying will not help.';
53
57
  readonly retryable: false;
58
+ readonly thrownBy: 'service';
54
59
  }, {
55
60
  readonly reason: 'malformed_id';
56
61
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
@@ -1 +1 @@
1
- {"version":3,"file":"convert-ids.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/convert-ids.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAiCjD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyHzB,CAAC"}
1
+ {"version":3,"file":"convert-ids.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/convert-ids.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAiCjD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyHzB,CAAC"}
@@ -107,33 +107,38 @@ export declare const fetchArticlesTool: import("@cyanheads/mcp-ts-core").ToolDef
107
107
  }, z.core.$strip>, readonly [{
108
108
  readonly reason: 'queue_full';
109
109
  readonly code: JsonRpcErrorCode.RateLimited;
110
- readonly when: 'Local NCBI request queue is at capacity.';
111
- readonly recovery: 'Retry after 1-2 seconds; the request queue hit the NCBI rate limit.';
110
+ readonly when: '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).';
111
+ readonly recovery: 'Wait the number of seconds in `retryAfter`, then retry; the NCBI request queue is saturated or cooling down after a rate limit.';
112
112
  readonly retryable: true;
113
+ readonly thrownBy: 'service';
113
114
  }, {
114
115
  readonly reason: 'ncbi_unreachable';
115
116
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
116
117
  readonly when: 'NCBI E-utilities is unreachable after all retry attempts.';
117
118
  readonly recovery: 'Retry after a brief delay; NCBI was unreachable across all retry attempts.';
118
119
  readonly retryable: true;
120
+ readonly thrownBy: 'service';
119
121
  }, {
120
122
  readonly reason: 'ncbi_deadline_exceeded';
121
123
  readonly code: JsonRpcErrorCode.Timeout;
122
124
  readonly when: 'Total request deadline expired before NCBI returned a response.';
123
125
  readonly recovery: 'Reduce batch size or retry; NCBI may be under temporary load.';
124
126
  readonly retryable: true;
127
+ readonly thrownBy: 'service';
125
128
  }, {
126
129
  readonly reason: 'ncbi_invalid_response';
127
130
  readonly code: JsonRpcErrorCode.SerializationError;
128
131
  readonly when: 'NCBI returned a body that could not be parsed (invalid XML/JSON).';
129
132
  readonly recovery: 'Retry the request; NCBI returned a malformed response that could not be parsed.';
130
133
  readonly retryable: true;
134
+ readonly thrownBy: 'service';
131
135
  }, {
132
136
  readonly reason: 'ncbi_resource_not_found';
133
137
  readonly code: JsonRpcErrorCode.NotFound;
134
138
  readonly when: 'NCBI returned a structured "not found" error for the requested ID(s).';
135
139
  readonly recovery: 'Verify the ID exists in PubMed; the resource was not found in NCBI and retrying will not help.';
136
140
  readonly retryable: false;
141
+ readonly thrownBy: 'service';
137
142
  }, {
138
143
  readonly reason: 'invalid_efetch_response';
139
144
  readonly code: JsonRpcErrorCode.SerializationError;
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-articles.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fetch-articles.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAwRjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAWhB,yBAAyB;;mBAE3B,sEAAsE;uBAE1E,qFAAqF;;;;EAkR3F,CAAC"}
1
+ {"version":3,"file":"fetch-articles.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fetch-articles.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAwRjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAWhB,yBAAyB;;mBAE3B,sEAAsE;uBAE1E,qFAAqF;;;;EAkR3F,CAAC"}
@@ -234,57 +234,66 @@ export declare const fetchFulltextTool: import("@cyanheads/mcp-ts-core").ToolDef
234
234
  }, z.core.$strip>, readonly [{
235
235
  readonly reason: 'queue_full';
236
236
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.RateLimited;
237
- readonly when: 'Local NCBI request queue is at capacity.';
238
- readonly recovery: 'Retry after 1-2 seconds; the request queue hit the NCBI rate limit.';
237
+ readonly when: '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).';
238
+ readonly recovery: 'Wait the number of seconds in `retryAfter`, then retry; the NCBI request queue is saturated or cooling down after a rate limit.';
239
239
  readonly retryable: true;
240
+ readonly thrownBy: 'service';
240
241
  }, {
241
242
  readonly reason: 'ncbi_unreachable';
242
243
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable;
243
244
  readonly when: 'NCBI E-utilities is unreachable after all retry attempts.';
244
245
  readonly recovery: 'Retry after a brief delay; NCBI was unreachable across all retry attempts.';
245
246
  readonly retryable: true;
247
+ readonly thrownBy: 'service';
246
248
  }, {
247
249
  readonly reason: 'ncbi_deadline_exceeded';
248
250
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.Timeout;
249
251
  readonly when: 'Total request deadline expired before NCBI returned a response.';
250
252
  readonly recovery: 'Reduce batch size or retry; NCBI may be under temporary load.';
251
253
  readonly retryable: true;
254
+ readonly thrownBy: 'service';
252
255
  }, {
253
256
  readonly reason: 'ncbi_invalid_response';
254
257
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.SerializationError;
255
258
  readonly when: 'NCBI returned a body that could not be parsed (invalid XML/JSON).';
256
259
  readonly recovery: 'Retry the request; NCBI returned a malformed response that could not be parsed.';
257
260
  readonly retryable: true;
261
+ readonly thrownBy: 'service';
258
262
  }, {
259
263
  readonly reason: 'ncbi_resource_not_found';
260
264
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.NotFound;
261
265
  readonly when: 'NCBI returned a structured "not found" error for the requested ID(s).';
262
266
  readonly recovery: 'Verify the ID exists in PubMed; the resource was not found in NCBI and retrying will not help.';
263
267
  readonly retryable: false;
268
+ readonly thrownBy: 'service';
264
269
  }, {
265
270
  readonly reason: 'unpaywall_unreachable';
266
271
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable;
267
272
  readonly when: 'Unpaywall was unreachable when resolving a DOI or fetching content.';
268
273
  readonly recovery: 'Retry after a brief delay; Unpaywall was unreachable. The PMC source remains the primary path.';
269
274
  readonly retryable: true;
275
+ readonly thrownBy: 'service';
270
276
  }, {
271
277
  readonly reason: 'europepmc_unreachable';
272
278
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ServiceUnavailable;
273
- readonly when: 'Europe PMC was unreachable after all retry attempts.';
279
+ readonly when: '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.';
274
280
  readonly recovery: 'Retry after a brief delay; Europe PMC was unreachable. NCBI PMC and Unpaywall remain available.';
275
281
  readonly retryable: true;
282
+ readonly thrownBy: 'service';
276
283
  }, {
277
284
  readonly reason: 'europepmc_invalid_response';
278
285
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.SerializationError;
279
286
  readonly when: 'Europe PMC returned a body that could not be parsed (invalid JSON or XML).';
280
287
  readonly recovery: 'Retry the request; Europe PMC returned a malformed response that could not be parsed.';
281
288
  readonly retryable: true;
289
+ readonly thrownBy: 'service';
282
290
  }, {
283
291
  readonly reason: 'europepmc_invalid_input';
284
292
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
285
- readonly when: 'Europe PMC rejected the request input (empty query, unknown sort field, malformed parameter).';
286
- readonly recovery: 'Adjust the input — usually the query or sort field — before retrying; the same input will be rejected again.';
293
+ readonly when: '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.';
294
+ readonly recovery: 'Adjust the input — the query, the sort, or the cursorMark — before retrying; the same input will be rejected again.';
287
295
  readonly retryable: false;
296
+ readonly thrownBy: 'service';
288
297
  }], {
289
298
  readonly notice: z.ZodOptional<z.ZodString>;
290
299
  readonly truncated: z.ZodOptional<z.ZodBoolean>;
@@ -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;AAu0C/D;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CAiCT;AAID,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+2B5B,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;AAu0C/D;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CAiCT;AAID,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+2B5B,CAAC"}