Server data from the Official MCP Registry
956k Swiss court decisions: full-text search, citation graph, statute lookup (DE/FR/IT)
956k Swiss court decisions: full-text search, citation graph, statute lookup (DE/FR/IT)
Remote endpoints: sse: https://mcp.opencaselaw.ch
This is a well-structured MCP server for Swiss legal case law search with proper authentication patterns and appropriate permissions for its purpose. Minor concerns include broad exception handling and the use of `exec()` for code evaluation, but these don't significantly impact security as they're in appropriate contexts for the server's legal research functionality. Supply chain analysis found 9 known vulnerabilities in dependencies (1 critical, 4 high severity).
4 files analyzed · 12 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Available as Local & Remote
This plugin can run on your machine or connect to a hosted endpoint. during install.
From the project's GitHub README.
The complete machine-readable archive of Swiss case law and legislation — built for humans, designed for AI agents.
965,000+ court decisions · ~5,500 federal laws · ~26,000 cantonal acts · 8.8 M citation links · 11.3 M statute references · 1,100+ Botschaften (legislative history)
Spans 1875 to today, covers every Swiss federal court and all 26 cantonal court systems (plus regulators: FINMA, ComCo, FDPIC, IndepBC, ElCom, PostCom, ComCom), mirrors the full Fedlex and LexFind legislation corpora, includes the legislative history (Botschaft references and parliamentary debate transcripts) for 2,500+ federal laws, and ships with a resolved citation graph and 23 MCP tools usable from Claude, ChatGPT, Cursor, Gemini, Grok, or any MCP/function-calling client. CC0 public-domain data, MIT-licensed code, no sign-up, no API keys, no paywall.
Swiss legal research today is fragmented across paywalls, inaccessible to language models, and prohibitively expensive for the people who need it most — law students, independent researchers, and anyone outside the major firms. Commercial databases (Weblaw, Swisslex, Legalis) charge hundreds of francs per month and still don't expose a clean API. LLMs hallucinate statute text because they have no authoritative source. Small cantons publish decisions in PDF archives nobody indexes.
OpenCaseLaw fixes this. Every published Swiss court decision, every federal and cantonal law, the resolved citation graph between them, and 23 MCP tools that let any modern LLM act as a Swiss legal research assistant — all free, all open, all refreshed automatically.
Case law — 965,000+ decisions from 1875 to today, full text + structured metadata, covering:
rm for RomanshLegislation — every Swiss law, federal and cantonal, locally mirrored with article-level indexing:
Citation graph — the only public large-scale citation graph of the Swiss legal system:
find_leading_cases, find_citations, find_appeal_chain, analyze_legal_trend23 MCP tools — specialised research tools that run in your LLM of choice:
Multiple access paths — same data, two distinct audiences:
For LLM users, researchers and developers — full 23-tool surface:
mcp.opencaselaw.ch (SSE + Streamable HTTP) — 30-second setup in any MCP client (Claude, ChatGPT, Cursor, Gemini, Windsurf)For legal practitioners drafting documents — curated practitioner surface:
Performance you can defend in a paper:
| Metric | Value |
|---|---|
| Decision search quality | MRR@10 = 0.647 (online) / 0.470 (offline reproducible) · +102 % over baseline |
| Article lookup latency | < 1 ms (local FTS5) |
| BGer publication → searchable | ~15 min (was 24 h pre-poller) |
| Daily full-text rebuild | ~5 h, zero downtime (atomic swap) |
| Citation-to-decision resolution rate | 73.8 % (8.77 M / 11.89 M raw refs) |
A structured, searchable archive of Swiss court decisions — from the Federal Supreme Court (BGer) down to cantonal courts in all 26 cantons. Every decision includes the full decision text, docket number, date, language, legal area, judges, cited decisions, and 20+ additional metadata fields.
The dataset is built by direct scraping of official court websites and cantonal court portals. New decisions are scraped, deduplicated, and published every night.
There are eight ways to use it, depending on what you need:
| Method | For whom | What you get |
|---|---|---|
| Search with AI | Everyone | Natural-language search in Claude, ChatGPT, Cursor, or Gemini — instant access, no download, full 23-tool surface |
| Citation Analysis | Legal scholars, researchers | Leading cases, citation networks, appeal chains, jurisprudence trends over time |
| Statute Lookup | Legal professionals | Full article text from 5,000+ federal laws and 26,000+ cantonal acts, federated FTS5, sub-millisecond lookup |
| Legislation Search | Legal professionals | LexFind-backed discovery search with fetch_top_n_texts for single-call natural-language workflows |
| Education tools | Law students, instructors | Structured case briefs, doctrine timelines, real-BGE exam questions with hidden analysis |
| Word Add-in | Legal practitioners writing briefs | Insert formatted Swiss citations into Word · click Erwägung / § to insert with correct sub-reference · Pro: verify quotes against case text, find support, scan documents (curated ~8-tool subset) |
| REST API / Download | Developers, data scientists, NLP researchers | 30-route REST API, bulk Parquet download via HuggingFace (~7 GB) |
| Web UI | Everyone | Live dashboard with corpus stats, daily delta, top movers, multilingual browsing |
Not sure where to start? Connect to the remote MCP server — works with Claude, ChatGPT, and Gemini CLI. Instant access to all 965K+ decisions, citation analysis, statute lookup, legislation search, and education tools, no download needed.
The dataset comes with an MCP server whose exact tool surface is deployment-dependent. Local deployments can expose up to 23 tools; remote mode omits local update tools, and legislation tools depend on LexFind-backed configuration. You ask a question in natural language; the tool runs a full-text search and returns matching decisions with snippets.
| Remote | Local | |
|---|---|---|
| Setup | 30 seconds | 30–60 minutes |
| Disk | None | ~65 GB |
| Tools | Deployment-dependent; no local update tools | Up to 23, including update_database and check_update_status |
| Freshness | Nightly (automatic) | Manual |
| Offline | No | Yes |
| Requires | Claude, ChatGPT, or Gemini CLI (see plans below) | Any MCP client |
Start with the remote server. Switch to local only if you need offline access.
Connect directly to the hosted MCP server — no data download, no local database, instant access to 965K+ decisions.
Claude.ai / Claude Desktop (easiest):
https://mcp.opencaselaw.chSame steps in the browser (claude.ai) and the desktop app. No Node.js, no config files, no downloads.
Available on Pro, Max, Team, and Enterprise plans. For the free plan, use Claude Code or the manual JSON config.
Claude Code:
claude mcp add swiss-caselaw --transport sse https://mcp.opencaselaw.ch
Add to claude_desktop_config.json (Node.js required):
{
"mcpServers": {
"swiss-caselaw": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.opencaselaw.ch"]
}
}
}
Restart Claude Desktop after saving.
ChatGPT:
Swiss Caselaw, paste https://mcp.opencaselaw.ch/sse, auth: NoneAvailable on Plus, Pro, Team, Enterprise, and Edu plans. Recommended with GPT-5.3 (GPT-5.4 does not currently support MCP tool invocation).
Gemini CLI:
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"swiss-caselaw": {
"url": "https://mcp.opencaselaw.ch"
}
}
}
Restart Gemini CLI after saving. No account plan required — Gemini CLI is free.
Google ADK (Agent Development Kit):
Build a Gemini-powered agent with access to all tools:
from google.adk.agents import LlmAgent
from google.adk.tools import MCPToolset
from mcp.client.sse import SseConnectionParams
agent = LlmAgent(
model="gemini-3.1-pro",
name="swiss_law_agent",
instruction="You are a Swiss legal research assistant.",
tools=[
MCPToolset(
connection_params=SseConnectionParams(
url="https://mcp.opencaselaw.ch/sse",
),
),
],
)
See the full MCP setup guide for Google Gen AI SDK examples and all other platforms.
See the full MCP setup guide for detailed instructions for all platforms.
The
update_databaseandcheck_update_statustools are only available on the local server — the remote dataset is updated automatically every night.
Run the MCP server locally with your own copy of the database (~65 GB disk). This gives you offline access and full control over the data.
Claude Code is Anthropic's CLI for working with Claude in the terminal.
Step 1. Clone this repository:
git clone https://github.com/jonashertner/caselaw-repo-1.git
cd caselaw-repo-1
Step 2. Create a virtual environment and install the MCP server dependencies:
python3 -m venv .venv
# macOS / Linux
source .venv/bin/activate
pip install mcp pydantic huggingface-hub pyarrow fastapi
# Windows (PowerShell)
.venv\Scripts\Activate.ps1
pip install mcp pydantic huggingface-hub pyarrow
Step 3. Register the MCP server with Claude Code:
# macOS / Linux
claude mcp add swiss-caselaw -- /path/to/caselaw-repo-1/.venv/bin/python3 /path/to/caselaw-repo-1/mcp_server.py
# Windows
claude mcp add swiss-caselaw -- C:\path\to\caselaw-repo-1\.venv\Scripts\python.exe C:\path\to\caselaw-repo-1\mcp_server.py
Use the full absolute path to the Python binary inside .venv so that the server always finds its dependencies, regardless of which directory you run Claude Code from.
Step 4. Restart Claude Code and run your first search.
On first use, the server automatically:
~/.swiss-caselaw/parquet/~/.swiss-caselaw/decisions.db (~58 GB)This takes 30–60 minutes depending on your machine and connection. It only happens once — after that, searches run instantly against the local database.
Total disk usage: ~65 GB in ~/.swiss-caselaw/ (macOS/Linux) or %USERPROFILE%\.swiss-caselaw\ (Windows).
See the Claude Desktop setup guide for step-by-step instructions (macOS + Windows).
Quick version — add this to your claude_desktop_config.json:
{
"mcpServers": {
"swiss-caselaw": {
"command": "/path/to/caselaw-repo-1/.venv/bin/python3",
"args": ["/path/to/caselaw-repo-1/mcp_server.py"]
}
}
}
Config file location: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows). On Windows, use .venv\\Scripts\\python.exe instead.
Any MCP-compatible client works with the same command + args pattern.
The dataset is updated daily. To get the latest decisions, ask Claude to run the update_database tool, or call it explicitly. This re-downloads the Parquet files from HuggingFace and rebuilds the local database.
~/.swiss-caselaw/
├── parquet/ # Downloaded Parquet files from HuggingFace (~7 GB)
│ └── data/
│ ├── bger.parquet
│ ├── bvger.parquet
│ └── ... # 100 files, one per court
├── decisions.db # SQLite FTS5 search index (~58 GB)
├── reference_graph.db # Case citations + statute links (~3.5 GB)
└── statutes.db # Federal law articles from Fedlex (~42 MB)
All data stays on your machine. No API calls are made during search — the MCP server queries the local SQLite database directly.
Database structure. decisions.db is a single SQLite file with two tables:
decisions — the main table with one row per decision. Holds 24 columns, including the search-facing fields plus json_data (full record blob) and canonical_key for dedup-aware lookup. Indexed on court, canton, decision_date, language, docket_number, chamber, and decision_type for fast filtered queries.
decisions_fts — an FTS5 virtual table that mirrors 7 text columns from decisions: court, canton, docket_number, language, title, regeste, and full_text. FTS5 builds an inverted index over these columns, enabling sub-second full-text search across 965K+ decisions. The tokenizer is unicode61 remove_diacritics 2, which handles accented characters across German, French, Italian, and Romansh. Insert/update/delete triggers keep the FTS index in sync with the main table automatically.
Why ~58 GB. The full text of 962K+ court decisions averages ~15 KB per decision. The FTS5 inverted index adds overhead for every unique token, its position, and the column it appears in. This is a known trade-off: FTS5 indexes over large text corpora are substantially larger than the source data, but they enable instant ranked search without external infrastructure.
Search pipeline. When you search, the server:
Detects query intent — docket number lookup (6B_1234/2023), explicit FTS syntax (Mietrecht AND Kündigung), or natural language (decisions on tenant eviction).
Runs multiple FTS5 query strategies — For natural-language queries, the server generates several FTS query variants (AND, OR, phrase, field-focused on regeste/title, with multilingual term expansion) and executes them in sequence. Each strategy produces a ranked candidate set. For explicit syntax (AND/OR/NOT, quoted phrases, column filters), the raw query is tried first.
Fuses candidates via RRF — Results from all strategies are merged using Reciprocal Rank Fusion: each candidate's score is the weighted sum of 1/(k + rank) across all strategies that returned it. Decisions found by multiple strategies get a boost.
Reranks with signal scoring — The top candidates are reranked using a composite score that combines:
full_text 1.2, regeste 5.0, title 6.0 — headnotes and titles are weighted heavily over body text)Selects the best passage — For each result, the server scans the full text for the most relevant passage and returns it as a snippet.
Available on both remote and local unless noted.
| Tool | Description |
|---|---|
search_decisions | Full-text search with filters (court, canton, language, date range, chamber, decision type) |
get_decision | Fetch a single decision by docket number or ID. Includes citation graph counts (cited by / cites). |
list_courts | List all courts with decision counts |
get_statistics | Aggregate stats by court, canton, or year |
find_citations | Show what a decision cites and what cites it, with confidence scores |
find_appeal_chain | Trace the appeal chain (Instanzenzug) — prior and subsequent instances |
find_leading_cases | Find the most-cited decisions for a topic or statute |
analyze_legal_trend | Year-by-year decision counts for a statute or topic |
draft_mock_decision | Build a research-only mock decision outline from facts, grounded in caselaw + statute references; asks clarification questions before conclusion |
get_case_brief | Structured brief for any case — regeste, key Erwägungen, cited statutes, and citation authority |
get_doctrine | Statute article or legal concept → ranked leading cases + doctrine timeline |
generate_exam_question | Legal topic → real BGE fact pattern with hidden analysis for Fallbearbeitung practice |
get_law | Look up a federal or cantonal Swiss law by SR number / abbreviation + optional canton. Returns full article text from the local mirror (Fedlex for federal, LexFind for cantonal) |
search_laws | Unified federal + cantonal FTS5 search with BM25 rank interleaving. Filter by canton= for a specific jurisdiction, or jurisdiction='federal' / 'cantonal' |
get_commentary | Scholarly commentary for a specific federal law article from OnlineKommentar.ch (CC-BY-4.0) |
search_commentaries | Full-text search across 362 legal commentaries from OnlineKommentar.ch across 19 federal laws |
search_legislation | LexFind-backed discovery search across federal + cantonal legislation. fetch_top_n_texts=N enriches the top N results with full article text in a single call |
get_legislation | Full metadata + article text for any federal or cantonal law. Local-first (statutes.db → cantonal_laws.db → LexFind API fallback) |
browse_legislation_changes | Recent-changes feed per canton or federal level (live LexFind API, no local mirror) |
update_database | Re-download latest Parquet files from HuggingFace and rebuild the local database (local only) |
check_update_status | Check progress of a running database update (local only) |
These work on both the remote and local server:
> Search for BGer decisions on Mietrecht Kündigung from 2024
> What did the BVGer rule on asylum seekers from Eritrea?
> Show me the full text of 6B_1234/2023
> How many decisions does each court in canton Zürich have?
> Find decisions citing Art. 8 BV
> What are the leading cases on Art. 8 EMRK?
> Show me the citation network for BGE 138 III 374
> How has Mietrecht jurisprudence evolved over time?
> Show me Art. 41 OR (statute lookup)
> Search for statute provisions about Verjährung
> Trace the appeal chain for 5A_234/2026
> Explain BGE 133 III 121 to me
> What are the leading cases on Art. 41 OR and how has the doctrine evolved?
> Give me a practice case on Haftpflichtrecht
> Search for cantonal data protection laws
> Show me the details of SR 220 (Obligationenrecht)
> What legislation changed recently in Zürich?
The AI calls the MCP tools automatically — you see the search results inline and can ask follow-up questions about specific decisions.
Four tools expose the reference graph: 8.85 million resolved decision-to-decision citation edges and 11.34 million statute references. These require the graph database (output/reference_graph.db); if it's not available, the tools return a message instead of failing.
find_citations — Given a decision, show its outgoing citations (what it references) and incoming citations (what references it). Each resolved citation includes the target decision's metadata and a confidence score. Unresolved references (e.g., older decisions not in the dataset) appear with their raw reference text.
> Show me the citation network for BGE 138 III 374
## Outgoing (13 — what this decision cites)
1. BGE 136 III 365 (2010-01-01) [bge] conf=0.98 mentions=1
2. BGE 133 III 189 (2007-01-01) [bge] conf=0.93 mentions=1
...
## Incoming (13,621 — what cites this decision)
1. 5A_234/2026 (2026-02-19) [bger] conf=0.92 mentions=2
2. 5A_117/2026 (2026-01-30) [bger] conf=0.88 mentions=1
...
Parameters: decision_id (required), direction (both/outgoing/incoming), min_confidence (0–1, default 0.3), limit (default 50, max 200).
find_appeal_chain — Trace the appeal chain (Instanzenzug) for a decision. Shows prior instances (lower courts) and subsequent instances (appeals to higher courts), reconstructing the full procedural path (e.g., Bezirksgericht → Obergericht → Bundesgericht).
Parameters: decision_id (required), min_confidence (0–1, default 0.3).
find_leading_cases — Find the most-cited decisions, ranked by how many other decisions reference them. Filter by statute (law code + article), text query, court, or date range.
> What are the leading cases on Art. 8 EMRK?
1. BGE 135 I 143 (2009) — 3,840 citations
Regeste: Anspruch auf Aufenthaltsbewilligung...
2. BGE 130 II 281 (2004) — 3,155 citations
Regeste: Familiennachzug; gefestigtes Anwesenheitsrecht...
Parameters: query (optional text), law_code + article (optional statute), court, date_from, date_to, limit (default 20, max 100). At least one of query or law_code is recommended; without any filter it returns the globally most-cited decisions.
analyze_legal_trend — Year-by-year decision counts showing how jurisprudence on a topic or statute has evolved over time. Returns a table with counts and a visual bar chart.
> How has Art. 29 BV jurisprudence evolved?
**Filter:** Art. 29 BV
**Total:** 34,669 decisions
Year Count Bar
2000 275 █████
2005 733 ████████████
2010 1,028 █████████████████
2015 1,536 ██████████████████████████
2020 1,896 ████████████████████████████████
2025 2,400 ████████████████████████████████████████
Parameters: query (optional text), law_code + article (optional statute), court, date_from, date_to. At least one of query or law_code is required.
Two tools provide direct access to Swiss law text from the local mirror, covering both federal and cantonal jurisdictions with article-level FTS5 indexing and sub-millisecond lookup:
statutes.db. Covers every consolidated federal act in German, French, and Italian.cantonal_laws.db. PDFs are extracted with PyMuPDF and segmented into articles. Covers all 26 cantons plus bilingual secondary-language passes for BE / FR / VS / GR.get_law — Look up any Swiss law (federal or cantonal) by SR number or abbreviation, optionally fetching a specific article with full text.
> Show me Art. 8 BV
# BV — SR 101
**Bundesverfassung der Schweizerischen Eidgenossenschaft vom 18. April 1999**
### Art. 8 — Rechtsgleichheit
1 Alle Menschen sind vor dem Gesetz gleich.
2 Niemand darf diskriminiert werden, namentlich nicht wegen der Herkunft, ...
> Show me Art. 1 of the Zurich Hundegesetz
get_law(canton="ZH", sr_number="554.5", article="1")
Parameters: sr_number or abbreviation (at least one required), article (optional — omit to see the full article list), language (de/fr/it, default de), canton (default CH; set to ZH, BE, etc. for cantonal lookup).
search_laws — Unified FTS5 search across every Swiss statute article, federal and cantonal. BM25-ranked per corpus, merged by rank interleaving so each response surfaces both jurisdictions.
> Search for statute provisions about Verjährung
1. [CH] Art. 130 OR (SR 220): Die Verjährung beginnt mit der Fälligkeit der Forderung...
2. [ZH] § 19 Kirchgemeindenreglement (SR 182.60): ... Verjährungsbestimmungen ...
3. [CH] Art. 132 OR (SR 220): Bei der Berechnung der Frist ist der Tag...
Parameters: query (required, FTS5 syntax), sr_number (optional — one specific federal law, implies federal-only), canton (optional — restrict to one canton, or CH for federal-only), jurisdiction (all / federal / cantonal, default all), language (de/fr/it), limit (1–50).
Three additional tools layer the live LexFind API on top of the local mirror for cases where the mirror isn't enough — newly published versions between refresh cycles, full version history, recent-changes feeds. These are the broader discovery surface; for plain "give me the current text" queries get_law / search_laws are faster and more reliable.
search_legislation — Broader discovery search across Swiss legislation, with optional single-call full-text enrichment. Useful when you don't know whether the law is federal or cantonal, or when you need a one-shot natural-language workflow.
> Search for the Bernese dog act with full text
search_legislation(query="Hundegesetz", canton="BE", fetch_top_n_texts=2)
→ returns top 2 matches with full_text_preview + sample_articles inline,
no follow-up get_legislation call needed.
Parameters: query (required), canton (optional — CH, ZH, BE, etc.), active_only (default true), search_in_content (default false — searches titles/keywords; set true to search law text), language (de/fr/it), limit (1–60, default 20), fetch_top_n_texts (0–10, default 0 — set to N to enrich top N results with parsed full article text).
get_legislation — Get details for a specific law including metadata, version history, and links to official sources (Fedlex, cantonal portals).
> Show me the Obligationenrecht on LexFind
SR 220 — Bundesgesetz betreffend die Ergänzung des Schweizerischen
Zivilgesetzbuches (Fünfter Teil: Obligationenrecht)
Entity: Bund (CH) | Category: Gesetz | Keywords: OR
In force since: 01.01.2026
Sources:
DE: https://www.fedlex.admin.ch/eli/cc/27/317_321_377/de
FR: https://www.fedlex.admin.ch/eli/cc/27/317_321_377/fr
Parameters: lexfind_id (from search results) or systematic_number + canton (e.g., "220" + "CH"), include_versions (default false), language (de/fr/it).
browse_legislation_changes — Recent legislation changes for a canton or federal level. Shows new laws, amendments, and abrogations with dates and links.
> What legislation changed recently in Zürich?
1. [01.03.2026] version — Vollzugsverordnung zur Finanzverordnung (SR 181.131)
2. [01.03.2026] new — Studienordnung für den Masterstudiengang... (SR 414.253.125)
3. [01.03.2026] version — Organisationsverordnung der Finanzdirektion (SR 172.110.3)
Parameters: canton (default CH), language (de/fr/it).
Three tools support legal study covering the three core student workflows: understanding a case, understanding a doctrine, and practicing exam subsumption. Tools return rich structured data; Claude acts as the tutor and generates all pedagogy dynamically.
get_case_brief — Any case reference ("BGE 133 III 121", docket number, or decision_id) → structured brief. Returns regeste, Sachverhalt, key numbered Erwägungen, Dispositiv, cited statutes with text excerpts, citation authority (incoming/outgoing count), and the top cited-by and cites cases.
get_doctrine — Statute article ("Art. 41 OR") or legal concept ("culpa in contrahendo", "Tierhalterhaftung") → doctrine overview. Returns the leading cases ranked by citation count, a chronological doctrine timeline showing how rules evolved, and the statute text (if applicable).
generate_exam_question — Legal topic ("Haftpflichtrecht", "Art. 41 OR", "Mietrecht") → real Fallbearbeitung. Picks a leading BGE, returns the anonymized Sachverhalt as fact pattern plus a hidden analysis (applicable statutes, legal test, correct outcome). The student writes a subsumption, then asks Claude to reveal the analysis for comparison and feedback. Pass exclude_ids to avoid repeating the same case.
draft_mock_decision can use optional Fedlex URLs and caches fetched statute excerpts in
~/.swiss-caselaw/fedlex_cache.json (configurable via SWISS_CASELAW_FEDLEX_CACHE).
Use a fixed golden query set to track search relevance over time:
python3 benchmarks/run_search_benchmark.py \
--db ~/.swiss-caselaw/decisions.db \
-k 10 \
--json-output benchmarks/latest_search_benchmark.json
Metrics: MRR@k, Recall@k, nDCG@k, Hit@1
The repository also ships a frozen offline baseline at benchmarks/search_benchmark_2026-03-19_offline_full.json. On the full 100-query set against a 1,078,177-row local decisions.db, that run recorded MRR@10 = 0.4697, Recall@10 = 0.4958, nDCG@10 = 0.5250, and Hit@1 = 0.33. Treat it as a reproducible offline baseline rather than a fully provisioned hosted-deployment score.
You can enforce minimum quality gates (non-zero exit on failure):
python3 benchmarks/run_search_benchmark.py \
--db ~/.swiss-caselaw/decisions.db \
-k 10 \
--min-mrr 0.50 \
--min-recall 0.75 \
--min-ndcg 0.85
For statute/citation-aware reranking, build the local graph database:
python3 search_stack/build_reference_graph.py \
--source-db ~/.swiss-caselaw/decisions.db \
--courts bger,bge,bvger \
--db output/reference_graph.db
Then point the server to it:
export SWISS_CASELAW_GRAPH_DB=output/reference_graph.db
Graph signals are enabled by default. To disable them, set SWISS_CASELAW_GRAPH_SIGNALS=0.
For statute lookup (get_law, search_laws), build the Fedlex statute database:
# Download the top 100 most-cited federal laws from Fedlex
python3 -m scrapers.fedlex --top 100
# Build the SQLite FTS5 statutes database
python3 -m search_stack.build_statutes_db
Then copy to the data directory:
cp output/statutes.db ~/.swiss-caselaw/
Or set the path explicitly:
export SWISS_CASELAW_STATUTES_DB=output/statutes.db
The full dataset is on HuggingFace as Parquet files — one file per court, 34 fields per decision including complete decision text.
Step 1. Install the library:
pip install datasets
Step 2. Load the data:
from datasets import load_dataset
# Load a single court (~170k decisions, ~800 MB)
bger = load_dataset("voilaj/swiss-caselaw", data_files="data/bger.parquet")
# Load all courts (~900K decisions, ~6.5 GB download)
ds = load_dataset("voilaj/swiss-caselaw", data_files="data/*.parquet")
Step 3. Explore:
# Print a single decision
decision = bger["train"][0]
print(decision["docket_number"]) # "6B_1/2024"
print(decision["decision_date"]) # "2024-03-15"
print(decision["language"]) # "de"
print(decision["regeste"][:200]) # First 200 chars of the headnote
print(decision["full_text"][:500]) # First 500 chars of the full text
import pandas as pd
# Load one court
df = pd.read_parquet("hf://datasets/voilaj/swiss-caselaw/data/bger.parquet")
# Filter by date
df_recent = df[df["decision_date"] >= "2024-01-01"]
print(f"{len(df_recent)} decisions since 2024")
# Filter by language
df_french = df[df["language"] == "fr"]
# Group by legal area
df.groupby("legal_area").size().sort_values(ascending=False).head(10)
Every court is a single Parquet file. Download directly:
https://huggingface.co/datasets/voilaj/swiss-caselaw/resolve/main/data/bger.parquet
https://huggingface.co/datasets/voilaj/swiss-caselaw/resolve/main/data/bvger.parquet
https://huggingface.co/datasets/voilaj/swiss-caselaw/resolve/main/data/zh_gerichte.parquet
...
Full list of files: huggingface.co/datasets/voilaj/swiss-caselaw/tree/main/data
Query the dataset over HTTP without installing anything. This uses the HuggingFace Datasets Server.
Get rows:
curl "https://datasets-server.huggingface.co/rows?dataset=voilaj/swiss-caselaw&config=default&split=train&offset=0&length=5"
Get dataset info:
curl "https://datasets-server.huggingface.co/info?dataset=voilaj/swiss-caselaw"
Search by SQL (DuckDB endpoint):
curl -X POST "https://datasets-server.huggingface.co/search?dataset=voilaj/swiss-caselaw&config=default&split=train" \
-d '{"query": "SELECT docket_number, decision_date, language FROM data WHERE court = '\''bger'\'' LIMIT 10"}'
Note: The REST API queries the dataset as configured in the HuggingFace repo (per-court Parquet files, full 34-field schema). For bulk access or local analysis, use the download method above.
A local chat interface for searching Swiss court decisions. Ask questions in natural language, and an AI assistant searches the full corpus and answers with cited decisions.
Browser (localhost:5173) → FastAPI backend → MCP server → Local SQLite FTS5 DB
Everything runs on your machine. No data leaves your computer (except LLM API calls to the provider you choose).
| Requirement | How to check | Where to get it |
|---|---|---|
| Python 3.10+ | python3 --version (macOS/Linux) or python --version (Windows) | python.org/downloads |
| Node.js 18+ | node --version | nodejs.org — download the LTS version |
| An LLM provider | (see below) | At least one cloud API key or a local model via Ollama |
| ~65 GB free disk | df -h . (macOS/Linux) | For the search index (downloaded on first run) |
Windows users: Install Python from python.org and check "Add Python to PATH" during installation. Node.js installs npm automatically.
| Provider | Env variable | Where to get a key | Cost |
|---|---|---|---|
| Google Gemini | GEMINI_API_KEY | aistudio.google.com/apikey | Free tier available |
| OpenAI | OPENAI_API_KEY | platform.openai.com/api-keys | Free credits for new accounts |
| Anthropic (Claude) | ANTHROPIC_API_KEY | console.anthropic.com | Pay-as-you-go |
Important: A Claude Desktop or Claude Pro subscription does NOT include an API key. You need a separate developer account at console.anthropic.com.
If you prefer not to use cloud APIs, you can run everything locally with Ollama:
| Model | Command to install | Download size | RAM needed |
|---|---|---|---|
| Qwen 2.5 (14B) | ollama pull qwen2.5:14b | ~9 GB | ~16 GB |
| Llama 3.3 (70B) | ollama pull llama3.3:70b | ~40 GB | ~48 GB |
Install Ollama from ollama.com (macOS, Linux, Windows), then:
ollama serve # start the Ollama server (leave running)
ollama pull qwen2.5:14b # download a model (one-time)
The Web UI auto-detects Ollama and shows local models as available.
Step 1. Clone the repository:
git clone https://github.com/jonashertner/caselaw-repo-1.git
cd caselaw-repo-1
Step 2. Create a Python virtual environment:
python3 -m venv .venv
Activate it:
| OS | Command |
|---|---|
| macOS / Linux | source .venv/bin/activate |
| Windows (PowerShell) | .venv\Scripts\Activate.ps1 |
| Windows (cmd) | .venv\Scripts\activate.bat |
Documentation truncated — see the full README on GitHub.
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
by Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
by mcp-marketplace · Developer Tools
Scaffold, build, and publish TypeScript MCP servers to npm — conversationally
by mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.