mcpField
S
swiss-courts-mcp

swiss-courts-mcp

本地服务
github.com法律与政务11 天前更新

关于 swiss-courts-mcp

用于研究瑞士联邦及全部 26 个州法院判决的 MCP 服务,结合全文与法律条文检索及多种筛选条件。实时数据源不可用时,可改用明确标注来源和覆盖范围的部分离线数据。

主要功能

  1. 01搜索判决全文
  2. 02按引用的法律条文搜索
  3. 03按州、法院级别和日期筛选
  4. 04按审判庭搜索联邦最高法院判决
  5. 05查看近期判决和法院列表
  6. 06使用标注来源的离线备用数据

适用场景

  1. 01研究瑞士某法律主题的判例
  2. 02查找引用特定法条的判决
  3. 03按州或法院级别查看近期裁决
  4. 04实时数据源中断时继续搜索联邦判决

MCP 相关

向 MCP 客户端提供只读搜索、判决查询、法院信息和统计工具,并附带提示词。离线备用数据会标明来源及覆盖范围。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"malkreide-swiss-courts": {
"command": "uvx",
"args": [
"swiss-courts-mcp"
]
}
}
}
启动命令uvx swiss-courts-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiswiss-courts-mcp0.5.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

属于 Swiss Public Data MCP Portfolio

🏛️ swiss-courts-mcp

Version License: MIT Python 3.11+ MCP No Auth Required CI

瑞士法院判决 MCP 服务——涵盖瑞士联邦最高法院(BGer)、联邦行政法院(BVGer)、联邦刑事法院(BStGer)以及通过 entscheidsuche.ch 提供的全部 26 个州级法院

德语版

演示:Claude 通过 MCP 工具调用搜索瑞士法院判决


概述

通过单一 MCP 接口获取瑞士各级法院的判决。结合全文搜索与州、法院级别、日期范围和法律条文引用等结构化筛选条件。

🎯 示例查询: “查找 2020 年以来瑞士联邦最高法院关于数据保护(Art. 25 DSG)的判例;如果 entscheidsuche.ch 无法访问,则从离线转储中作答,并明确标注。”

来源覆盖范围数据
entscheidsuche.ch(实时,默认)联邦 + 26 个州约自 2000 年以来的法院判决
SCD dump(离线备用)仅瑞士联邦最高法院,2007–2024 年元数据/判决摘要,无全文

与 fedlex-mcp 协同使用: 法规(SR)+ 判例 = 完整的法律研究。

可用性: entscheidsuche.ch 是一项没有 SLA 的非营利基础设施。无法访问时,服务会透明地回退到缓存的公共转储(参见离线备用)。每个响应都会声明其来源(source: "live" | "dump"),转储数据的回答还会附带 coverage_note——备用数据仅覆盖部分内容,并不等同于实时数据。


功能

  • 对所有瑞士法院判决进行全文搜索
  • 多阶段法律条文引用搜索,支持正则表达式解析器和 Elasticsearch 加权评分
  • 专用瑞士联邦最高法院搜索,支持审判庭筛选
  • 按州和法院级别筛选
  • 最新判决动态
  • 法院分类列表
  • 含聚合统计的判决统计信息
  • 支持三种语言(德语、法语、意大利语)
  • 当 entscheidsuche.ch 无法访问时,离线回退到缓存的公共转储,并在每个响应中明确标注来源
  • 无需 API 密钥

前提条件

  • Python 3.11 或更高版本
  • 兼容 MCP 的客户端(Claude Desktop、Cursor、Windsurf 等)

安装

pip install swiss-courts-mcp

或从源码安装:

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

快速开始

# Run directly
swiss-courts-mcp

# Or via Python module
python -m swiss_courts_mcp

配置

Claude Desktop

将以下内容添加到你的 claude_desktop_config.json:

{
  "mcpServers": {
    "swiss-courts": {
      "command": "python",
      "args": ["-m", "swiss_courts_mcp"]
    }
  }
}
云端部署(HTTP 传输)

HTTP 传输默认关闭。默认绑定主机为 127.0.0.1 (仅限回环地址)——必须显式选择 0.0.0.0(Dockerfile 中已如此设置)。 在未启用身份验证的情况下运行 HTTP 会记录警告;仅应在经过身份验证的反向代理后运行。

# 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

相关环境变量(参见 .env.example):

变量默认值用途
MCP_HOST127.0.0.1绑定主机。仅在容器中设置为 0.0.0.0。
MCP_PORT8000绑定端口。
MCP_ALLOW_PUBLIC_BINDfalse抑制 0.0.0.0 警告(容器)。
MCP_STATELESS_HTTPtrue无状态 HTTP → 无需粘性会话即可水平扩展。
MCP_AUTH_ENABLEDfalse为 HTTP 启用 bearer 令牌身份验证。
MCP_AUTH_SECRET—HS256 签名密钥(开发环境)。
MCP_OAUTH_JWKS_URL—用于 RS256 验证的 JWKS URL(生产环境)。
MCP_OAUTH_AUDIENCE—启用身份验证时必填。 IdP 将令牌绑定到的资源标识符(aud)。
MCP_OAUTH_ISSUER—启用身份验证时必填。 签发令牌的 IdP 的签发者(iss),按字符逐一比对。
MCP_RESOURCE_URL绑定地址此服务的公开 URL——RFC 9728 资源标识符。在任何非回环绑定时都应设置。
MCP_REQUIRED_SCOPES—以逗号分隔的必需作用域。
MCP_CORS_ORIGINS—以逗号分隔的允许来源(生产环境中不能使用通配符)。

身份验证仅根据 JWT 的 sub 声明验证用户身份;参见 ADR 0001。

启用身份验证后,必须设置 MCP_OAUTH_AUDIENCE。 aud 声明用于将令牌绑定到此服务。如果没有该设置,验证器完全不会检查受众,并会接受来自同一签发者的任何有效签名令牌——包括为其他服务签发的令牌(混淆代理问题)。现在,服务在身份验证模式下启动时若未设置该变量,就会拒绝启动。

出于令牌另一端的相同原因,也必须设置 MCP_OAUTH_ISSUER。 iss 声明将令牌绑定到此服务信任的那个 IdP。多个租户共用一个 JWKS URL 时(托管 IdP 中的常见情况),这一点尤其重要:此时签名对所有租户都有效,只有 iss 能将它们区分开来。实测中,未设置该变量但受众正确时,iss: https://another-tenant.example 的令牌被接受,不含 iss 的令牌也被接受。该值按照 RFC 8414/9207 进行字面比对,包括结尾斜杠,因此不会被规范化——这与会去除结尾斜杠的 MCP_RESOURCE_URL 不同。

该变量也是发现机制正常工作所必需的。RFC 9728 文档中的 authorization_servers[0] 是 SDK 客户端采用的授权服务器值。如果未设置该变量,服务会将自身列为授权服务器——而访问该地址下的 /.well-known/oauth-authorization-server、 /.well-known/openid-configuration、/authorize、/token 和 /register 时都会返回 404,因为此服务是资源服务器,而非授权服务器。

OAuth 客户端需要 MCP_RESOURCE_URL。 根据 RFC 9728,服务会在 /.well-known/oauth-protected-resource 发布资源标识符,并将其写入每个 401 响应的 WWW-Authenticate 标头——客户端会通过它查找获取令牌的位置。如果未设置该变量,服务会发布其绑定地址;在容器绑定场景下实测结果为 {"resource": "http://0.0.0.0:8000", …},客户端无法连接到该地址。在任何非回环绑定时都应设置该变量;若未设置,服务会在启动时发出警告。

由于有实测原因,SDK 自带的 validate_token_resource 保持关闭:它会将令牌的资源指示符与 resource_server_url 进行字面比对,而此处的 resource_server_url 是绑定地址。受众并非该精确 URL 的令牌会被拒绝并返回 401——因此,启用此检查会排斥所有真实客户端,而上文的受众检查才是真正保护服务的机制。

离线回退(环境变量)
变量默认值用途
SWISS_COURTS_FALLBACK_ENABLEDtrue总开关。设为 0 可禁用转储回退(仅实时模式)。
SWISS_COURTS_FORCE_DUMPfalse强制使用转储路径(跳过实时模式)——用于预热缓存或离线测试。
SWISS_COURTS_CACHE_DIRplatformdirs cache覆盖下载转储文件的缓存目录。
SWISS_COURTS_DUMP_RECORD14867950要使用的 SCD 转储文件的 Zenodo 记录 ID。

预热缓存(一次性下载约 120 MB 的 SCD CSV 文件,避免首次真正发生中断时还要花时间下载):

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

MCP 协议版本

此服务通过同一端点提供两个协议时代;客户端的第一个请求决定使用哪个:

时代修订版本server.py 中的常量握手
旧版2025-11-25HANDSHAKE_PROTOCOL_VERSIONinitialize,会话 ID
现代2026-07-28MODERN_PROTOCOL_VERSION无——每个请求都带有 _meta 信封

两个修订版本均已固定,且都有针对已安装 SDK 的漂移防护,因此协议升级会是经过慎重考虑的变更(常量 + CHANGELOG + 本节)。SDK 每月通过 Dependabot 更新。

SDK 自带的客户端选择的是规范 2026-07-28 所属的时代。 mcp.Client 会探测 server/discover,只有在探测被拒绝时才回退到握手;对于此服务,它不会回退。此结果是在 tests/test_modern_era.py 中通过组装后的 ASGI 堆栈测得,而非根据常量名称推断得出。

现代时代的差异:

  • 没有 initialize,没有会话 ID。 每个 POST 都是独立的,并带有包含协议版本和客户端能力的 params._meta,以及路由标头 MCP-Protocol-Version、Mcp-Method,还有(对于 tools/call、 prompts/get、resources/read)Mcp-Name。
  • server/discover 取代握手以发现能力,而 subscriptions/listen 取代变更通知。
  • ping、logging/setLevel 和 resources/subscribe 组合均已移除。 在此时代,服务会以 -32601 响应这些请求;旧版时代则仍保留这些功能。
  • ttlMs / cacheScope 随列表方法传递(SEP-2549)——参见 CACHE_HINTS。
  • serverInfo 会写入每个响应的 _meta,因为握手不再承载一次性信息。它包含构建版本、显示标题和项目 URL;用途说明保留在 instructions 中,该字段随 server/discover 传递一次。

即使 initialize 请求使用 2026-07-28,得到的仍是 2025-11-25:握手不是进入现代时代的方式,而该响应也不能说明服务是否支持现代时代。

项目阶段

阶段 1——只读(参见 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离线转储缓存状态、覆盖范围、版本及预热情况(只读)
工具注释

所有 8 个工具具有相同的提示:它们是只读、幂等、非破坏性的,并且会访问外部系统:

注释值
readOnlyHinttrue
destructiveHintfalse
idempotentHinttrue
openWorldHinttrue

此外还提供了一个 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")

→ 按受众浏览更多使用场景 →


架构

┌─────────────────────────────────────┐
│         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 │
└──────────────────────────┘   └───────────────────────────────────────┘

始终优先使用实时数据:只有在实时数据不可用(机器人拦截、HTTP 5xx/429、超时)或被强制启用时,才会使用离线转储。这是现有工具的行为,并非独立的搜索工具 — 为什么选择此数据源而非全文数据源,请参阅 ADR 0002;有关其覆盖范围及未覆盖内容,请参阅已知限制。你可以随时使用 get_fallback_status 检查缓存。


安全与限制

方面详情
访问权限只读(readOnlyHint: true)— 服务无法修改或删除任何数据
个人数据不含个人数据 — 所有裁决均为公开的法院判决
速率限制内置每次查询上限(每次搜索最多 50 条结果,最多 50 个聚合桶)
超时每次 API 调用 30 秒
数据源身份验证无需 API 密钥 — entscheidsuche.ch 可公开访问
HTTP 传输身份验证可选的 bearer-token 身份验证(JWT,sub 声明用于标识身份);请参阅 ADR 0001
出站流量代码层允许列表(实时数据为 entscheidsuche.ch;离线转储为 zenodo.org),强制使用 HTTPS;请参阅出站流量策略
错误屏蔽内部异常仅记录在服务端;客户端会收到易于理解的消息
密钥代码和日志中不包含密钥;.env 已加入 Git 忽略规则,PR 上运行 Gitleaks;请参阅密钥管理
许可根据瑞士法律,法院裁决属于公有领域(BGG Art. 27)
服务条款受 entscheidsuche.ch 使用条款约束 — 请友善使用服务器

已知限制

  • 搜索仅限 entscheidsuche.ch 已编入索引的判决(并非所有判决都已公开)
  • 不会返回文档全文内容——仅返回元数据、标题和摘要
  • 统计数据取决于后端对 Elasticsearch 聚合的支持
  • Facetten_alle.json 中的法院分类结构可能会变化

**离线回退(覆盖范围有限——请阅读):**回退机制是保障可用性的安全网,并非实时来源的等效镜像:

  • 法院范围:仅涵盖联邦最高法院(BGer/BGE)。不涵盖联邦行政法院、联邦刑事法院以及全部 26 个州级法院。
  • **时间范围:**2007 年至 2024 年 12 月(SCD 转储的范围)。此时间段以外的判决不在转储中。
  • 内容:仅包含元数据/摘要——离线时没有全文。
  • **更新延迟:**SCD 转储大约每季度在 Zenodo 上更新一次,因此离线数据会滞后于实时索引。get_fallback_status 会报告缓存版本,并可检查 Zenodo 是否有更新版本。
  • 离线法律条文引用搜索仅匹配判决主题/摘要(topic/issue)中提及的引用——离线没有法律条文引用索引。
  • **离线时的 get_court_decision 尽力而为:**SCD 案件 ID(docref,例如 1C_517/2016)与 entscheidsuche 签名不同,因此有些查询会如实报告为无法解析。
  • 响应始终通过 source(live/dump)和 coverage_note 说明来源;服务绝不会静默缩小覆盖范围——查询未涵盖时会明确回答“未涵盖”,绝不会静默返回空结果。

测试

单元测试使用 respx 模拟所有 HTTP 请求。请从项目根目录运行。CI 运行的五项检查——check_gate_docs.py 会将此列表与 ci.yml 对照,确保它不会悄然过时:

PYTHONPATH=src pytest tests/ -m "not live"
python scripts/check_ruff_pin.py
ruff check src/ tests/ scripts/
ruff format --check src/ tests/ scripts/
python scripts/check_version_sync.py
python scripts/check_gate_docs.py

实时测试不是检查门槛——它们会访问真实来源,并按计划运行(live.yml),而不是在拉取请求时运行:

PYTHONPATH=src pytest tests/ -v -m live

编辑 live.yml 属于特殊情况:GitHub 仅会在默认分支上执行 schedule,因此更改要在合并后才会生效——请手动触发(workflow_dispatch),以便在此之前测试更改。

离线回退测试使用 respx 模拟 Zenodo 下载,并使用一个已提交的小型测试样本——CI 不会下载约 120 MB 的转储文件。


更新日志

请参阅 CHANGELOG.md。


参与贡献

请参阅 CONTRIBUTING.md。


安全

有关安全状况以及如何报告漏洞,请参阅 SECURITY.md。


许可证

MIT


作者

Hayal Oezkan · malkreide


致谢与相关项目

安装

通过 uv 的 uvx 运行——无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):

{
  "mcpServers": {
    "swiss-courts-mcp": {
      "command": "uvx",
      "args": [
        "swiss-courts-mcp"
      ]
    }
  }
}

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。