{
  "markdown": "# at-ris-mcp\n\n<!-- mcp-name: io.github.paragraflabs/at-ris-mcp -->\n\n[![CI](https://github.com/paragraflabs/at-ris-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/paragraflabs/at-ris-mcp/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/at-ris-mcp.svg)](https://pypi.org/project/at-ris-mcp/)\n[![Python](https://img.shields.io/pypi/pyversions/at-ris-mcp.svg)](https://pypi.org/project/at-ris-mcp/)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n\nA generic **MCP server** and standalone **Python client library** for the\nAustrian **RIS** (Rechtsinformationssystem des Bundes), the official legal\ninformation system of the Republic of Austria, operated by the Bundeskanzleramt.\n\nIt covers **federal law** (Bundesrecht — including *consolidated* law `BrKons`,\nthe official gazettes, drafts and government bills), **state law** (Landesrecht\nof the nine Bundesländer), **case law** (Judikatur — OGH, VfGH, VwGH, BVwG,\nLVwG and more), ministerial decrees, district and municipal law, plus a\nchange-monitoring feed — via the keyless OGD API at\n`https://data.bka.gv.at/ris/api/v2.6/`.\n\n## Why this exists\n\nCompared with existing RIS tooling, `at-ris-mcp` adds:\n\n- **Consolidated law** (`BrKons`) — the currently applicable text, not just the\n  gazette novellas.\n- **Section-precise access** — retrieve a single `§`/Artikel/Anlage\n  (`Abschnitt.*`).\n- **Historical version** — the law as it stood on a given date\n  (`Fassung.FassungVom`).\n- **Clean Markdown** — RIS HTML (≈40 KB of CSS boilerplate per document) is\n  stripped to the legal text, with a `raw` switch for the untouched original.\n\n## Two packages, one repo\n\n- **`ris_client`** — a standalone, MCP-independent library. Import it directly.\n- **`ris_mcp`** — a thin FastMCP/stdio wrapper exposing 10 tools. Contains no\n  logic of its own.\n\n## Install\n\n```bash\npip install at-ris-mcp          # library only\npip install \"at-ris-mcp[mcp]\"   # + the MCP server (FastMCP)\n```\n\n## Run the MCP server (stdio)\n\n```bash\nat-ris-mcp\n# or\npython -m ris_mcp\n```\n\n### Remote transport (HTTP / SSE)\n\nFor hosted or remote deployments the server can also speak streamable HTTP or\nSSE instead of stdio:\n\n```bash\nat-ris-mcp --transport http --host 0.0.0.0 --port 8000   # streamable HTTP\nat-ris-mcp --transport sse  --port 9000                  # SSE\n# or via environment:\nRIS_MCP_TRANSPORT=http RIS_MCP_PORT=8000 at-ris-mcp\n```\n\nThe HTTP endpoint is served at `/mcp` by default (override with `--path` /\n`RIS_MCP_PATH`). stdio remains the default when no transport is given.\n\n### Tools\n\n| Tool | Purpose |\n|---|---|\n| `ris_search_law` | Search Bundesrecht (default `BrKons`; also `BgblAuth`, `Begut`, `RegV`, …). Section + Fassung filters. |\n| `ris_get_law_text` | Full text of a statute/section (markdown \\| html \\| xml \\| raw). |\n| `ris_search_case` | Search Judikatur (default `Justiz`; all courts). Filter by applied `norm`. |\n| `ris_get_case_text` | Full text of a decision. |\n| `ris_search_state_law` | Search Landesrecht (9 Bundesländer; default `LrKons`). Select states via `bundeslaender`. |\n| `ris_search_misc` | Search `Sonstige` (ministerial decrees `Erlaesse`, `Avsv`, …). |\n| `ris_search_district` | Search district authority notices (`Bezirke` / `Bvb`). |\n| `ris_search_municipality` | Search municipal law (`Gemeinden` / Gemeinderecht `Gr`/`GrA`). |\n| `ris_list_collections` | Which endpoints/applications are covered. |\n| `ris_list_changes` | Change/early-warning feed (RIS History) via the OGD SOAP endpoint, incl. deleted documents. |\n\n## Library usage\n\n```python\nimport asyncio\nfrom ris_client import RisClient, LawSearchRequest, TextFormat\n\nasync def main():\n    async with RisClient() as c:\n        res = await c.search_law(LawSearchRequest(suchworte=\"Datenschutzgesetz\",\n                                                  page_size=\"Ten\"))\n        hit = res.items[0]\n        print(hit.human_readable_citation, hit.eli_uri)\n        text = await c.get_text(hit.content_urls[\"html\"], TextFormat.markdown)\n        print(text.content[:500])\n\nasyncio.run(main())\n```\n\n## Configuration (environment variables)\n\n| Variable | Default | Meaning |\n|---|---|---|\n| `RIS_BASE_URL` | `https://data.bka.gv.at/ris/api/v2.6` | API base (version isolation). |\n| `RIS_SOAP_URL` | `https://data.bka.gv.at/ris/ogd/v2.6/` | OGD SOAP endpoint (used by `ris_list_changes`). |\n| `RIS_USER_AGENT` | `at-ris-mcp/<version> (+…)` | Descriptive UA (netiquette). |\n| `RIS_RATE_MS` | `1200` | Minimum delay between requests (ms). |\n| `RIS_TIMEOUT_S` | `30` | HTTP timeout. |\n| `RIS_MAX_RETRIES` | `3` | Retries on 429/5xx (incl. 503). |\n| `RIS_CACHE_DIR` | `~/.cache/at-ris-mcp` | SQLite cache location. |\n| `RIS_CACHE_ENABLED` | `true` | Toggle the cache. |\n| `RIS_AUDIT_DIR` | *(unset)* | If set, append a JSONL audit line per call (no full text, no client data). |\n| `RIS_MCP_TRANSPORT` | `stdio` | Server transport: `stdio` \\| `http` \\| `sse` \\| `streamable-http`. |\n| `RIS_MCP_HOST` | `127.0.0.1` | Bind host for http/sse. |\n| `RIS_MCP_PORT` | `8000` | Bind port for http/sse. |\n| `RIS_MCP_PATH` | *(transport default)* | URL path for the HTTP endpoint. |\n\n## Netiquette & rate limiting\n\nPer the RIS OGD FAQ: a 1–2 s pause per page is enforced by the client; bulk\naccess should occur outside office hours (18:00–06:00) or on weekends and be\nannounced to `ris.it@bka.gv.at`. A descriptive User-Agent is sent by default.\n\n## Licensing\n\n- **Code:** Apache-2.0 (see `LICENSE`).\n- **Data:** the retrieved documents are provided by the Republic of Austria\n  under **CC BY 4.0**. Every tool response carries an `attribution` field:\n\n  > Quelle: RIS – Rechtsinformationssystem des Bundes (data.bka.gv.at), CC BY 4.0\n\n- **No legal advice.** Only the authentic promulgation text\n  (Bundesgesetzblatt/Landesgesetzblatt authentisch) is legally binding.\n  Consolidated law and all other documents are for information only. Every\n  response carries a `legal_notice` to that effect.\n\n## Scope (v1.0)\n\nCovered: `Bundesrecht` (`BrKons`, `BgblAuth`, `BgblPdf`, `BgblAlt`, `Begut`,\n`RegV`, `Erv` — English translations), `Judikatur` (all courts), the **History\nchange-feed** (`ris_list_changes`, incl. deleted documents), **Landesrecht**\n(9 Bundesländer: `LrKons`, `LgblAuth`, `Lgbl`, `LgblNO`, `Vbl`), **Sonstige**\n(`Erlaesse`, `Avsv`, `Avn`, `Spg`, `KmGer`, `Upts`, `Mrp`, `PruefGewO` — with\napp-specific fine filters), **Bezirke** (`Bvb`) and **Gemeinden** (`Gr`, `GrA`).\n\n> **English translations (`Erv`):** search via `ris_search_law` with\n> `applikation=\"Erv\"`. `suchworte`/`titel` map to the RIS `SearchTerms`/`Title`\n> parameters automatically.\n\n> **State-law note:** for consolidated state law (`LrKons`), select the states\n> via `bundeslaender` (e.g. `[\"Kaernten\",\"Tirol\"]`); this maps to the dotted\n> `Bundesland.SucheIn<Land>=true` flags the API requires (the flat form is\n> silently ignored for `LrKons`).\n\n> **History note:** consolidated federal law is monitored under the application\n> name `Bundesnormen` (not `BrKons`), consolidated state law under\n> `Landesnormen`. The History query uses the OGD **SOAP** endpoint, since it is\n> not exposed via the REST GET API.\n\n## Development\n\n```bash\npip install -e \".[dev,mcp]\"\npytest                       # offline tests\nRIS_SMOKE=1 pytest -m smoke  # live smoke tests against the real API\n```\n\n## Release\n\nReleases are automated. Pushing a version tag (`vX.Y.Z`) triggers GitHub\nActions to build the distributions, publish to **PyPI** (via Trusted\nPublishing / OIDC — no API token), create a **GitHub Release**, and register\nthe new version in the **MCP Registry**.\n\n```bash\n# bump the version in pyproject.toml, src/ris_client/config.py and server.json,\n# update CHANGELOG.md, then:\ngit tag -a vX.Y.Z -m \"vX.Y.Z\"\ngit push origin vX.Y.Z\n```\n\nTo build locally without publishing:\n\n```bash\npython -m build              # sdist + wheel into dist/\npython -m twine check dist/*\n```\n\nThe MCP-registry entry is described by `server.json`\n(name `io.github.paragraflabs/at-ris-mcp`); the matching `mcp-name:` marker is\nembedded near the top of this README.\n\n## Contributing & support\n\nIssues and pull requests are welcome at\n<https://github.com/paragraflabs/at-ris-mcp>. See [`CHANGELOG.md`](CHANGELOG.md)\nfor the release history. This project is not affiliated with or endorsed by the\nRepublic of Austria or the Bundeskanzleramt; it is an independent client for the\npublic RIS OGD interface.\n\n",
  "bytes": 8415,
  "sha": "5134ad707c5d1b39f0ef4edd775fe0331800a4752ecdd310831acd8f85dde95c",
  "repo_slug": "paragraflabs/at-ris-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_paragraflabs_at_ris_mcp_023fe9b4/readme"
}