@cyanheads/pubmed-mcp-server 2.10.9 → 2.10.10

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 (47) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +4 -3
  4. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts +17 -0
  5. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts.map +1 -1
  6. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js +297 -62
  7. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js.map +1 -1
  8. package/dist/mcp-server/tools/definitions/find-related.tool.d.ts +8 -0
  9. package/dist/mcp-server/tools/definitions/find-related.tool.d.ts.map +1 -1
  10. package/dist/mcp-server/tools/definitions/find-related.tool.js +131 -23
  11. package/dist/mcp-server/tools/definitions/find-related.tool.js.map +1 -1
  12. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts +6 -0
  13. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts.map +1 -1
  14. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.js +14 -3
  15. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.js.map +1 -1
  16. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts +6 -0
  17. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts.map +1 -1
  18. package/dist/mcp-server/tools/definitions/search-articles.tool.js +15 -3
  19. package/dist/mcp-server/tools/definitions/search-articles.tool.js.map +1 -1
  20. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts +6 -0
  21. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts.map +1 -1
  22. package/dist/mcp-server/tools/definitions/spell-check.tool.js +15 -3
  23. package/dist/mcp-server/tools/definitions/spell-check.tool.js.map +1 -1
  24. package/dist/services/error-contracts.d.ts +22 -2
  25. package/dist/services/error-contracts.d.ts.map +1 -1
  26. package/dist/services/error-contracts.js +24 -2
  27. package/dist/services/error-contracts.js.map +1 -1
  28. package/dist/services/ncbi/parsing/pmc-article-parser.d.ts +24 -4
  29. package/dist/services/ncbi/parsing/pmc-article-parser.d.ts.map +1 -1
  30. package/dist/services/ncbi/parsing/pmc-article-parser.js +498 -56
  31. package/dist/services/ncbi/parsing/pmc-article-parser.js.map +1 -1
  32. package/dist/services/ncbi/types.d.ts +43 -0
  33. package/dist/services/ncbi/types.d.ts.map +1 -1
  34. package/dist/services/openalex/api-client.d.ts +13 -4
  35. package/dist/services/openalex/api-client.d.ts.map +1 -1
  36. package/dist/services/openalex/api-client.js +19 -8
  37. package/dist/services/openalex/api-client.js.map +1 -1
  38. package/dist/services/openalex/openalex-service.d.ts +34 -17
  39. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  40. package/dist/services/openalex/openalex-service.js +119 -35
  41. package/dist/services/openalex/openalex-service.js.map +1 -1
  42. package/dist/services/openalex/types.d.ts +34 -1
  43. package/dist/services/openalex/types.d.ts.map +1 -1
  44. package/dist/services/openalex/types.js +20 -0
  45. package/dist/services/openalex/types.js.map +1 -1
  46. package/package.json +1 -1
  47. package/server.json +3 -3
@@ -4,7 +4,7 @@
4
4
  * @module src/mcp-server/tools/definitions/spell-check.tool
5
5
  */
6
6
  import { tool, z } from '@cyanheads/mcp-ts-core';
7
- import { NCBI_SERVICE_ERRORS } from '../../../services/error-contracts.js';
7
+ import { NCBI_QUERY_INPUT_ERRORS, NCBI_SERVICE_ERRORS } from '../../../services/error-contracts.js';
8
8
  import { getNcbiService } from '../../../services/ncbi/ncbi-service.js';
9
9
  import { conceptMeta, SCHEMA_SEARCH_ACTION } from './_concepts.js';
10
10
  export const spellCheckTool = tool('pubmed_spell_check', {
@@ -12,9 +12,12 @@ export const spellCheckTool = tool('pubmed_spell_check', {
12
12
  annotations: { readOnlyHint: true, openWorldHint: true },
13
13
  _meta: conceptMeta([SCHEMA_SEARCH_ACTION]),
14
14
  sourceUrl: 'https://github.com/cyanheads/pubmed-mcp-server/blob/main/src/mcp-server/tools/definitions/spell-check.tool.ts',
15
- errors: [...NCBI_SERVICE_ERRORS],
15
+ errors: [...NCBI_SERVICE_ERRORS, ...NCBI_QUERY_INPUT_ERRORS],
16
16
  input: z.object({
17
- query: z.string().min(2).describe('PubMed search query to spell-check'),
17
+ query: z
18
+ .string()
19
+ .min(2)
20
+ .describe('PubMed search query to spell-check. Must carry a term: a blank or whitespace-only value is rejected rather than sent to ESpell.'),
18
21
  }),
19
22
  output: z.object({
20
23
  original: z.string().describe('Original query'),
@@ -23,6 +26,15 @@ export const spellCheckTool = tool('pubmed_spell_check', {
23
26
  }),
24
27
  async handler(input, ctx) {
25
28
  ctx.log.info('Executing pubmed_spell_check tool', { query: input.query });
29
+ // `min(2)` counts the spaces, so a whitespace-only query passes the schema.
30
+ // ESpell answers a blank term with an empty `<ERROR/>` element the response
31
+ // handler does not detect, and the tool would report the blank input as
32
+ // spell-checked. Reject before the call. (#133)
33
+ if (input.query.trim().length === 0) {
34
+ throw ctx.fail('blank_query', 'The `query` is blank — there is nothing to spell-check.', {
35
+ ...ctx.recoveryFor('blank_query'),
36
+ });
37
+ }
26
38
  const result = await getNcbiService().eSpell({ db: 'pubmed', term: input.query }, { signal: ctx.signal });
27
39
  return {
28
40
  original: result.original,
@@ -1 +1 @@
1
- {"version":3,"file":"spell-check.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/spell-check.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE;IACvD,WAAW,EACT,8FAA8F;IAChG,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACxD,KAAK,EAAE,WAAW,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC1C,SAAS,EACP,+GAA+G;IAEjH,MAAM,EAAE,CAAC,GAAG,mBAAmB,CAAU;IAEzC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KACxE,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;QACrF,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KAC3E,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC,MAAM,CAC1C,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,EACnC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CACvB,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,OAAO;gBACL;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,QAAQ,IAAI;iBAC/E;aACF,CAAC;QACJ,CAAC;QACD,OAAO;YACL;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,0BAA0B,MAAM,CAAC,QAAQ,+BAA+B;aAC/E;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"spell-check.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/spell-check.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE;IACvD,WAAW,EACT,8FAA8F;IAChG,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACxD,KAAK,EAAE,WAAW,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC1C,SAAS,EACP,+GAA+G;IAEjH,MAAM,EAAE,CAAC,GAAG,mBAAmB,EAAE,GAAG,uBAAuB,CAAU;IAErE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,iIAAiI,CAClI;KACJ,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;QACrF,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KAC3E,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1E,4EAA4E;QAC5E,4EAA4E;QAC5E,wEAAwE;QACxE,gDAAgD;QAChD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,yDAAyD,EAAE;gBACvF,GAAG,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC,MAAM,CAC1C,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,EACnC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CACvB,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,OAAO;gBACL;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,QAAQ,IAAI;iBAC/E;aACF,CAAC;QACJ,CAAC;QACD,OAAO;YACL;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,0BAA0B,MAAM,CAAC,QAAQ,+BAA+B;aAC/E;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -1,6 +1,8 @@
1
1
  /**
2
- * @fileoverview Canonical service-layer error contracts. Single source of truth
3
- * for the failure modes both services throw and tools declare in `errors[]`.
2
+ * @fileoverview Canonical error contracts. Single source of truth for the
3
+ * failure modes services throw and tools declare in `errors[]`, plus the
4
+ * input rejections shared by the tools that forward a free-text query
5
+ * upstream.
4
6
  *
5
7
  * Service-layer code can't reach `ctx.recoveryFor` (no Context), so it spreads
6
8
  * `recoveryFor(reason)` from this module into the error factory's `data` arg.
@@ -50,6 +52,24 @@ export declare const NCBI_SERVICE_ERRORS: readonly [{
50
52
  readonly recovery: 'Verify the ID exists in PubMed; the resource was not found in NCBI and retrying will not help.';
51
53
  readonly retryable: false;
52
54
  }];
55
+ /**
56
+ * Input failure the NCBI query tools reject before any call is made. Declared
57
+ * here rather than inside `NCBI_SERVICE_ERRORS` so only the tools that actually
58
+ * throw it advertise it — a tool that takes no free-text query can never
59
+ * produce it, and declaring it there would advertise a failure mode that
60
+ * cannot happen.
61
+ *
62
+ * Unlike the service arrays in this module, this one is thrown from a tool
63
+ * handler via `ctx.fail('blank_query', …)`, so its recovery hint resolves
64
+ * through `ctx.recoveryFor` and it stays out of {@link ServiceErrorReason}.
65
+ */
66
+ export declare const NCBI_QUERY_INPUT_ERRORS: readonly [{
67
+ readonly reason: 'blank_query';
68
+ readonly code: JsonRpcErrorCode.ValidationError;
69
+ readonly when: 'The query holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term.';
70
+ readonly recovery: 'Supply a nonblank search term; NCBI cannot search a blank term and retrying the same input will not help.';
71
+ readonly retryable: false;
72
+ }];
53
73
  /**
54
74
  * Failure modes the Unpaywall service layer can surface. Tools that consume
55
75
  * `getUnpaywallService()` (currently `pubmed_fetch_fulltext`) should spread
@@ -1 +1 @@
1
- {"version":3,"file":"error-contracts.d.ts","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;aAE5B,MAAM,EAAE,YAAY;aACpB,IAAI;aACJ,IAAI,EAAE,0CAA0C;aAChD,QAAQ,EAAE,qEAAqE;aAC/E,SAAS;;aAGT,MAAM,EAAE,kBAAkB;aAC1B,IAAI;aACJ,IAAI,EAAE,2DAA2D;aACjE,QAAQ,EAAE,4EAA4E;aACtF,SAAS;;aAGT,MAAM,EAAE,wBAAwB;aAChC,IAAI;aACJ,IAAI,EAAE,iEAAiE;aACvE,QAAQ,EAAE,+DAA+D;aACzE,SAAS;;aAGT,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,iFAAiF;aAC3F,SAAS;;aAGT,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,uEAAuE;aAC7E,QAAQ,EACN,gGAAgG;aAClG,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;aAEjC,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,qEAAqE;aAC3E,QAAQ,EACN,gGAAgG;aAClG,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;aAEhC,MAAM,EAAE,sBAAsB;aAC9B,IAAI;aACJ,IAAI,EAAE,oDAAoD;aAC1D,QAAQ,EACN,4FAA4F;aAC9F,SAAS;;aAGT,MAAM,EAAE,2BAA2B;aACnC,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,qFAAqF;aAC/F,SAAS;EAEH,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,wBAAwB;aAEjC,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,sDAAsD;aAC5D,QAAQ,EACN,iGAAiG;aACnG,SAAS;;aAGT,MAAM,EAAE,4BAA4B;aACpC,IAAI;aACJ,IAAI,EAAE,4EAA4E;aAClF,QAAQ,EACN,uFAAuF;aACzF,SAAS;;aAGT,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,+FAA+F;aACrG,QAAQ,EACN,8GAA8G;aAChH,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAC9C,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GACnD,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GACnD,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;AAWvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAAE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAMtF"}
1
+ {"version":3,"file":"error-contracts.d.ts","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;aAE5B,MAAM,EAAE,YAAY;aACpB,IAAI;aACJ,IAAI,EAAE,0CAA0C;aAChD,QAAQ,EAAE,qEAAqE;aAC/E,SAAS;;aAGT,MAAM,EAAE,kBAAkB;aAC1B,IAAI;aACJ,IAAI,EAAE,2DAA2D;aACjE,QAAQ,EAAE,4EAA4E;aACtF,SAAS;;aAGT,MAAM,EAAE,wBAAwB;aAChC,IAAI;aACJ,IAAI,EAAE,iEAAiE;aACvE,QAAQ,EAAE,+DAA+D;aACzE,SAAS;;aAGT,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,iFAAiF;aAC3F,SAAS;;aAGT,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,uEAAuE;aAC7E,QAAQ,EACN,gGAAgG;aAClG,SAAS;EAEH,CAAC;AAEX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB;aAEhC,MAAM,EAAE,aAAa;aACrB,IAAI;aACJ,IAAI,EAAE,yIAAyI;aAC/I,QAAQ,EACN,2GAA2G;aAC7G,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;aAEjC,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,qEAAqE;aAC3E,QAAQ,EACN,gGAAgG;aAClG,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;aAEhC,MAAM,EAAE,sBAAsB;aAC9B,IAAI;aACJ,IAAI,EAAE,oDAAoD;aAC1D,QAAQ,EACN,4FAA4F;aAC9F,SAAS;;aAGT,MAAM,EAAE,2BAA2B;aACnC,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,qFAAqF;aAC/F,SAAS;EAEH,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,wBAAwB;aAEjC,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,sDAAsD;aAC5D,QAAQ,EACN,iGAAiG;aACnG,SAAS;;aAGT,MAAM,EAAE,4BAA4B;aACpC,IAAI;aACJ,IAAI,EAAE,4EAA4E;aAClF,QAAQ,EACN,uFAAuF;aACzF,SAAS;;aAGT,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,+FAA+F;aACrG,QAAQ,EACN,8GAA8G;aAChH,SAAS;EAEH,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAC9C,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GACnD,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GACnD,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;AAWvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAAE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAMtF"}
@@ -1,6 +1,8 @@
1
1
  /**
2
- * @fileoverview Canonical service-layer error contracts. Single source of truth
3
- * for the failure modes both services throw and tools declare in `errors[]`.
2
+ * @fileoverview Canonical error contracts. Single source of truth for the
3
+ * failure modes services throw and tools declare in `errors[]`, plus the
4
+ * input rejections shared by the tools that forward a free-text query
5
+ * upstream.
4
6
  *
5
7
  * Service-layer code can't reach `ctx.recoveryFor` (no Context), so it spreads
6
8
  * `recoveryFor(reason)` from this module into the error factory's `data` arg.
@@ -56,6 +58,26 @@ export const NCBI_SERVICE_ERRORS = [
56
58
  retryable: false,
57
59
  },
58
60
  ];
61
+ /**
62
+ * Input failure the NCBI query tools reject before any call is made. Declared
63
+ * here rather than inside `NCBI_SERVICE_ERRORS` so only the tools that actually
64
+ * throw it advertise it — a tool that takes no free-text query can never
65
+ * produce it, and declaring it there would advertise a failure mode that
66
+ * cannot happen.
67
+ *
68
+ * Unlike the service arrays in this module, this one is thrown from a tool
69
+ * handler via `ctx.fail('blank_query', …)`, so its recovery hint resolves
70
+ * through `ctx.recoveryFor` and it stays out of {@link ServiceErrorReason}.
71
+ */
72
+ export const NCBI_QUERY_INPUT_ERRORS = [
73
+ {
74
+ reason: 'blank_query',
75
+ code: JsonRpcErrorCode.ValidationError,
76
+ when: 'The query holds no search term once whitespace, and any markup the tool strips first, are removed — so NCBI would receive a blank term.',
77
+ recovery: 'Supply a nonblank search term; NCBI cannot search a blank term and retrying the same input will not help.',
78
+ retryable: false,
79
+ },
80
+ ];
59
81
  /**
60
82
  * Failure modes the Unpaywall service layer can surface. Tools that consume
61
83
  * `getUnpaywallService()` (currently `pubmed_fetch_fulltext`) should spread
@@ -1 +1 @@
1
- {"version":3,"file":"error-contracts.js","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"error-contracts.js","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"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"}
@@ -7,15 +7,22 @@
7
7
  * inline children and drops body sections for markup-heavy articles.
8
8
  * @module src/services/ncbi/parsing/pmc-article-parser
9
9
  */
10
- import type { ParsedPmcArticle, ParsedPmcAuthor, ParsedPmcReference, ParsedPmcSection, ParsedPmcTable } from '../types.js';
10
+ import type { ParsedPmcArticle, ParsedPmcAsset, ParsedPmcAuthor, ParsedPmcReference, ParsedPmcSection, ParsedPmcTable } from '../types.js';
11
11
  import { type JatsNode } from './pmc-xml-helpers.js';
12
12
  /** Extract authors from a single `<contrib-group>` node. Non-author contributors are skipped. */
13
13
  export declare function extractJatsAuthors(contribGroup: JatsNode | undefined): ParsedPmcAuthor[];
14
14
  /**
15
15
  * Extract body sections from a `<body>` node, walking children in document order.
16
- * Consecutive bare `<p>` siblings are collected into an untitled section so
17
- * articles with mixed structure (direct paragraphs + trailing `<sec>`, common
18
- * in manuscript-submitted PMC deposits) preserve their main text.
16
+ * Consecutive bare `<p>` siblings — and any block element sitting directly under
17
+ * `<body>` — are collected into an untitled section so articles with mixed
18
+ * structure (direct paragraphs + trailing `<sec>`, common in
19
+ * manuscript-submitted PMC deposits) preserve their main text.
20
+ *
21
+ * A `<body>` whose whole content is one block and no `<sec>` therefore yields a
22
+ * section carrying that block's text, rather than the empty list the tool layer
23
+ * reads as an article with no body at all. Legacy
24
+ * `<preformat preformat-type="pmc-ocr-text">` deposits, which put the entire
25
+ * article in one such element, are the case that matters. (#130)
19
26
  */
20
27
  export declare function extractBodySections(body: JatsNode | undefined): ParsedPmcSection[];
21
28
  /**
@@ -48,6 +55,19 @@ export declare function extractPmcTables(root: JatsNode | undefined): ParsedPmcT
48
55
  * source `<tr>` elements and needs no cap of its own. (#111)
49
56
  */
50
57
  export declare const MAX_TABLE_COLUMNS = 512;
58
+ /**
59
+ * Extract every `<fig>` and `<supplementary-material>` under `root` in document
60
+ * order — pass the `<article>` node.
61
+ *
62
+ * Whole-article, for the reason the table walk is: 17% of figures and 23% of
63
+ * supplementary material sit outside `<body>` entirely — `<floats-group>`
64
+ * deposits, `<back>/<sec>` and `<app-group>/<app>` placements, and figures
65
+ * hanging off the abstract in `<front>`. Each asset names the innermost
66
+ * enclosing `<sec>` wherever that sits, an untitled one inheriting its parent's
67
+ * title, so the reader keeps a positional cue; an asset inside no `<sec>` at all
68
+ * carries no section name. (#130)
69
+ */
70
+ export declare function extractPmcAssets(root: JatsNode | undefined): ParsedPmcAsset[];
51
71
  /**
52
72
  * Extract references from anywhere under `root` — pass the `<article>` node to
53
73
  * cover a whole document, or a `<back>` node to scope the search to it.
@@ -1 +1 @@
1
- {"version":3,"file":"pmc-article-parser.d.ts","sourceRoot":"","sources":["../../../../src/services/ncbi/parsing/pmc-article-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAEf,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAOL,KAAK,QAAQ,EAMd,MAAM,sBAAsB,CAAC;AA2D9B,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,QAAQ,GAAG,SAAS,GAAG,eAAe,EAAE,CA2BxF;AA2HD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,gBAAgB,EAAE,CA2BlF;AA6BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,EAAE,CAK7E;AA2DD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAkRrC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,kBAAkB,EAAE,CAsClF;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,QAAQ,GAAG,gBAAgB,CA6CvE"}
1
+ {"version":3,"file":"pmc-article-parser.d.ts","sourceRoot":"","sources":["../../../../src/services/ncbi/parsing/pmc-article-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAEd,eAAe,EAEf,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAOL,KAAK,QAAQ,EAOd,MAAM,sBAAsB,CAAC;AAsH9B,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,QAAQ,GAAG,SAAS,GAAG,eAAe,EAAE,CA2BxF;AA+aD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,gBAAgB,EAAE,CAyBlF;AAkDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,EAAE,CAO7E;AAqED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAmGrC;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,EAAE,CAQ7E;AAuND;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,kBAAkB,EAAE,CAsClF;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,QAAQ,GAAG,gBAAgB,CA+CvE"}