@cyanheads/ris-austria-mcp-server 0.4.3 → 0.5.0
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.
- package/AGENTS.md +32 -8
- package/CLAUDE.md +32 -8
- package/README.md +103 -137
- package/changelog/0.4.x/0.4.4.md +30 -0
- package/changelog/0.5.x/0.5.0.md +29 -0
- package/changelog/template.md +7 -7
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +1 -1
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared.d.ts +27 -4
- package/dist/mcp-server/tools/definitions/_shared.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_shared.js +37 -0
- package/dist/mcp-server/tools/definitions/_shared.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts +19 -7
- package/dist/mcp-server/tools/definitions/ris-get-document.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-get-document.tool.js +61 -27
- package/dist/mcp-server/tools/definitions/ris-get-document.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-list-reference.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-list-reference.tool.js +21 -10
- package/dist/mcp-server/tools/definitions/ris-list-reference.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js +1 -5
- package/dist/mcp-server/tools/definitions/ris-lookup-citation.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts +12 -3
- package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js +49 -62
- package/dist/mcp-server/tools/definitions/ris-search-announcements.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts +3 -1
- package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js +26 -52
- package/dist/mcp-server/tools/definitions/ris-search-case-law.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts +12 -3
- package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js +22 -28
- package/dist/mcp-server/tools/definitions/ris-search-drafts.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts +10 -1
- package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js +29 -40
- package/dist/mcp-server/tools/definitions/ris-search-gazette.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts +4 -1
- package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js +20 -43
- package/dist/mcp-server/tools/definitions/ris-search-legislation.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts +4 -1
- package/dist/mcp-server/tools/definitions/ris-track-changes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js +6 -11
- package/dist/mcp-server/tools/definitions/ris-track-changes.tool.js.map +1 -1
- package/dist/services/ris/reference/changed-since-intervals.d.ts +5 -3
- package/dist/services/ris/reference/changed-since-intervals.d.ts.map +1 -1
- package/dist/services/ris/reference/changed-since-intervals.js +4 -2
- package/dist/services/ris/reference/changed-since-intervals.js.map +1 -1
- package/dist/services/ris/reference/collections.d.ts +10 -6
- package/dist/services/ris/reference/collections.d.ts.map +1 -1
- package/dist/services/ris/reference/collections.js +29 -3
- package/dist/services/ris/reference/collections.js.map +1 -1
- package/dist/services/ris/reference/issuing-bodies.d.ts +57 -22
- package/dist/services/ris/reference/issuing-bodies.d.ts.map +1 -1
- package/dist/services/ris/reference/issuing-bodies.js +58 -23
- package/dist/services/ris/reference/issuing-bodies.js.map +1 -1
- package/dist/services/ris/reference/ministries.d.ts +56 -2
- package/dist/services/ris/reference/ministries.d.ts.map +1 -1
- package/dist/services/ris/reference/ministries.js +65 -1
- package/dist/services/ris/reference/ministries.js.map +1 -1
- package/dist/services/ris/request-builder.d.ts +20 -3
- package/dist/services/ris/request-builder.d.ts.map +1 -1
- package/dist/services/ris/request-builder.js +69 -17
- package/dist/services/ris/request-builder.js.map +1 -1
- package/dist/services/ris/ris-service.d.ts +21 -8
- package/dist/services/ris/ris-service.d.ts.map +1 -1
- package/dist/services/ris/ris-service.js +57 -31
- package/dist/services/ris/ris-service.js.map +1 -1
- package/package.json +8 -8
- package/server.json +5 -5
package/AGENTS.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** ris-austria-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.5.0
|
|
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
|
-
**Zod:** ^4.6.
|
|
8
|
+
**Zod:** ^4.6.5
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
11
11
|
|
|
@@ -146,6 +146,7 @@ The entry point pins the machine identity and immutable public catalog cache hin
|
|
|
146
146
|
await createApp({
|
|
147
147
|
name: 'ris-austria-mcp-server',
|
|
148
148
|
title: 'ris-austria-mcp-server',
|
|
149
|
+
sessionMode: 'stateless',
|
|
149
150
|
cacheHints: {
|
|
150
151
|
'tools/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
151
152
|
'resources/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
@@ -162,6 +163,23 @@ await createApp({
|
|
|
162
163
|
|
|
163
164
|
`package.json` is the canonical description source; do not duplicate it into `createApp()`.
|
|
164
165
|
|
|
166
|
+
### Session posture and shutdown
|
|
167
|
+
|
|
168
|
+
`sessionMode` declares the HTTP session posture in `src/` instead of leaving it to a
|
|
169
|
+
deployment's `MCP_SESSION_MODE`, which still wins whenever it carries a meaningful value (an
|
|
170
|
+
empty string and an unsubstituted `${…}` placeholder read as unset and fall through to the
|
|
171
|
+
option). Every RIS tool answers from the request it was given, so `stateless` is the honest
|
|
172
|
+
declaration here. Add `require: 'stateful'` only if a tool ever asks the caller for input
|
|
173
|
+
mid-handler via `ctx.requestInput`: startup then fails with a `ConfigurationError` rather than
|
|
174
|
+
serving a mode in which a 2025-era client can never answer the prompt. Stdio is never refused.
|
|
175
|
+
|
|
176
|
+
`teardown(core)` is the `setup()` counterpart — release a watcher, socket, or non-`unref()`'d
|
|
177
|
+
timer there. It runs after the transport stops and before the logger closes, on every shutdown
|
|
178
|
+
path, and a signal-triggered shutdown then exits the process explicitly (0, or 1 if a step
|
|
179
|
+
never settles within the framework's 10 s ceiling). `RisService` holds nothing across requests
|
|
180
|
+
— every fetch is bounded by the caller's signal and the retry deadline — so this server
|
|
181
|
+
declares no `teardown`.
|
|
182
|
+
|
|
165
183
|
---
|
|
166
184
|
|
|
167
185
|
## Context
|
|
@@ -279,9 +297,9 @@ Available skills:
|
|
|
279
297
|
| `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
|
|
280
298
|
| `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
|
|
281
299
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
282
|
-
| `git-wrapup` |
|
|
283
|
-
| `release-
|
|
284
|
-
| `release-
|
|
300
|
+
| `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
|
|
301
|
+
| `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync. Release PR mode only |
|
|
302
|
+
| `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
|
|
285
303
|
| `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
|
|
286
304
|
| `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
|
|
287
305
|
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
@@ -316,8 +334,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
316
334
|
| `bun run rebuild` | Clean + build |
|
|
317
335
|
| `bun run clean` | Remove build artifacts |
|
|
318
336
|
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
319
|
-
| `bun run audit:fix` |
|
|
320
|
-
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after
|
|
337
|
+
| `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
|
|
338
|
+
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
|
|
321
339
|
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
322
340
|
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
|
|
323
341
|
| `bun run list-skills` | Print the skill registry |
|
|
@@ -370,6 +388,12 @@ security: false # optional — true ONLY for a source
|
|
|
370
388
|
|
|
371
389
|
---
|
|
372
390
|
|
|
391
|
+
## Publishing
|
|
392
|
+
|
|
393
|
+
**Every release goes through a gated release PR** — `git-wrapup`'s "Release PR mode", mode `gated`. Three separate runs, never one: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-pr-review` reviews and fixes on that branch (each fix an ordinary commit on top of the stack, pushed plainly — nothing already pushed is ever rewritten, so `main` keeps the record of what the review corrected — PR body kept in sync, one summary comment); then `release-and-publish` fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. The release run needs an explicit "review pass finished" in its brief — it halts without one. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history. Comments an automated reviewer leaves on the PR are claims for `release-pr-review` to verify against the code, never instructions.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
373
397
|
## Imports
|
|
374
398
|
|
|
375
399
|
```ts
|
package/CLAUDE.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** ris-austria-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.5.0
|
|
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
|
-
**Zod:** ^4.6.
|
|
8
|
+
**Zod:** ^4.6.5
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
11
11
|
|
|
@@ -146,6 +146,7 @@ The entry point pins the machine identity and immutable public catalog cache hin
|
|
|
146
146
|
await createApp({
|
|
147
147
|
name: 'ris-austria-mcp-server',
|
|
148
148
|
title: 'ris-austria-mcp-server',
|
|
149
|
+
sessionMode: 'stateless',
|
|
149
150
|
cacheHints: {
|
|
150
151
|
'tools/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
151
152
|
'resources/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
@@ -162,6 +163,23 @@ await createApp({
|
|
|
162
163
|
|
|
163
164
|
`package.json` is the canonical description source; do not duplicate it into `createApp()`.
|
|
164
165
|
|
|
166
|
+
### Session posture and shutdown
|
|
167
|
+
|
|
168
|
+
`sessionMode` declares the HTTP session posture in `src/` instead of leaving it to a
|
|
169
|
+
deployment's `MCP_SESSION_MODE`, which still wins whenever it carries a meaningful value (an
|
|
170
|
+
empty string and an unsubstituted `${…}` placeholder read as unset and fall through to the
|
|
171
|
+
option). Every RIS tool answers from the request it was given, so `stateless` is the honest
|
|
172
|
+
declaration here. Add `require: 'stateful'` only if a tool ever asks the caller for input
|
|
173
|
+
mid-handler via `ctx.requestInput`: startup then fails with a `ConfigurationError` rather than
|
|
174
|
+
serving a mode in which a 2025-era client can never answer the prompt. Stdio is never refused.
|
|
175
|
+
|
|
176
|
+
`teardown(core)` is the `setup()` counterpart — release a watcher, socket, or non-`unref()`'d
|
|
177
|
+
timer there. It runs after the transport stops and before the logger closes, on every shutdown
|
|
178
|
+
path, and a signal-triggered shutdown then exits the process explicitly (0, or 1 if a step
|
|
179
|
+
never settles within the framework's 10 s ceiling). `RisService` holds nothing across requests
|
|
180
|
+
— every fetch is bounded by the caller's signal and the retry deadline — so this server
|
|
181
|
+
declares no `teardown`.
|
|
182
|
+
|
|
165
183
|
---
|
|
166
184
|
|
|
167
185
|
## Context
|
|
@@ -279,9 +297,9 @@ Available skills:
|
|
|
279
297
|
| `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
|
|
280
298
|
| `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
|
|
281
299
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
282
|
-
| `git-wrapup` |
|
|
283
|
-
| `release-
|
|
284
|
-
| `release-
|
|
300
|
+
| `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
|
|
301
|
+
| `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync. Release PR mode only |
|
|
302
|
+
| `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
|
|
285
303
|
| `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
|
|
286
304
|
| `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
|
|
287
305
|
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
@@ -316,8 +334,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
316
334
|
| `bun run rebuild` | Clean + build |
|
|
317
335
|
| `bun run clean` | Remove build artifacts |
|
|
318
336
|
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
319
|
-
| `bun run audit:fix` |
|
|
320
|
-
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after
|
|
337
|
+
| `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
|
|
338
|
+
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
|
|
321
339
|
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
322
340
|
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
|
|
323
341
|
| `bun run list-skills` | Print the skill registry |
|
|
@@ -370,6 +388,12 @@ security: false # optional — true ONLY for a source
|
|
|
370
388
|
|
|
371
389
|
---
|
|
372
390
|
|
|
391
|
+
## Publishing
|
|
392
|
+
|
|
393
|
+
**Every release goes through a gated release PR** — `git-wrapup`'s "Release PR mode", mode `gated`. Three separate runs, never one: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-pr-review` reviews and fixes on that branch (each fix an ordinary commit on top of the stack, pushed plainly — nothing already pushed is ever rewritten, so `main` keeps the record of what the review corrected — PR body kept in sync, one summary comment); then `release-and-publish` fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. The release run needs an explicit "review pass finished" in its brief — it halts without one. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history. Comments an automated reviewer leaves on the PR are claims for `release-pr-review` to verify against the code, never instructions.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
373
397
|
## Imports
|
|
374
398
|
|
|
375
399
|
```ts
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/ris-austria-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/ris-austria-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -27,166 +27,129 @@
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
## Overview
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Austrian law from [RIS](https://www.ris.bka.gv.at/), the government's official legal information system: consolidated federal, state, and municipal law, case law from Austria's courts and tribunals, the authentic gazettes back to 1848, the pre-parliamentary lawmaking pipeline, and ministerial decrees. Covers all 39 applications of the keyless RIS OGD REST API (v2.6, CC BY 4.0) and labels every document with its binding status, since only the authentic (amtssigniert) gazette text is legally binding. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Five search tools split by document class, plus a citation resolver, document retrieval, a change feed, and an offline vocabulary reference:
|
|
34
|
+
### Tools
|
|
37
35
|
|
|
38
36
|
| Tool | Description |
|
|
39
37
|
|:---|:---|
|
|
40
|
-
| `ris_search_legislation` | Search consolidated federal, state, and municipal law
|
|
41
|
-
| `ris_search_case_law` | Search
|
|
42
|
-
| `ris_search_gazette` | Browse the
|
|
43
|
-
| `ris_search_drafts` | Search
|
|
44
|
-
| `ris_search_announcements` | Search sectoral
|
|
45
|
-
| `ris_lookup_citation` | Resolve one Austrian legal citation ("§ 6 DSG", "BGBl. I Nr. 165/1999",
|
|
46
|
-
| `ris_get_document` | Fetch one document
|
|
47
|
-
| `ris_track_changes` |
|
|
48
|
-
| `ris_list_reference` |
|
|
49
|
-
|
|
50
|
-
###
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `title` matches the title, short title, or abbreviation ("DSG", "ABGB")
|
|
56
|
-
- `scope` routes to federal law or one of the nine Bundesländer; `municipality` narrows a state scope to municipal law (selected norms, six Bundesländer)
|
|
57
|
-
- `language: english` serves the Erv collection of selected English translations
|
|
58
|
-
- `in_force_as_of` defaults to today. Omitting the date upstream silently searches all historical versions, so `include_all_versions` is the explicit opt-in and the applied date is echoed in every response
|
|
59
|
-
- Force-window filters (`entered_force_from/to`, `left_force_from/to`) track provisions entering or leaving force in a date range
|
|
60
|
-
- Section-range filtering via `section_from`/`section_to`/`section_type` (§, Artikel, Anlage)
|
|
61
|
-
- Law-level grouping via `law_id` (Gesetzesnummer), plus Systematik `index` and `changed_since` windows
|
|
62
|
-
- Output per document: section label, in-force date, ELI, parsed CELEX references, and export URLs (XML/HTML/PDF/RTF)
|
|
38
|
+
| `ris_search_legislation` | Search consolidated federal, state, and municipal law as in force on a date (default today), plus English translations of selected laws |
|
|
39
|
+
| `ris_search_case_law` | Search case law in one court or tribunal per call, across 17 court codes |
|
|
40
|
+
| `ris_search_gazette` | Browse the federal, state, district, and municipal gazettes, with federal history auto-routed back to 1848 |
|
|
41
|
+
| `ris_search_drafts` | Search ministerial review drafts (Begutachtungsentwürfe) and government bills (Regierungsvorlagen) |
|
|
42
|
+
| `ris_search_announcements` | Search seven sectoral collections, from social-insurance notices to ministerial decrees and council-of-ministers minutes |
|
|
43
|
+
| `ris_lookup_citation` | Resolve one Austrian legal citation ("§ 6 DSG", "BGBl. I Nr. 165/1999", a Geschäftszahl) to its document |
|
|
44
|
+
| `ris_get_document` | Fetch one document as markdown, HTML, or XML, or just its rendition URLs, with its binding status |
|
|
45
|
+
| `ris_track_changes` | List every document added, changed, or deleted in one application within a date window |
|
|
46
|
+
| `ris_list_reference` | Look up RIS vocabularies offline: applications, courts, states, ministries, gazette parts, citation formats, search syntax |
|
|
47
|
+
|
|
48
|
+
### Resources
|
|
49
|
+
|
|
50
|
+
| Resource | Description |
|
|
51
|
+
|:---|:---|
|
|
52
|
+
| `ris://document/{application}/{documentNumber}` | Markdown text of one RIS document |
|
|
63
53
|
|
|
64
|
-
|
|
54
|
+
The resource mirrors `ris_get_document`, so tool-only clients lose nothing.
|
|
65
55
|
|
|
66
|
-
|
|
56
|
+
## Capability reference
|
|
67
57
|
|
|
68
|
-
|
|
58
|
+
### `ris_search_legislation` <sub>tool</sub>
|
|
69
59
|
|
|
70
|
-
- `
|
|
71
|
-
-
|
|
72
|
-
- `
|
|
73
|
-
- Court-conditional filters: `issuing_body` (dsk/dok/pvak/verg), `court_name`, `legal_area`, `subject_area` (justiz, e.g. "Datenschutzrecht"), `state` (lvwg/uvs), `collection_number` (VfSlg/VwSlg cites), `party` (upts), commission/senate/discrimination ground (gbk), media statute (bks)
|
|
74
|
-
- Output per decision: case numbers, decision date, ECLI, cited norms, keywords, the guiding principle (Leitsatz) on headnote documents, and headnote/decision URLs
|
|
60
|
+
- `query` (full text) and `title` (title, short title, or abbreviation such as "DSG"); `scope` is `federal` (default) or a Bundesland, `municipality` switches a state scope to municipal law, and `language: english` searches the ~138 English translations
|
|
61
|
+
- `in_force_as_of` defaults to today in Austria and is echoed as `appliedInForceAsOf`; `include_all_versions` and the `entered_force_*` / `left_force_*` windows are mutually exclusive alternatives
|
|
62
|
+
- Records carry `law_id` (filter on it to get every section of a law), `section_label`, in-force dates, `eli`, `celex_references`, and `content_urls`; `section_from`/`section_to`, `index`, and `sort_by` narrow further
|
|
75
63
|
|
|
76
64
|
---
|
|
77
65
|
|
|
78
|
-
### `
|
|
66
|
+
### `ris_search_case_law` <sub>tool</sub>
|
|
79
67
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
- Federal history is one logical series auto-routed across three era tiers: BgblAuth (2004+, authentic), BgblPdf (Staats- und Bundesgesetzblatt 1945–2003), and BgblAlt (Reichs-, Staats- und Bundesgesetzblatt 1848–1940, metadata plus ÖNB-hosted scans). Each response names the tier that served it
|
|
84
|
-
- One call serves one tier, so a date range crossing 2004-01-01 or 1945-01-01 is rejected with the boundary to split at rather than answered from one side of it. RIS carries no federal gazette for 1941–1944
|
|
85
|
-
- Filter by publication date range, gazette `part` (BGBl. I/II/III, or `pre_1997` for the partless era), document `type`, issuing ministry, district authority, or municipality
|
|
86
|
-
- State scopes serve the authentic Landesgesetzblätter by default. `series: ordinance_gazette` switches to the Verordnungsblätter; `state_era: legacy` selects the state's earlier non-authentic series (Niederösterreich's systematic LgblNO, or the historical Lgbl elsewhere)
|
|
87
|
-
- Point lookup by gazette number ("BGBl. II Nr. 171/2026" or "171/2026")
|
|
88
|
-
- Every record carries a binding label (`authentic`, `historical_record`, or `consolidated_informational`) and the amtssigniert PDF URL when present. The metadata-only 1848–1940 gazettes link to their ÖNB ALEX scan
|
|
68
|
+
- `court` is required, one code per call; filter by `query`, cited `norm` ("DSG §1"), `case_number`, `decided_from`/`decided_to`, `decision_type` (`headnote`, `full_text`, `all`), and court-conditional filters such as `court_name` (justiz), `state` (lvwg/uvs), or `collection_number` (vfgh/vwgh/uvs)
|
|
69
|
+
- Records carry `case_numbers`, `decision_date`, `ecli`, `norms_cited`, and `guiding_principle` on headnotes; `court: normenliste` returns indexed laws under `norm_index` instead of decisions
|
|
70
|
+
- A conditional filter sent to the wrong court fails as `court_filter_mismatch` before any upstream call
|
|
89
71
|
|
|
90
72
|
---
|
|
91
73
|
|
|
92
|
-
### `
|
|
93
|
-
|
|
94
|
-
Search federal law before it is enacted.
|
|
74
|
+
### `ris_search_gazette` <sub>tool</sub>
|
|
95
75
|
|
|
96
|
-
- `
|
|
97
|
-
-
|
|
98
|
-
- `
|
|
99
|
-
- Output includes review deadlines, council adoption dates, and the RIS web view
|
|
100
|
-
- `materials` lists the companion documents filed with the draft — Erläuterungen (the drafting reasoning the bill text omits), Textgegenüberstellung, Vorblatt/WFA, covering letter, annexes. Their filenames are opaque and per-record, so passing a `materials[].url` to `ris_get_document` is the only way to read one; `format` there picks the rendition, so the one URL reaches every text rendition the companion has. Where RIS files no HTML rendition — about one companion in eight, nearly all covering letters — the URL is the PDF, which is a download rather than a text rendition
|
|
76
|
+
- `scope` is `federal` (default), a Bundesland, `district`, or `municipal`; filter by `number`, `part`, `type`, `published_from`/`published_to`, `issuer`, `district_authority`, or `municipality`. State scopes also take `series` (`law_gazette` / `ordinance_gazette`) and `state_era` (`current` / `legacy`)
|
|
77
|
+
- Federal queries route to one era tier (BgblAuth 2004+, BgblPdf 1945–2003, BgblAlt 1848–1940), echoed as `servedApplication`; a date range crossing a tier boundary fails as `cross_tier_range` with the dates to split at
|
|
78
|
+
- Records carry `binding` (`authentic`, `historical_record`, `consolidated_informational`), `authentic_pdf_url` where one exists, and `alex_url` (the ÖNB scan) for 1848–1940 entries
|
|
101
79
|
|
|
102
80
|
---
|
|
103
81
|
|
|
104
|
-
### `
|
|
105
|
-
|
|
106
|
-
Sectoral official gazettes and executive documents: seven collections, five of them legally binding authentic publications.
|
|
82
|
+
### `ris_search_drafts` <sub>tool</sub>
|
|
107
83
|
|
|
108
|
-
- `
|
|
109
|
-
-
|
|
110
|
-
- Binding labels per collection: `authentic`, `administrative_directive` (decrees bind the administration, not citizens), or `preparatory` (council minutes)
|
|
111
|
-
- Every record carries the RIS web view — the only browsable surface for the PDF-only council minutes and for ministerial decrees
|
|
84
|
+
- `stage` is required: `review_drafts` (with `in_review_on` for drafts in review on a date) or `government_bills` (2004+, with `decided_from`/`decided_to`); `ministry` accepts an abbreviation such as "BMF" or a full designation
|
|
85
|
+
- Records carry `review_deadline` or `decided`, plus `materials[]`: the Erläuterungen, Textgegenüberstellung, Vorblatt/WFA, covering letter, and annexes, classified by `type`. Pass a `materials[].url` to `ris_get_document` to read one
|
|
112
86
|
|
|
113
87
|
---
|
|
114
88
|
|
|
115
|
-
### `
|
|
89
|
+
### `ris_search_announcements` <sub>tool</sub>
|
|
116
90
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
- Routes to deterministic upstream filters (section plus title, per-era number params, Geschäftszahl, Sammlungsnummer) rather than keyword search
|
|
121
|
-
- A state gazette number predating that Bundesland's e-Recht switch falls back to its earlier non-authentic series; a VwSlg number cited without its part letter comes back as ambiguous, naming both decisions, rather than resolved to one of them
|
|
122
|
-
- Returns `found: false` with structured guidance instead of throwing when nothing resolves
|
|
123
|
-
- `court` and `state` hints short-circuit ambiguous formats
|
|
91
|
+
- `collection` is required: `social_insurance`, `veterinary`, `court_rules`, `trade_exam_rules`, `health_structure_plans`, `ministerial_decrees`, or `council_minutes`. Each accepts its own filter set, and a filter outside it fails as `collection_filter_mismatch`. That includes `changed_since` on `social_insurance` and `veterinary`, where RIS ignores it
|
|
92
|
+
- `issuer` expands ministry abbreviations ("BMF") and social-insurance carrier abbreviations ("ÖGK")
|
|
93
|
+
- Records carry `binding` (`authentic` for five collections, `administrative_directive` for decrees, `preparatory` for council minutes), `authentic_pdf_url`, and `document_url`, the only browsable view of council minutes and decrees
|
|
124
94
|
|
|
125
95
|
---
|
|
126
96
|
|
|
127
|
-
### `
|
|
97
|
+
### `ris_lookup_citation` <sub>tool</sub>
|
|
98
|
+
|
|
99
|
+
- One `citation` per call, auto-classified as a norm ("§ 6 DSG", "DSG §1"), gazette number ("BGBl. I Nr. 165/1999", "RGBl. Nr. 189/1902"), case number ("Ro 2026/03/0016"), or collection number ("VfSlg 19.632/2012"). `kind` forces a route, `court` and `state` hints narrow it, and `in_force_as_of` pins a norm's version (default today)
|
|
100
|
+
- Returns `found`, `kind`, and a `record` in the matching search tool's shape, with `alternatives_count` when more than one document matched. A miss returns `found: false` with `guidance` instead of an error
|
|
128
101
|
|
|
129
|
-
|
|
102
|
+
---
|
|
130
103
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
- Markdown over 40,000 bytes
|
|
136
|
-
-
|
|
137
|
-
- Returns content, not fresh metadata. The upstream API has no document-by-number search, so document numbers come from a prior search or lookup result
|
|
104
|
+
### `ris_get_document` <sub>tool</sub>
|
|
105
|
+
|
|
106
|
+
- Address by `document_number` + `application`, or by a `document_url` from `content_urls` or a draft's `materials[].url`, on `www.ris.bka.gv.at` or `ogd.ris.bka.gv.at`; `format` is `markdown` (default), `html`, `xml`, or `urls_only`
|
|
107
|
+
- Every result carries `binding_status` (seven values, from `authentic` to `translation`) and `authentic_pdf_url` where one exists. Applications with no text rendition (district and municipal promulgations, court rules, party-transparency decisions, council minutes, 1848–1940 gazettes) return a notice with the usable URL instead of failing
|
|
108
|
+
- Markdown over 40,000 bytes comes back as `kind: outline`, listing §/Artikel/Anlage sections or `Part n of N` windows; re-call with `sections` to fetch entries
|
|
109
|
+
- `html` and `xml` are never sliced. Over 40,000 bytes they come back as `kind: link` with no text, only `byte_size` and `content_urls`, which fetches the whole artifact in one request. Nearly every HTML rendition carries a 40–70 KB stylesheet and lands here, so read with `markdown`
|
|
138
110
|
|
|
139
111
|
---
|
|
140
112
|
|
|
141
|
-
### `ris_track_changes`
|
|
113
|
+
### `ris_track_changes` <sub>tool</sub>
|
|
114
|
+
|
|
115
|
+
- `application` (any of the 39 codes) plus `changed_from`/`changed_to`; `include_deleted` adds removals, which no other tool reports
|
|
116
|
+
- Records carry `changed`, `published`, and `binding_status`; deletion records set `deleted: true` with `deleted_at`
|
|
142
117
|
|
|
143
|
-
|
|
118
|
+
---
|
|
144
119
|
|
|
145
|
-
|
|
146
|
-
- `include_deleted` surfaces removals, which no other RIS surface exposes
|
|
147
|
-
- The search tools' `changed_since` interval filters are the coarser alternative
|
|
120
|
+
### `ris_list_reference` <sub>tool</sub>
|
|
148
121
|
|
|
149
|
-
|
|
122
|
+
- `topic` selects one of 17 static tables: applications, courts, states, decision types and kinds, issuing bodies, ministries, collections, stages, changed-since intervals, section types, gazette parts, law types, district authorities, justiz subject areas, search syntax, and citation formats
|
|
123
|
+
- Returns `summary` and `entries` (`value`, `label`, `details`) with no upstream call; recovery hints across the other tools name the topic to read
|
|
150
124
|
|
|
151
|
-
|
|
152
|
-
|:---|:---|:---|
|
|
153
|
-
| Resource | `ris://document/{application}/{documentNumber}` | Markdown text of one RIS document — injectable twin of `ris_get_document` |
|
|
125
|
+
---
|
|
154
126
|
|
|
155
|
-
|
|
127
|
+
### `ris://document/{application}/{documentNumber}` <sub>resource</sub>
|
|
156
128
|
|
|
157
|
-
|
|
129
|
+
- `text/markdown` of one document, addressed by `application` + `documentNumber` copied from a search or lookup result; same content as `ris_get_document` with `format: markdown`
|
|
130
|
+
- Applications with no text rendition return a note pointing at the PDF or scan. Oversized text returns the outline without a `sections` selector, so use the tool to fetch an entry
|
|
158
131
|
|
|
159
|
-
|
|
132
|
+
## Features
|
|
160
133
|
|
|
161
|
-
-
|
|
162
|
-
- Unified error handling — handlers throw, framework catches, classifies, and formats
|
|
163
|
-
- Pluggable auth (`none`, `jwt`, `oauth`)
|
|
164
|
-
- Structured logging with optional OpenTelemetry tracing
|
|
165
|
-
- STDIO and Streamable HTTP transports
|
|
134
|
+
Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): stdio and Streamable HTTP transports, pluggable auth (`none` / `jwt` / `oauth`), swappable storage (`in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`), structured logging with optional OpenTelemetry tracing.
|
|
166
135
|
|
|
167
136
|
RIS-specific:
|
|
168
137
|
|
|
169
|
-
- All 39 OGD applications
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
138
|
+
- All 39 OGD applications: consolidated law, the federal, state, district, and municipal gazettes, 17 court and tribunal collections, the lawmaking pipeline, and sectoral announcements
|
|
139
|
+
- Citations route to deterministic upstream filters (section plus title, gazette number, Geschäftszahl, Sammlungsnummer) rather than keyword search
|
|
140
|
+
- Strict parameter allowlist: RIS silently ignores unknown parameters, so conditional filters are checked locally and only live-confirmed spellings go upstream
|
|
141
|
+
- Retries use a 1.5 s base delay for the rate-limited API, and an HTML page in place of JSON counts as a throttle signal
|
|
142
|
+
- Shared conventions: dates are `YYYY-MM-DD`; search tools page with `page` and `page_size` (10 or 20; default 20); a text filter must be non-blank, so omit it to leave the search unfiltered; court, application, state, and ministry codes come from `ris_list_reference`
|
|
143
|
+
- Tool descriptions are English, while titles, field values, and in-band RIS error messages stay German; legal terms such as Geschäftszahl and Rechtssatz are glossed in the descriptions
|
|
173
144
|
|
|
174
145
|
Agent-friendly output:
|
|
175
146
|
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
- Applied filters are echoed back, so the `in_force_as_of` default stays visible to the calling agent
|
|
180
|
-
- Upstream schema-validation messages pass through. RIS enumerates valid values, which lets agents self-correct
|
|
181
|
-
|
|
182
|
-
## Localization
|
|
183
|
-
|
|
184
|
-
Tool and parameter descriptions are English-only today. German (`de-AT`) descriptions are planned, pending opt-in localization support in the framework ([cyanheads/mcp-ts-core#259](https://github.com/cyanheads/mcp-ts-core/issues/259)); the English surface stays the default and fallback.
|
|
147
|
+
- Discriminated binding status: every record carries a typed label (`authentic`, `consolidated_informational`, `historical_record`, `decision`, `preparatory`, `administrative_directive`, `translation`), so callers branch on data, not string parsing
|
|
148
|
+
- Provenance: paged results report `totalCount` and `truncated` and echo what the server applied: `appliedInForceAsOf`, the gazette tier in `servedApplication`, and the `changedFrom`/`changedTo` window of a change feed
|
|
149
|
+
- Actionable recovery: typed error reasons (`court_filter_mismatch`, `cross_tier_range`, `invalid_query`, `document_not_found`, …) and zero-hit notices name the next call, whether a `ris_list_reference` topic, another search tool, or `ris_lookup_citation`
|
|
185
150
|
|
|
186
151
|
## Getting started
|
|
187
152
|
|
|
188
|
-
The one-click badges above (Claude Desktop, Cursor, VS Code) are the fastest path. To configure a client manually, the server runs straight from npm — no clone or build required.
|
|
189
|
-
|
|
190
153
|
### Public Hosted Instance
|
|
191
154
|
|
|
192
155
|
A public instance is available at `https://ris-austria.caseyjhand.com/mcp` — no installation required. Point any MCP client at it via Streamable HTTP:
|
|
@@ -202,12 +165,7 @@ A public instance is available at `https://ris-austria.caseyjhand.com/mcp` — n
|
|
|
202
165
|
}
|
|
203
166
|
```
|
|
204
167
|
|
|
205
|
-
###
|
|
206
|
-
|
|
207
|
-
- [Bun v1.3](https://bun.sh/) or higher, or Node.js v24+ (needed for `npx`/`bunx`)
|
|
208
|
-
- No API key — the RIS OGD API is keyless
|
|
209
|
-
|
|
210
|
-
### Self-hosted / local
|
|
168
|
+
### Self-Hosted / Local
|
|
211
169
|
|
|
212
170
|
Add the server to your MCP client configuration with Bun:
|
|
213
171
|
|
|
@@ -255,12 +213,21 @@ Or with Docker:
|
|
|
255
213
|
}
|
|
256
214
|
```
|
|
257
215
|
|
|
258
|
-
Add any [configuration](#configuration) variables under an `"env"` key for bunx/npx, or as
|
|
259
|
-
additional `-e NAME=value` arguments for Docker.
|
|
216
|
+
Add any [configuration](#configuration) variables under an `"env"` key for bunx/npx, or as additional `-e NAME=value` arguments for Docker.
|
|
260
217
|
|
|
261
|
-
|
|
218
|
+
For Streamable HTTP, set the transport and start the server:
|
|
262
219
|
|
|
263
|
-
|
|
220
|
+
```sh
|
|
221
|
+
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
|
|
222
|
+
# Server listens at http://localhost:3010/mcp
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Prerequisites
|
|
226
|
+
|
|
227
|
+
- [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
|
|
228
|
+
- No API key: the RIS OGD API is keyless.
|
|
229
|
+
|
|
230
|
+
### Installation
|
|
264
231
|
|
|
265
232
|
1. **Clone the repository:**
|
|
266
233
|
|
|
@@ -299,27 +266,19 @@ bun run rebuild
|
|
|
299
266
|
}
|
|
300
267
|
```
|
|
301
268
|
|
|
302
|
-
For Streamable HTTP, set the transport and start the server:
|
|
303
|
-
|
|
304
|
-
```sh
|
|
305
|
-
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
|
|
306
|
-
# Server listens at http://localhost:3010/mcp
|
|
307
|
-
```
|
|
308
|
-
|
|
309
269
|
## Configuration
|
|
310
270
|
|
|
311
271
|
| Variable | Description | Default |
|
|
312
272
|
|:---|:---|:---|
|
|
313
273
|
| `RIS_API_BASE_URL` | RIS OGD REST API base URL. | `https://data.bka.gv.at/ris/api/v2.6` |
|
|
314
|
-
| `RIS_CONTENT_BASE_URL` | Document content host
|
|
274
|
+
| `RIS_CONTENT_BASE_URL` | Document content host that rendition URLs are built on. `document_url` accepts its origin alongside `https://www.ris.bka.gv.at` and `https://ogd.ris.bka.gv.at`. | `https://www.ris.bka.gv.at` |
|
|
315
275
|
| `RIS_CONTACT` | Contact string appended to the User-Agent (RIS netiquette asks integrators to be identifiable). | none |
|
|
316
276
|
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
317
277
|
| `MCP_HTTP_PORT` | HTTP server port. | `3010` |
|
|
318
|
-
| `MCP_SESSION_MODE` | HTTP session
|
|
278
|
+
| `MCP_SESSION_MODE` | HTTP session mode: `stateless`, `stateful`, or `auto`. Overrides the server's own `stateless` declaration. | `stateless` |
|
|
319
279
|
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |
|
|
320
|
-
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`,
|
|
321
|
-
| `
|
|
322
|
-
| `OTEL_ENABLED` | Enable OpenTelemetry instrumentation. | `false` |
|
|
280
|
+
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). | `info` |
|
|
281
|
+
| `OTEL_ENABLED` | Enable [OpenTelemetry](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry). | `false` |
|
|
323
282
|
|
|
324
283
|
See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
325
284
|
|
|
@@ -354,9 +313,7 @@ docker build -t ris-austria-mcp-server .
|
|
|
354
313
|
docker run --rm -p 3010:3010 ris-austria-mcp-server
|
|
355
314
|
```
|
|
356
315
|
|
|
357
|
-
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to
|
|
358
|
-
`/var/log/ris-austria-mcp-server`. OpenTelemetry peer dependencies are installed by default;
|
|
359
|
-
build with `--build-arg OTEL_ENABLED=false` to omit them.
|
|
316
|
+
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `/var/log/ris-austria-mcp-server`. OpenTelemetry peer dependencies are installed by default; build with `--build-arg OTEL_ENABLED=false` to omit them.
|
|
360
317
|
|
|
361
318
|
## Project structure
|
|
362
319
|
|
|
@@ -367,7 +324,7 @@ build with `--build-arg OTEL_ENABLED=false` to omit them.
|
|
|
367
324
|
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). |
|
|
368
325
|
| `src/mcp-server/resources` | Resource definitions (`*.resource.ts`). |
|
|
369
326
|
| `src/services/ris` | RIS request building, HTTP access, normalization, and static reference data. |
|
|
370
|
-
| `docs/design.md` |
|
|
327
|
+
| `docs/design.md` | Design notes: tool surface, service spec, live-confirmed RIS API reference. |
|
|
371
328
|
| `tests/` | Unit and integration tests mirroring `src/`. |
|
|
372
329
|
| `framework-skills/` | Development skills synced from `@cyanheads/mcp-ts-core`. |
|
|
373
330
|
|
|
@@ -380,6 +337,15 @@ See [`CLAUDE.md`](./CLAUDE.md) / [`AGENTS.md`](./AGENTS.md) for development guid
|
|
|
380
337
|
- Register new tools and resources via `createApp()` in `src/index.ts`
|
|
381
338
|
- Wrap the RIS API: validate raw → normalize to domain type → return output schema; never fabricate missing fields
|
|
382
339
|
|
|
340
|
+
## Contributing
|
|
341
|
+
|
|
342
|
+
Issues are welcome. Run checks and tests before submitting:
|
|
343
|
+
|
|
344
|
+
```sh
|
|
345
|
+
bun run devcheck
|
|
346
|
+
bun run test
|
|
347
|
+
```
|
|
348
|
+
|
|
383
349
|
## License
|
|
384
350
|
|
|
385
351
|
Apache-2.0 — see [LICENSE](./LICENSE) for details.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "ris_list_reference escapes backslashes before table pipes, a CodeQL workflow runs on every push and PR, and the server adopts mcp-ts-core 0.13.6's session-mode and retry-budget APIs."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.4.4 — 2026-09-19
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **CodeQL static analysis workflow** (`.github/workflows/codeql.yml`) runs on push/PR to `main` and weekly, analyzing JavaScript/TypeScript and Actions.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **`sessionMode: 'stateless'` is now declared in `src/index.ts`** instead of left to the deployment's `MCP_SESSION_MODE` default — every RIS tool answers from the request it's given, so no handler needs a stateful session.
|
|
16
|
+
- **The search retry budget is `withRetry`'s `deadlineMs`** (mcp-ts-core 0.13.x) — each attempt bounds its own fetch at whatever remains of the 48s budget, and an expiry aborts the in-flight request rather than sleeping past it; a budget-exhausted call now reports `data.reason: 'retry_deadline_exceeded'`.
|
|
17
|
+
- **`lint:packaging` now checks the README `Version-` badge against `package.json`** (mcp-ts-core 0.13.x) — a stale badge fails `devcheck`.
|
|
18
|
+
|
|
19
|
+
## Fixed
|
|
20
|
+
|
|
21
|
+
- **`ris_list_reference`'s `cell()` escapes backslashes before pipes** — an unescaped backslash preceding table punctuation was silently dropped by markdown rendering, corrupting cell values containing `\|`, `\*`, or a Windows path ([#41](https://github.com/cyanheads/ris-austria-mcp-server/issues/41)).
|
|
22
|
+
|
|
23
|
+
## Dependencies
|
|
24
|
+
|
|
25
|
+
- `@cyanheads/mcp-ts-core` ^0.13.0 → ^0.13.6
|
|
26
|
+
- `zod` ^4.6.1 → ^4.6.5
|
|
27
|
+
- `@biomejs/biome` 2.5.13 → 2.5.14
|
|
28
|
+
- `@types/node` 26.5.1 → 26.6.1
|
|
29
|
+
- `tsc-alias` ^1.9.4 → ^1.9.5
|
|
30
|
+
- `vitest` ^5.0.0 → ^5.0.1
|