内容
> **瑞士公共数据MCP投资组合的一部分**
# 🏛️ swiss-courts-mcp

[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://modelcontextprotocol.io/)
[](https://github.com/malkreide/swiss-courts-mcp)

> 瑞士法院决策MCP服务器 - 联邦最高法院(BGer)、联邦行政法院(BVGer)、联邦刑事法院(BStGer)和所有26个州法院,通过entscheidsuche.ch
[德语版本](README.de.md)
<p align="center">
<img src="assets/demo.svg" alt="Demo: Claude通过MCP工具调用搜索瑞士法院判决" width="720">
</p>
---
## 概述
通过单一的MCP接口访问瑞士所有司法级别的法院判决。结合全文搜索和结构化过滤,适用于州、法院级别、日期范围和法律引用。
**🎯 示例查询:** *"查找2020年以来与数据保护相关的联邦最高法院案例(Art. 25 DSG)- 如果entscheidsuche.ch不可用,仍可从离线转储中回答,并明确标记。*
| 来源 | 覆盖范围 | 数据 |
|--------|----------|------|
| [entscheidsuche.ch](https://entscheidsuche.ch) (实时,默认) | 联邦 + 26个州 | ~2000年以来的法院判决 |
| [SCD转储](https://doi.org/10.5281/zenodo.14867950) (离线备用) | **仅联邦最高法院,2007-2024** | 元数据/注册,无全文 |
**与 [fedlex-mcp](https://github.com/malkreide/fedlex-mcp) 的协同作用:** 立法(SR)+ 案例法 = 完整的法律研究。
**可用性:** entscheidsuche.ch是非盈利基础设施,无SLA。当它无法访问时,服务器会透明地回退到缓存的公共转储(参见[离线备用](#离线备用))。每个响应都声明其来源(`source: "live" | "dump"`),并且转储答案带有`coverage_note` - 备用是**部分,不是等效的**。
---
## 功能
- 跨所有瑞士法院判决的全文搜索
- 多级法律引用搜索,带有正则表达式解析器和Elasticsearch提升评分
- 专门的联邦最高法院搜索,带有商会过滤器
- 州和法院级别过滤
- 最近的判决提要
- 法院分类列表
- 判决统计,带有聚合
- 三语支持(德语,法语,意大利语)
- **离线备用**,当entscheidsuche.ch不可用时,使用缓存的公共转储,并明确每个响应
- 无需API密钥
---
## 先决条件
- Python 3.11或更高版本
- 与MCP兼容的客户端(Claude Desktop,Cursor,Windsurf等)
---
## 安装
```bash
pip install swiss-courts-mcp
```
或从源代码安装:
```bash
git clone https://github.com/malkreide/swiss-courts-mcp.git
cd swiss-courts-mcp
pip install -e ".[dev]"
```
---
## 快速入门
```bash
# 直接运行
swiss-courts-mcp
# 或通过Python模块
python -m swiss_courts_mcp
```
---
## 配置
### 克劳德桌面
添加到您的 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"swiss-courts": {
"command": "python",
"args": ["-m", "swiss_courts_mcp"]
}
}
}
```
### 云部署(HTTP传输)
HTTP传输**默认关闭**。默认绑定主机是`127.0.0.1`(仅限环回)- 必须显式选择`0.0.0.0`(Dockerfile执行此操作)。在没有身份验证的HTTP运行时,会记录警告;请仅在身份验证反向代理后面执行此操作。
```bash
# 本地HTTP(环回),无身份验证 - 仅限开发
swiss-courts-mcp --http --port 8000
# 容器(绑定0.0.0.0,启用身份验证)- 参见Dockerfile
docker build -t swiss-courts-mcp .
docker run -p 8000:8000 -e MCP_AUTH_SECRET="$(openssl rand -hex 32)" swiss-courts-mcp
```
相关环境变量(参见[`.env.example`](.env.example)):
| 变量 | 默认值 | 用途 |
|---|---|---|
| `MCP_HOST` | `127.0.0.1` | 绑定主机。仅在容器中设置为`0.0.0.0`。 |
| `MCP_PORT` | `8000` | 绑定端口。 |
| `MCP_ALLOW_PUBLIC_BIND` | `false` | 禁止`0.0.0.0`警告(容器)。 |
| `MCP_STATELESS_HTTP` | `true` | 无状态HTTP → 水平扩展,无需粘性会话。 |
| `MCP_AUTH_ENABLED` | `false` | 为HTTP启用Bearer令牌身份验证。 |
| `MCP_AUTH_SECRET` | - | HS256签名密钥(开发)。 |
| `MCP_OAUTH_JWKS_URL` | - | JWKS URL,用于RS256验证(生产)。 |
| `MCP_REQUIRED_SCOPES` | - | 以逗号分隔的所需范围列表。 |
| `MCP_CORS_ORIGINS` | - | 以逗号分隔的允许来源列表(生产中无通配符)。 |
身份验证仅验证JWT `sub`声明中的用户身份;参见
[ADR 0001](docs/adr/0001-http-auth.md)。
### 离线备用(env)
| 变量 | 默认值 | 用途 |
|---|---|---|
| `SWISS_COURTS_FALLBACK_ENABLED` | `true` | 主开关。`0`禁用转储备用(仅限实时)。 |
| `SWISS_COURTS_FORCE_DUMP` | `false` | 强制转储路径(跳过实时)- 用于预热缓存或离线测试。 |
| `SWISS_COURTS_CACHE_DIR` | `platformdirs`缓存 | 覆盖下载转储的缓存目录。 |
| `SWISS_COURTS_DUMP_RECORD` | `14867950` | 要使用的SCD转储的Zenodo记录ID。 |
预热缓存(一次性下载~120 MB SCD CSV,因此第一次实际停机不会支付下载费用):
```bash
SWISS_COURTS_FORCE_DUMP=1 python -m swiss_courts_mcp # 然后发出一个搜索请求
```
---
## MCP协议版本
该服务器固定MCP协议版本 **`2025-11-25`** (`server.py`中的常量`PROTOCOL_VERSION`)。回归测试会检测到与安装的SDK的漂移,因此协议更改是有意识的更改(版本 + CHANGELOG + 本节)。SDK更新通过Dependabot每月发布。
## 项目阶段
**第一阶段 - 只读**(参见 [ROADMAP.md](ROADMAP.md))。所有工具都是`readOnlyHint: true`;没有写入或破坏性操作。迁移到第2阶段(写入)需要干净的重审和路线图中列出的门控。
---
## 可用工具
### 法院判决搜索
| 工具 | 描述 |
|------|-------------|
| `search_court_decisions` | 跨所有法院判决的全文搜索,带有州、法院级别和日期过滤器 |
| `get_court_decision` | 通过其唯一签名检索单个判决 |
| `search_bger_decisions` | 搜索联邦最高法院判决,可选商会过滤器 |
| `search_by_law_reference` | 查找引用特定法律条款的判决(例如“Art. 8 BV”) |
### 法院信息
| 工具 | 描述 |
|------|-------------|
| `list_courts` | 列出所有索引法院,可选按州过滤 |
| `get_recent_decisions` | 最新判决,可按州和法院级别过滤 |
| `get_decision_statistics` | 按州和年份的索引判决统计 |
| `get_fallback_status` | 离线转储缓存状态、覆盖范围、版本、预热(只读) |
### 工具注解
所有八种工具共享相同的提示 - 它们是只读的、幂等的、非破坏性的,并且到达外部系统:
| 注解 | 值 |
|---|---|
| `readOnlyHint` | `true` |
| `destructiveHint` | `false` |
| `idempotentHint` | `true` |
| `openWorldHint` | `true` |
还提供了一个`rechtsrecherche` **提示**(一种与工具并行的MCP基元)。
### 示例用例
| 用例 | 工具链 |
|----------|------------|
| 研究数据保护的案例法 | `search_court_decisions("Datenschutz")` |
| 查找宪法权利的实践 | `search_by_law_reference("Art. 8 BV")` |
| 最新联邦最高法院判决 | `search_bger_decisions("Arbeitsrecht", date_from="2024-01-01")` |
| 组合:法律文本 + 案例法 | `fedlex_search_laws("DSG")` 然后 `search_by_law_reference("Art. 25 DSG")` |
[→ 更多受众的用例 →](EXAMPLES.md)
---
## 架构
```
┌─────────────────────────────────────┐
│ MCP客户端(LLM) │
│ Claude / Cursor / Windsurf │
└──────────────┬──────────────────────┘
│ MCP协议
┌──────────────▼──────────────────────────────┐
│ swiss-courts-mcp │
│ 8种工具 · Pydantic验证 │
│ Elasticsearch查询构建器 │
│ 来源信封:source = live | dump │
└───────┬──────────────────────────────┬──────┘
│ ① live(默认) │ ② 备用
│ HTTPS POST/GET │ bot-block / 5xx / 429 /
│ │ timeout, 或 SWISS_COURTS_FORCE_DUMP=1
┌───────▼──────────────────┐ ┌───────▼───────────────────────────────┐
│ entscheidsuche.ch │ │ SCD转储 - Zenodo 14867950(CC BY) │
│ Elasticsearch后端 │ │ 延迟下载 → platformdirs缓存 │
│ 联邦 + 26个州 │ │ → 本地SQLite搜索 │
│ 无身份验证 · 无SLA │ │ BGer only · 2007–2024 · 无全文 │
└──────────────────────────┘ └───────────────────────────────────────┘
```
### 架构决策
该服务器使用 **架构C(仅元数据备用),通过延迟下载交付(A选项机制)** - 2026-07-19实时探测后决定:
- **始终优先使用实时数据。** entscheidsuche.ch仍然是成功的唯一来源;其行为保持不变。备用仅在可用性失败时启用(bot-block、HTTP 5xx/429、超时、连接错误)或强制执行。
- **来源:SCD转储**(Zenodo `10.5281/zenodo.14867950`,版本2024-3, **CC BY 4.0**),~120 MB CSV - 仅元数据/注册,无全文。 375 MB全文本Parquet及其繁重的`pyarrow`依赖项被拒绝:部分备用不证明其开销,完整文本会伪造不存在的等价性(BGer仅限)。
- **第二个候选被拒绝:** Zenodo `5529712`(“SwissJudgmentPrediction”)是CC BY-**NC-SA** 4.0 - 与MIT项目不兼容。
- **后果:** CSV缓存在磁盘上(`platformdirs`)并通过SQLite搜索;更新检测使用Zenodo版本API(`conceptrecid` 7793043)。每个响应都声明`source`(`live`/`dump`)和dump响应添加`coverage_note`。 CC-BY属性在**工具输出**中提供,不仅仅在这里。
### 离线备用
备用是 **现有工具的行为**,而不是单独的搜索工具(仅添加`get_fallback_status`用于透明度)。它是 **部分,不是等效** 的实时源:
- **法院范围:** 仅联邦最高法院(BGer/BGE)。 Bundesverwaltungsgericht、Bundesstrafgericht 和 **26个州法院不涵盖**。
- **时间范围:** 2007 - 2024(SCD转储的范围)。此窗口之外的判决不存储在转储中。
- **内容:** 仅元数据/注册 - **无全文** 离线。
- **更新延迟:** SCD转储在Zenodo上每季度刷新一次,因此离线数据滞后于实时索引。 `get_fallback_status`报告缓存版本并可以检查Zenodo以获取更新版本。
- **法律引用搜索** 离线仅匹配判决的主题/问题(`topic`/`issue`)- 没有离线引用索引。
- 响应始终通过`source`(`live`/`dump`)和`coverage_note`公开其来源;服务器从不静默缩小覆盖范围。
---
## 安全与限制
| 方面 | 详情 |
|--------|---------|
| **访问** | 只读(`readOnlyHint: true`)- 服务器无法修改或删除任何数据 |
| **个人数据** | 无个人数据 - 所有判决都是公开的法院裁决 |
| **速率限制** | 每个查询的内置上限(每搜索最多50个结果,最多50个聚合桶) |
| **超时** | 每个API调用30秒 |
| **数据来源验证** | 无需API密钥 - entscheidsuche.ch是公开可访问的 |
| **HTTP传输身份验证** | 可选的承载令牌身份验证(JWT,`sub`声明身份验证);参见 [ADR 0001](docs/adr/0001-http-auth.md) |
| **出口** | 代码层允许列表(`entscheidsuche.ch`用于实时;`zenodo.org`用于离线转储),强制HTTPS;参见 [出口策略](docs/network-egress.md) |
| **错误掩蔽** | 内部异常仅在服务器端记录;客户端接收友好消息 |
| **秘密** | 代码/日志中没有秘密;`.env` git-ignored,PR上有Gitleaks;参见 [秘密管理](docs/secret-management.md) |
| **许可证** | 瑞士法律下的法院判决在瑞士法律下是公共领域([BGG Art. 27](https://www.fedlex.admin.ch/eli/cc/2006/218/de#art_27)) |
| **服务条款** | 遵守 entscheidsuche.ch 的使用条款 - 请善待服务器 |
---
## 项目结构
```
swiss-courts-mcp/
├── src/
│ └── swiss_courts_mcp/
│ ├── __init__.py
│ ├── __main__.py
│ ├── server.py # MCP服务器,8种工具 + 1提示,生命周期,身份验证
│ ├── api_client.py # HTTP客户端,ES查询构建器,出口允许列表
│ ├── fallback.py # 离线转储层(Zenodo → 缓存 → SQLite)
│ ├── auth.py # JWT承载令牌验证器(HTTP传输)
│ ├── config.py # 设置对象(环境驱动)
│ ├── logging_config.py # struct日志输出到stderr
│ └── models.py # 结构化响应信封(来源:live|dump)
├── tests/ # 单元测试(respx模拟)+ 实时测试 + 安全测试
├── docs/ # 出口,秘密管理,ADR
├── .github/workflows/ # ci · 安全(gitleaks)· 实时 · 发布
├── Dockerfile # 强化容器(非root,0.0.0.0仅在此处)
├── ROADMAP.md
├── pyproject.toml · CHANGELOG.md · LICENSE
├── CONTRIBUTING.md · CONTRIBUTING.de.md
├── SECURITY.md · SECURITY.de.md
└── README.md · README.de.md
```
> **注意(单文件工具):** 8种工具位于 `server.py` 而不是 `tools/` 包。在此计数中,单个模块仍然可读;注册表(`register_tools`)保持声明性。这是与“拆分为> 5种工具时”这一惯例的刻意偏离,如果工具数量增加,将重新审视。离线备用逻辑在 `fallback.py` 中隔离,与实时客户端清晰分离。
---
## 已知限制
- 搜索仅限于entscheidsuche.ch索引的判决(并非所有判决都是公开可用的)
- 不返回全文文档内容 - 仅元数据,标题和摘要
- 统计数据取决于Elasticsearch聚合支持的后端
- 法院分类结构可能有所不同
**离线备用(部分覆盖 - 请阅读):** 备用是可用性的安全网 **,而不是等效镜像**:
- **法院范围:** 仅联邦最高法院(BGer/BGE)。 Bundesverwaltungsgericht,Bundesstrafgericht 和 **所有26个州法院均不涵盖**。
- **时间范围:** 2007年 - 2024年12月(SCD转储的范围)。判决超出此范围的不在转储中。
- **内容:** 仅元数据/注册 - **无全文** 离线。
- **更新延迟:** SCD转储在Zenodo上大约每季度刷新一次,因此离线数据滞后于实时索引。 `get_fallback_status` 报告缓存版本并可以检查Zenodo以获取更新版本。
- **法律引用搜索** 离线仅匹配判决书中提到的法律条文(`topic`/`issue`)- 没有离线引用法律索引。
- 响应始终通过 `source`(`live`/`dump`)和 `coverage_note` 公开其来源;服务器从不静默缩小覆盖范围。
---
## 测试
单元测试使用`respx`模拟所有HTTP;实时测试会访问真实API,并在单独的夜间工作流中运行(`live.yml`),绝不阻塞PR。
从项目根目录运行 `PYTHONPATH=src`:
```bash
# 单元测试(模拟HTTP)- CI运行的内容
PYTHONPATH=src pytest tests/ -v -m "not live"
# 实时API测试(真实entscheidsuche.ch + Zenodo)
PYTHONPATH=src pytest tests/ -v -m live
# 代码 linting
ruff check src/ tests/
ruff format src/ tests/
```
离线备用测试使用小型提交模式fixture(`tests/fixtures/scd_sample.csv`)并使用`respx`模拟Zenodo下载 - 完整的~120 MB转储从不提交或下载到CI中。
---
## 变更日志
参见 [CHANGELOG.md](CHANGELOG.md)。
---
## 贡献
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
---
## 安全
参见 [SECURITY.md](SECURITY.md) 以了解安全姿态和如何报告漏洞。
---
## 许可证
[MIT](LICENSE)
---
## 作者
Hayal Oezkan · [malkreide](https://github.com/malkreide)
---
## 致谢与相关项目
- [entscheidsuche.ch](https://entscheidsuche.ch) - 瑞士法院判决搜索引擎(实时来源)
- **瑞士联邦最高法院数据集(SCD)** - 离线备用来源, **CC BY 4.0**:Geering, F. & Merane, J. (2025). *Swiss Federal Supreme Court Dataset (SCD)*, Version 2024-3. Zenodo. https://doi.org/10.5281/zenodo.14867950
- [fedlex-mcp](https://github.com/malkreide/fedlex-mcp) - 瑞士联邦法律MCP服务器(立法与案例法协同工作)
- [zurich-opendata-mcp](https://github.com/malkreide/zurich-opendata-mcp) - 苏黎世开放数据MCP服务器
- [Model Context Protocol](https://modelcontextprotocol.io/) - 开放式AI工具集成协议
<!-- mcp-name: io.github.malkreide/swiss-courts-mcp -->
<!-- BEGIN GENERATED: install -->
## 安装
通过 [`uv`](https://docs.astral.sh/uv/) 的 `uvx` 运行 - 无需克隆或手动安装。只需在MCP客户端配置中添加(Claude Desktop,Cursor和Windsurf的`mcpServers`;VS Code在`.vscode/mcp.json`中使用顶级`servers`键):
```json
{
"mcpServers": {
"swiss-courts-mcp": {
"command": "uvx",
"args": [
"swiss-courts-mcp"
]
}
}
}
```
<!-- END GENERATED: install -->
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器