ris-austria-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ris-austria-mcp-serverSearch for the latest VwGH decision on privacy."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Public Hosted Server: https://ris-austria.caseyjhand.com/mcp
Overview
Austrian law from RIS, the government's official legal information system: federal, state, and municipal law, court decisions, official gazettes back to 1848, draft legislation, and ministerial decrees. Every document is labeled with its binding status. No API key required.
Tools
Tool | Description |
| Search consolidated federal, state, and municipal law as in force on a date (default today), plus English translations of selected laws |
| Search case law in one court or tribunal per call, across 17 court codes |
| Browse the federal, state, district, and municipal gazettes, with federal history auto-routed back to 1848 |
| Search ministerial review drafts (Begutachtungsentwürfe) and government bills (Regierungsvorlagen) |
| Search seven sectoral collections, from social-insurance notices to ministerial decrees and council-of-ministers minutes |
| Resolve one Austrian legal citation ("§ 6 DSG", "BGBl. I Nr. 165/1999", a Geschäftszahl or ECLI) to its document |
| Fetch one document as markdown, HTML, or XML, or just its rendition URLs, with its binding status |
| List every document added, changed, or deleted in one application within a date window |
| Look up RIS vocabularies offline: applications, courts, states, ministries, gazette parts, citation formats, search syntax |
Resources
Resource | Description |
| Markdown text of one RIS document |
The resource mirrors ris_get_document, so tool-only clients lose nothing.
Related MCP server: swiss-courts-mcp
Capability reference
ris_search_legislation tool
Search by
query(full text) ortitle(title, short title, or abbreviation such as "DSG").scopeisfederal(default) or a Bundesland,municipalityswitches a state scope to municipal law, andlanguage: englishsearches the ~138 English translationsin_force_as_ofdefaults to today in Austria and is echoed asappliedInForceAsOf;include_all_versionsand theentered_force_*/left_force_*windows are mutually exclusive alternativesRecords carry
law_id(filter on it for every section of a law),section_label,abbreviation,keywords, in-force dates,eli,celex_references, andcontent_urls
ris_search_case_law tool
courtis required, one code per call. Filter byquery, citednorm("DSG §1"),case_number,decided_from/decided_to, anddecision_type(headnote,full_text, orall, the default). Court-specific filters includecourt_name(justiz),state(lvwg/uvs), andcollection_number(vfgh/vwgh/uvs); one sent to the wrong court fails ascourt_filter_mismatchRecords carry
case_numbers(a headnote lists every decision it covers),decision_date,ecli,norms_cited, andguiding_principleon headnotescourt: normenlistereturns indexed laws undernorm_indexinstead of decisions
ris_search_gazette tool
scopeisfederal(default), a Bundesland,district, ormunicipal. Filter bynumber,part,type,published_from/published_to,issuer,district_authority, ormunicipality; state scopes also takeseriesandstate_eraFederal queries are served from one era (BgblAuth 2004+, BgblPdf 1945–2003, BgblAlt 1848–1940), echoed as
servedApplication; a date range spanning two eras fails ascross_tier_rangewith the dates to split atRecords carry
binding(authentic,historical_record,consolidated_informational),authentic_pdf_urlwhere one exists,alex_url(ÖNB scan) for 1848–1940,celex_referenceswhere applicable, andpromulgationon federal entries from 1848–2003
ris_search_drafts tool
stageis required:review_drafts(within_review_on) orgovernment_bills(2004+, withdecided_from/decided_to);ministryaccepts an abbreviation such as "BMF" or a full designationRecords carry
review_startandreview_deadlineordecided,abbreviationandkeywordswhere RIS supplies them, plusmaterials[](Erläuterungen, Textgegenüberstellung, Vorblatt/WFA, annexes) classified bytype. Pass amaterials[].urltoris_get_documentto read one
ris_search_announcements tool
collectionis required:social_insurance,veterinary,court_rules,trade_exam_rules,health_structure_plans,ministerial_decrees, orcouncil_minutes. A filter its collection doesn't accept fails ascollection_filter_mismatch, includingchanged_sinceonsocial_insuranceandveterinary.issuerexpands ministry ("BMF") and social-insurance carrier ("ÖGK") abbreviationsRecords carry
binding(authentic,administrative_directive, orpreparatory),authentic_pdf_url, anddocument_url, the only browsable view of council minutes and decreesEach collection adds its own metadata where RIS supplies it, such as
case_numbers,in_force_from/in_force_until,keywords,court_name,plan_state, andsession_number
ris_lookup_citation tool
One
citationper call, classified as a norm ("§ 6 DSG"), gazette number ("BGBl. I Nr. 165/1999"), case number ("VfGH G 13/2025") or ECLI, or collection number ("VfSlg 19.632/2012").kindforces a route,courtandstatenarrow it, andin_force_as_ofpins a norm's version (default today)Returns
found,kind, and arecordin the matching search tool's shape, withalternatives_countwhen several documents matched. A miss returnsfound: falsewithguidanceinstead of an errorA norm resolves to the cited law:
the law is matched as RIS files it ("§ 2 EStG" → EStG 1988 § 2; "AlVG 1977" → the AlVG, filed without its year; "VwGVG 2014 §28" → VwGVG § 28), and a long title is read by its short form ("StaatsanwaltschaftsG - StAG §35" → StAG § 35)
sub-provisions and a trailing ";" are set aside ("Art. 6 (1) B-VG" → B-VG Art 6), and an ordinal-led abbreviation reads like any other ("1. COVID-19-JuBG §1")
a cited version is set aside ("ABGB idF BGBl I 2010/28 §988" → ABGB § 988 as in force on the requested date, never the amending act's gazette entry), with a note saying the cited version was not applied
an entry citing several provisions ("DSG §1, §24", "ZPO §179. ZPO §275 Abs2") resolves the first and names the rest
An EU act RIS does not consolidate ("DSGVO Art32", "RL 2006/123/EG", "VO (EG) 178/2002 Art3") returns
found: falsewith its EUR-Lex link, without a RIS requestA gazette number without its part ("BGBl. Nr. 50/2025") comes back ambiguous, naming parts I, II, and III
ris_get_document tool
Address by
document_number+application, or by adocument_urlfromcontent_urlsor a draft'smaterials[].url;formatismarkdown(default),html,xml, orurls_onlyEvery result carries
binding_statusandauthentic_pdf_urlwhere one exists. Where a PDF is the only rendition (district and municipal promulgations, court rules, party-transparency decisions, council minutes, and draft companions filed without HTML),markdownreturns the text extracted from it: plain text with a--- Page N of M ---line before each page,text_source: pdf, and a notice naming the PDF. A scanned PDF with no text layer, one over 16 MiB, or one that cannot be fetched in time returns a notice with the usable URL instead of failing, as dohtmlandxmlthere and the 1848–1940 gazettes, which have no PDF to readMarkdown writes image references as absolute URLs on the content host. A rendition that is nothing but page images reads its PDF's text, and keeps the image URLs with a notice when the PDF has none
Markdown over 40,000 bytes returns
kind: outline; re-call withsectionsto fetch entries.htmlandxmlover 40,000 bytes returnkind: linkwithbyte_sizeandcontent_urls, so read withmarkdown
ris_track_changes tool
application(any of the 39 codes) pluschanged_from/changed_to;include_deletedadds removals, which no other tool reportsRecords carry
changed,published, andbinding_status; deletions setdeleted: truewithdeleted_atLaw rows carry
section_label,law_id, andin_force_from/in_force_until(no end date is not the same as in force now), and decision rows carrycase_numbersanddecision_date
ris_list_reference tool
topicselects 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 formatsReturns
summaryandentries(value,label,details) with no upstream call
ris://document/{application}/{documentNumber} resource
text/markdownof one document, addressed byapplication+documentNumberfrom a search or lookup result; same content asris_get_documentwithformat: markdownApplications that publish only a PDF return its extracted text in a fenced block with a note naming the PDF; the 1848–1940 gazettes and a PDF with no extractable text return a note pointing at the PDF or scan. Oversized text returns the outline, so use the tool to fetch an entry
Features
Built on @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.
RIS-specific:
All 39 OGD applications: consolidated law, federal, state, district, and municipal gazettes, 17 court and tribunal collections, the lawmaking pipeline, and sectoral announcements
Citations resolve through exact filters (section plus title, gazette number, Geschäftszahl, Sammlungsnummer) rather than keyword search
Dates are
YYYY-MM-DD; search tools page withpageandpage_size(1–100, served as pages of 10 or 20; default 20); omit a text filter rather than sending it blankCourt, application, state, and ministry codes come from
ris_list_referenceTool descriptions are English; titles, field values, and RIS error messages stay German
Agent-friendly output:
Every record carries a typed binding status (
authentic,consolidated_informational,historical_record,decision,preparatory,administrative_directive,translation)Paged results report
totalCountandtruncatedand echo what the server applied, such asappliedInForceAsOfandservedApplicationTyped error reasons (
court_filter_mismatch,cross_tier_range,invalid_query,document_not_found, …) and zero-hit notices name the next call
Getting started
Connect to the hosted instance, no install:
claude mcp add --transport http ris-austria-mcp-server https://ris-austria.caseyjhand.com/mcpOr run it locally:
claude mcp add ris-austria-mcp-server -- npx -y @cyanheads/ris-austria-mcp-serverFor other clients, add this to the MCP config file:
{
"mcpServers": {
"ris-austria-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/ris-austria-mcp-server"]
}
}
}No API key is needed. For Docker or a source build, see Running the server.
Configuration
Variable | Description | Default |
| RIS OGD REST API base URL. |
|
| Document content host that rendition URLs are built on and documents are fetched from. |
|
| Contact string appended to the User-Agent. | none |
| Transport: |
|
| HTTP server port. |
|
| HTTP session mode: |
|
| Authentication: |
|
| Log level ( |
|
| Enable OpenTelemetry. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
Clone and install:
git clone https://github.com/cyanheads/ris-austria-mcp-server.git cd ris-austria-mcp-server && bun installBuild and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker run --rm -p 3010:3010 ghcr.io/cyanheads/ris-austria-mcp-server:latestThe image defaults to HTTP transport, stateless session mode, and logs to /var/log/ris-austria-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/ris-austria-mcp-server:latest"]. To build locally, docker build -t ris-austria-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Optional RIS endpoint and contact configuration, parsed with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| RIS request building, HTTP access, normalization, and static reference data. |
| Design notes: tool surface, service spec, live-confirmed RIS API reference. |
| Unit and integration tests mirroring |
| Development skills synced from |
Development guide
See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via
createApp()insrc/index.tsWrap the RIS API: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
RIS OGD data is CC BY 4.0 (attribution: RIS, Bundeskanzleramt Österreich). The underlying legal texts are copyright-free official works. Only the authentic, amtssignierte gazette wording is legally binding — consolidated RIS text is informational.
This server cannot be deployed
Maintenance
Related MCP Connectors
Search Swiss federal legislation: laws, articles, amendments via the Fedlex SPARQL endpoint.
Public Indian legal search MCP for Roop judgments, statutes, and corpus grounding.
Search German and EU law from official sources with your AI assistant. PRIMAMCP provides citable legal texts via MCP, with daily updates and hosting in Germany.
Search Swiss parliamentary business, votes, debates, members, and declared interests.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server that exposes Austrian federal law (Bundesrecht) to LLMs, enabling full-text search, paragraph retrieval, historical versions, statute lookup, BGBl lookups, amendment timelines, and citation searches via the public RIS OGD API.MIT
- AlicenseAqualityAmaintenanceMCP server for searching Swiss court decisions from federal and cantonal courts via entscheidsuche.ch. Enables full-text search, law reference lookup, and filtering by canton, court level, and date without API keys.845 PyPI1MIT
- AlicenseAqualityAmaintenanceEnables searching and retrieving Austrian federal legislation and case law from the official legal information system RIS, with verifiable ELI and ECLI identifiers.6Apache 2.0
- AlicenseAqualityCmaintenanceMCP server for Polish legislation (ISAP / Sejm) — search acts (Dz.U., M.P.) and fetch full texts with ELI identifiers and verifiable citations.3101 npm1MIT