@cyanheads/pubmed-mcp-server 2.10.18 → 2.10.19

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 (96) hide show
  1. package/AGENTS.md +11 -13
  2. package/CLAUDE.md +11 -13
  3. package/Dockerfile +77 -36
  4. package/README.md +86 -109
  5. package/changelog/2.10.x/2.10.19.md +42 -0
  6. package/dist/mcp-server/resources/definitions/database-info.resource.d.ts +43 -1
  7. package/dist/mcp-server/resources/definitions/database-info.resource.d.ts.map +1 -1
  8. package/dist/mcp-server/resources/definitions/database-info.resource.js +2 -0
  9. package/dist/mcp-server/resources/definitions/database-info.resource.js.map +1 -1
  10. package/dist/mcp-server/tools/definitions/_visible-text.d.ts +19 -0
  11. package/dist/mcp-server/tools/definitions/_visible-text.d.ts.map +1 -0
  12. package/dist/mcp-server/tools/definitions/_visible-text.js +22 -0
  13. package/dist/mcp-server/tools/definitions/_visible-text.js.map +1 -0
  14. package/dist/mcp-server/tools/definitions/convert-ids.tool.d.ts +11 -4
  15. package/dist/mcp-server/tools/definitions/convert-ids.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/convert-ids.tool.js +1 -1
  17. package/dist/mcp-server/tools/definitions/convert-ids.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/fetch-articles.tool.d.ts +20 -7
  19. package/dist/mcp-server/tools/definitions/fetch-articles.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/fetch-articles.tool.js +40 -5
  21. package/dist/mcp-server/tools/definitions/fetch-articles.tool.js.map +1 -1
  22. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts +11 -4
  23. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js +18 -1
  25. package/dist/mcp-server/tools/definitions/fetch-fulltext.tool.js.map +1 -1
  26. package/dist/mcp-server/tools/definitions/find-related.tool.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/find-related.tool.js +19 -5
  28. package/dist/mcp-server/tools/definitions/find-related.tool.js.map +1 -1
  29. package/dist/mcp-server/tools/definitions/format-citations.tool.d.ts +11 -4
  30. package/dist/mcp-server/tools/definitions/format-citations.tool.d.ts.map +1 -1
  31. package/dist/mcp-server/tools/definitions/lookup-citation.tool.d.ts +16 -15
  32. package/dist/mcp-server/tools/definitions/lookup-citation.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/definitions/lookup-citation.tool.js +40 -22
  34. package/dist/mcp-server/tools/definitions/lookup-citation.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts +13 -6
  36. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.js +8 -8
  38. package/dist/mcp-server/tools/definitions/lookup-mesh.tool.js.map +1 -1
  39. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts +2 -2
  40. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.d.ts.map +1 -1
  41. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js +1 -1
  42. package/dist/mcp-server/tools/definitions/pubmed-europepmc-fetch.tool.js.map +1 -1
  43. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts +19 -5
  44. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.d.ts.map +1 -1
  45. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js +37 -7
  46. package/dist/mcp-server/tools/definitions/pubmed-europepmc-search.tool.js.map +1 -1
  47. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts +40 -18
  48. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts.map +1 -1
  49. package/dist/mcp-server/tools/definitions/search-articles.tool.js +193 -43
  50. package/dist/mcp-server/tools/definitions/search-articles.tool.js.map +1 -1
  51. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts +13 -6
  52. package/dist/mcp-server/tools/definitions/spell-check.tool.d.ts.map +1 -1
  53. package/dist/mcp-server/tools/definitions/spell-check.tool.js +8 -8
  54. package/dist/mcp-server/tools/definitions/spell-check.tool.js.map +1 -1
  55. package/dist/services/error-contracts.d.ts +42 -71
  56. package/dist/services/error-contracts.d.ts.map +1 -1
  57. package/dist/services/error-contracts.js +43 -75
  58. package/dist/services/error-contracts.js.map +1 -1
  59. package/dist/services/europe-pmc/api-client.d.ts +8 -2
  60. package/dist/services/europe-pmc/api-client.d.ts.map +1 -1
  61. package/dist/services/europe-pmc/api-client.js +13 -8
  62. package/dist/services/europe-pmc/api-client.js.map +1 -1
  63. package/dist/services/europe-pmc/europe-pmc-service.d.ts +25 -2
  64. package/dist/services/europe-pmc/europe-pmc-service.d.ts.map +1 -1
  65. package/dist/services/europe-pmc/europe-pmc-service.js +90 -25
  66. package/dist/services/europe-pmc/europe-pmc-service.js.map +1 -1
  67. package/dist/services/europe-pmc/types.d.ts +6 -1
  68. package/dist/services/europe-pmc/types.d.ts.map +1 -1
  69. package/dist/services/ncbi/api-client.d.ts.map +1 -1
  70. package/dist/services/ncbi/api-client.js +2 -3
  71. package/dist/services/ncbi/api-client.js.map +1 -1
  72. package/dist/services/ncbi/ncbi-service.d.ts +2 -1
  73. package/dist/services/ncbi/ncbi-service.d.ts.map +1 -1
  74. package/dist/services/ncbi/ncbi-service.js +67 -20
  75. package/dist/services/ncbi/ncbi-service.js.map +1 -1
  76. package/dist/services/ncbi/parsing/article-parser.d.ts +15 -1
  77. package/dist/services/ncbi/parsing/article-parser.d.ts.map +1 -1
  78. package/dist/services/ncbi/parsing/article-parser.js +29 -0
  79. package/dist/services/ncbi/parsing/article-parser.js.map +1 -1
  80. package/dist/services/ncbi/response-handler.d.ts.map +1 -1
  81. package/dist/services/ncbi/response-handler.js +22 -19
  82. package/dist/services/ncbi/response-handler.js.map +1 -1
  83. package/dist/services/ncbi/types.d.ts +33 -0
  84. package/dist/services/ncbi/types.d.ts.map +1 -1
  85. package/dist/services/openalex/api-client.d.ts.map +1 -1
  86. package/dist/services/openalex/api-client.js +6 -7
  87. package/dist/services/openalex/api-client.js.map +1 -1
  88. package/dist/services/openalex/openalex-service.d.ts +3 -3
  89. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  90. package/dist/services/openalex/openalex-service.js +4 -6
  91. package/dist/services/openalex/openalex-service.js.map +1 -1
  92. package/dist/services/unpaywall/unpaywall-service.d.ts.map +1 -1
  93. package/dist/services/unpaywall/unpaywall-service.js +1 -3
  94. package/dist/services/unpaywall/unpaywall-service.js.map +1 -1
  95. package/package.json +6 -5
  96. package/server.json +3 -3
@@ -1,17 +1,22 @@
1
1
  /**
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.
2
+ * @fileoverview Canonical error contracts: the failure modes the NCBI, Europe
3
+ * PMC, and OpenAlex services throw and tools declare in `errors[]`, plus the
4
+ * input rejections some tools raise before any upstream call. Unpaywall has no
5
+ * array here: its one caller, `pubmed_fetch_fulltext`, catches every Unpaywall
6
+ * failure and reports it as a tier outcome, so no Unpaywall reason reaches a
7
+ * caller as an error.
6
8
  *
7
- * Service-layer code can't reach `ctx.recoveryFor` (no Context), so it spreads
8
- * `recoveryFor(reason)` from this module into the error factory's `data` arg.
9
- * The framework mirrors `data.recovery.hint` into the wire payload's
10
- * `content[]` text, so clients get the same actionable hint they would from a
11
- * handler-level `ctx.fail`.
9
+ * Service-layer code stamps `data: { reason }` on its throws, adding its own
10
+ * `data.recovery` only where the hint depends on runtime detail. When a failure
11
+ * with no hint of its own reaches a tool or resource that declares the reason,
12
+ * the framework fills that entry's `recovery` in as `data.recovery.hint` — the
13
+ * same hint a handler-level `ctx.fail` gets. A tool's error also renders the
14
+ * hint as a `Recovery:` line in its `content[]` text (dropped when the message
15
+ * already contains it); a resource's carries it only in the JSON-RPC error's
16
+ * `data`.
12
17
  *
13
- * Tool definitions import the contract arrays directly and spread them into
14
- * their `errors: [...]` declarations to surface the failure modes to the LLM.
18
+ * Definitions import the contract arrays directly and spread them into their
19
+ * `errors: [...]` declarations to surface the failure modes to the LLM.
15
20
  * Every service-array entry carries `thrownBy: 'service'` so the linter's
16
21
  * `error-contract-unthrown` check skips it while still checking the handler's
17
22
  * own reasons. Spread a service array only into a tool whose handler lets that
@@ -36,15 +41,22 @@ export declare const NCBI_SERVICE_ERRORS: readonly [{
36
41
  }, {
37
42
  readonly reason: 'ncbi_unreachable';
38
43
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
39
- readonly when: 'NCBI E-utilities is unreachable after all retry attempts.';
40
- readonly recovery: 'Retry after a brief delay; NCBI was unreachable across all retry attempts.';
44
+ readonly when: 'NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline.';
45
+ readonly recovery: 'Retry after a brief delay; NCBI failed on every attempt this call made.';
46
+ readonly retryable: true;
47
+ readonly thrownBy: 'service';
48
+ }, {
49
+ readonly reason: 'ncbi_rate_limited';
50
+ readonly code: JsonRpcErrorCode.RateLimited;
51
+ readonly when: 'NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap.';
52
+ readonly recovery: "Wait as long as `retryAfter` says when present (a number of seconds or an HTTP date), otherwise a few seconds, then retry; NCBI is throttling this server's requests. If the server runs without NCBI_API_KEY, setting it raises the E-utilities ceiling from about 3 to about 10 requests per second and shortens the default gap between requests — an operator setting in the server's environment, not a tool input.";
41
53
  readonly retryable: true;
42
54
  readonly thrownBy: 'service';
43
55
  }, {
44
56
  readonly reason: 'ncbi_deadline_exceeded';
45
57
  readonly code: JsonRpcErrorCode.Timeout;
46
- readonly when: 'Total request deadline expired before NCBI returned a response.';
47
- readonly recovery: 'Reduce batch size or retry; NCBI may be under temporary load.';
58
+ readonly when: 'The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff.';
59
+ readonly recovery: 'Retry after a brief delay; NCBI may be under temporary load. For a large batch, split it into smaller calls.';
48
60
  readonly retryable: true;
49
61
  readonly thrownBy: 'service';
50
62
  }, {
@@ -63,32 +75,30 @@ export declare const NCBI_SERVICE_ERRORS: readonly [{
63
75
  readonly thrownBy: 'service';
64
76
  }];
65
77
  /**
66
- * Input failure the NCBI query tools reject before any call is made. Declared
67
- * here rather than inside `NCBI_SERVICE_ERRORS` so only the tools that actually
68
- * throw it advertise it — a tool that takes no free-text query can never
69
- * produce it, and declaring it there would advertise a failure mode that
70
- * cannot happen.
78
+ * Input failure the free-text query tools reject before any call is made —
79
+ * the NCBI query tools and `pubmed_europepmc_search` alike. Declared here
80
+ * rather than inside a service array so only the tools that actually throw it
81
+ * advertise it — a tool that takes no free-text query can never produce it,
82
+ * and declaring it there would advertise a failure mode that cannot happen.
71
83
  *
72
84
  * Unlike the service arrays in this module, this one is thrown from a tool
73
- * handler via `ctx.fail('blank_query', …)`, so its recovery hint resolves
74
- * through `ctx.recoveryFor` and it stays out of {@link ServiceErrorReason}.
85
+ * handler via `ctx.fail('blank_query', …)`, so its entry carries no `thrownBy`.
75
86
  */
76
- export declare const NCBI_QUERY_INPUT_ERRORS: readonly [{
87
+ export declare const QUERY_INPUT_ERRORS: readonly [{
77
88
  readonly reason: 'blank_query';
78
89
  readonly code: JsonRpcErrorCode.ValidationError;
79
- readonly when: 'The query holds no search term once whitespace, and anything the tool strips before searching, are removed — so NCBI would receive a blank term. pubmed_search_articles strips markup, bracketed field tags, and parentheses, so a bare field tag such as `[pdat]` or empty parentheses `()` count as blank there.';
80
- readonly recovery: 'Supply a nonblank search term — a bare field tag or empty parentheses carry none; NCBI cannot search a blank term and retrying the same input will not help.';
90
+ readonly when: 'The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`.';
91
+ readonly recovery: 'Supply a nonblank search term; retrying the same blank input will not help.';
81
92
  readonly retryable: false;
82
93
  }];
83
94
  /**
84
95
  * Input failure the identifier-conversion path rejects before any call is made.
85
- * Separate from {@link NCBI_QUERY_INPUT_ERRORS} for the same reason that array
96
+ * Separate from {@link QUERY_INPUT_ERRORS} for the same reason that array
86
97
  * is separate from the service contracts: only a tool that takes caller-supplied
87
98
  * identifiers can produce it.
88
99
  *
89
- * Thrown from a tool handler via `ctx.fail('malformed_id', …)`, so its recovery
90
- * hint resolves through `ctx.recoveryFor` and it stays out of
91
- * {@link ServiceErrorReason}.
100
+ * Thrown from a tool handler via `ctx.fail('malformed_id', …)`, so its entry
101
+ * carries no `thrownBy`.
92
102
  */
93
103
  export declare const NCBI_ID_INPUT_ERRORS: readonly [{
94
104
  readonly reason: 'malformed_id';
@@ -97,21 +107,6 @@ export declare const NCBI_ID_INPUT_ERRORS: readonly [{
97
107
  readonly recovery: 'Submit one identifier per `ids` element, in the declared idType format; the same packed value will be rejected again.';
98
108
  readonly retryable: false;
99
109
  }];
100
- /**
101
- * Failure modes the Unpaywall service layer can surface. A tool whose handler
102
- * lets `getUnpaywallService()` failures propagate spreads these into its
103
- * `errors[]`. None does today: `pubmed_fetch_fulltext`, the only consumer,
104
- * folds every Unpaywall failure into its tier chain, so the entries serve the
105
- * service's own `recoveryFor` hints.
106
- */
107
- export declare const UNPAYWALL_SERVICE_ERRORS: readonly [{
108
- readonly reason: 'unpaywall_unreachable';
109
- readonly code: JsonRpcErrorCode.ServiceUnavailable;
110
- readonly when: 'Unpaywall was unreachable when resolving a DOI or fetching content.';
111
- readonly recovery: 'Retry after a brief delay; Unpaywall was unreachable. The PMC source remains the primary path.';
112
- readonly retryable: true;
113
- readonly thrownBy: 'service';
114
- }];
115
110
  /**
116
111
  * Failure modes the OpenAlex service layer can surface. Tools whose handler
117
112
  * lets `getOpenAlexService()` / `getOpenAlexServiceOptional()` failures
@@ -126,7 +121,7 @@ export declare const OPENALEX_SERVICE_ERRORS: readonly [{
126
121
  readonly thrownBy: 'service';
127
122
  }, {
128
123
  readonly reason: 'openalex_invalid_response';
129
- readonly code: JsonRpcErrorCode.SerializationError;
124
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
130
125
  readonly when: 'OpenAlex returned a body that could not be parsed (invalid JSON).';
131
126
  readonly recovery: 'Retry the request; OpenAlex returned a malformed response that could not be parsed.';
132
127
  readonly retryable: true;
@@ -154,33 +149,9 @@ export declare const EUROPEPMC_SERVICE_ERRORS: readonly [{
154
149
  }, {
155
150
  readonly reason: 'europepmc_invalid_input';
156
151
  readonly code: JsonRpcErrorCode.ValidationError;
157
- 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.';
158
- readonly recovery: 'Adjust the input — the query, the sort, or the cursorMark — before retrying; the same input will be rejected again.';
152
+ readonly when: 'Europe PMC rejected the request input — an error message in place of results, an empty response to a sort with an undocumented field or no asc/desc direction, or a pagination cursor it cannot read (an empty response on the last attempt the retry budget allows, or a second HTTP 503 when the first page of the same query is served).';
153
+ readonly recovery: "Fix the rejected input before retrying — the query, the sort, or the cursorMark (pass the previous response's `nextCursorMark` verbatim, or `*` to restart); the same input will most likely be rejected again.";
159
154
  readonly retryable: false;
160
155
  readonly thrownBy: 'service';
161
156
  }];
162
- /**
163
- * Reason identifier union for type-safe authoring on the service layer.
164
- * Tool handlers get a tighter typed union from `ctx.fail` / `ctx.recoveryFor`
165
- * via the framework — this is the service-side fallback.
166
- */
167
- export type ServiceErrorReason = (typeof NCBI_SERVICE_ERRORS)[number]['reason'] | (typeof UNPAYWALL_SERVICE_ERRORS)[number]['reason'] | (typeof EUROPEPMC_SERVICE_ERRORS)[number]['reason'] | (typeof OPENALEX_SERVICE_ERRORS)[number]['reason'];
168
- /**
169
- * Service-layer counterpart to `ctx.recoveryFor`. Returns `{ recovery: { hint } }`
170
- * for the contract reason. Use at every service throw that stamps a `reason` so
171
- * the wire payload carries the same actionable hint the LLM gets from
172
- * handler-level `ctx.fail`.
173
- *
174
- * The parameter is constrained to `ServiceErrorReason`, so typos fail at compile
175
- * time. The runtime guard catches the impossible case where the reason union
176
- * and the recovery map drift apart in future edits.
177
- *
178
- * @example
179
- * throw serviceUnavailable(msg, { reason: 'ncbi_unreachable', ...recoveryFor('ncbi_unreachable') });
180
- */
181
- export declare function recoveryFor(reason: ServiceErrorReason): {
182
- recovery: {
183
- hint: string;
184
- };
185
- };
186
157
  //# sourceMappingURL=error-contracts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-contracts.d.ts","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"error-contracts.d.ts","sourceRoot":"","sources":["../../src/services/error-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;aAE5B,MAAM,EAAE,YAAY;aACpB,IAAI;aACJ,IAAI,EAAE,gLAAgL;aACtL,QAAQ,EACN,iIAAiI;aACnI,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,kBAAkB;aAC1B,IAAI;aACJ,IAAI,EAAE,4IAA4I;aAClJ,QAAQ,EAAE,yEAAyE;aACnF,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,mBAAmB;aAC3B,IAAI;aACJ,IAAI,EAAE,gOAAgO;aACtO,QAAQ,EACN,0ZAA0Z;aAC5Z,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,wBAAwB;aAChC,IAAI;aACJ,IAAI,EAAE,mIAAmI;aACzI,QAAQ,EACN,8GAA8G;aAChH,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,iFAAiF;aAC3F,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,uEAAuE;aAC7E,QAAQ,EACN,gGAAgG;aAClG,SAAS;aACT,QAAQ,EAAE,SAAS;EAEb,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB;aAE3B,MAAM,EAAE,aAAa;aACrB,IAAI;aACJ,IAAI,EAAE,qYAAqY;aAC3Y,QAAQ,EAAE,6EAA6E;aACvF,SAAS;EAEH,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;aAE7B,MAAM,EAAE,cAAc;aACtB,IAAI;aACJ,IAAI,EAAE,0LAA0L;aAChM,QAAQ,EACN,uHAAuH;aACzH,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;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,2BAA2B;aACnC,IAAI;aACJ,IAAI,EAAE,mEAAmE;aACzE,QAAQ,EAAE,qFAAqF;aAC/F,SAAS;aACT,QAAQ,EAAE,SAAS;EAEb,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;aAEjC,MAAM,EAAE,uBAAuB;aAC/B,IAAI;aACJ,IAAI,EAAE,qKAAqK;aAC3K,QAAQ,EACN,iGAAiG;aACnG,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,4BAA4B;aACpC,IAAI;aACJ,IAAI,EAAE,4EAA4E;aAClF,QAAQ,EACN,uFAAuF;aACzF,SAAS;aACT,QAAQ,EAAE,SAAS;;aAGnB,MAAM,EAAE,yBAAyB;aACjC,IAAI;aACJ,IAAI,EAAE,6UAA6U;aACnV,QAAQ,EACN,iNAAiN;aACnN,SAAS;aACT,QAAQ,EAAE,SAAS;EAEb,CAAC"}
@@ -1,17 +1,22 @@
1
1
  /**
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.
2
+ * @fileoverview Canonical error contracts: the failure modes the NCBI, Europe
3
+ * PMC, and OpenAlex services throw and tools declare in `errors[]`, plus the
4
+ * input rejections some tools raise before any upstream call. Unpaywall has no
5
+ * array here: its one caller, `pubmed_fetch_fulltext`, catches every Unpaywall
6
+ * failure and reports it as a tier outcome, so no Unpaywall reason reaches a
7
+ * caller as an error.
6
8
  *
7
- * Service-layer code can't reach `ctx.recoveryFor` (no Context), so it spreads
8
- * `recoveryFor(reason)` from this module into the error factory's `data` arg.
9
- * The framework mirrors `data.recovery.hint` into the wire payload's
10
- * `content[]` text, so clients get the same actionable hint they would from a
11
- * handler-level `ctx.fail`.
9
+ * Service-layer code stamps `data: { reason }` on its throws, adding its own
10
+ * `data.recovery` only where the hint depends on runtime detail. When a failure
11
+ * with no hint of its own reaches a tool or resource that declares the reason,
12
+ * the framework fills that entry's `recovery` in as `data.recovery.hint` — the
13
+ * same hint a handler-level `ctx.fail` gets. A tool's error also renders the
14
+ * hint as a `Recovery:` line in its `content[]` text (dropped when the message
15
+ * already contains it); a resource's carries it only in the JSON-RPC error's
16
+ * `data`.
12
17
  *
13
- * Tool definitions import the contract arrays directly and spread them into
14
- * their `errors: [...]` declarations to surface the failure modes to the LLM.
18
+ * Definitions import the contract arrays directly and spread them into their
19
+ * `errors: [...]` declarations to surface the failure modes to the LLM.
15
20
  * Every service-array entry carries `thrownBy: 'service'` so the linter's
16
21
  * `error-contract-unthrown` check skips it while still checking the handler's
17
22
  * own reasons. Spread a service array only into a tool whose handler lets that
@@ -38,16 +43,24 @@ export const NCBI_SERVICE_ERRORS = [
38
43
  {
39
44
  reason: 'ncbi_unreachable',
40
45
  code: JsonRpcErrorCode.ServiceUnavailable,
41
- when: 'NCBI E-utilities is unreachable after all retry attempts.',
42
- recovery: 'Retry after a brief delay; NCBI was unreachable across all retry attempts.',
46
+ when: 'NCBI E-utilities failed on every attempt the retry budget allowed — retries ran out, or the next backoff would overrun the total deadline.',
47
+ recovery: 'Retry after a brief delay; NCBI failed on every attempt this call made.',
48
+ retryable: true,
49
+ thrownBy: 'service',
50
+ },
51
+ {
52
+ reason: 'ncbi_rate_limited',
53
+ code: JsonRpcErrorCode.RateLimited,
54
+ when: 'NCBI answered HTTP 429 (too many requests) and the call stopped on it — retries ran out, the next backoff would overrun the total deadline, or the Retry-After NCBI named outlasts the time left or the 30-second backoff cap.',
55
+ recovery: "Wait as long as `retryAfter` says when present (a number of seconds or an HTTP date), otherwise a few seconds, then retry; NCBI is throttling this server's requests. If the server runs without NCBI_API_KEY, setting it raises the E-utilities ceiling from about 3 to about 10 requests per second and shortens the default gap between requests — an operator setting in the server's environment, not a tool input.",
43
56
  retryable: true,
44
57
  thrownBy: 'service',
45
58
  },
46
59
  {
47
60
  reason: 'ncbi_deadline_exceeded',
48
61
  code: JsonRpcErrorCode.Timeout,
49
- when: 'Total request deadline expired before NCBI returned a response.',
50
- recovery: 'Reduce batch size or retry; NCBI may be under temporary load.',
62
+ when: 'The total NCBI request deadline expired before NCBI answered successfully — mid-request, while queued, or during a retry backoff.',
63
+ recovery: 'Retry after a brief delay; NCBI may be under temporary load. For a large batch, split it into smaller calls.',
51
64
  retryable: true,
52
65
  thrownBy: 'service',
53
66
  },
@@ -69,34 +82,32 @@ export const NCBI_SERVICE_ERRORS = [
69
82
  },
70
83
  ];
71
84
  /**
72
- * Input failure the NCBI query tools reject before any call is made. Declared
73
- * here rather than inside `NCBI_SERVICE_ERRORS` so only the tools that actually
74
- * throw it advertise it — a tool that takes no free-text query can never
75
- * produce it, and declaring it there would advertise a failure mode that
76
- * cannot happen.
85
+ * Input failure the free-text query tools reject before any call is made —
86
+ * the NCBI query tools and `pubmed_europepmc_search` alike. Declared here
87
+ * rather than inside a service array so only the tools that actually throw it
88
+ * advertise it — a tool that takes no free-text query can never produce it,
89
+ * and declaring it there would advertise a failure mode that cannot happen.
77
90
  *
78
91
  * Unlike the service arrays in this module, this one is thrown from a tool
79
- * handler via `ctx.fail('blank_query', …)`, so its recovery hint resolves
80
- * through `ctx.recoveryFor` and it stays out of {@link ServiceErrorReason}.
92
+ * handler via `ctx.fail('blank_query', …)`, so its entry carries no `thrownBy`.
81
93
  */
82
- export const NCBI_QUERY_INPUT_ERRORS = [
94
+ export const QUERY_INPUT_ERRORS = [
83
95
  {
84
96
  reason: 'blank_query',
85
97
  code: JsonRpcErrorCode.ValidationError,
86
- when: 'The query holds no search term once whitespace, and anything the tool strips before searching, are removed — so NCBI would receive a blank term. pubmed_search_articles strips markup, bracketed field tags, and parentheses, so a bare field tag such as `[pdat]` or empty parentheses `()` count as blank there.',
87
- recovery: 'Supply a nonblank search term — a bare field tag or empty parentheses carry none; NCBI cannot search a blank term and retrying the same input will not help.',
98
+ when: 'The query contains no search term: nothing is left once whitespace and invisible characters such as a zero-width space are disregarded. pubmed_search_articles and pubmed_europepmc_search first decode HTML entities and also disregard markup and parentheses, so `()`, `<b></b>`, and `&nbsp;` hold no term there; pubmed_search_articles also disregards bracketed field tags such as `[pdat]`.',
99
+ recovery: 'Supply a nonblank search term; retrying the same blank input will not help.',
88
100
  retryable: false,
89
101
  },
90
102
  ];
91
103
  /**
92
104
  * Input failure the identifier-conversion path rejects before any call is made.
93
- * Separate from {@link NCBI_QUERY_INPUT_ERRORS} for the same reason that array
105
+ * Separate from {@link QUERY_INPUT_ERRORS} for the same reason that array
94
106
  * is separate from the service contracts: only a tool that takes caller-supplied
95
107
  * identifiers can produce it.
96
108
  *
97
- * Thrown from a tool handler via `ctx.fail('malformed_id', …)`, so its recovery
98
- * hint resolves through `ctx.recoveryFor` and it stays out of
99
- * {@link ServiceErrorReason}.
109
+ * Thrown from a tool handler via `ctx.fail('malformed_id', …)`, so its entry
110
+ * carries no `thrownBy`.
100
111
  */
101
112
  export const NCBI_ID_INPUT_ERRORS = [
102
113
  {
@@ -107,23 +118,6 @@ export const NCBI_ID_INPUT_ERRORS = [
107
118
  retryable: false,
108
119
  },
109
120
  ];
110
- /**
111
- * Failure modes the Unpaywall service layer can surface. A tool whose handler
112
- * lets `getUnpaywallService()` failures propagate spreads these into its
113
- * `errors[]`. None does today: `pubmed_fetch_fulltext`, the only consumer,
114
- * folds every Unpaywall failure into its tier chain, so the entries serve the
115
- * service's own `recoveryFor` hints.
116
- */
117
- export const UNPAYWALL_SERVICE_ERRORS = [
118
- {
119
- reason: 'unpaywall_unreachable',
120
- code: JsonRpcErrorCode.ServiceUnavailable,
121
- when: 'Unpaywall was unreachable when resolving a DOI or fetching content.',
122
- recovery: 'Retry after a brief delay; Unpaywall was unreachable. The PMC source remains the primary path.',
123
- retryable: true,
124
- thrownBy: 'service',
125
- },
126
- ];
127
121
  /**
128
122
  * Failure modes the OpenAlex service layer can surface. Tools whose handler
129
123
  * lets `getOpenAlexService()` / `getOpenAlexServiceOptional()` failures
@@ -140,7 +134,7 @@ export const OPENALEX_SERVICE_ERRORS = [
140
134
  },
141
135
  {
142
136
  reason: 'openalex_invalid_response',
143
- code: JsonRpcErrorCode.SerializationError,
137
+ code: JsonRpcErrorCode.ServiceUnavailable,
144
138
  when: 'OpenAlex returned a body that could not be parsed (invalid JSON).',
145
139
  recovery: 'Retry the request; OpenAlex returned a malformed response that could not be parsed.',
146
140
  retryable: true,
@@ -172,36 +166,10 @@ export const EUROPEPMC_SERVICE_ERRORS = [
172
166
  {
173
167
  reason: 'europepmc_invalid_input',
174
168
  code: JsonRpcErrorCode.ValidationError,
175
- 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.',
176
- recovery: 'Adjust the input — the query, the sort, or the cursorMark — before retrying; the same input will be rejected again.',
169
+ when: 'Europe PMC rejected the request input — an error message in place of results, an empty response to a sort with an undocumented field or no asc/desc direction, or a pagination cursor it cannot read (an empty response on the last attempt the retry budget allows, or a second HTTP 503 when the first page of the same query is served).',
170
+ recovery: "Fix the rejected input before retrying — the query, the sort, or the cursorMark (pass the previous response's `nextCursorMark` verbatim, or `*` to restart); the same input will most likely be rejected again.",
177
171
  retryable: false,
178
172
  thrownBy: 'service',
179
173
  },
180
174
  ];
181
- const REASON_TO_RECOVERY = new Map([
182
- ...NCBI_SERVICE_ERRORS,
183
- ...UNPAYWALL_SERVICE_ERRORS,
184
- ...EUROPEPMC_SERVICE_ERRORS,
185
- ...OPENALEX_SERVICE_ERRORS,
186
- ].map((entry) => [entry.reason, entry.recovery]));
187
- /**
188
- * Service-layer counterpart to `ctx.recoveryFor`. Returns `{ recovery: { hint } }`
189
- * for the contract reason. Use at every service throw that stamps a `reason` so
190
- * the wire payload carries the same actionable hint the LLM gets from
191
- * handler-level `ctx.fail`.
192
- *
193
- * The parameter is constrained to `ServiceErrorReason`, so typos fail at compile
194
- * time. The runtime guard catches the impossible case where the reason union
195
- * and the recovery map drift apart in future edits.
196
- *
197
- * @example
198
- * throw serviceUnavailable(msg, { reason: 'ncbi_unreachable', ...recoveryFor('ncbi_unreachable') });
199
- */
200
- export function recoveryFor(reason) {
201
- const hint = REASON_TO_RECOVERY.get(reason);
202
- if (hint === undefined) {
203
- throw new Error(`recoveryFor: no recovery hint registered for reason "${reason}"`);
204
- }
205
- return { recovery: { hint } };
206
- }
207
175
  //# sourceMappingURL=error-contracts.js.map
@@ -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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"}
@@ -45,8 +45,8 @@ export declare class EuropePmcApiClient {
45
45
  * query is HTTP 200 with `hitCount: 0`. A 404 is reclassified from its
46
46
  * status-mapped `NotFound` to `ServiceUnavailable` so the service retries it.
47
47
  * A retryable 5xx keeps its code, so a 504 stays `Timeout`. Only a failure
48
- * that ends up `ServiceUnavailable` carries `europepmc_unreachable` and its
49
- * recovery hint, the one code that reason is declared for. An upstream
48
+ * that ends up `ServiceUnavailable` carries `europepmc_unreachable`, the one
49
+ * code that reason is declared for. An upstream
50
50
  * `retryAfter` is kept. A 429 and every other 4xx pass through unchanged, as
51
51
  * does a 501, whose `data.retryable: false` keeps it out of the retry loop.
52
52
  * (#152)
@@ -84,6 +84,12 @@ export declare class EuropePmcApiClient {
84
84
  * optional source filter. EPMC's query syntax supports `SRC:"X"` field tokens —
85
85
  * the requested sources are OR-joined into a parenthesized clause and ANDed
86
86
  * with the caller's query.
87
+ *
88
+ * A single source is repeated (`SRC:"MED" OR SRC:"MED"`). Europe PMC matches
89
+ * nothing when a query is exactly one `EXT_ID` clause ANDed with one `SRC`
90
+ * clause and either value is quoted; the repeated clause matches quoted and
91
+ * unquoted `EXT_ID` alike and returns the same total as a lone clause for any
92
+ * other query. Multi-source clauses are sent as they are. (#175)
87
93
  */
88
94
  export declare function buildSearchQuery(params: Pick<EuropePmcSearchParams, 'query' | 'sources'>): string;
89
95
  //# sourceMappingURL=api-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/services/europe-pmc/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAI5E,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C;;;;;;;;GAQG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAnC,YAA6B,MAAM,EAAE,wBAAwB,EAAI;IAEjE;;;;;;;;;;;;;;OAcG;IACG,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C3D;IAED;;;;;;;;;OASG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA4C7F;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;IAED;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9F;IAED,iFAAiF;YACnE,cAAc;IA8B5B,OAAO,CAAC,cAAc;CAavB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,MAAM,CAKjG"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/services/europe-pmc/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAI5E,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C;;;;;;;;GAQG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAnC,YAA6B,MAAM,EAAE,wBAAwB,EAAI;IAEjE;;;;;;;;;;;;;;OAcG;IACG,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2C3D;IAED;;;;;;;;;OASG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA4C7F;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;IAED;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9F;IAED,iFAAiF;YACnE,cAAc;IA8B5B,OAAO,CAAC,cAAc;CAavB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,MAAM,CAOjG"}
@@ -10,7 +10,6 @@
10
10
  */
11
11
  import { JsonRpcErrorCode, McpError, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
12
12
  import { fetchWithTimeout, logger, requestContextService } from '@cyanheads/mcp-ts-core/utils';
13
- import { recoveryFor } from '../error-contracts.js';
14
13
  import { EUROPEPMC_API_BASE } from './types.js';
15
14
  const USER_AGENT = 'pubmed-mcp-server (+https://github.com/cyanheads/pubmed-mcp-server)';
16
15
  /**
@@ -36,8 +35,8 @@ export class EuropePmcApiClient {
36
35
  * query is HTTP 200 with `hitCount: 0`. A 404 is reclassified from its
37
36
  * status-mapped `NotFound` to `ServiceUnavailable` so the service retries it.
38
37
  * A retryable 5xx keeps its code, so a 504 stays `Timeout`. Only a failure
39
- * that ends up `ServiceUnavailable` carries `europepmc_unreachable` and its
40
- * recovery hint, the one code that reason is declared for. An upstream
38
+ * that ends up `ServiceUnavailable` carries `europepmc_unreachable`, the one
39
+ * code that reason is declared for. An upstream
41
40
  * `retryAfter` is kept. A 429 and every other 4xx pass through unchanged, as
42
41
  * does a 501, whose `data.retryable: false` keeps it out of the retry loop.
43
42
  * (#152)
@@ -66,14 +65,13 @@ export class EuropePmcApiClient {
66
65
  throw new McpError(code, `Europe PMC search request failed: ${error.message}`, {
67
66
  ...(code === JsonRpcErrorCode.ServiceUnavailable && {
68
67
  reason: 'europepmc_unreachable',
69
- ...recoveryFor('europepmc_unreachable'),
70
68
  }),
71
69
  status,
72
70
  ...(error.data?.retryAfter !== undefined && { retryAfter: error.data.retryAfter }),
73
71
  }, { cause: error });
74
72
  }
75
73
  const msg = error instanceof Error ? error.message : String(error);
76
- throw serviceUnavailable(`Europe PMC search request failed: ${msg}`, { reason: 'europepmc_unreachable', ...recoveryFor('europepmc_unreachable') }, { cause: error });
74
+ throw serviceUnavailable(`Europe PMC search request failed: ${msg}`, { reason: 'europepmc_unreachable' }, { cause: error });
77
75
  }
78
76
  return response.text();
79
77
  }
@@ -112,7 +110,7 @@ export class EuropePmcApiClient {
112
110
  throw error;
113
111
  }
114
112
  const msg = error instanceof Error ? error.message : String(error);
115
- throw serviceUnavailable(`Europe PMC fullTextXML request failed: ${msg}`, { reason: 'europepmc_unreachable', epmcId, ...recoveryFor('europepmc_unreachable') }, { cause: error });
113
+ throw serviceUnavailable(`Europe PMC fullTextXML request failed: ${msg}`, { reason: 'europepmc_unreachable', epmcId }, { cause: error });
116
114
  }
117
115
  const xml = await response.text();
118
116
  if (!xml.trim()) {
@@ -159,7 +157,7 @@ export class EuropePmcApiClient {
159
157
  if (error instanceof McpError)
160
158
  throw error;
161
159
  const msg = error instanceof Error ? error.message : String(error);
162
- throw serviceUnavailable(`Europe PMC links request failed: ${msg}`, { reason: 'europepmc_unreachable', ...recoveryFor('europepmc_unreachable') }, { cause: error });
160
+ throw serviceUnavailable(`Europe PMC links request failed: ${msg}`, { reason: 'europepmc_unreachable' }, { cause: error });
163
161
  }
164
162
  return response.text();
165
163
  }
@@ -183,12 +181,19 @@ export class EuropePmcApiClient {
183
181
  * optional source filter. EPMC's query syntax supports `SRC:"X"` field tokens —
184
182
  * the requested sources are OR-joined into a parenthesized clause and ANDed
185
183
  * with the caller's query.
184
+ *
185
+ * A single source is repeated (`SRC:"MED" OR SRC:"MED"`). Europe PMC matches
186
+ * nothing when a query is exactly one `EXT_ID` clause ANDed with one `SRC`
187
+ * clause and either value is quoted; the repeated clause matches quoted and
188
+ * unquoted `EXT_ID` alike and returns the same total as a lone clause for any
189
+ * other query. Multi-source clauses are sent as they are. (#175)
186
190
  */
187
191
  export function buildSearchQuery(params) {
188
192
  const base = params.query.trim();
189
193
  if (!params.sources || params.sources.length === 0)
190
194
  return base;
191
- const sourceClause = params.sources.map((s) => `SRC:"${s}"`).join(' OR ');
195
+ const sources = params.sources.length === 1 ? [...params.sources, ...params.sources] : params.sources;
196
+ const sourceClause = sources.map((s) => `SRC:"${s}"`).join(' OR ');
192
197
  return `(${base}) AND (${sourceClause})`;
193
198
  }
194
199
  //# sourceMappingURL=api-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/services/europe-pmc/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/services/europe-pmc/api-client.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,10 @@
14
14
  * A search's retry boundary covers fetch and response classification, so
15
15
  * Europe PMC's intermittent empty `{ version }` envelope is retried like an
16
16
  * HTTP outage; only a sort or cursor that explains it is reported as bad input.
17
+ * Europe PMC answers an unreadable cursor with the HTTP 503 it uses for an
18
+ * outage, so a 503 on a caller-supplied cursor is checked against the first
19
+ * page of the same query, and the cursor is blamed only when a retry draws
20
+ * the 503 again while that first page was served.
17
21
  * A search reports the effective query Europe PMC echoes back, or — with no
18
22
  * echo — the source-filtered query it sent.
19
23
  *
@@ -51,12 +55,26 @@ export declare class EuropePmcService {
51
55
  * The retry boundary covers the fetch and the response classification
52
56
  * together, so an empty envelope retries like any other transient failure
53
57
  * rather than surfacing after the loop has already returned. (#159)
58
+ *
59
+ * The first HTTP 503 on a caller-supplied cursor draws one probe of the same
60
+ * query's first page, and the cursor is retried either way: one 503 is not
61
+ * enough to tell a bad cursor from a transient outage. A later 503 fails the
62
+ * search at once as non-retryable input only when that probe was served;
63
+ * otherwise it goes on through the ordinary retry path. A 503 with no retry
64
+ * left is never probed, since nothing could use the answer. (#180)
54
65
  */
55
66
  search(params: EuropePmcSearchParams): Promise<EuropePmcSearchResult>;
67
+ /**
68
+ * Whether Europe PMC serves the first page of the search in `params`: one
69
+ * request (`cursorMark: '*'`, `pageSize: 1`), paced like any other, with no
70
+ * retries of its own. Any failure reads as not served — except the caller's
71
+ * cancellation, which propagates.
72
+ */
73
+ private firstPageServed;
56
74
  /**
57
75
  * One search attempt: fetch, parse, and classify the body. `isLastAttempt`
58
- * lets an empty envelope that has persisted through the whole retry budget
59
- * be attributed to a caller-supplied cursor.
76
+ * lets an empty envelope on the last attempt the retry budget allows be
77
+ * attributed to a caller-supplied cursor.
60
78
  */
61
79
  private searchOnce;
62
80
  /**
@@ -129,6 +147,11 @@ export declare class EuropePmcService {
129
147
  * signal reaches the queue wait and the backoff sleep. `execute` receives the
130
148
  * one-based attempt number.
131
149
  *
150
+ * `reclassify`, when given, sees each failed attempt after its queue slot is
151
+ * released and before the retry decision, with the attempt's signal and its
152
+ * one-based number. The error it returns is the one the loop judges, so it
153
+ * can end the retries by returning a non-transient error.
154
+ *
132
155
  * A caller abort rethrows the caller's own reason; an exhausted failure is
133
156
  * reshaped by {@link toServiceError}, after the loop.
134
157
  */
@@ -1 +1 @@
1
- {"version":3,"file":"europe-pmc-service.d.ts","sourceRoot":"","sources":["../../../src/services/europe-pmc/europe-pmc-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AASH,OAAO,EAGL,KAAK,KAAK,EAGX,MAAM,8BAA8B,CAAC;AAOtC,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,4CAA4C,CAAC;AAEzF,OAAO,EAAoB,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EACV,uBAAuB,EAEvB,kBAAkB,EAElB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EAErB,qBAAqB,EACrB,eAAe,EAChB,MAAM,YAAY,CAAC;AA2FpB;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAL7B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAY;IAE7C,YACmB,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAQpC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAIpE;IAED;;;;OAIG;YACW,UAAU;IAwHxB;;;;;;;;;;OAUG;IACG,YAAY,CAChB,IAAI,EAAE,SAAS,kBAAkB,EAAE,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAQ/B;IAED;;;;;;;OAOG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,uBAAuB,CAAC,CASlC;IAED;;;;;;;;;;OAUG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAQjC;IAED;;;;;;;;;;OAUG;IACH,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAQjC;IAED;;;;;OAKG;YACW,iBAAiB;IAkE/B;;;;;;;;OAQG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CA8BlD;IAED;;;;;;;;;;OAUG;YACW,QAAQ;CA0CvB;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAyB3C;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS,CAElE"}
1
+ {"version":3,"file":"europe-pmc-service.d.ts","sourceRoot":"","sources":["../../../src/services/europe-pmc/europe-pmc-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AASH,OAAO,EAGL,KAAK,KAAK,EAGX,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,4CAA4C,CAAC;AAEzF,OAAO,EAAoB,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EACV,uBAAuB,EAEvB,kBAAkB,EAElB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EAErB,qBAAqB,EACrB,eAAe,EAChB,MAAM,YAAY,CAAC;AAsGpB;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAL7B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAY;IAE7C,YACmB,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAQpC;IAED;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+BpE;IAED;;;;;OAKG;YACW,eAAe;IAgB7B;;;;OAIG;YACW,UAAU;IAyHxB;;;;;;;;;;OAUG;IACG,YAAY,CAChB,IAAI,EAAE,SAAS,kBAAkB,EAAE,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAQ/B;IAED;;;;;;;OAOG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,uBAAuB,CAAC,CASlC;IAED;;;;;;;;;;OAUG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAQjC;IAED;;;;;;;;;;OAUG;IACH,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAQjC;IAED;;;;;OAKG;YACW,iBAAiB;IAkE/B;;;;;;;;OAQG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CA4BlD;IAED;;;;;;;;;;;;;;;OAeG;YACW,QAAQ;CA8CvB;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAyB3C;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS,CAElE"}