ris-mcp 0.2.0__tar.gz
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.
- ris_mcp-0.2.0/.github/workflows/ci.yml +13 -0
- ris_mcp-0.2.0/.github/workflows/release.yml +28 -0
- ris_mcp-0.2.0/.gitignore +14 -0
- ris_mcp-0.2.0/.python-version +1 -0
- ris_mcp-0.2.0/DATA_LICENSE +5 -0
- ris_mcp-0.2.0/LICENSE +21 -0
- ris_mcp-0.2.0/PKG-INFO +76 -0
- ris_mcp-0.2.0/README.md +54 -0
- ris_mcp-0.2.0/docs/index.html +227 -0
- ris_mcp-0.2.0/docs/publishing-the-dataset.md +53 -0
- ris_mcp-0.2.0/docs/stats.json +14 -0
- ris_mcp-0.2.0/docs/superpowers/plans/2026-04-15-ris-mcp-phase1.5-distribution.md +1090 -0
- ris_mcp-0.2.0/docs/superpowers/plans/2026-04-15-ris-mcp-phase1.md +2167 -0
- ris_mcp-0.2.0/docs/superpowers/specs/2026-04-15-ris-mcp-phase1-design.md +360 -0
- ris_mcp-0.2.0/docs/superpowers/specs/2026-04-15-ris-mcp-phase1.5-distribution-design.md +176 -0
- ris_mcp-0.2.0/pyproject.toml +45 -0
- ris_mcp-0.2.0/src/ris_mcp/__init__.py +1 -0
- ris_mcp-0.2.0/src/ris_mcp/applikation.py +47 -0
- ris_mcp-0.2.0/src/ris_mcp/cli.py +100 -0
- ris_mcp-0.2.0/src/ris_mcp/client.py +452 -0
- ris_mcp-0.2.0/src/ris_mcp/coverage.py +37 -0
- ris_mcp-0.2.0/src/ris_mcp/hf_import.py +58 -0
- ris_mcp-0.2.0/src/ris_mcp/ingest.py +105 -0
- ris_mcp-0.2.0/src/ris_mcp/ingest_bundesrecht.py +38 -0
- ris_mcp-0.2.0/src/ris_mcp/schema.sql +80 -0
- ris_mcp-0.2.0/src/ris_mcp/server.py +50 -0
- ris_mcp-0.2.0/src/ris_mcp/store.py +102 -0
- ris_mcp-0.2.0/src/ris_mcp/tools/__init__.py +0 -0
- ris_mcp-0.2.0/src/ris_mcp/tools/get_decision.py +68 -0
- ris_mcp-0.2.0/src/ris_mcp/tools/get_law.py +49 -0
- ris_mcp-0.2.0/src/ris_mcp/tools/search_decisions.py +82 -0
- ris_mcp-0.2.0/tests/__init__.py +0 -0
- ris_mcp-0.2.0/tests/conftest.py +16 -0
- ris_mcp-0.2.0/tests/fixtures/bundesrecht_search_page1.json +1 -0
- ris_mcp-0.2.0/tests/fixtures/bvwg_search_page1.json +1 -0
- ris_mcp-0.2.0/tests/fixtures/vfgh_search_page1.json +1 -0
- ris_mcp-0.2.0/tests/test_applikation.py +35 -0
- ris_mcp-0.2.0/tests/test_cli.py +28 -0
- ris_mcp-0.2.0/tests/test_client.py +161 -0
- ris_mcp-0.2.0/tests/test_coverage.py +64 -0
- ris_mcp-0.2.0/tests/test_e2e_smoke.py +35 -0
- ris_mcp-0.2.0/tests/test_get_decision.py +42 -0
- ris_mcp-0.2.0/tests/test_get_law.py +33 -0
- ris_mcp-0.2.0/tests/test_hf_import.py +79 -0
- ris_mcp-0.2.0/tests/test_ingest.py +73 -0
- ris_mcp-0.2.0/tests/test_ingest_bundesrecht.py +49 -0
- ris_mcp-0.2.0/tests/test_search_decisions.py +56 -0
- ris_mcp-0.2.0/tests/test_store.py +81 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push: { branches: [main, master] }
|
|
4
|
+
pull_request:
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v4
|
|
10
|
+
- uses: astral-sh/setup-uv@v3
|
|
11
|
+
- run: uv venv && uv pip install -e ".[dev]"
|
|
12
|
+
- run: uv run ruff check src tests
|
|
13
|
+
- run: uv run pytest -v
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ['v*']
|
|
5
|
+
jobs:
|
|
6
|
+
build:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v4
|
|
10
|
+
- uses: astral-sh/setup-uv@v3
|
|
11
|
+
- run: uv build
|
|
12
|
+
- uses: actions/upload-artifact@v4
|
|
13
|
+
with:
|
|
14
|
+
name: dist
|
|
15
|
+
path: dist/
|
|
16
|
+
|
|
17
|
+
publish:
|
|
18
|
+
needs: build
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
environment: pypi
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/download-artifact@v4
|
|
25
|
+
with:
|
|
26
|
+
name: dist
|
|
27
|
+
path: dist/
|
|
28
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
ris_mcp-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
The data ingested by this software from the Austrian Rechtsinformationssystem
|
|
2
|
+
(RIS, https://www.ris.bka.gv.at) consists of amtliche Werke within the meaning
|
|
3
|
+
of § 7 öUrhG and is in the public domain. Any redistribution of such data by
|
|
4
|
+
projects using this software is dedicated to the public domain under
|
|
5
|
+
Creative Commons Zero v1.0 (CC0-1.0): https://creativecommons.org/publicdomain/zero/1.0/
|
ris_mcp-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jonas Hertner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ris_mcp-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ris-mcp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: MCP server for Austrian RIS (court decisions + federal law) backed by a local FTS5-indexed SQLite mirror
|
|
5
|
+
Author-email: Jonas Hertner <jonashertner@protonmail.ch>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
10
|
+
Requires-Dist: click>=8.1
|
|
11
|
+
Requires-Dist: httpx>=0.27
|
|
12
|
+
Requires-Dist: huggingface-hub>=0.24
|
|
13
|
+
Requires-Dist: lxml>=5.0
|
|
14
|
+
Requires-Dist: mcp>=1.2
|
|
15
|
+
Requires-Dist: pydantic>=2.7
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
19
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
20
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# ris-mcp
|
|
24
|
+
|
|
25
|
+
> **👉 For end users: see [jonashertner.github.io/ris-mcp](https://jonashertner.github.io/ris-mcp/) for the three-command install.**
|
|
26
|
+
|
|
27
|
+
Local MCP server for the Austrian Rechtsinformationssystem (RIS) — court decisions and consolidated federal law, queryable from Claude (Code, Desktop, claude.ai).
|
|
28
|
+
|
|
29
|
+
[](https://github.com/jonashertner/ris-mcp/actions/workflows/ci.yml)
|
|
30
|
+
|
|
31
|
+
## What
|
|
32
|
+
|
|
33
|
+
`ris-mcp` maintains a locally-mirrored, FTS5-indexed SQLite copy of the full Austrian RIS corpus and exposes it to Claude via MCP. Compare to [`philrox/ris-mcp-ts`](https://github.com/philrox/ris-mcp-ts), which is a thin live-API proxy: local mirror wins on search quality, latency, offline capability, and future citation-graph/reranking work.
|
|
34
|
+
|
|
35
|
+
## Install (users)
|
|
36
|
+
|
|
37
|
+
See the [landing page](https://jonashertner.github.io/ris-mcp/).
|
|
38
|
+
|
|
39
|
+
## Develop (contributors)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/jonashertner/ris-mcp.git
|
|
43
|
+
cd ris-mcp
|
|
44
|
+
uv venv && uv pip install -e ".[dev]"
|
|
45
|
+
.venv/bin/pytest -v
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Run the MCP server locally:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
.venv/bin/ris-mcp serve
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Kick off a full backfill (2–3 days):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
.venv/bin/ris-ingest --full
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Emit coverage stats:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
.venv/bin/ris-ingest coverage --out docs/stats.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Licenses
|
|
67
|
+
|
|
68
|
+
- Code: MIT
|
|
69
|
+
- Data: CC0-1.0 (amtliches Werk per § 7 öUrhG)
|
|
70
|
+
|
|
71
|
+
## Credits
|
|
72
|
+
|
|
73
|
+
- [ximex/ris-bka](https://github.com/ximex/ris-bka) — RIS OGD documentation
|
|
74
|
+
- [philrox/ris-mcp-ts](https://github.com/philrox/ris-mcp-ts) — different design, same goal
|
|
75
|
+
- [PhilippTh/ris-API-wrapper](https://github.com/PhilippTh/ris-API-wrapper) — Python wrapper precedent
|
|
76
|
+
- [opencaselaw.ch](https://opencaselaw.ch) — architectural inspiration
|
ris_mcp-0.2.0/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# ris-mcp
|
|
2
|
+
|
|
3
|
+
> **👉 For end users: see [jonashertner.github.io/ris-mcp](https://jonashertner.github.io/ris-mcp/) for the three-command install.**
|
|
4
|
+
|
|
5
|
+
Local MCP server for the Austrian Rechtsinformationssystem (RIS) — court decisions and consolidated federal law, queryable from Claude (Code, Desktop, claude.ai).
|
|
6
|
+
|
|
7
|
+
[](https://github.com/jonashertner/ris-mcp/actions/workflows/ci.yml)
|
|
8
|
+
|
|
9
|
+
## What
|
|
10
|
+
|
|
11
|
+
`ris-mcp` maintains a locally-mirrored, FTS5-indexed SQLite copy of the full Austrian RIS corpus and exposes it to Claude via MCP. Compare to [`philrox/ris-mcp-ts`](https://github.com/philrox/ris-mcp-ts), which is a thin live-API proxy: local mirror wins on search quality, latency, offline capability, and future citation-graph/reranking work.
|
|
12
|
+
|
|
13
|
+
## Install (users)
|
|
14
|
+
|
|
15
|
+
See the [landing page](https://jonashertner.github.io/ris-mcp/).
|
|
16
|
+
|
|
17
|
+
## Develop (contributors)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/jonashertner/ris-mcp.git
|
|
21
|
+
cd ris-mcp
|
|
22
|
+
uv venv && uv pip install -e ".[dev]"
|
|
23
|
+
.venv/bin/pytest -v
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Run the MCP server locally:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
.venv/bin/ris-mcp serve
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Kick off a full backfill (2–3 days):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
.venv/bin/ris-ingest --full
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Emit coverage stats:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
.venv/bin/ris-ingest coverage --out docs/stats.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Licenses
|
|
45
|
+
|
|
46
|
+
- Code: MIT
|
|
47
|
+
- Data: CC0-1.0 (amtliches Werk per § 7 öUrhG)
|
|
48
|
+
|
|
49
|
+
## Credits
|
|
50
|
+
|
|
51
|
+
- [ximex/ris-bka](https://github.com/ximex/ris-bka) — RIS OGD documentation
|
|
52
|
+
- [philrox/ris-mcp-ts](https://github.com/philrox/ris-mcp-ts) — different design, same goal
|
|
53
|
+
- [PhilippTh/ris-API-wrapper](https://github.com/PhilippTh/ris-API-wrapper) — Python wrapper precedent
|
|
54
|
+
- [opencaselaw.ch](https://opencaselaw.ch) — architectural inspiration
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>ris-mcp — Austrian RIS inside Claude</title>
|
|
7
|
+
<meta name="description" content="Local MCP server for Austrian court decisions and federal law. 700k+ decisions, fully offline, queryable from Claude." />
|
|
8
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚖️</text></svg>" />
|
|
10
|
+
</head>
|
|
11
|
+
<body class="bg-slate-50 text-slate-900 font-sans antialiased">
|
|
12
|
+
|
|
13
|
+
<header class="border-b border-slate-200 bg-white">
|
|
14
|
+
<div class="max-w-5xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
15
|
+
<div class="flex items-center gap-3">
|
|
16
|
+
<span class="text-2xl">⚖️</span>
|
|
17
|
+
<span class="font-semibold">ris-mcp</span>
|
|
18
|
+
</div>
|
|
19
|
+
<nav class="flex gap-6 text-sm">
|
|
20
|
+
<a href="#install" class="hover:text-slate-600">Install</a>
|
|
21
|
+
<a href="#stats" class="hover:text-slate-600">Stats</a>
|
|
22
|
+
<a href="#roadmap" class="hover:text-slate-600">Roadmap</a>
|
|
23
|
+
<a href="https://github.com/jonashertner/ris-mcp" class="hover:text-slate-600">GitHub</a>
|
|
24
|
+
</nav>
|
|
25
|
+
</div>
|
|
26
|
+
</header>
|
|
27
|
+
|
|
28
|
+
<section class="max-w-5xl mx-auto px-6 py-20">
|
|
29
|
+
<h1 class="text-4xl md:text-5xl font-bold tracking-tight">Austrian case law + federal statutes, inside Claude.</h1>
|
|
30
|
+
<p class="mt-6 text-lg text-slate-600 max-w-3xl">
|
|
31
|
+
<code>ris-mcp</code> is a local MCP server that mirrors the Austrian Rechtsinformationssystem
|
|
32
|
+
(RIS) into a searchable SQLite database, so Claude (Desktop, Code, claude.ai) can answer
|
|
33
|
+
legal-research questions against the full corpus of published Austrian court decisions and
|
|
34
|
+
consolidated federal law. Free, open, CC0 data.
|
|
35
|
+
</p>
|
|
36
|
+
<div class="mt-10 flex flex-wrap gap-3">
|
|
37
|
+
<a href="#install" class="bg-slate-900 text-white px-5 py-3 rounded-lg font-medium hover:bg-slate-800">Install</a>
|
|
38
|
+
<a href="https://github.com/jonashertner/ris-mcp" class="border border-slate-300 px-5 py-3 rounded-lg font-medium hover:border-slate-400">GitHub</a>
|
|
39
|
+
</div>
|
|
40
|
+
</section>
|
|
41
|
+
|
|
42
|
+
<section class="max-w-5xl mx-auto px-6 py-12 grid md:grid-cols-3 gap-8">
|
|
43
|
+
<div>
|
|
44
|
+
<div class="text-3xl">🏛️</div>
|
|
45
|
+
<h2 class="mt-3 font-semibold">All published case law</h2>
|
|
46
|
+
<p class="mt-2 text-slate-600 text-sm">OGH, VfGH, VwGH, BVwG, 9 Landesverwaltungsgerichte, and special-body decisions — every judikatur source RIS publishes.</p>
|
|
47
|
+
</div>
|
|
48
|
+
<div>
|
|
49
|
+
<div class="text-3xl">📚</div>
|
|
50
|
+
<h2 class="mt-3 font-semibold">Consolidated federal law</h2>
|
|
51
|
+
<p class="mt-2 text-slate-600 text-sm">Every § and Artikel of Austrian Bundesrecht in its current Fassung, searchable alongside the case law that applies it.</p>
|
|
52
|
+
</div>
|
|
53
|
+
<div>
|
|
54
|
+
<div class="text-3xl">⚡</div>
|
|
55
|
+
<h2 class="mt-3 font-semibold">Sub-ms local search</h2>
|
|
56
|
+
<p class="mt-2 text-slate-600 text-sm">SQLite + FTS5 BM25 ranking. Your queries never leave your machine. Works offline.</p>
|
|
57
|
+
</div>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<section id="install" class="max-w-5xl mx-auto px-6 py-16 border-t border-slate-200">
|
|
61
|
+
<h2 class="text-3xl font-bold">Install</h2>
|
|
62
|
+
|
|
63
|
+
<!-- HF-DATASET-PENDING -->
|
|
64
|
+
<div class="mt-6 bg-amber-50 border border-amber-200 rounded-lg p-4 text-sm">
|
|
65
|
+
<strong>Status:</strong> the pre-built dataset is being uploaded (full backfill takes 2–3 days).
|
|
66
|
+
Until it lands on HuggingFace, step 3 below will fail with a friendly message telling you
|
|
67
|
+
to run <code>ris-ingest --full</code> locally. Watch the <a href="#stats" class="underline">stats</a> section for updates.
|
|
68
|
+
</div>
|
|
69
|
+
<!-- /HF-DATASET-PENDING -->
|
|
70
|
+
|
|
71
|
+
<ol class="mt-8 space-y-6 text-slate-800">
|
|
72
|
+
<li>
|
|
73
|
+
<div class="font-medium">1. Install <code>uv</code> (the Python package runner).</div>
|
|
74
|
+
<pre class="mt-2 bg-slate-900 text-slate-100 rounded-lg p-4 text-sm overflow-x-auto"><code>curl -LsSf https://astral.sh/uv/install.sh | sh</code></pre>
|
|
75
|
+
<p class="text-sm text-slate-500 mt-1">See <a class="underline" href="https://docs.astral.sh/uv/">docs.astral.sh/uv</a> for Windows instructions.</p>
|
|
76
|
+
</li>
|
|
77
|
+
<li>
|
|
78
|
+
<div class="font-medium">2. Register the MCP server with Claude.</div>
|
|
79
|
+
<pre class="mt-2 bg-slate-900 text-slate-100 rounded-lg p-4 text-sm overflow-x-auto"><code>claude mcp add ris -- uvx --from git+https://github.com/jonashertner/ris-mcp ris-mcp serve</code></pre>
|
|
80
|
+
<p class="text-sm text-slate-500 mt-1">After <code>ris-mcp</code> is published on PyPI, this simplifies to <code>uvx ris-mcp serve</code>.</p>
|
|
81
|
+
</li>
|
|
82
|
+
<li>
|
|
83
|
+
<div class="font-medium">3. Download the pre-built corpus (one-time, ~12 GB).</div>
|
|
84
|
+
<pre class="mt-2 bg-slate-900 text-slate-100 rounded-lg p-4 text-sm overflow-x-auto"><code>uvx --from git+https://github.com/jonashertner/ris-mcp ris-ingest import-from-hf</code></pre>
|
|
85
|
+
<p class="text-sm text-slate-500 mt-1">Or run your own ingest with <code>ris-ingest --full</code> (2–3 days).</p>
|
|
86
|
+
</li>
|
|
87
|
+
</ol>
|
|
88
|
+
|
|
89
|
+
<h3 class="mt-10 text-xl font-semibold">Claude Desktop config</h3>
|
|
90
|
+
<p class="text-sm text-slate-600 mt-2">If you'd rather hand-edit <code>~/Library/Application Support/Claude/claude_desktop_config.json</code>:</p>
|
|
91
|
+
<pre class="mt-3 bg-slate-900 text-slate-100 rounded-lg p-4 text-sm overflow-x-auto"><code>{
|
|
92
|
+
"mcpServers": {
|
|
93
|
+
"ris": {
|
|
94
|
+
"command": "uvx",
|
|
95
|
+
"args": ["--from", "git+https://github.com/jonashertner/ris-mcp", "ris-mcp", "serve"]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}</code></pre>
|
|
99
|
+
</section>
|
|
100
|
+
|
|
101
|
+
<section class="max-w-5xl mx-auto px-6 py-16 border-t border-slate-200">
|
|
102
|
+
<h2 class="text-3xl font-bold">Why not <code>philrox/ris-mcp-ts</code>?</h2>
|
|
103
|
+
<p class="mt-4 text-slate-600 max-w-3xl">A legitimate TypeScript MCP wrapper for RIS already exists. It's a great fit for casual queries. <code>ris-mcp</code> is a different trade-off: build and maintain a local mirror so you get better answers.</p>
|
|
104
|
+
<div class="mt-8 overflow-x-auto">
|
|
105
|
+
<table class="w-full text-sm border border-slate-200 rounded-lg overflow-hidden">
|
|
106
|
+
<thead class="bg-slate-100 text-left">
|
|
107
|
+
<tr><th class="p-3">Capability</th><th class="p-3">philrox (live proxy)</th><th class="p-3">ris-mcp (local mirror)</th></tr>
|
|
108
|
+
</thead>
|
|
109
|
+
<tbody class="divide-y divide-slate-200">
|
|
110
|
+
<tr><td class="p-3">Claude can query Austrian law</td><td class="p-3">✅</td><td class="p-3">✅</td></tr>
|
|
111
|
+
<tr><td class="p-3">Search quality</td><td class="p-3">RIS field-based keyword</td><td class="p-3">FTS5 BM25 over full text</td></tr>
|
|
112
|
+
<tr><td class="p-3">Latency</td><td class="p-3">2–5 s per query</td><td class="p-3">< 10 ms</td></tr>
|
|
113
|
+
<tr><td class="p-3">Works offline</td><td class="p-3">❌</td><td class="p-3">✅</td></tr>
|
|
114
|
+
<tr><td class="p-3">Survives RIS API outages</td><td class="p-3">❌</td><td class="p-3">✅</td></tr>
|
|
115
|
+
<tr><td class="p-3">Citation graph (future)</td><td class="p-3">❌</td><td class="p-3">Phase 2</td></tr>
|
|
116
|
+
</tbody>
|
|
117
|
+
</table>
|
|
118
|
+
</div>
|
|
119
|
+
</section>
|
|
120
|
+
|
|
121
|
+
<section id="stats" class="max-w-5xl mx-auto px-6 py-16 border-t border-slate-200">
|
|
122
|
+
<h2 class="text-3xl font-bold">Corpus</h2>
|
|
123
|
+
<div id="stats-loading" class="mt-4 text-slate-500 text-sm">Loading stats…</div>
|
|
124
|
+
<div id="stats-body" class="mt-6 hidden">
|
|
125
|
+
<div class="grid md:grid-cols-3 gap-6">
|
|
126
|
+
<div class="bg-white border border-slate-200 rounded-lg p-5">
|
|
127
|
+
<div class="text-sm text-slate-500">Decisions</div>
|
|
128
|
+
<div id="stats-decisions" class="text-4xl font-bold mt-1">—</div>
|
|
129
|
+
</div>
|
|
130
|
+
<div class="bg-white border border-slate-200 rounded-lg p-5">
|
|
131
|
+
<div class="text-sm text-slate-500">Laws (articles)</div>
|
|
132
|
+
<div id="stats-laws" class="text-4xl font-bold mt-1">—</div>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="bg-white border border-slate-200 rounded-lg p-5">
|
|
135
|
+
<div class="text-sm text-slate-500">Last refreshed</div>
|
|
136
|
+
<div id="stats-refreshed" class="text-lg font-medium mt-1">—</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
<h3 class="mt-10 font-semibold">By court</h3>
|
|
140
|
+
<div id="stats-by-court" class="mt-3 grid md:grid-cols-3 gap-2 text-sm"></div>
|
|
141
|
+
</div>
|
|
142
|
+
</section>
|
|
143
|
+
|
|
144
|
+
<section id="roadmap" class="max-w-5xl mx-auto px-6 py-16 border-t border-slate-200">
|
|
145
|
+
<h2 class="text-3xl font-bold">Roadmap</h2>
|
|
146
|
+
<ul class="mt-6 space-y-3 text-slate-700">
|
|
147
|
+
<li>✅ <strong>Phase 1</strong> — ingester, SQLite/FTS5 store, three MCP tools.</li>
|
|
148
|
+
<li>🚧 <strong>Phase 1.5</strong> — PyPI release, public landing page, pre-built HF dataset.</li>
|
|
149
|
+
<li>🔜 <strong>Phase 2</strong> — resolved citation graph: find_leading_cases, find_citations, find_appeal_chain.</li>
|
|
150
|
+
<li>🔜 <strong>Phase 3</strong> — semantic reranking and a remote hosted MCP endpoint (no local install).</li>
|
|
151
|
+
<li>🔜 <strong>Phase 4</strong> — Materialien: RV-Begründungen and Stenographische Protokolle for teleological interpretation.</li>
|
|
152
|
+
<li>🔜 <strong>Phase 5</strong> — Landesrecht, commentary integration if viable.</li>
|
|
153
|
+
</ul>
|
|
154
|
+
</section>
|
|
155
|
+
|
|
156
|
+
<footer class="border-t border-slate-200 mt-16">
|
|
157
|
+
<div class="max-w-5xl mx-auto px-6 py-10 text-sm text-slate-600">
|
|
158
|
+
<p>
|
|
159
|
+
Code: MIT. Data: CC0-1.0 — Austrian RIS content is amtliches Werk per § 7 öUrhG.
|
|
160
|
+
Not legal advice. Builds on the documentation work of
|
|
161
|
+
<a class="underline" href="https://github.com/ximex/ris-bka">ximex/ris-bka</a>,
|
|
162
|
+
learns from
|
|
163
|
+
<a class="underline" href="https://github.com/philrox/ris-mcp-ts">philrox/ris-mcp-ts</a>,
|
|
164
|
+
<a class="underline" href="https://github.com/PhilippTh/ris-API-wrapper">PhilippTh/ris-API-wrapper</a>, and
|
|
165
|
+
<a class="underline" href="https://opencaselaw.ch">opencaselaw.ch</a>.
|
|
166
|
+
</p>
|
|
167
|
+
</div>
|
|
168
|
+
</footer>
|
|
169
|
+
|
|
170
|
+
<script>
|
|
171
|
+
(async () => {
|
|
172
|
+
const loading = document.getElementById("stats-loading");
|
|
173
|
+
const body = document.getElementById("stats-body");
|
|
174
|
+
const courtsEl = document.getElementById("stats-by-court");
|
|
175
|
+
|
|
176
|
+
const makeRow = (court, count, fmt) => {
|
|
177
|
+
const row = document.createElement("div");
|
|
178
|
+
row.className = "flex justify-between bg-white border border-slate-200 rounded-lg p-3";
|
|
179
|
+
const name = document.createElement("span");
|
|
180
|
+
name.textContent = court;
|
|
181
|
+
const num = document.createElement("span");
|
|
182
|
+
num.className = "font-medium";
|
|
183
|
+
num.textContent = fmt(count);
|
|
184
|
+
row.appendChild(name);
|
|
185
|
+
row.appendChild(num);
|
|
186
|
+
return row;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const makeEmpty = (msg) => {
|
|
190
|
+
const d = document.createElement("div");
|
|
191
|
+
d.className = "text-slate-500";
|
|
192
|
+
d.textContent = msg;
|
|
193
|
+
return d;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const r = await fetch("stats.json", { cache: "no-cache" });
|
|
198
|
+
if (!r.ok) throw new Error("no stats");
|
|
199
|
+
const s = await r.json();
|
|
200
|
+
const fmt = (n) => (n || 0).toLocaleString("en-US");
|
|
201
|
+
|
|
202
|
+
document.getElementById("stats-decisions").textContent = fmt(s.total_decisions);
|
|
203
|
+
document.getElementById("stats-laws").textContent = fmt(s.total_laws);
|
|
204
|
+
const refreshed = s.generated_at
|
|
205
|
+
? s.generated_at.slice(0, 19).replace("T", " ") + " UTC"
|
|
206
|
+
: "—";
|
|
207
|
+
document.getElementById("stats-refreshed").textContent = refreshed;
|
|
208
|
+
|
|
209
|
+
const byCourt = s.decisions_by_court || {};
|
|
210
|
+
const entries = Object.entries(byCourt).sort((a, b) => b[1] - a[1]);
|
|
211
|
+
if (entries.length === 0) {
|
|
212
|
+
courtsEl.appendChild(makeEmpty("No decisions yet — backfill in progress."));
|
|
213
|
+
} else {
|
|
214
|
+
for (const [court, count] of entries) {
|
|
215
|
+
courtsEl.appendChild(makeRow(court, count, fmt));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
loading.classList.add("hidden");
|
|
220
|
+
body.classList.remove("hidden");
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loading.textContent = "Stats not available yet.";
|
|
223
|
+
}
|
|
224
|
+
})();
|
|
225
|
+
</script>
|
|
226
|
+
</body>
|
|
227
|
+
</html>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Publishing the pre-built ris-mcp dataset to HuggingFace
|
|
2
|
+
|
|
3
|
+
Run after the full backfill (`ris-ingest --full`) completes on any one machine.
|
|
4
|
+
|
|
5
|
+
## 1. Generate a fresh stats report
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ris-ingest coverage --out docs/stats.json
|
|
9
|
+
git add docs/stats.json
|
|
10
|
+
git commit -m "Refresh stats.json after backfill"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 2. Prepare the DB for upload
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
DB=~/.local/share/ris-mcp/ris.db
|
|
17
|
+
sqlite3 "$DB" "PRAGMA wal_checkpoint(TRUNCATE);"
|
|
18
|
+
shasum -a 256 "$DB" | tee "${DB}.sha256"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 3. Upload to HuggingFace
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
huggingface-cli login # one-time
|
|
25
|
+
huggingface-cli upload voilaj/austrian-caselaw "$DB" ris.db
|
|
26
|
+
huggingface-cli upload voilaj/austrian-caselaw "${DB}.sha256" ris.db.sha256
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If the repo does not exist, first:
|
|
30
|
+
`huggingface-cli repo create austrian-caselaw --type dataset --organization voilaj`.
|
|
31
|
+
|
|
32
|
+
## 4. Write a dataset card
|
|
33
|
+
|
|
34
|
+
Manually edit `README.md` on the HF repo (web UI). Include:
|
|
35
|
+
- Source: Austrian RIS Web Service v2.6 (data.bka.gv.at)
|
|
36
|
+
- License: CC0-1.0 (amtliches Werk per § 7 öUrhG)
|
|
37
|
+
- Schema reference: this repo's `src/ris_mcp/schema.sql`
|
|
38
|
+
- How to use: `pip install ris-mcp && ris-ingest import-from-hf`
|
|
39
|
+
|
|
40
|
+
## 5. Remove "coming soon" banners from the landing page
|
|
41
|
+
|
|
42
|
+
In `docs/index.html`, search for `<!-- HF-DATASET-PENDING -->` and remove each marked block (2 places). Commit:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git commit -m "Announce HF dataset availability"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 6. Tag a docs-only release
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git tag -a v0.2.1 -m "Pre-built dataset now available on HuggingFace"
|
|
52
|
+
git push origin v0.2.1
|
|
53
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated_at": "2026-04-15T22:04:07Z",
|
|
3
|
+
"total_decisions": 3200,
|
|
4
|
+
"total_laws": 0,
|
|
5
|
+
"decisions_by_court": {
|
|
6
|
+
"Justiz": 3200
|
|
7
|
+
},
|
|
8
|
+
"corpus_span": {
|
|
9
|
+
"earliest": "2025-09-29",
|
|
10
|
+
"latest": "2026-03-25"
|
|
11
|
+
},
|
|
12
|
+
"last_aenderungsdatum": "2026-04-15",
|
|
13
|
+
"schema_version": 1
|
|
14
|
+
}
|