Skip to main content
ClaudeWave
malkreide avatar
malkreide

swiss-courts-mcp

View on GitHub

MCP Server for Swiss court decisions via entscheidsuche.ch - BGer, BVGer, BStGer + 26 cantonal courts

MCP ServersOfficial Registry1 stars0 forksPythonMITUpdated today
ClaudeWave Trust Score
87/100
Trusted
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
Last scanned: 6/11/2026
Install in Claude Code / Claude Desktop
Method: pip / Python · swiss-courts-mcp
Claude Code CLI
claude mcp add swiss-courts-mcp -- python -m swiss-courts-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "swiss-courts-mcp": {
      "command": "python",
      "args": ["-m", "swiss_courts_mcp"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install first: pip install swiss-courts-mcp
Use cases

MCP Servers overview

> **Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)**

# 🏛️ swiss-courts-mcp

![Version](https://img.shields.io/badge/version-0.3.1-blue)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![MCP](https://img.shields.io/badge/MCP-Model%20Context%20Protocol-purple)](https://modelcontextprotocol.io/)
[![No Auth Required](https://img.shields.io/badge/auth-none%20required-brightgreen)](https://github.com/malkreide/swiss-courts-mcp)
![CI](https://github.com/malkreide/swiss-courts-mcp/actions/workflows/ci.yml/badge.svg)

> MCP Server for Swiss court decisions — Federal Supreme Court (BGer), Federal Administrative Court (BVGer), Federal Criminal Court (BStGer), and all 26 cantonal courts via entscheidsuche.ch

[Deutsche Version](README.de.md)

<p align="center">
  <img src="assets/demo.svg" alt="Demo: Claude searches Swiss court decisions via MCP tool call" width="720">
</p>

---

## Overview

Access Swiss court decisions from all judicial levels through a single MCP interface. Combines full-text search with structured filters for canton, court level, date range, and law references.

**🎯 Anchor demo query:** *"Find Federal Supreme Court case law on data protection (Art. 25 DSG) since 2020 — and if entscheidsuche.ch is down, still answer from the offline dump, clearly flagged."*

| Source | Coverage | Data |
|--------|----------|------|
| [entscheidsuche.ch](https://entscheidsuche.ch) (live, default) | Federal + 26 cantons | Court decisions since ~2000 |
| [SCD dump](https://doi.org/10.5281/zenodo.14867950) (offline fallback) | **Federal Supreme Court only, 2007–2024** | Metadata/regesten, **no full text** |

**Synergy with [fedlex-mcp](https://github.com/malkreide/fedlex-mcp):** Legislation (SR) + case law = complete legal research.

**Availability:** entscheidsuche.ch is non-profit infrastructure without an SLA. When it is unreachable, the server transparently falls back to a cached public dump (see [Offline fallback](#offline-fallback)). Every response declares its origin (`source: "live" | "dump"`), and dump answers carry a `coverage_note` — the fallback is **partial, not equivalent**.

---

## Features

- Full-text search across all Swiss court decisions
- Multi-stage law reference search with regex parser and Elasticsearch boost scoring
- Dedicated Federal Supreme Court search with chamber filter
- Canton and court level filtering
- Recent decisions feed
- Court taxonomy listing
- Decision statistics with aggregations
- Trilingual support (German, French, Italian)
- **Offline fallback** to a cached public dump when entscheidsuche.ch is unreachable — with explicit provenance on every response
- No API key required

---

## Prerequisites

- Python 3.11 or higher
- An MCP-compatible client (Claude Desktop, Cursor, Windsurf, etc.)

---

## Installation

```bash
pip install swiss-courts-mcp
```

Or install from source:

```bash
git clone https://github.com/malkreide/swiss-courts-mcp.git
cd swiss-courts-mcp
pip install -e ".[dev]"
```

---

## Quickstart

```bash
# Run directly
swiss-courts-mcp

# Or via Python module
python -m swiss_courts_mcp
```

---

## Configuration

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "swiss-courts": {
      "command": "python",
      "args": ["-m", "swiss_courts_mcp"]
    }
  }
}
```

### Cloud Deployment (HTTP transport)

The HTTP transport is **off by default**. The default bind host is `127.0.0.1`
(loopback only) — `0.0.0.0` must be opted into explicitly (the Dockerfile does
this). Running HTTP without authentication logs a warning; only do so behind an
authenticating reverse proxy.

```bash
# Local HTTP (loopback), no auth — development only
swiss-courts-mcp --http --port 8000

# Container (binds 0.0.0.0, auth enabled) — see Dockerfile
docker build -t swiss-courts-mcp .
docker run -p 8000:8000 -e MCP_AUTH_SECRET="$(openssl rand -hex 32)" swiss-courts-mcp
```

Relevant environment variables (see [`.env.example`](.env.example)):

| Variable | Default | Purpose |
|---|---|---|
| `MCP_HOST` | `127.0.0.1` | Bind host. Set to `0.0.0.0` only in containers. |
| `MCP_PORT` | `8000` | Bind port. |
| `MCP_ALLOW_PUBLIC_BIND` | `false` | Suppress the `0.0.0.0` warning (containers). |
| `MCP_STATELESS_HTTP` | `true` | Stateless HTTP → horizontal scaling without sticky sessions. |
| `MCP_AUTH_ENABLED` | `false` | Enable bearer-token auth for HTTP. |
| `MCP_AUTH_SECRET` | — | HS256 signing key (dev). |
| `MCP_OAUTH_JWKS_URL` | — | JWKS URL for RS256 validation (production). |
| `MCP_REQUIRED_SCOPES` | — | Comma-separated required scopes. |
| `MCP_CORS_ORIGINS` | — | Comma-separated allowed origins (no wildcard in prod). |

Authentication validates the user identity from the JWT `sub` claim only; see
[ADR 0001](docs/adr/0001-http-auth.md).

### Offline fallback (env)

| Variable | Default | Purpose |
|---|---|---|
| `SWISS_COURTS_FALLBACK_ENABLED` | `true` | Master switch. `0` disables the dump fallback (live-only). |
| `SWISS_COURTS_FORCE_DUMP` | `false` | Force the dump path (skip live) — for pre-warming the cache or offline testing. |
| `SWISS_COURTS_CACHE_DIR` | `platformdirs` cache | Override the cache directory for the downloaded dump. |
| `SWISS_COURTS_DUMP_RECORD` | `14867950` | Zenodo record id of the SCD dump to use. |

Pre-warm the cache (downloads the ~120 MB SCD CSV once, so the first real
outage does not pay the download cost):

```bash
SWISS_COURTS_FORCE_DUMP=1 python -m swiss_courts_mcp  # then issue one search
```

---

## MCP Protocol Version

This server pins MCP protocol version **`2025-11-25`** (constant
`PROTOCOL_VERSION` in `server.py`). A regression test detects drift against the
installed SDK so a protocol bump is a conscious change (version + CHANGELOG +
this section). SDK updates land monthly via Dependabot.

## Project Phase

**Phase 1 — read-only** (see [ROADMAP.md](ROADMAP.md)). All tools are
`readOnlyHint: true`; there are no writing or destructive operations. A move to
Phase 2 (write) requires a clean re-audit and the gates listed in the roadmap.

---

## Available Tools

### Court Decision Search

| Tool | Description |
|------|-------------|
| `search_court_decisions` | Full-text search across all court decisions with canton, court level, and date filters |
| `get_court_decision` | Retrieve a single decision by its unique signature |
| `search_bger_decisions` | Search Federal Supreme Court decisions with optional chamber filter |
| `search_by_law_reference` | Find decisions citing a specific law article (e.g., "Art. 8 BV") |

### Court Information

| Tool | Description |
|------|-------------|
| `list_courts` | List all indexed courts, optionally filtered by canton |
| `get_recent_decisions` | Latest decisions, filterable by canton and court level |
| `get_decision_statistics` | Statistics on indexed decisions by canton and year |
| `get_fallback_status` | Offline-dump cache state, coverage, version, pre-warming (read-only) |

### Tool Annotations

All eight tools share the same hints — they are read-only, idempotent,
non-destructive, and reach an external system:

| Annotation | Value |
|---|---|
| `readOnlyHint` | `true` |
| `destructiveHint` | `false` |
| `idempotentHint` | `true` |
| `openWorldHint` | `true` |

A `rechtsrecherche` **prompt** is also provided (a second MCP primitive
alongside tools).

### Example Use Cases

| Use Case | Tool Chain |
|----------|------------|
| Research case law on data protection | `search_court_decisions("Datenschutz")` |
| Find practice on a constitutional right | `search_by_law_reference("Art. 8 BV")` |
| Latest Federal Supreme Court rulings | `search_bger_decisions("Arbeitsrecht", date_from="2024-01-01")` |
| Combined: Law text + case law | `fedlex_search_laws("DSG")` then `search_by_law_reference("Art. 25 DSG")` |

[→ More use cases by audience →](EXAMPLES.md)

---

## Architecture

```
┌─────────────────────────────────────┐
│         MCP Client (LLM)            │
│   Claude / Cursor / Windsurf        │
└──────────────┬──────────────────────┘
               │ MCP Protocol
┌──────────────▼──────────────────────────────┐
│              swiss-courts-mcp               │
│  8 tools · Pydantic validation              │
│  Elasticsearch query builder                │
│  Provenance envelope: source = live | dump  │
└───────┬──────────────────────────────┬──────┘
        │ ① live (default)             │ ② fallback
        │ HTTPS POST/GET               │ on bot-block / 5xx / 429 /
        │                              │ timeout, or SWISS_COURTS_FORCE_DUMP=1
┌───────▼──────────────────┐   ┌───────▼───────────────────────────────┐
│     entscheidsuche.ch    │   │   SCD dump — Zenodo 14867950 (CC BY)  │
│  Elasticsearch backend   │   │   lazy download → platformdirs cache  │
│  Federal + 26 cantons    │   │   → local SQLite search               │
│  no auth · no SLA        │   │   BGer only · 2007–2024 · no full text │
└──────────────────────────┘   └───────────────────────────────────────┘
```

### Architecture decision

This server uses **Architecture C (metadata-only offline fallback), delivered
via lazy download (Option A mechanics)** — decided after a live probe on
2026-07-19:

- **Live-first, always.** entscheidsuche.ch remains the sole source on success;
  its behaviour is unchanged. The fallback only engages on an availability
  failure (bot-block, HTTP 5xx/429, timeout, connect error) or when forced.
- **Source: the SCD dump** (Zenodo `10.5281/zenodo.14867950`, Version 2024-3,
  **CC BY 4.0**), the ~120 MB CSV — metadata/regesten only, **no full text**. The
  375 MB full-text Parquet and its heavy `pyarrow` dependency were rejected: a
  partial fallback does not justify the footprint, and full text would fake an
  equivalence that does not exist (BGer only).
- **A second candidate was r
ai-toolsbundesgerichtcase-lawclaudecourt-decisionselasticsearchentscheidsuchefastmcplegal-researchlegal-techllmmcpmodel-context-protocolopen-dataopen-governmentpythonrechtsprechungswiss-lawswiss-public-data-mcpswitzerland

What people ask about swiss-courts-mcp

What is malkreide/swiss-courts-mcp?

+

malkreide/swiss-courts-mcp is mcp servers for the Claude AI ecosystem. MCP Server for Swiss court decisions via entscheidsuche.ch - BGer, BVGer, BStGer + 26 cantonal courts It has 1 GitHub stars and was last updated today.

How do I install swiss-courts-mcp?

+

You can install swiss-courts-mcp by cloning the repository (https://github.com/malkreide/swiss-courts-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is malkreide/swiss-courts-mcp safe to use?

+

Our security agent has analyzed malkreide/swiss-courts-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains malkreide/swiss-courts-mcp?

+

malkreide/swiss-courts-mcp is maintained by malkreide. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to swiss-courts-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy swiss-courts-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: malkreide/swiss-courts-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/malkreide-swiss-courts-mcp)](https://claudewave.com/repo/malkreide-swiss-courts-mcp)
<a href="https://claudewave.com/repo/malkreide-swiss-courts-mcp"><img src="https://claudewave.com/api/badge/malkreide-swiss-courts-mcp" alt="Featured on ClaudeWave: malkreide/swiss-courts-mcp" width="320" height="64" /></a>

More MCP Servers

swiss-courts-mcp alternatives