mcpField
O
openlex-mcp

openlex-mcp

本地服务
github.com法律与政务04 周前更新

关于 openlex-mcp

openlex-mcp 为 MCP 客户端提供苏黎世州约 970 部法律的查询与条文提取,结合本地全文索引和 zh.ch 实时元数据。适用于法律检索及教育法规查询。

主要功能

  1. 01全文检索并按相关性排序
  2. 02按编号或简称获取法规
  3. 03提取条文并搜索条文内容
  4. 04专用教育法规检索
  5. 05获取实时有效状态和 PDF 链接

适用场景

  1. 01查找有关数据保护的法规
  2. 02检索 Volksschulgesetz 指定条文
  3. 03查找提及特定词语的教育法规条文

MCP 相关

以 MCP 服务形式向客户端提供法规搜索、获取、条文提取、元数据和缓存管理工具,支持 stdio 与 Streamable HTTP。

配置

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

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

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

安装包
pypiopenlex-mcp0.3.0

工具

还没有获取到工具列表

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

详细介绍

🇨🇭 属于 Swiss Public Data MCP Portfolio

⚖️ openlex-mcp

Version License: MIT Python 3.11+ MCP No Auth Required

苏黎世州立法(ZH-Lex)的 MCP 服务——为约 970 部州级法律提供全文搜索、条文提取和教育法工具

🇩🇪 德语版

演示:Claude 通过 MCP 工具调用搜索苏黎世教育法


概述

openlex-mcp 提供对苏黎世州全部法律汇编(Zürcher Gesetzessammlung)的 AI 原生访问。它结合来自 HuggingFace 的全文数据与瑞士联邦网站 zh.ch 的实时元数据,并将所有内容存储在本地 SQLite 数据库中,通过 FTS5 全文索引实现低于 50 ms 的搜索性能。

来源数据访问方式
HuggingFace974 部 ZH 法律——全文(PDF 提取内容)在本地缓存为 SQLite + FTS5
zh.ch ZH-Lex当前元数据、PDF 链接、有效状态实时 HTTP 请求

本项目为苏黎世市教育局(Schulamt)打造,但涵盖州级法律的所有领域——从税法到建筑法规。

演示示例查询: “《义务教育法》(Volksschulgesetz)对家长参与有何规定?请展示 VSG 第 55 条,并找出所有提及‘Elternrat’的条文。”


功能

  • ⚖️ 8 个工具,涵盖搜索、检索、条文提取和缓存管理
  • 🔍 FTS5 全文搜索,覆盖约 970 部州级法律,并采用 BM25 排序
  • 📑 条文提取——解析单条条文(Art. / §),并检测段落
  • 🏫 教育法快捷工具——针对 LS 412.x 系列提供专门搜索(《义务教育法》、教师条例等)
  • 🌐 来自 zh.ch 的实时元数据,提供当前有效状态和 PDF 链接
  • 💾 混合架构——缓存全文(HuggingFace)+ 实时元数据(zh.ch)
  • 🔓 无需 API 密钥——所有数据均采用开放许可(CC-BY-SA 4.0)
  • ☁️ 双传输方式——stdio(Claude Desktop)+ Streamable HTTP(云端)

开发阶段

当前阶段:第 1 阶段——只读。 所有工具均为只读(readOnlyHint: true);不会向外部系统写入数据。有关阶段计划及添加任何写入或多 Agent 功能前的转换门槛,请参阅 ROADMAP.md。


前置条件

  • Python 3.11+
  • uv(推荐)或 pip
  • 互联网连接(用于首次下载数据和获取实时元数据)

安装

# Clone the repository
git clone https://github.com/malkreide/openlex-mcp.git
cd openlex-mcp

# Install
pip install -e .
# or with uv:
uv pip install -e .

快速开始

# stdio (for Claude Desktop)
python -m openlex_mcp.server

# Streamable HTTP — binds to 127.0.0.1:8000 by default (localhost only)
python -m openlex_mcp.server --http --port 8000
网络绑定

默认情况下,HTTP 传输绑定到 127.0.0.1(仅限本地主机)。主机和端口可通过 MCP_HOST / MCP_PORT 环境变量配置 (也可使用 --host / --port CLI 标志;后者优先)。

在容器外切勿绑定到 0.0.0.0——这会将服务暴露给本地网络(存在 NeighborJack 风险)。对于容器化或云端部署,请显式设置 MCP_HOST=0.0.0.0;如果在未检测到容器的情况下这样设置,服务会记录警告。

立即在 Claude Desktop 中试用:

“什么是《义务教育法》(VSG)?” “查找所有关于数据保护的苏黎世法律” “请展示《义务教育法》第 1 条” “哪些教育法提到了‘Schulleitung’?”


配置

Claude Desktop

编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):

{
  "mcpServers": {
    "openlex": {
      "command": "python",
      "args": ["-m", "openlex_mcp.server"]
    }
  }
}

或使用已安装的入口点:

{
  "mcpServers": {
    "openlex": {
      "command": "openlex-mcp"
    }
  }
}

配置文件位置:

  • macOS:~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json
云部署(用于浏览器访问的 SSE)

通过浏览器中的 claude.ai 使用(例如,在没有本地软件的受管工作站上):

Render.com(推荐):

  1. 将仓库推送到 GitHub,或在 GitHub 上派生仓库
  2. 在 render.com 上:新建 Web Service → 连接 GitHub 仓库
  3. 设置启动命令:python -m openlex_mcp.server --http --port 8000
  4. 设置环境变量 MCP_HOST=0.0.0.0,使容器可访问 (代码默认值为 127.0.0.1;Render 会设置 RENDER 环境变量,因此 不会记录 NeighborJack 警告)
  5. 设置 MCP_CORS_ORIGINS=https://claude.ai,以便浏览器读取 Mcp-Session-Id 标头(以逗号分隔的列表;不能使用通配符——默认值为 空,即不允许跨域访问)
  6. 在 claude.ai 的“Settings → MCP Servers”下,添加:https://your-app.onrender.com/sse

💡 “面向开发者笔记本电脑使用 stdio,面向浏览器使用 SSE。”


可用工具

搜索与浏览
工具描述
openlex__zhlaw_search_laws在全部约 970 部 ZH 法律中进行全文搜索(FTS5 + BM25 排序)
openlex__zhlaw_get_law按 LS 编号(例如 412.100)或缩写(例如 VSG)获取法律
openlex__zhlaw_list_laws按法律领域前缀列出并筛选法律
openlex__zhlaw_find_education_laws在教育法(LS 412.x 系列)中进行专项搜索
条文提取
工具描述
openlex__zhlaw_get_article从法律中提取特定条文(例如 Art. 28 VSG)
openlex__zhlaw_search_articles在特定法律的所有条文中搜索
元数据与缓存
工具描述
openlex__zhlaw_get_law_metadata从 zh.ch 获取实时元数据(PDF 链接、有效状态)
openlex__zhlaw_update_cache从 HuggingFace 刷新本地数据缓存
主要法律领域前缀(LS 编号)
前缀法律领域示例
131宪法与公民权利Kantonsverfassung
170行政程序Datenschutzgesetz
331税法Steuergesetz
412教育与学校Volksschulgesetz(VSG)
700空间规划与建筑Planungs- und Baugesetz
810卫生Gesundheitsgesetz
示例用例
查询工具
“什么是 Volksschulgesetz?”openlex__zhlaw_get_law
“查找有关数据保护的法律”openlex__zhlaw_search_laws
“显示 Art. 55 VSG”openlex__zhlaw_get_article
“哪些教育法律提到了 Schulleitung?”openlex__zhlaw_find_education_laws
“查找 VSG 中所有关于 Elternrat 的条文”openlex__zhlaw_search_articles
“LS 412.100 目前仍有效吗?”openlex__zhlaw_get_law_metadata

架构

┌─────────────────┐     ┌──────────────────────────────┐     ┌──────────────────────────┐
│   Claude / AI   │────▶│  OpenLex MCP                 │────▶│  HuggingFace             │
│   (MCP Host)    │◀────│  (MCP Server)                │◀────│  rcds/swiss_legislation   │
└─────────────────┘     │                              │     │  (974 ZH laws, cached)   │
                        │  8 Tools                     │     ├──────────────────────────┤
                        │  SQLite + FTS5 Cache         │────▶│  zh.ch ZH-Lex            │
                        │  Stdio | HTTP                │◀────│  (live metadata + PDFs)  │
                        │                              │     ├──────────────────────────┤
                        │  No authentication required  │     │  LexFind.ch              │
                        └──────────────────────────────┘     │  (links only)            │
                                                             └──────────────────────────┘
数据源特征
来源协议覆盖范围身份验证许可证
HuggingFace rcds/swiss_legislationDatasets API974 部 ZH 法律(全文)无CC-BY-SA 4.0
zh.ch ZH-LexHTTP/HTML当前元数据、PDF无公共
LexFind.chHTTP跨州链接无公共
设计决策:仅使用工具(不使用 MCP 资源)

全部 8 个端点都作为 工具 暴露,而不是 MCP 资源。原因如下:

  • 每次查询都是参数化的——查询内容、缩写和条文编号会因调用而异。静态资源(每份文档对应一个 URI)无法自然地适应这一点。
  • 语料库包含 974 部法律 × 众多条文——若将每部法律都注册为资源 URI,资源列表会大到不切实际。
  • MCP 资源模板(zhlex://laws/{sr_number})可作为 Phase 2 的未来考虑,前提是客户端能从资源级缓存或订阅中受益。
扩展限制

限制取决于客户端使用的协议时代:

  • 2026-07-28(现代)——每个请求都是一个独立的 POST,携带自己的 _meta 信封;服务端无需发送 Mcp-Session-Id 即可响应,并且不会在请求之间保留会话。任意副本都可以处理任意请求;无需共享存储,也无需固定路由。(subscriptions/listen 流会留在开启它的副本上——此服务的列表在导入时即已固定,因此无需向其他副本转发。)
  • 握手时代(initialize,截至 2025-11-25)——会话状态保存在进程内。多个副本会破坏活动会话,因为没有共享会话存储(Redis、Durable Objects 等)。单副本 Render 部署会将所有请求路由到同一进程,因此目前不需要粘性会话负载均衡器。

在将握手时代的客户端扩展到多个实例之前:要么添加共享会话存储,要么配置边缘负载均衡器,根据 Mcp-Session-Id 标头使用粘性表和适当的 TTL 进行路由。


MCP 协议版本

项目值
通过 initialize 握手提供2024-11-05 … 2025-11-25 — 握手上限
通过每请求信封提供2026-07-28
由谁选择客户端在每次连接的首次请求中选择。携带 2026-07-28 _meta 信封的请求会开启现代连接;其他请求则会开启握手连接。
SDKmcp[cli]>=2.0.0,<3
缓存提示tools/list、prompts/list、resources/list、resources/templates/list 和 server/discover:ttlMs 300000,cacheScope public
serverInfo.version软件包版本(openlex_mcp.__version__),包含在每个 server/discover 结果中
在 2026-07-28 中已弃用,未使用日志记录(ctx.info/ctx.warning,SEP-2577)——状态放入工具结果,诊断信息写入服务端日志
固定于src/openlex_mcp/server.py — MCP_PROTOCOL_VERSION 常量
更新策略
  1. 升级 mcp(通过 Dependabot PR)时,核对 SDK 发行说明中的协议版本。
  2. 如果协议版本发生变化,更新 server.py 中的 MCP_PROTOCOL_VERSION,重新生成 docs/tool-hashes.json(PYTHONPATH=src python scripts/gen_tool_hashes.py --write),并在 CHANGELOG.md 中注明变更。
  3. 合并前运行 pytest tests/ -m "not live",确认兼容性。

项目结构

openlex-mcp/
├── src/openlex_mcp/
│   ├── __init__.py              # Package
│   ├── __main__.py              # Entry point for python -m
│   ├── server.py                # 8 MCP tool definitions (FastMCP) + Settings
│   ├── responses.py             # Typed structured response envelopes (SDK-002)
│   ├── logging_config.py        # structlog JSON logging setup (OBS-003)
│   ├── net.py                   # SSRF/egress-hardened outbound HTTP
│   ├── api_client.py            # zh.ch HTTP client + metadata extraction
│   ├── data_cache.py            # SQLite + FTS5 cache management
│   └── law_parser.py            # Article extraction from law texts
├── tests/                       # 89 unit tests (parser, cache, net, tools…)
├── scripts/gen_tool_hashes.py   # Tool-definition hash snapshot (SEC-022)
├── docs/                        # network-egress, secret-management, tool-hashes
├── .github/workflows/ci.yml     # GitHub Actions (Python 3.11/3.12/3.13)
├── .github/dependabot.yml       # Monthly grouped dependency PRs (ARCH-012)
├── Dockerfile                   # Hardened multi-stage build (SEC-007/SCALE-004)
├── compose.yml                  # Resource limits for local testing (SCALE-006)
├── pyproject.toml
├── claude_desktop_config.json   # Example config for Claude Desktop
├── CHANGELOG.md
├── ROADMAP.md                   # Phase plan + accepted-risk register
├── CONTRIBUTING.md              # Contribution guide (English)
├── CONTRIBUTING.de.md           # Contribution guide (German)
├── SECURITY.md                  # Security policy (English)
├── SECURITY.de.md               # Security policy (German)
├── LICENSE
├── README.md                    # This file (English)
└── README.de.md                 # German version
工具输出格式

所有工具都会返回结构化响应信封(而非 Markdown 文本),因此 MCP 客户端会收到可直接解析的 structuredContent:

{
  "source": "Kanton Zürich Rechtssammlung — HuggingFace … & zh.ch",
  "provenance": "cache",          // cache | live | parser | cache+parser | none
  "result_type": "law_summaries", // law_summaries | law_detail | articles | metadata | cache_status
  "count": 2,
  "message": null,                // human-readable guidance for empty/edge results
  "results": [ /* typed items */ ]
}

已知限制

  • HuggingFace 数据集: html_content 字段不可靠(不同法律的内容相互污染);服务使用 pdf_content 代替,该字段内容正确,但存在 PDF 提取瑕疵(断词、布局瑕疵)
  • 条文解析器: PDF 文本提取有时会合并条文边界;复杂的嵌套条文可能无法完美解析
  • 首次加载: 首次启动需要约 25 秒从 HuggingFace 下载并索引 974 部法律(SQLite 数据库约 38 MB)
  • zh.ch 元数据: 没有官方 API;元数据提取依赖可能发生变化的 HTML 模式
  • 离线模式: 首次加载后,全文搜索可离线使用;实时元数据需要互联网连接
  • 语料库冻结于 2023-01-01。 对法律服务而言,这是最重要的限制,但此前并未说明。整个数据集中最新版本的 version_active_since = 2023-01-01;HuggingFace 数据集本身最后更新于 2024-10-10。24 小时缓存 TTL 和 provenance="cache" 描述的是答案的来源,而不是其中法律的年代。现在每条响应都会在 provenance 旁附带 corpus_as_of 和 corpus_note。
  • 截止日期之后废止的法律不会显示为已废止。 全部 974 条记录的 is_active = True,且没有一条包含 version_inactive_since。这不是服务缺陷——源数据仅列出快照时生效的法规。重要的是其后果:此后废止的法律仍会显示为有效。请查阅 ZH-Lex 永久链接获取现行文本。
  • zhlaw_update_cache 不会更新法律。 它会重新下载同一份冻结的数据集。其文档字符串之前写着“仅在法律搜索结果似乎过时时调用”,这恰好暗示了它并不具备的效果。

安全与限制

方面详情
访问权限只读(readOnlyHint: true)——服务无法修改或删除任何数据
个人数据不含个人数据——所有来源均为汇总后的公开法律文本
速率限制内置单次查询上限(最多 50 条搜索结果,内容预览最多 5000 个字符)
超时每次向 zh.ch 发起的 HTTP 调用为 30 秒
出站请求出站请求限制在允许列表内(仅允许通过 HTTPS 访问 www.zh.ch,以及仅支持 HTTP 的旧版永久链接主机 www.zhlex.zh.ch),并启用了 SSRF IP 屏蔽和 DNS 固定——参见 docs/network-egress.md
身份验证无需 API 密钥——HuggingFace 数据集为公开数据,zh.ch 开放访问
安全态势(致命三要素)得分 1 / 3:仅公开数据(无私人或敏感数据)✓ · 仅向 *.zh.ch 发起 GET 出站请求——无 POST、无 Webhook、无电子邮件 ✓ · 不执行代码 ✓。从结构上而言,设计安全。
会话处理Mcp-Session-Id 由 MCP SDK 生成和管理(使用密码学安全的 UUID)。不绑定用户身份——对于公开的只读数据,auth_model=none 是正确的。如果将来添加身份验证,请在部署前将会话绑定到经过验证的 OAuth sub 声明。
机密信息不持有机密信息——所有数据源均为公开数据。参见 docs/secret-management.md。
许可协议法律数据:CC-BY-SA 4.0(rcds/swiss_legislation);zh.ch 元数据:公开
服务条款受 HuggingFace 和 苏黎世州 的服务条款约束
免责声明本服务仅出于信息目的提供法律文本,不构成法律建议

如需报告漏洞,请参阅安全政策。


测试

# Unit + contract tests (no network) — this is what CI runs
PYTHONPATH=src pytest tests/ -m "not live"

# Live tests against zh.ch and HuggingFace
PYTHONPATH=src pytest tests/ -m "live"

# Re-measure the corpus date and the live hosts
PYTHONPATH=src python scripts/record_fixtures.py

150 项测试——142 项离线测试,8 项实时测试。八个工具,八项实时测试:这是本项目组合中覆盖率最高的,因此这里发现的问题与运行机制无关,而在于混淆了两个问题。provenance="cache" 回答答案来自何处;corpus_as_of 回答其中的法律有多旧。只有第一个问题得到了回答,而用户问“这是最新的吗?”时,指的正是第二个问题。

有意不通过修改测试来解决的测量限制

在记录环境中,test_live_get_law_metadata 测试失败:该环境无法访问 zhlex.zh.ch。这说明不了任何问题。 公共 DNS 能解析该主机(NOERROR,194.247.8.174),NXDOMAIN 对照也表明查询具有区分能力——因此限制来自环境,而非数据源。

因此,该测试保持原样。如果你的网络无法访问外部资源,导致测试显示红色,就不应该重写测试;重写只会让你测量自己的环境,而不是数据源。PROVENANCE.md 将此问题记录为待解决事项。


更新日志

参见 CHANGELOG.md


路线图

参见 ROADMAP.md


贡献

参见 CONTRIBUTING.md


安全

参见 SECURITY.md


许可证

MIT License——参见 LICENSE


作者

Hayal Oezkan · malkreide


致谢与相关项目

安装

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

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

评论

支持 Markdown

第一次接触 MCP?

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

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