@cyanheads/ris-austria-mcp-server 0.2.0 → 0.2.2

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 (87) hide show
  1. package/AGENTS.md +3 -3
  2. package/CLAUDE.md +3 -3
  3. package/Dockerfile +1 -1
  4. package/README.md +1 -1
  5. package/changelog/0.2.x/0.2.1.md +25 -0
  6. package/changelog/0.2.x/0.2.2.md +18 -0
  7. package/dist/mcp-server/resources/definitions/ris-document.resource.d.ts +6 -0
  8. package/dist/mcp-server/resources/definitions/ris-document.resource.d.ts.map +1 -1
  9. package/dist/mcp-server/resources/definitions/ris-document.resource.js +15 -0
  10. package/dist/mcp-server/resources/definitions/ris-document.resource.js.map +1 -1
  11. package/dist/mcp-server/tools/definitions/_shared.d.ts +25 -1
  12. package/dist/mcp-server/tools/definitions/_shared.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/definitions/_shared.js +36 -1
  14. package/dist/mcp-server/tools/definitions/_shared.js.map +1 -1
  15. package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts +37 -16
  16. package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/definitions/ris-get-document.tool.js +132 -28
  18. package/dist/mcp-server/tools/definitions/ris-get-document.tool.js.map +1 -1
  19. package/dist/mcp-server/tools/definitions/ris-list-reference.tool.d.ts +11 -11
  20. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.d.ts +26 -19
  21. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.d.ts.map +1 -1
  22. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js +25 -9
  23. package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js.map +1 -1
  24. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts +17 -11
  25. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts.map +1 -1
  26. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js +14 -13
  27. package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js.map +1 -1
  28. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts +24 -18
  29. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts.map +1 -1
  30. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js +14 -13
  31. package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js.map +1 -1
  32. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts +14 -8
  33. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts.map +1 -1
  34. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js +14 -13
  35. package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js.map +1 -1
  36. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts +12 -6
  37. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts.map +1 -1
  38. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js +14 -13
  39. package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js.map +1 -1
  40. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts +15 -9
  41. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts.map +1 -1
  42. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js +14 -13
  43. package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js.map +1 -1
  44. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts +11 -5
  45. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts.map +1 -1
  46. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js +14 -13
  47. package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js.map +1 -1
  48. package/dist/services/ris/reference/applications.d.ts +407 -407
  49. package/dist/services/ris/reference/applications.d.ts.map +1 -1
  50. package/dist/services/ris/reference/changed-since-intervals.d.ts +18 -18
  51. package/dist/services/ris/reference/changed-since-intervals.d.ts.map +1 -1
  52. package/dist/services/ris/reference/citation-formats.d.ts +12 -12
  53. package/dist/services/ris/reference/citation-formats.d.ts.map +1 -1
  54. package/dist/services/ris/reference/collections.d.ts +32 -32
  55. package/dist/services/ris/reference/collections.d.ts.map +1 -1
  56. package/dist/services/ris/reference/courts.d.ts +135 -135
  57. package/dist/services/ris/reference/courts.d.ts.map +1 -1
  58. package/dist/services/ris/reference/decision-kinds.d.ts +26 -26
  59. package/dist/services/ris/reference/decision-kinds.d.ts.map +1 -1
  60. package/dist/services/ris/reference/decision-types.d.ts +12 -12
  61. package/dist/services/ris/reference/decision-types.d.ts.map +1 -1
  62. package/dist/services/ris/reference/district-authorities.d.ts +222 -222
  63. package/dist/services/ris/reference/district-authorities.d.ts.map +1 -1
  64. package/dist/services/ris/reference/gazette-parts.d.ts +28 -28
  65. package/dist/services/ris/reference/gazette-parts.d.ts.map +1 -1
  66. package/dist/services/ris/reference/issuing-bodies.d.ts +380 -380
  67. package/dist/services/ris/reference/issuing-bodies.d.ts.map +1 -1
  68. package/dist/services/ris/reference/justiz-subject-areas.d.ts +78 -78
  69. package/dist/services/ris/reference/justiz-subject-areas.d.ts.map +1 -1
  70. package/dist/services/ris/reference/law-types.d.ts +16 -16
  71. package/dist/services/ris/reference/law-types.d.ts.map +1 -1
  72. package/dist/services/ris/reference/ministries.d.ts +151 -151
  73. package/dist/services/ris/reference/ministries.d.ts.map +1 -1
  74. package/dist/services/ris/reference/search-syntax.d.ts +36 -36
  75. package/dist/services/ris/reference/search-syntax.d.ts.map +1 -1
  76. package/dist/services/ris/reference/section-types.d.ts +10 -10
  77. package/dist/services/ris/reference/section-types.d.ts.map +1 -1
  78. package/dist/services/ris/reference/stages.d.ts +12 -12
  79. package/dist/services/ris/reference/stages.d.ts.map +1 -1
  80. package/dist/services/ris/reference/states.d.ts +45 -45
  81. package/dist/services/ris/reference/states.d.ts.map +1 -1
  82. package/dist/services/ris/ris-service.d.ts +5 -2
  83. package/dist/services/ris/ris-service.d.ts.map +1 -1
  84. package/dist/services/ris/ris-service.js +56 -7
  85. package/dist/services/ris/ris-service.js.map +1 -1
  86. package/package.json +6 -6
  87. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** ris-austria-mcp-server
4
- **Version:** 0.2.0
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.14`
4
+ **Version:** 0.2.2
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
8
8
  **Zod:** ^4.4.3
@@ -334,7 +334,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
334
334
 
335
335
  ## Bundling
336
336
 
337
- `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
337
+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
338
338
 
339
339
  **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
340
340
 
package/CLAUDE.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** ris-austria-mcp-server
4
- **Version:** 0.2.0
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.14`
4
+ **Version:** 0.2.2
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
8
8
  **Zod:** ^4.4.3
@@ -334,7 +334,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
334
334
 
335
335
  ## Bundling
336
336
 
337
- `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
337
+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
338
338
 
339
339
  **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
340
340
 
package/Dockerfile CHANGED
@@ -60,7 +60,7 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
60
60
  ARG OTEL_ENABLED=true
61
61
  RUN --mount=type=cache,target=/root/.bun/install/cache \
62
62
  if [ "$OTEL_ENABLED" = "true" ]; then \
63
- bun add @hono/otel \
63
+ bun add --omit=dev --ignore-scripts @hono/otel \
64
64
  @opentelemetry/instrumentation-http \
65
65
  @opentelemetry/exporter-metrics-otlp-http \
66
66
  @opentelemetry/exporter-trace-otlp-http \
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.2.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/ris-austria-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/ris-austria-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/ris-austria-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.2.2-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/ris-austria-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/ris-austria-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/ris-austria-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -0,0 +1,25 @@
1
+ ---
2
+ summary: "Schema-valid rejections, generic upstream 5xx, and slow content renders now carry the declared error contract instead of a bare undocumented code."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.1 — 2026-07-26
8
+
9
+ ## Added
10
+
11
+ - **`upstream_timeout` error reason** on every network-backed tool (`ris_search_legislation`, `ris_search_case_law`, `ris_search_gazette`, `ris_search_drafts`, `ris_search_announcements`, `ris_track_changes`, `ris_lookup_citation`, `ris_get_document`) and the `ris://document/{application}/{documentNumber}` resource — code `Timeout` (-32004), `retryable: true`, with recovery distinct from a degraded upstream. `ctx.fail` resolves its code from the contract entry, so folding a deadline into `upstream_error` would report -32000 for it. ([#15](https://github.com/cyanheads/ris-austria-mcp-server/issues/15), [#21](https://github.com/cyanheads/ris-austria-mcp-server/issues/21))
12
+ - **`failSearchError`** in `src/mcp-server/tools/definitions/_shared.ts` — a shared mapper wired into every search-family tool's `.catch()`, mapping `ValidationError`/`InvalidParams` to `invalid_query`, `ServiceUnavailable` to `upstream_error`, and `Timeout` to `upstream_timeout`. Each tool still declares its own `errors[]` contract; the mapper only resolves the reason. ([#12](https://github.com/cyanheads/ris-austria-mcp-server/issues/12))
13
+
14
+ ## Changed
15
+
16
+ - **Schema-valid request-builder rejections** — an unsupported-but-valid combination (a `sort_by` column the target application has no mapping for, an unresolvable `ministry`/`issuer`, a gazette `state_era` a state doesn't carry) now lands on the tool's declared `invalid_query` contract with `reason` and recovery, instead of a bare `-32007 ValidationError` with no `reason` in `data`. Reproduces and is fixed across `ris_search_case_law`, `ris_search_gazette`, `ris_search_announcements`, and `ris_search_drafts`. Recovery hints no longer claim RIS named the parameter — for a local rejection, it didn't. ([#12](https://github.com/cyanheads/ris-austria-mcp-server/issues/12))
17
+ - **Generic upstream HTTP 5xx** — `RisService` reclassifies an upstream 500/501 carrying no RIS `OgdSearchResult.Error` envelope from a bare `InternalError` (-32603, no `reason`, no `retryable`, no recovery) to `ServiceUnavailable`, so `ris_search_legislation`, `ris_get_document`, and the `ris://document/…` resource now surface their declared `upstream_error` (-32000, `retryable: true`, recovery). The gate keys on the canonical `error.data.status` field (a 500+ value), which also excludes an abort-sourced `InternalError` (no `status`) from reclassification. Runs after the RIS in-band error-envelope translation gets its chance, so a 500 carrying `OgdSearchResult.Error` still becomes `InvalidParams`. ([#15](https://github.com/cyanheads/ris-austria-mcp-server/issues/15))
18
+ - **`CONTENT_TIMEOUT_MS`** 20s → **25s**, and `fetchDocumentContent` now caps at `maxRetries: 1` (2 attempts) instead of `withRetry`'s default of 4 — worst case ~51–52s, inside the MCP SDK's 60s default request timeout (the prior 20s × 4 attempts ran ~93s, past that budget). The content host renders a document on first request and caches it; a render that finishes between attempt 1 and attempt 2 is served from cache on the retry, so the second attempt is still worth making. `SEARCH_TIMEOUT_MS` (15s) is unaffected. ([#21](https://github.com/cyanheads/ris-austria-mcp-server/issues/21))
19
+ - **Content fetches pass `expectedStatuses: [404]`** — a mistyped `document_number` (the most common caller error) now logs at `debug` instead of `error`; 500 is deliberately excluded from the list since a genuine server fault and a RIS input-error 500 are indistinguishable by status.
20
+ - **`@cyanheads/mcp-ts-core`** `^0.10.14` → `^0.11.0`, `typescript` `^6.0.3` → `^7.0.2`, `@biomejs/biome` `2.5.2` → `2.5.5`, `tsc-alias` `^1.8.17` → `^1.9.1`, `vitest` `^4.1.8` → `^4.1.10`. Project skills, scaffold scripts (`clean-mcpb.ts`, `lint-packaging.ts`, `check-dependency-specifiers.ts`, `devcheck.ts`), and template files (`Dockerfile`, `.gitignore`, `devcheck.config.json`) synced from the framework's `0.11.0` templates.
21
+
22
+ ## Fixed
23
+
24
+ - **`ris_get_document` and the `ris://document/…` resource no longer report a slow cold render as a retryable `upstream_error`** after ~80s of retrying — they now report `upstream_timeout` (or succeed on the retry that lands in cache). A wrong `document_number` still renders a slow 404 indistinguishable from a real cold render on the first attempt; the `upstream_timeout` recovery hint says to check the number against a fresh search result, or re-call with `format: urls_only` and fetch the URL without this deadline. ([#21](https://github.com/cyanheads/ris-austria-mcp-server/issues/21))
25
+
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: "ris_get_document: malformed document_url escapes, duplicated screen-reader citations, and unmatched section selectors now surface their real outcome instead of falling back silently."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.2 — 2026-07-26
8
+
9
+ ## Changed
10
+
11
+ - **`selectDocumentSections()`** returns `{ available, text, unmatched }` instead of `string | undefined` — the selector's full outcome (matched text, unmatched names, the document's full section roster) instead of a bare hit/miss.
12
+ - **`renderOutlineSections()`** drops the hardcoded "document too large to inline" header — the same roster now renders for both a byte-budget overflow and a selector mismatch, so the accompanying notice carries the reason instead of the header.
13
+
14
+ ## Fixed
15
+
16
+ - **`parseDocumentUrl`** — a malformed percent escape in a `document_url`'s document-number or filename position (e.g. `%ZZ`) no longer lets a native `URIError` escape the errors-as-values boundary; it now maps to the declared `unsupported_url` reason with recovery, in place of a bare `-32007 URI malformed` with no `reason`. ([#13](https://github.com/cyanheads/ris-austria-mcp-server/issues/13))
17
+ - **`ris_get_document` markdown / the `ris://document/…` resource** — drop the `.sr-only` screen-reader twin RIS ships beside every abbreviated citation before HTML→markdown conversion, registered across all six node-html-markdown translator collections (RIS's Inhaltsverzeichnis and Anmerkungen tables carry twins inside table cells, a separate translator collection from the top level). Cuts payload 38–45% on affected documents — `BrKons` NOR40262691 71,655 B → 44,522 B, `RegV` REGV_3A68CE39_6184_4BBF_8F02_57236DCABE91 353,294 B → 195,652 B — and `byte_size` / outline `DocumentSection.bytes` now report the real rendered size. `html` and `xml` renditions are untouched. ([#16](https://github.com/cyanheads/ris-austria-mcp-server/issues/16))
18
+ - **`ris_get_document` `sections:[…]` selector** — an unmatched selector no longer silently returns the whole document when under the byte budget. A total miss now returns the section outline (`kind: outline`) with a notice distinguishing a selector mismatch from a size overflow; a partial miss returns the matched sections plus a notice naming the dropped entries; a rendition with no addressable sections returns whole with a notice explaining why the selector was ignored. ([#20](https://github.com/cyanheads/ris-austria-mcp-server/issues/20))
@@ -26,5 +26,11 @@ export declare const risDocumentResource: import("@cyanheads/mcp-ts-core").Resou
26
26
  readonly when: "The RIS content host was unreachable or returned a server error.";
27
27
  readonly retryable: true;
28
28
  readonly recovery: "The RIS content host is temporarily unavailable — retry the read after a short delay.";
29
+ }, {
30
+ readonly reason: "upstream_timeout";
31
+ readonly code: JsonRpcErrorCode.Timeout;
32
+ readonly when: "The content host did not return the rendition within the fetch deadline — typically a cold render, which it performs on first request before caching the result.";
33
+ readonly retryable: true;
34
+ readonly recovery: "Retry the identical read once or twice — the host renders a document on first request and caches it, so a later read often returns instantly. If it keeps timing out, check the document number against a fresh search result (a wrong number renders a slow 404 that looks identical), or use ris_get_document with format: urls_only and fetch the rendition URL yourself, without this deadline.";
29
35
  }]>;
30
36
  //# sourceMappingURL=ris-document.resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ris-document.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/ris-document.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAY3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;GA2E9B,CAAC"}
1
+ {"version":3,"file":"ris-document.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/ris-document.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAY3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;GA2F9B,CAAC"}
@@ -43,6 +43,13 @@ export const risDocumentResource = resource('ris://document/{application}/{docum
43
43
  retryable: true,
44
44
  recovery: 'The RIS content host is temporarily unavailable — retry the read after a short delay.',
45
45
  },
46
+ {
47
+ reason: 'upstream_timeout',
48
+ code: JsonRpcErrorCode.Timeout,
49
+ when: 'The content host did not return the rendition within the fetch deadline — typically a cold render, which it performs on first request before caching the result.',
50
+ retryable: true,
51
+ recovery: 'Retry the identical read once or twice — the host renders a document on first request and caches it, so a later read often returns instantly. If it keeps timing out, check the document number against a fresh search result (a wrong number renders a slow 404 that looks identical), or use ris_get_document with format: urls_only and fetch the rendition URL yourself, without this deadline.',
52
+ },
46
53
  ],
47
54
  async handler(params, ctx) {
48
55
  // Map framework errors from resolution/fetch onto this resource's declared contract.
@@ -57,6 +64,14 @@ export const risDocumentResource = resource('ris://document/{application}/{docum
57
64
  if (err.code === JsonRpcErrorCode.ServiceUnavailable) {
58
65
  throw ctx.fail('upstream_error', err.message, { ...ctx.recoveryFor('upstream_error') });
59
66
  }
67
+ // Its own reason, not a widened upstream_error guard: `ctx.fail` resolves the code
68
+ // from the contract entry, so folding a deadline into upstream_error would report
69
+ // -32000 for it — and the two want different recovery (degraded host vs. cold render).
70
+ if (err.code === JsonRpcErrorCode.Timeout) {
71
+ throw ctx.fail('upstream_timeout', err.message, {
72
+ ...ctx.recoveryFor('upstream_timeout'),
73
+ });
74
+ }
60
75
  }
61
76
  throw err;
62
77
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ris-document.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/ris-document.resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ris-document.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/ris-document.resource.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,32 @@
1
1
  /**
2
- * @fileoverview Shared Zod schemas reused across multiple tool definitions.
2
+ * @fileoverview Shared Zod schemas and error-contract plumbing reused across multiple tool
3
+ * definitions.
3
4
  * @module mcp-server/tools/definitions/_shared
4
5
  */
6
+ import type { TypedFail, TypedRecoveryFor } from '@cyanheads/mcp-ts-core';
5
7
  import { z } from '@cyanheads/mcp-ts-core';
6
8
  /** An ISO calendar date (YYYY-MM-DD), validated client-side before any upstream call. */
7
9
  export declare const isoDateString: z.ZodString;
10
+ /**
11
+ * The three reasons every search-family tool declares for a failure raised below the
12
+ * handler — in the request builder or in `RisService`. Each tool still declares its own
13
+ * full `errors[]` inline (the contract is part of its public surface); this union is only
14
+ * the subset {@link failSearchError} resolves against.
15
+ */
16
+ type SearchFailureReason = 'invalid_query' | 'upstream_error' | 'upstream_timeout';
17
+ /** The slice of a handler `ctx` {@link failSearchError} needs. */
18
+ interface SearchFailureContext {
19
+ readonly fail: TypedFail<SearchFailureReason>;
20
+ readonly recoveryFor: TypedRecoveryFor<SearchFailureReason>;
21
+ }
22
+ /**
23
+ * Map a request-builder or service failure onto the declared contract, so `reason` and
24
+ * `recovery` reach the wire — neither the builder's `validationError` nor the service's
25
+ * framework errors carry either on their own. An unmapped code is returned untouched for
26
+ * the framework to classify.
27
+ *
28
+ * Returns the error for the caller to `throw`, keeping the throw visible at the call site.
29
+ */
30
+ export declare function failSearchError(error: unknown, ctx: SearchFailureContext): unknown;
31
+ export {};
8
32
  //# sourceMappingURL=_shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_shared.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,yFAAyF;AACzF,eAAO,MAAM,aAAa,aAEkD,CAAC"}
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,yFAAyF;AACzF,eAAO,MAAM,aAAa,aAEkD,CAAC;AAE7E;;;;;GAKG;AACH,KAAK,mBAAmB,GAAG,eAAe,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;AAEnF,kEAAkE;AAClE,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;CAC7D;AAoBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAMlF"}
@@ -1,10 +1,45 @@
1
1
  /**
2
- * @fileoverview Shared Zod schemas reused across multiple tool definitions.
2
+ * @fileoverview Shared Zod schemas and error-contract plumbing reused across multiple tool
3
+ * definitions.
3
4
  * @module mcp-server/tools/definitions/_shared
4
5
  */
5
6
  import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
6
8
  /** An ISO calendar date (YYYY-MM-DD), validated client-side before any upstream call. */
7
9
  export const isoDateString = z
8
10
  .string()
9
11
  .regex(/^\d{4}-\d{2}-\d{2}$/u, 'Expected an ISO date in YYYY-MM-DD form.');
12
+ /**
13
+ * Framework codes raised below the handler, mapped to the contract reason describing them.
14
+ *
15
+ * - `ValidationError` — a schema-valid but unsupported parameter combination the request
16
+ * builder rejected locally, before any upstream call.
17
+ * - `InvalidParams` — RIS rejected a parameter value in its in-band error envelope.
18
+ * - `ServiceUnavailable` — RIS unreachable, degraded, or serving an HTML error page.
19
+ * - `Timeout` — the request deadline elapsed. Its own reason rather than a widened
20
+ * `upstream_error` guard: `ctx.fail` resolves the code from the contract entry, so folding
21
+ * the two would put -32000 back on the wire for every deadline.
22
+ */
23
+ const REASON_BY_CODE = new Map([
24
+ [JsonRpcErrorCode.ValidationError, 'invalid_query'],
25
+ [JsonRpcErrorCode.InvalidParams, 'invalid_query'],
26
+ [JsonRpcErrorCode.ServiceUnavailable, 'upstream_error'],
27
+ [JsonRpcErrorCode.Timeout, 'upstream_timeout'],
28
+ ]);
29
+ /**
30
+ * Map a request-builder or service failure onto the declared contract, so `reason` and
31
+ * `recovery` reach the wire — neither the builder's `validationError` nor the service's
32
+ * framework errors carry either on their own. An unmapped code is returned untouched for
33
+ * the framework to classify.
34
+ *
35
+ * Returns the error for the caller to `throw`, keeping the throw visible at the call site.
36
+ */
37
+ export function failSearchError(error, ctx) {
38
+ if (!(error instanceof McpError))
39
+ return error;
40
+ const reason = REASON_BY_CODE.get(error.code);
41
+ return reason === undefined
42
+ ? error
43
+ : ctx.fail(reason, error.message, { ...ctx.recoveryFor(reason) });
44
+ }
10
45
  //# sourceMappingURL=_shared.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_shared.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE3C,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC;KAC3B,MAAM,EAAE;KACR,KAAK,CAAC,sBAAsB,EAAE,0CAA0C,CAAC,CAAC"}
1
+ {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE3E,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC;KAC3B,MAAM,EAAE;KACR,KAAK,CAAC,sBAAsB,EAAE,0CAA0C,CAAC,CAAC;AAgB7E;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAwC;IACpE,CAAC,gBAAgB,CAAC,eAAe,EAAE,eAAe,CAAC;IACnD,CAAC,gBAAgB,CAAC,aAAa,EAAE,eAAe,CAAC;IACjD,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IACvD,CAAC,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,CAAC;CAC/C,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,GAAyB;IACvE,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC"}
@@ -5,9 +5,12 @@
5
5
  * `document_number` + `application`, or a `document_url` from a result's content_urls.
6
6
  * Format availability varies by application (full text · authentic-PDF-only · PDF-only ·
7
7
  * metadata-only) — a text-format request against a non-text application degrades to a
8
- * `format_unavailable` notice on a success result, never an error. Oversized markdown
9
- * overflows to a retrievable §/Artikel/Anlage section outline (never a silent truncation);
10
- * a follow-up call with `sections:[…]` returns just the chosen sections. The shared
8
+ * `format_unavailable` notice on a success result, never an error. Markdown conversion drops
9
+ * the `.sr-only` screen-reader twin RIS ships beside every abbreviated citation, keeping the
10
+ * visible form; `html` and `xml` pass through untouched. Oversized markdown overflows to a
11
+ * retrievable §/Artikel/Anlage section outline (never a silent truncation); a follow-up call
12
+ * with `sections:[…]` returns just the chosen sections, and a selector matching nothing gets
13
+ * the outline back with a notice rather than the whole document. The shared
11
14
  * {@link renderDocument} helper backs both this tool and the `ris://document/…` resource.
12
15
  * @module mcp-server/tools/definitions/ris-get-document
13
16
  */
@@ -81,13 +84,23 @@ export interface DocumentSection {
81
84
  * html/xml rendition) — the caller reads that as "nothing to outline".
82
85
  */
83
86
  export declare function segmentDocument(text: string): DocumentSection[];
87
+ /** Outcome of resolving a `sections:[…]` selector against a rendered document. */
88
+ export interface SectionSelection {
89
+ /** The document's whole section roster, largest first — what the caller can re-pick from. */
90
+ readonly available: SectionMeta[];
91
+ /** Concatenated text of the matched sections, in document order; `''` when none matched. */
92
+ readonly text: string;
93
+ /** Requested names that matched no section, in the order requested. */
94
+ readonly unmatched: string[];
95
+ }
84
96
  /**
85
- * Return the concatenated text of the named sections, or `undefined` when none match — the
86
- * selective-retrieval counterpart to the outline. The handler re-fetches the document (the
87
- * upstream query is deterministic, so it reproduces the same text) and slices it to the
88
- * requested sections; a no-match falls through to a fresh outline so the agent can re-pick.
97
+ * Resolve a `sections:[…]` selector against rendered document text — the selective-retrieval
98
+ * counterpart to the outline. The handler re-fetches the document (the upstream query is
99
+ * deterministic, so it reproduces the same text) and slices it to the requested sections.
100
+ * Reports the unmatched names and the full roster alongside the matched text so the handler
101
+ * can disclose a mismatch instead of silently returning something the caller didn't ask for.
89
102
  */
90
- export declare function selectDocumentSections(text: string, want: readonly string[]): string | undefined;
103
+ export declare function selectDocumentSections(text: string, want: readonly string[]): SectionSelection;
91
104
  /**
92
105
  * Apply the outline-on-overflow contract to rendered document text: whole under the byte
93
106
  * budget (or with fewer than two structural sections), else a section outline. Shares
@@ -100,9 +113,11 @@ export declare function outlineDocument(text: string, notice: (sections: Section
100
113
  /** Name the three largest sections, quoted, as examples for a re-call notice. */
101
114
  export declare function exampleSectionNames(sections: readonly SectionMeta[]): string;
102
115
  /**
103
- * Render an overflow outline — the section roster the agent picks from — to markdown.
104
- * Shared by the tool's `format()` (as a content block) and the resource (as its body), so
105
- * both client surfaces list identical sections.
116
+ * Render an outline — the section roster the agent picks from — to markdown. Shared by the
117
+ * tool's `format()` (as a content block) and the resource (as its body), so both client
118
+ * surfaces list identical sections. Deliberately says nothing about *why* the outline was
119
+ * returned: the tool emits one both on a byte overflow and on an unmatched `sections`
120
+ * selector, and the accompanying notice is what separates the two.
106
121
  */
107
122
  export declare function renderOutlineSections(sections: readonly SectionMeta[]): string;
108
123
  /**
@@ -120,18 +135,18 @@ export declare const risGetDocument: import("@cyanheads/mcp-ts-core").ToolDefini
120
135
  document_url: z.ZodOptional<z.ZodString>;
121
136
  format: z.ZodDefault<z.ZodEnum<{
122
137
  html: "html";
123
- xml: "xml";
124
138
  markdown: "markdown";
125
139
  urls_only: "urls_only";
140
+ xml: "xml";
126
141
  }>>;
127
142
  sections: z.ZodOptional<z.ZodArray<z.ZodString>>;
128
143
  }, z.core.$strip>, z.ZodObject<{
129
144
  text: z.ZodOptional<z.ZodString>;
130
145
  format: z.ZodEnum<{
131
146
  html: "html";
132
- xml: "xml";
133
147
  markdown: "markdown";
134
148
  urls_only: "urls_only";
149
+ xml: "xml";
135
150
  }>;
136
151
  byte_size: z.ZodOptional<z.ZodNumber>;
137
152
  truncated: z.ZodOptional<z.ZodBoolean>;
@@ -144,13 +159,13 @@ export declare const risGetDocument: import("@cyanheads/mcp-ts-core").ToolDefini
144
159
  bytes: z.ZodNumber;
145
160
  }, z.core.$strip>>>;
146
161
  binding_status: z.ZodEnum<{
147
- translation: "translation";
162
+ administrative_directive: "administrative_directive";
148
163
  authentic: "authentic";
149
164
  consolidated_informational: "consolidated_informational";
150
- historical_record: "historical_record";
151
165
  decision: "decision";
166
+ historical_record: "historical_record";
152
167
  preparatory: "preparatory";
153
- administrative_directive: "administrative_directive";
168
+ translation: "translation";
154
169
  }>;
155
170
  content_urls: z.ZodObject<{
156
171
  xml: z.ZodOptional<z.ZodString>;
@@ -182,6 +197,12 @@ export declare const risGetDocument: import("@cyanheads/mcp-ts-core").ToolDefini
182
197
  readonly when: "The RIS content host was unreachable or returned a server error.";
183
198
  readonly retryable: true;
184
199
  readonly recovery: "The RIS content host is temporarily unavailable — retry the fetch after a short delay.";
200
+ }, {
201
+ readonly reason: "upstream_timeout";
202
+ readonly code: JsonRpcErrorCode.Timeout;
203
+ readonly when: "The content host did not return the rendition within the fetch deadline — typically a cold render, which it performs on first request before caching the result.";
204
+ readonly retryable: true;
205
+ readonly recovery: "Retry the identical call once or twice — the host renders a document on first request and caches it, so a later fetch often returns instantly. If it keeps timing out, check document_number against a fresh search result (a wrong number renders a slow 404 that looks identical), then re-call with format: urls_only and fetch content_urls yourself, without this deadline.";
185
206
  }], {
186
207
  readonly notice: z.ZodOptional<z.ZodString>;
187
208
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"ris-get-document.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/ris-get-document.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ris-get-document.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/ris-get-document.tool.ts"],"names":[],"mappings":"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"}