@cyanheads/openalex-mcp-server 0.7.14 → 0.7.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 (32) hide show
  1. package/AGENTS.md +8 -4
  2. package/CLAUDE.md +8 -4
  3. package/README.md +7 -6
  4. package/changelog/0.7.x/0.7.15.md +33 -0
  5. package/dist/mcp-server/prompts/definitions/literature-review.prompt.js +1 -1
  6. package/dist/mcp-server/prompts/definitions/literature-review.prompt.js.map +1 -1
  7. package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts +19 -0
  8. package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts.map +1 -1
  9. package/dist/mcp-server/tools/definitions/analyze-trends.tool.js +31 -3
  10. package/dist/mcp-server/tools/definitions/analyze-trends.tool.js.map +1 -1
  11. package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts +12 -1
  12. package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/definitions/citation-graph.tool.js +55 -38
  14. package/dist/mcp-server/tools/definitions/citation-graph.tool.js.map +1 -1
  15. package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts +11 -0
  16. package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/definitions/resolve-name.tool.js +12 -1
  18. package/dist/mcp-server/tools/definitions/resolve-name.tool.js.map +1 -1
  19. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +40 -0
  20. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/search-entities.tool.js +146 -39
  22. package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -1
  23. package/dist/services/openalex/openalex-service.d.ts +16 -0
  24. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  25. package/dist/services/openalex/openalex-service.js +103 -27
  26. package/dist/services/openalex/openalex-service.js.map +1 -1
  27. package/dist/services/openalex/types.d.ts +11 -0
  28. package/dist/services/openalex/types.d.ts.map +1 -1
  29. package/dist/services/openalex/types.js +7 -0
  30. package/dist/services/openalex/types.js.map +1 -1
  31. package/package.json +3 -3
  32. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** openalex-mcp-server
4
- **Version:** 0.7.14
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.5`
4
+ **Version:** 0.7.15
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
8
8
  **Zod:** ^4.6.5
@@ -168,7 +168,7 @@ Handlers receive a unified `ctx` object. Key properties:
168
168
 
169
169
  Handlers throw — the framework catches, classifies, and formats.
170
170
 
171
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union — `ctx.fail('typo')` is a TS error, `data.reason` is auto-populated, and the linter enforces conformance against the handler. The `recovery` field is required (≥5 words). Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire.
171
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, thrownBy? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union — `ctx.fail('typo')` is a TS error, `data.reason` is auto-populated, and the linter enforces conformance against the handler. The `recovery` field is required (≥5 words). Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire; `error-contract-recovery-unforwarded` warns per `ctx.fail` site that forwards neither the resolver nor its own `recovery` key.
172
172
 
173
173
  ```ts
174
174
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -177,6 +177,10 @@ errors: [
177
177
  { reason: 'semantic_per_page_cap', code: JsonRpcErrorCode.ValidationError,
178
178
  when: 'per_page exceeds the semantic-search cap',
179
179
  recovery: 'Reduce per_page to 50 or less, or switch search_mode to keyword.' },
180
+ { reason: 'upstream_timeout', code: JsonRpcErrorCode.Timeout,
181
+ when: 'OpenAlex did not respond within the request deadline',
182
+ recovery: 'Retry after a short delay, or narrow the request with tighter filters.',
183
+ thrownBy: 'service' },
180
184
  ],
181
185
  async handler(input, ctx) {
182
186
  if (overCap) throw ctx.fail('semantic_per_page_cap', message, { ...ctx.recoveryFor('semantic_per_page_cap') });
@@ -185,7 +189,7 @@ async handler(input, ctx) {
185
189
 
186
190
  **Declare contracts inline on each tool, even when similar across tools.** The contract is part of the tool's documented public surface — reading one tool definition file should give the full picture. Don't extract a shared `errors[]` constant; per-tool repetition is the intended cost of locality.
187
191
 
188
- The OpenAlex service throws factory errors (`notFound`, `rateLimited`, etc.) based on upstream status codes, carrying the contract `reason` on `data.reason` and the recovery via `ctx.recoveryFor(reason)`; those bubble through and are auto-classified. Because most declared reasons are produced in the service, handler-local precondition throws (`semantic_per_page_cap`, `reserved_filter_key`, …) live in module-level helpers (`assertListQueryConstraints`, `assertNoReservedFilterKey`, `resolveSeedToWorkId`) rather than inline: `error-contract-unthrown` only scans handlers holding a literal `ctx.fail(`, and an inline one would flag every service-produced reason as dead. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely without needing to be declared on a contract.
192
+ The OpenAlex service throws factory errors (`notFound`, `rateLimited`, etc.) based on upstream status codes, carrying the contract `reason` on `data.reason` and the recovery via `ctx.recoveryFor(reason)`; those bubble through and are auto-classified. Every such entry carries `thrownBy: 'service'` — lint-only metadata that tells `error-contract-unthrown`, whose scan reads the handler body alone, to skip a reason produced a layer below it. Handler-local precondition throws stay inline and unmarked so the rule keeps checking them: `semantic_without_query`, `semantic_per_page_cap`, `semantic_with_cursor`, `page_without_semantic`, `sample_with_cursor`, `sample_with_page`, and `seed_without_sample` on `openalex_search_entities`; `reserved_filter_key` and the seed-lookup `entity_not_found` on `openalex_get_citation_graph`. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely without needing to be declared on a contract.
189
193
 
190
194
  **Fallback for ad-hoc throws:** error factories or plain `Error`.
191
195
 
package/CLAUDE.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** openalex-mcp-server
4
- **Version:** 0.7.14
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.5`
4
+ **Version:** 0.7.15
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
8
8
  **Zod:** ^4.6.5
@@ -168,7 +168,7 @@ Handlers receive a unified `ctx` object. Key properties:
168
168
 
169
169
  Handlers throw — the framework catches, classifies, and formats.
170
170
 
171
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union — `ctx.fail('typo')` is a TS error, `data.reason` is auto-populated, and the linter enforces conformance against the handler. The `recovery` field is required (≥5 words). Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire.
171
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, thrownBy? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union — `ctx.fail('typo')` is a TS error, `data.reason` is auto-populated, and the linter enforces conformance against the handler. The `recovery` field is required (≥5 words). Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire; `error-contract-recovery-unforwarded` warns per `ctx.fail` site that forwards neither the resolver nor its own `recovery` key.
172
172
 
173
173
  ```ts
174
174
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -177,6 +177,10 @@ errors: [
177
177
  { reason: 'semantic_per_page_cap', code: JsonRpcErrorCode.ValidationError,
178
178
  when: 'per_page exceeds the semantic-search cap',
179
179
  recovery: 'Reduce per_page to 50 or less, or switch search_mode to keyword.' },
180
+ { reason: 'upstream_timeout', code: JsonRpcErrorCode.Timeout,
181
+ when: 'OpenAlex did not respond within the request deadline',
182
+ recovery: 'Retry after a short delay, or narrow the request with tighter filters.',
183
+ thrownBy: 'service' },
180
184
  ],
181
185
  async handler(input, ctx) {
182
186
  if (overCap) throw ctx.fail('semantic_per_page_cap', message, { ...ctx.recoveryFor('semantic_per_page_cap') });
@@ -185,7 +189,7 @@ async handler(input, ctx) {
185
189
 
186
190
  **Declare contracts inline on each tool, even when similar across tools.** The contract is part of the tool's documented public surface — reading one tool definition file should give the full picture. Don't extract a shared `errors[]` constant; per-tool repetition is the intended cost of locality.
187
191
 
188
- The OpenAlex service throws factory errors (`notFound`, `rateLimited`, etc.) based on upstream status codes, carrying the contract `reason` on `data.reason` and the recovery via `ctx.recoveryFor(reason)`; those bubble through and are auto-classified. Because most declared reasons are produced in the service, handler-local precondition throws (`semantic_per_page_cap`, `reserved_filter_key`, …) live in module-level helpers (`assertListQueryConstraints`, `assertNoReservedFilterKey`, `resolveSeedToWorkId`) rather than inline: `error-contract-unthrown` only scans handlers holding a literal `ctx.fail(`, and an inline one would flag every service-produced reason as dead. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely without needing to be declared on a contract.
192
+ The OpenAlex service throws factory errors (`notFound`, `rateLimited`, etc.) based on upstream status codes, carrying the contract `reason` on `data.reason` and the recovery via `ctx.recoveryFor(reason)`; those bubble through and are auto-classified. Every such entry carries `thrownBy: 'service'` — lint-only metadata that tells `error-contract-unthrown`, whose scan reads the handler body alone, to skip a reason produced a layer below it. Handler-local precondition throws stay inline and unmarked so the rule keeps checking them: `semantic_without_query`, `semantic_per_page_cap`, `semantic_with_cursor`, `page_without_semantic`, `sample_with_cursor`, `sample_with_page`, and `seed_without_sample` on `openalex_search_entities`; `reserved_filter_key` and the seed-lookup `entity_not_found` on `openalex_get_citation_graph`. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely without needing to be declared on a contract.
189
193
 
190
194
  **Fallback for ad-hoc throws:** error factories or plain `Error`.
191
195
 
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.7.14-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openalex-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/openalex-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openalex-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.7.15-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openalex-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/openalex-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openalex-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -52,11 +52,12 @@ Scholarly catalog data from [OpenAlex](https://openalex.org) — 270M+ works, 90
52
52
 
53
53
  ### `openalex_search_entities` <sub>tool</sub>
54
54
 
55
- - Retrieve a single entity by ID — OpenAlex ID, DOI, ORCID, ROR, PMID, ISSN, or PMCID (bare or URL form). `id` takes precedence: search parameters passed alongside it are dropped, and the response names which ones. A PMCID resolves nothing (OpenAlex indexes none) — use the work's PMID or DOI instead
56
- - Keyword search (boolean operators, quoted phrases, wildcards, fuzzy match) plus `exact` and `semantic` search modes — semantic caps at 50 results per page and ~1 req/sec
55
+ - Retrieve a single entity by ID — OpenAlex ID, DOI, ORCID, ROR, PMID, ISSN, or PMCID (bare or URL form), or a keyword by its slug or keyword URL. `id` takes precedence: search parameters passed alongside it are dropped, and the response names which ones. A PMCID resolves nothing (OpenAlex indexes none) — use the work's PMID or DOI instead
56
+ - Keyword search (boolean operators, quoted phrases, wildcards, fuzzy match) plus `exact` and `semantic` search modes — semantic ranks at most 50 candidates at ~1 req/sec, and its `meta.count` reports that ceiling rather than a match total
57
57
  - Rich filter syntax: AND across fields, OR within a field (`|`), NOT (`!`), ranges, comparisons; a comma inside a filter value is rejected (use `|`, or a `.search` filter for free text)
58
58
  - `select` returns a curated per-entity-type default unless overridden, or `["*"]` for the full record; invalid field names error with the valid set
59
- - Cursor pagination, up to 100 results per page (default 25); `sample` (up to 100, single page only, no `cursor`) plus a deterministic `seed` for reproducible random sampling
59
+ - Cursor pagination for keyword and exact search, up to 100 results per page (default 25); semantic search walks its candidates with `page` (1-based) instead, and mixing either knob with the wrong `search_mode` is rejected before the upstream call
60
+ - `sample` (up to 100, single page only — neither `cursor` nor `page` applies) plus a deterministic `seed` for reproducible random sampling
60
61
  - `display_name` is nullable for untitled records; every call reports OpenAlex daily-budget cost and remaining balance
61
62
 
62
63
  ---
@@ -74,7 +75,7 @@ Scholarly catalog data from [OpenAlex](https://openalex.org) — 270M+ works, 90
74
75
  ### `openalex_resolve_name` <sub>tool</sub>
75
76
 
76
77
  - A name or partial name runs an autocomplete search: up to 10 matches with disambiguation hints (last institution, host organization, place, etc.)
77
- - An identifier — OpenAlex ID, DOI, ORCID, ROR, PMID, or ISSN, bare or in URL form — resolves directly to the one record it addresses; no `entity_type` needed, since the identifier determines its own. A PMCID is recognized but resolves nothing — OpenAlex indexes none
78
+ - An identifier — OpenAlex ID, DOI, ORCID, ROR, PMID, ISSN, or keyword URL, bare or in URL form — resolves directly to the one record it addresses; no `entity_type` needed, since the identifier determines its own. A PMCID is recognized but resolves nothing — OpenAlex indexes none
78
79
  - `filters` narrows autocomplete only; on an identifier lookup they're ignored and named in a notice
79
80
  - Reports OpenAlex daily-budget cost and remaining balance
80
81
 
@@ -84,7 +85,7 @@ Scholarly catalog data from [OpenAlex](https://openalex.org) — 270M+ works, 90
84
85
 
85
86
  - `direction` sets the edge: `cites` (works citing the seed), `cited_by` (the seed's own reference list), `related_to` (OpenAlex's algorithmic related works, ~8-30 typical, may be empty)
86
87
  - `seed_id` accepts an OpenAlex ID, DOI, or PMID (PMCID recognized but resolves nothing); validated against a live lookup first, so a non-existent seed fails as `NotFound` rather than returning an empty graph
87
- - Stacks with `filters`/`sort`/`select` to narrow the graph; `filters` cannot set `cites`/`cited_by`/`related_to` directly — those are reserved for `direction`
88
+ - Stacks with `filters`/`sort`/`select` to narrow the graph; `filters` cannot set `cites`/`cited_by`/`related_to`, nor an alias of one such as `cited_works` — those keys are reserved for `direction`
88
89
  - Cursor pagination, up to 100 results per page (default 25)
89
90
  - Reports OpenAlex daily-budget cost, covering both the seed-validation lookup and the graph page, plus remaining balance
90
91
 
@@ -0,0 +1,33 @@
1
+ ---
2
+ summary: "Keyword identifiers, semantic-mode `page` pagination, AND'd filter aliases, and honest pagination/notice handling across the paginating tools."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.15 — 2026-09-22
8
+
9
+ ## Added
10
+
11
+ - **Keyword identifiers** resolve via their OpenAlex URL or bare slug (`https://openalex.org/keywords/groundwater` or `groundwater`) — keywords never had a native alphanumeric ID, so the removed `K`-prefixed routing arm 404'd. ([#68](https://github.com/cyanheads/openalex-mcp-server/issues/68))
12
+ - **`page`** input on `openalex_search_entities` paginates semantic search (1-based), the one mode OpenAlex rejects `cursor` on. Combining `page`/`cursor`/`sample` with the wrong mode now throws `semantic_with_cursor`, `page_without_semantic`, or `sample_with_page`. ([#71](https://github.com/cyanheads/openalex-mcp-server/issues/71))
13
+ - **`best_oa_location`** joins the default `works` projection, naming a green-OA work's readable copy (`pdf_url`, `license`, `version`, hosting source) instead of leaving only the closed publisher location. ([#79](https://github.com/cyanheads/openalex-mcp-server/issues/79))
14
+ - **`query_too_long`** error reason on `openalex_search_entities` — an over-length `query` (HTTP 400) now maps to its own contract entry instead of the generic invalid-params one. ([#71](https://github.com/cyanheads/openalex-mcp-server/issues/71))
15
+
16
+ ## Changed
17
+
18
+ - **Filter aliases** resolving to the same upstream key are now AND'd instead of silently overwriting — `{year: "2020", publication_year: "2024"}` now matches works in both years, matching OpenAlex's own repeated-key behavior. ([#70](https://github.com/cyanheads/openalex-mcp-server/issues/70))
19
+ - **`openalex_get_citation_graph`'s reserved-key guard** now checks the *translated* filter key, so an alias of `cites`/`cited_by`/`related_to` (e.g. `cited_works`) is caught instead of colliding silently with `direction`. ([#70](https://github.com/cyanheads/openalex-mcp-server/issues/70))
20
+ - **Pagination-exhausted notices** — `openalex_search_entities`, `openalex_analyze_trends`, and `openalex_get_citation_graph` now report the traversal as finished on an empty page reached via `cursor`, instead of advising a broader query. ([#74](https://github.com/cyanheads/openalex-mcp-server/issues/74))
21
+ - **`meta.per_page`** on `openalex_search_entities` and `openalex_get_citation_graph` now documents itself as the requested page size, not the record count returned. ([#74](https://github.com/cyanheads/openalex-mcp-server/issues/74))
22
+ - **`meta.count`** under `search_mode: "semantic"` is disclosed as the capped candidate ceiling (≤50), not an exhaustive match total. ([#71](https://github.com/cyanheads/openalex-mcp-server/issues/71))
23
+
24
+ ## Fixed
25
+
26
+ - **Blank `id`/`query`/`cursor`/`group_by` inputs** on the paginating tools are now rejected at the schema, instead of running as an unfiltered listing or an accepted "exhausted" page. ([#69](https://github.com/cyanheads/openalex-mcp-server/issues/69), [#80](https://github.com/cyanheads/openalex-mcp-server/issues/80))
27
+ - **`openalex_analyze_trends`** no longer reports a successful empty aggregation when OpenAlex answers with its plain list shape (no `group_by` key) — it now throws `upstream_missing_group_by`. ([#69](https://github.com/cyanheads/openalex-mcp-server/issues/69))
28
+ - **`openalex_literature_review`** prompt's step 3 now re-runs the step-2 filtered search sorted by `-cited_by_count` instead of an unfiltered search, and names the fields to `select` on the detail lookup. ([#77](https://github.com/cyanheads/openalex-mcp-server/issues/77))
29
+
30
+ ## Dependencies
31
+
32
+ - `@cyanheads/mcp-ts-core` ^0.13.5 → ^0.13.6
33
+ - `@types/node` ^26.6.1 → ^26.6.2
@@ -41,7 +41,7 @@ Follow this workflow using the OpenAlex tools:
41
41
  - Search with multiple related topic IDs to capture adjacent areas`}
42
42
  Use select to keep payloads manageable.
43
43
 
44
- 3. **Identify key papers** — Sort by cited_by_count to find landmark works. Use openalex_search_entities with id to get full details on the most important ones.
44
+ 3. **Identify key papers** — Re-run the step 2 search with sort: "-cited_by_count" to surface landmark works, keeping the topical filters in place: an explicit sort replaces relevance ranking, so without them you get the most-cited works in the catalog rather than in "${args.topic}". Then call openalex_search_entities with id and a select naming the fields you need (e.g. ["abstract", "authorships", "primary_location"]) for the most important ones — an id lookup on its own returns the curated default projection.
45
45
 
46
46
  4. **Trace citations** — For each key paper, use openalex_get_citation_graph with direction "cites" to find subsequent work that cites it, and direction "cited_by" to find foundational work it references.
47
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"literature-review.prompt.js","sourceRoot":"","sources":["../../../../src/mcp-server/prompts/definitions/literature-review.prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,4BAA4B,EAAE;IACzE,WAAW,EACT,wHAAwH;IAC1H,SAAS,EACP,2HAA2H;IAC7H,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,CACP,+FAA+F,CAChG;QACH,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;aACzB,QAAQ,EAAE;aACV,QAAQ,CACP,wGAAwG,CACzG;KACJ,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;QACrC,OAAO;YACL;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,+CAA+C,IAAI,CAAC,KAAK;;SAEhE,KAAK;;;;mHAIqG,IAAI,CAAC,KAAK;;iFAGjH,KAAK,KAAK,QAAQ;wBAChB,CAAC,CAAC;;;qCAGqB;wBACvB,CAAC,CAAC;;;sEAIN;;;;;;;;;;;;+IAYqI;iBACtI;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"literature-review.prompt.js","sourceRoot":"","sources":["../../../../src/mcp-server/prompts/definitions/literature-review.prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,4BAA4B,EAAE;IACzE,WAAW,EACT,wHAAwH;IAC1H,SAAS,EACP,2HAA2H;IAC7H,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,CACP,+FAA+F,CAChG;QACH,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;aACzB,QAAQ,EAAE;aACV,QAAQ,CACP,wGAAwG,CACzG;KACJ,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;QACrC,OAAO;YACL;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,+CAA+C,IAAI,CAAC,KAAK;;SAEhE,KAAK;;;;mHAIqG,IAAI,CAAC,KAAK;;iFAGjH,KAAK,KAAK,QAAQ;wBAChB,CAAC,CAAC;;;qCAGqB;wBACvB,CAAC,CAAC;;;sEAIN;;;+QAGqQ,IAAI,CAAC,KAAK;;;;;;;;;+IAS1I;iBACtI;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -41,64 +41,83 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
41
41
  readonly when: "OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429).";
42
42
  readonly retryable: true;
43
43
  readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
44
+ readonly thrownBy: "service";
44
45
  }, {
45
46
  readonly reason: "upstream_budget_exhausted";
46
47
  readonly code: JsonRpcErrorCode.RateLimited;
47
48
  readonly when: "The OpenAlex daily usage budget is spent (HTTP 429).";
48
49
  readonly retryable: false;
49
50
  readonly recovery: "The daily budget refills at midnight UTC — retrying sooner will not succeed. Set OPENALEX_API_KEY to a free key (https://openalex.org/settings/api) for a larger daily budget than anonymous access, or wait for the reset.";
51
+ readonly thrownBy: "service";
50
52
  }, {
51
53
  readonly reason: "upstream_timeout";
52
54
  readonly code: JsonRpcErrorCode.Timeout;
53
55
  readonly when: "OpenAlex did not respond within the request deadline.";
54
56
  readonly retryable: true;
55
57
  readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
58
+ readonly thrownBy: "service";
56
59
  }, {
57
60
  readonly reason: "upstream_unavailable";
58
61
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
59
62
  readonly when: "OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON.";
60
63
  readonly retryable: true;
61
64
  readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
65
+ readonly thrownBy: "service";
62
66
  }, {
63
67
  readonly reason: "upstream_unauthorized";
64
68
  readonly code: JsonRpcErrorCode.Unauthorized;
65
69
  readonly when: "OpenAlex rejected the API key (HTTP 401).";
66
70
  readonly recovery: "Check that OPENALEX_API_KEY is set to a valid OpenAlex account API key (free from https://openalex.org/settings/api).";
71
+ readonly thrownBy: "service";
67
72
  }, {
68
73
  readonly reason: "upstream_forbidden";
69
74
  readonly code: JsonRpcErrorCode.Forbidden;
70
75
  readonly when: "OpenAlex denied access to the requested resource (HTTP 403).";
71
76
  readonly recovery: "Confirm the API key has access to this entity type or endpoint, then retry the request.";
77
+ readonly thrownBy: "service";
72
78
  }, {
73
79
  readonly reason: "comma_in_filter_value";
74
80
  readonly code: JsonRpcErrorCode.InvalidParams;
75
81
  readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator.";
76
82
  readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or use a `.search` filter or the `query` parameter for free-text phrases that contain commas.";
83
+ readonly thrownBy: "service";
77
84
  }, {
78
85
  readonly reason: "upstream_invalid_params";
79
86
  readonly code: JsonRpcErrorCode.InvalidParams;
80
87
  readonly when: "OpenAlex rejected an invalid group_by or filter field name (HTTP 400).";
81
88
  readonly recovery: "The upstream message names the rejected key and suggests close matches. Use openalex_describe_fields(entity_type, \"group_by\") to browse valid group_by fields, or openalex_describe_fields(entity_type, \"filter\") for filter fields.";
89
+ readonly thrownBy: "service";
82
90
  }, {
83
91
  readonly reason: "upstream_invalid_id_value";
84
92
  readonly code: JsonRpcErrorCode.InvalidParams;
85
93
  readonly when: "An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400).";
86
94
  readonly recovery: "Call openalex_resolve_name to turn the name into an OpenAlex ID, then filter by that ID. Entity filters such as authorships.author.id and primary_topic.id accept IDs only.";
95
+ readonly thrownBy: "service";
87
96
  }, {
88
97
  readonly reason: "upstream_ungroupable_group_by";
89
98
  readonly code: JsonRpcErrorCode.InvalidParams;
90
99
  readonly when: "group_by targets a raw date, float, or *.search field OpenAlex cannot aggregate (HTTP 400).";
91
100
  readonly recovery: "Group by a categorical or year field (e.g. publication_year, type, oa_status, or an integer count field) — raw date fields and *.search operators cannot be grouped. Call openalex_describe_fields(entity_type, \"group_by\") for the groupable set.";
101
+ readonly thrownBy: "service";
92
102
  }, {
93
103
  readonly reason: "upstream_invalid_params_other";
94
104
  readonly code: JsonRpcErrorCode.InvalidParams;
95
105
  readonly when: "OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name.";
96
106
  readonly recovery: "Read the upstream message in the error above and adjust the request — check filter operators, value formats, and the group_by field.";
107
+ readonly thrownBy: "service";
97
108
  }, {
98
109
  readonly reason: "upstream_validation_failed";
99
110
  readonly code: JsonRpcErrorCode.ValidationError;
100
111
  readonly when: "OpenAlex rejected the request as semantically invalid (HTTP 422).";
101
112
  readonly recovery: "Read the upstream message for the specific field, then adjust the request to satisfy validation.";
113
+ readonly thrownBy: "service";
114
+ }, {
115
+ readonly reason: "upstream_missing_group_by";
116
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
117
+ readonly when: "OpenAlex answered with its plain list shape, carrying no aggregation for the requested group_by.";
118
+ readonly retryable: true;
119
+ readonly recovery: "Retry the request; if it repeats, confirm group_by names a field OpenAlex can aggregate with openalex_describe_fields(entity_type, \"group_by\").";
120
+ readonly thrownBy: "service";
102
121
  }], {
103
122
  readonly echo: z.ZodString;
104
123
  readonly totalCount: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-trends.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+S5B,CAAC"}
1
+ {"version":3,"file":"analyze-trends.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4U5B,CAAC"}
@@ -18,6 +18,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
18
18
  when: 'OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429).',
19
19
  retryable: true,
20
20
  recovery: 'Wait several seconds and retry; consider lowering request frequency for this caller.',
21
+ thrownBy: 'service',
21
22
  },
22
23
  {
23
24
  reason: 'upstream_budget_exhausted',
@@ -25,6 +26,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
25
26
  when: 'The OpenAlex daily usage budget is spent (HTTP 429).',
26
27
  retryable: false,
27
28
  recovery: 'The daily budget refills at midnight UTC — retrying sooner will not succeed. Set OPENALEX_API_KEY to a free key (https://openalex.org/settings/api) for a larger daily budget than anonymous access, or wait for the reset.',
29
+ thrownBy: 'service',
28
30
  },
29
31
  {
30
32
  reason: 'upstream_timeout',
@@ -32,6 +34,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
32
34
  when: 'OpenAlex did not respond within the request deadline.',
33
35
  retryable: true,
34
36
  recovery: 'Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.',
37
+ thrownBy: 'service',
35
38
  },
36
39
  {
37
40
  reason: 'upstream_unavailable',
@@ -39,54 +42,71 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
39
42
  when: 'OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON.',
40
43
  retryable: true,
41
44
  recovery: 'Wait and retry; check https://openalex.org for service status if the outage persists.',
45
+ thrownBy: 'service',
42
46
  },
43
47
  {
44
48
  reason: 'upstream_unauthorized',
45
49
  code: JsonRpcErrorCode.Unauthorized,
46
50
  when: 'OpenAlex rejected the API key (HTTP 401).',
47
51
  recovery: 'Check that OPENALEX_API_KEY is set to a valid OpenAlex account API key (free from https://openalex.org/settings/api).',
52
+ thrownBy: 'service',
48
53
  },
49
54
  {
50
55
  reason: 'upstream_forbidden',
51
56
  code: JsonRpcErrorCode.Forbidden,
52
57
  when: 'OpenAlex denied access to the requested resource (HTTP 403).',
53
58
  recovery: 'Confirm the API key has access to this entity type or endpoint, then retry the request.',
59
+ thrownBy: 'service',
54
60
  },
55
61
  {
56
62
  reason: 'comma_in_filter_value',
57
63
  code: JsonRpcErrorCode.InvalidParams,
58
64
  when: 'A filter value contains a comma, which collides with the OpenAlex filter separator.',
59
65
  recovery: 'Use `|` for OR within a filter value (e.g. "2020|2021"), or use a `.search` filter or the `query` parameter for free-text phrases that contain commas.',
66
+ thrownBy: 'service',
60
67
  },
61
68
  {
62
69
  reason: 'upstream_invalid_params',
63
70
  code: JsonRpcErrorCode.InvalidParams,
64
71
  when: 'OpenAlex rejected an invalid group_by or filter field name (HTTP 400).',
65
72
  recovery: 'The upstream message names the rejected key and suggests close matches. Use openalex_describe_fields(entity_type, "group_by") to browse valid group_by fields, or openalex_describe_fields(entity_type, "filter") for filter fields.',
73
+ thrownBy: 'service',
66
74
  },
67
75
  {
68
76
  reason: 'upstream_invalid_id_value',
69
77
  code: JsonRpcErrorCode.InvalidParams,
70
78
  when: 'An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400).',
71
79
  recovery: 'Call openalex_resolve_name to turn the name into an OpenAlex ID, then filter by that ID. Entity filters such as authorships.author.id and primary_topic.id accept IDs only.',
80
+ thrownBy: 'service',
72
81
  },
73
82
  {
74
83
  reason: 'upstream_ungroupable_group_by',
75
84
  code: JsonRpcErrorCode.InvalidParams,
76
85
  when: 'group_by targets a raw date, float, or *.search field OpenAlex cannot aggregate (HTTP 400).',
77
86
  recovery: 'Group by a categorical or year field (e.g. publication_year, type, oa_status, or an integer count field) — raw date fields and *.search operators cannot be grouped. Call openalex_describe_fields(entity_type, "group_by") for the groupable set.',
87
+ thrownBy: 'service',
78
88
  },
79
89
  {
80
90
  reason: 'upstream_invalid_params_other',
81
91
  code: JsonRpcErrorCode.InvalidParams,
82
92
  when: 'OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name.',
83
93
  recovery: 'Read the upstream message in the error above and adjust the request — check filter operators, value formats, and the group_by field.',
94
+ thrownBy: 'service',
84
95
  },
85
96
  {
86
97
  reason: 'upstream_validation_failed',
87
98
  code: JsonRpcErrorCode.ValidationError,
88
99
  when: 'OpenAlex rejected the request as semantically invalid (HTTP 422).',
89
100
  recovery: 'Read the upstream message for the specific field, then adjust the request to satisfy validation.',
101
+ thrownBy: 'service',
102
+ },
103
+ {
104
+ reason: 'upstream_missing_group_by',
105
+ code: JsonRpcErrorCode.ServiceUnavailable,
106
+ when: 'OpenAlex answered with its plain list shape, carrying no aggregation for the requested group_by.',
107
+ retryable: true,
108
+ recovery: 'Retry the request; if it repeats, confirm group_by names a field OpenAlex can aggregate with openalex_describe_fields(entity_type, "group_by").',
109
+ thrownBy: 'service',
90
110
  },
91
111
  ],
92
112
  inputAliases: { filter: 'filters' },
@@ -94,6 +114,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
94
114
  entity_type: z.enum(ENTITY_TYPES).describe('Entity type to aggregate.'),
95
115
  group_by: z
96
116
  .string()
117
+ .min(1)
97
118
  .describe('Field to group by. Works examples: "publication_year", "type", "oa_status", "primary_topic.field.id", "authorships.institutions.country_code", "is_retracted". Authors: "last_known_institutions.country_code", "has_orcid". Sources: "type", "is_oa", "country_code". Not all fields support group_by — check entity docs if unsure.'),
98
119
  filters: z
99
120
  .record(z.string(), z.string())
@@ -116,8 +137,9 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
116
137
  .describe('Sort order for groups. Omit or pass "count" (default) to return the top-N groups by count descending — no further pages. Pass "key" to enumerate all distinct values in key-ascending order with cursor pagination. Use "key" only when you need a full traversal; most analysis calls want "count".'),
117
138
  cursor: z
118
139
  .string()
140
+ .min(1)
119
141
  .optional()
120
- .describe('Pagination cursor from a previous response. Only relevant when order is "key" — count-descending results have no next page. Pass the next_cursor from the previous response to advance.'),
142
+ .describe('Pagination cursor from a previous response. Only relevant when order is "key" — count-descending results have no next page. Pass the next_cursor from the previous response to advance. Omit it on the first call — an empty string is rejected, since a supplied-but-blank cursor is a caller mistake rather than a request for the first page.'),
121
143
  }),
122
144
  output: z.object({
123
145
  meta: z
@@ -153,7 +175,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
153
175
  notice: z
154
176
  .string()
155
177
  .optional()
156
- .describe('Guidance notice. Set when no groups are returned (recovery suggestions) or when the page is full and more groups likely exist (truncation signal with narrowing advice). Absent otherwise.'),
178
+ .describe('Guidance notice. Set when a first call returns no groups (recovery suggestions), when a `cursor` continuation returns none because the traversal is already finished, or when the page is full and more groups likely exist (truncation signal with narrowing advice). Absent otherwise.'),
157
179
  budget: z
158
180
  .object({
159
181
  costUsd: z
@@ -195,8 +217,14 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
195
217
  });
196
218
  const echo = buildAnalyzeEcho(input);
197
219
  ctx.enrich({ echo, totalCount: result.meta.count });
220
+ // An empty page on a `cursor` continuation means the key-ascending traversal already
221
+ // enumerated every group, so there is nothing left to remove or regroup. On a first call
222
+ // the same shape can still be an honest zero — including the all-values-unknown case,
223
+ // where `count` is nonzero but every matched entity is null for the grouped field.
198
224
  if (result.groups.length === 0) {
199
- ctx.enrich.notice(`No groups returned for ${echo}. Try removing filters or grouping by a different field.`);
225
+ ctx.enrich.notice(input.cursor === undefined
226
+ ? `No groups returned for ${echo}. Try removing filters or grouping by a different field.`
227
+ : `Pagination exhausted for ${echo} — the previous page held the last group, so this one came back empty. Stop paging rather than removing filters or regrouping.`);
200
228
  }
201
229
  else if (input.order === 'key') {
202
230
  // Key-ascending traversal: omitted groups sit beyond the cursor, not in a count tail, so
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-trends.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyze-trends.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"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"}
@@ -32,63 +32,74 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
32
32
  readonly when: "OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429).";
33
33
  readonly retryable: true;
34
34
  readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
35
+ readonly thrownBy: "service";
35
36
  }, {
36
37
  readonly reason: "upstream_budget_exhausted";
37
38
  readonly code: JsonRpcErrorCode.RateLimited;
38
39
  readonly when: "The OpenAlex daily usage budget is spent (HTTP 429).";
39
40
  readonly retryable: false;
40
41
  readonly recovery: "The daily budget refills at midnight UTC — retrying sooner will not succeed. Set OPENALEX_API_KEY to a free key (https://openalex.org/settings/api) for a larger daily budget than anonymous access, or wait for the reset.";
42
+ readonly thrownBy: "service";
41
43
  }, {
42
44
  readonly reason: "upstream_timeout";
43
45
  readonly code: JsonRpcErrorCode.Timeout;
44
46
  readonly when: "OpenAlex did not respond within the request deadline.";
45
47
  readonly retryable: true;
46
48
  readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
49
+ readonly thrownBy: "service";
47
50
  }, {
48
51
  readonly reason: "upstream_unavailable";
49
52
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
50
53
  readonly when: "OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON.";
51
54
  readonly retryable: true;
52
55
  readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
56
+ readonly thrownBy: "service";
53
57
  }, {
54
58
  readonly reason: "upstream_unauthorized";
55
59
  readonly code: JsonRpcErrorCode.Unauthorized;
56
60
  readonly when: "OpenAlex rejected the API key (HTTP 401).";
57
61
  readonly recovery: "Check that OPENALEX_API_KEY is set to a valid OpenAlex account API key (free from https://openalex.org/settings/api).";
62
+ readonly thrownBy: "service";
58
63
  }, {
59
64
  readonly reason: "upstream_forbidden";
60
65
  readonly code: JsonRpcErrorCode.Forbidden;
61
66
  readonly when: "OpenAlex denied access to the requested resource (HTTP 403).";
62
67
  readonly recovery: "Confirm the API key has access to this entity type or endpoint, then retry the request.";
68
+ readonly thrownBy: "service";
63
69
  }, {
64
70
  readonly reason: "comma_in_filter_value";
65
71
  readonly code: JsonRpcErrorCode.InvalidParams;
66
72
  readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator.";
67
73
  readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or use a `.search` filter or the `query` parameter for free-text phrases that contain commas.";
74
+ readonly thrownBy: "service";
68
75
  }, {
69
76
  readonly reason: "upstream_invalid_params";
70
77
  readonly code: JsonRpcErrorCode.InvalidParams;
71
78
  readonly when: "OpenAlex rejected an invalid filter or sort field name (HTTP 400).";
72
79
  readonly recovery: "The upstream message names the rejected token and suggests close matches. Pass a valid OpenAlex work ID (W…), DOI, or PMID for seed_id, or use openalex_describe_fields(entity_type, \"filter\") to browse valid filter fields.";
80
+ readonly thrownBy: "service";
73
81
  }, {
74
82
  readonly reason: "upstream_invalid_id_value";
75
83
  readonly code: JsonRpcErrorCode.InvalidParams;
76
84
  readonly when: "An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400).";
77
85
  readonly recovery: "Call openalex_resolve_name to turn the name into an OpenAlex ID, then filter by that ID. Entity filters such as authorships.author.id and primary_topic.id accept IDs only.";
86
+ readonly thrownBy: "service";
78
87
  }, {
79
88
  readonly reason: "upstream_sort_requires_search";
80
89
  readonly code: JsonRpcErrorCode.InvalidParams;
81
90
  readonly when: "sort=-relevance_score was used but the citation-graph query has no active search (HTTP 400).";
82
91
  readonly recovery: "Sorting by relevance_score requires an active search, which a citation-graph walk lacks — choose a concrete sort field such as -cited_by_count or -publication_date, or add a `*.search` filter.";
92
+ readonly thrownBy: "service";
83
93
  }, {
84
94
  readonly reason: "upstream_invalid_params_other";
85
95
  readonly code: JsonRpcErrorCode.InvalidParams;
86
96
  readonly when: "OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name.";
87
97
  readonly recovery: "Read the upstream message in the error above and adjust the request — check filter operators, value formats, and cursor/per_page bounds.";
98
+ readonly thrownBy: "service";
88
99
  }, {
89
100
  readonly reason: "reserved_filter_key";
90
101
  readonly code: JsonRpcErrorCode.ValidationError;
91
- readonly when: "filters contains cites/cited_by/related_to — the direction parameter reserves those keys.";
102
+ readonly when: "filters contains cites/cited_by/related_to, or an alias of one such as cited_works — the direction parameter reserves those keys.";
92
103
  readonly recovery: "Remove the reserved key from filters, or restate the relationship through direction.";
93
104
  }, {
94
105
  readonly reason: "entity_not_found";
@@ -1 +1 @@
1
- {"version":3,"file":"citation-graph.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAuEjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmS/B,CAAC"}
1
+ {"version":3,"file":"citation-graph.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA2BjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmW/B,CAAC"}