关于 parlament-mcp
parlament-mcp 通过 Curia Vista API 将瑞士联邦议会数据接入 AI 应用。它支持搜索议会事务,并提供带引文的辩论摘录或全文,无需 API 密钥。
主要功能
- 01搜索议会事务
- 02获取议案详情
- 03查找议员与投票
- 04列出议会会议
- 05搜索并获取辩论记录
适用场景
- 01按主题和状态查找待处理动议
- 02按州或党派查找议员
- 03获取议会发言的带引文原文
MCP 相关
向 MCP 客户端提供只读工具,用于搜索和获取联邦议会事务、议员、投票、会议及辩论记录。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🏛️ parlament-mcp
属于 Swiss Public Data MCP Portfolio – 将 AI 模型连接到瑞士公共数据源。
注意:此服务覆盖联邦层面(Curia Vista)。本仓库还包含一个独立的子项目
openparldata-mcp/——面向 26 个州和约 70 个市级议会的州及市级对应项目(OpenParlData.ch)。这两个项目是独立的服务。
一个通过 Curia Vista OData API(ws.parlament.ch)将 AI 模型连接到瑞士联邦议会的 MCP 服务。无需 API 密钥即可访问动议、质询、投票、议员、会议,以及《官方公报》(Amtliches Bulletin)的辩论逐字记录(第一阶段——优先免认证)。
🎯 标杆示例查询
元数据层:
“哪些关于学校 AI 的动议仍在处理中?” →
parlament_search_business(keyword="KI", keyword2="Schule", status="Eingereicht")
逐字记录(《官方公报》):
“Munz 国民议会议员在 2024 年春季会议上对 Volksschule 说了什么?请提供准确原文和正确的 AB 引用。” →
parlament_search_transcripts(speaker_name="Munz", session_id=5202, keyword="Volksschule")→ 然后调用parlament_get_transcript(transcript_id=…)获取完整原文。返回简短、可引用的摘录(
AB 2024 N, 2024-03-13, Munz Martina),并附带稳定的来源 URL;逐字文本按需获取,绝不批量获取。
非常适合苏黎世市政府 AI 专家组:查找有关教育领域 AI 的待处理动议,或即时引用议事厅里实际说过的话。
🔧 工具
| 工具 | 描述 |
|---|---|
parlament_search_business | 按关键词、类型、状态、议院和日期搜索动议 |
parlament_get_business | 获取单个议案的完整详情(文本、FC 答复) |
parlament_search_members | 按州(例如 ZH)、政党和议院查找议员 |
parlament_get_votes | 获取议会投票及 Ja/Nein 含义 |
parlament_get_sessions | 列出近期会议及其 ID,供后续查询使用 |
parlament_search_transcripts | 搜索辩论记录 → 可引用的摘录,附 AB 引用和来源 URL(可按发言者 / 会议 / 议案 / 日期筛选) |
parlament_get_transcript | 按 ID 获取单篇发言的完整逐字文本(设有上限、分页,并标记 is_excerpt) |
🏗️ 架构
┌──────────────────────────────────┐
│ MCP Host (Claude Desktop / │
│ Claude API / IDE) │
└─────────────┬─────────────────────┘
│ MCP Protocol (JSON-RPC 2.0)
│ Transport: stdio (local) / SSE (cloud)
┌─────────────▼─────────────────────┐
│ parlament-mcp │
│ FastMCP · Python · Pydantic v2 │
│ │
│ ┌── metadata layer (server.py) ──┐
│ │ search_business · get_business │
│ │ search_members · get_votes │
│ │ get_sessions │
│ └─────────────────────────────────┘
│ ┌── transcript layer ────────────┐ ← separate module (transcripts.py)
│ │ search_transcripts (excerpts) │ · Language='DE' dedups editions
│ │ get_transcript (verbatim) │ · Type=1 = real speeches only
│ └─────────────────────────────────┘ · retry + 45s read timeout
└─────────────┬─────────────────────┘
│ HTTPS / OData v3
┌─────────────▼─────────────────────┐
│ ws.parlament.ch / odata.svc │
│ Curia Vista – No Auth Required │
│ │
│ Business · Vote · MemberCouncil │ metadata path
│ Session ─< Meeting ─< Subject ─< Transcript transcript path
└───────────────────────────────────┘
🚀 安装
Claude Desktop(stdio)
添加到 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"parlament": {
"command": "uvx",
"args": ["parlament-mcp"]
}
}
}
本地开发
git clone https://github.com/malkreide/parlament-mcp
cd parlament-mcp
pip install -e .
python -m parlament_mcp.server
云端 / Railway(SSE)
MCP_TRANSPORT=sse MCP_HOST=0.0.0.0 PORT=8080 python -m parlament_mcp.server
# SSE endpoint: http://your-host:8080/sse
网络绑定
默认情况下,服务绑定到 127.0.0.1(仅限 localhost)。仅在容器 / 云环境(Docker、Railway、Render、Kubernetes)中设置 MCP_HOST=0.0.0.0。切勿在本地开发机器上绑定到 0.0.0.0,否则会将服务暴露给本地网络(存在 NeighborJack 风险);若在未检测到容器的环境中这样操作,服务会记录警告。
传输方式通过 MCP_TRANSPORT 选择(默认为 stdio,也可设为 sse / streamable-http);--http 仍作为 streamable-http 的别名保留。
身份验证(可选)
HTTP 传输默认开放(公开只读数据)。如需使用 bearer token,请通过 CORS/身份验证应用工厂提供服务,并设置 MCP_BEARER_TOKENS:
MCP_BEARER_TOKENS="alice:tok_abc,bob:tok_def" MCP_ALLOWED_ORIGINS="https://claude.ai" \
uvicorn parlament_mcp.server:create_http_app --factory --host 0.0.0.0 --port 8080
此后,每个请求都需要 Authorization: Bearer <token>;身份信息来自经过验证的 token,而非会话标头(参见 docs/security.md)。
Docker
docker compose up --build # binds 127.0.0.1:8080 only
# or build the hardened image directly (non-root, read-only FS):
docker build -t parlament-mcp .
Kubernetes 清单(加固的 securityContext、资源限制、出站 NetworkPolicy、Mcp-Session-Id 粘性路由)位于 deploy/k8s/;HAProxy 粘性表示例位于 deploy/haproxy.cfg。
🔗 协同组合
| 合作方服务 | 组合方式 |
|---|---|
openparldata-mcp | 联邦 ↔ 次国家级 — 同一问题横跨各州和市镇 |
fedlex-mcp | 法律文本 ↔ 制定该法律的议会辩论 |
zurich-opendata-mcp | 城市政策 ↔ 州级/联邦动议 |
swiss-statistics-mcp | 数据依据 ↔ 引用统计数据的动议 |
强力查询示例:
"Zeige mir alle Zürcher Motionen zu KI in der Bildung
und verlinke die relevanten Bundesgesetze aus fedlex-mcp."
📊 数据来源
- API: ws.parlament.ch/odata.svc
- 身份验证: 无(阶段 1——优先采用无身份验证方式)
- 协议: OData v3 / JSON
- 覆盖范围: 自 1978 年以来的所有议会事务;约自 2000 年以来的表决。 自 1999-12-06 起的结构化逐字记录(Amtliches Bulletin) (1891–1999 年的较早记录仅以档案扫描件形式存在——参见已知限制)。
- 更新周期: 实时(官方政府数据)
版权——允许逐字引用
瑞士当局的官方记录不受版权保护,依据为 Art. 5 para. 1 lit. a URG(《瑞士版权法》)。因此,Amtliches Bulletin 中 议会辩论的逐字内容可以自由转载和引用——这正是记录工具返回的内容:原文 本身,而非代替原文的摘要。
📜 数据来源与许可证
| 来源 | 许可证 | 署名 |
|---|---|---|
| Curia Vista (ws.parlament.ch) | CC BY 4.0 | © Schweizer Parlament,CC BY 4.0 |
每个工具都会返回带类型的结构化响应(FastMCP 会公开输出架构),其中包含
source、license、provenance、match_type 和 count,以及带类型的
results。数据未经修改直接传递。
🧭 阶段
此服务处于阶段 1——只读封装器(所有工具均为 readOnlyHint: true,
不执行写入)。完整的阶段模型和转换标准见
docs/roadmap.md。
🔖 MCP 协议版本
此服务通过同一个端点支持两个协议时期。客户端在连接上的首个请求决定适用哪个时期;之后若声称属于另一个时期,则会被拒绝。
| 时期 | 修订版本 | 适用对象 |
|---|---|---|
initialize 握手 | 2024-11-05 … 2025-11-25 | 当前客户端使用的协议。服务会使用请求指定的修订版本作答;若请求指定了更新的版本,则使用 2025-11-25 这一上限。 |
| 按请求封装 | 2026-07-28 | 携带 2026-07-28 _meta 封装的请求会建立现代连接。 |
两个修订版本都在
tests/test_protocol_version.py 中固定,并与已安装的 SDK 进行断言,因此 Dependabot 升级 mcp 时,不会悄然更改其中任何一个。该文件还会测量协商情况:每个时期都使用一个真实客户端连接已注册的服务,并直接读取连接上的修订版本,而不是根据常量推断。
在 2026-07-28 时期,没有用于承载服务身份信息的握手;SDK 会将 io.modelcontextprotocol/serverInfo 写入结果的 _meta。服务会在其中传递自己的软件包版本
(tests/test_server_info.py),因此两个时期报告的版本相同。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时期的别名,而非握手时期的别名——仅以它为基准固定版本,会使当前客户端实际协商的时期版本继续漂移。
更新策略。 门禁检查失败时,不要盲目编辑常量:请阅读两个修订版本之间的规范更新日志,验证服务仍能正常工作,然后一并更新常量、本节、README.de.md 和 CHANGELOG.md。
🧱 MCP 原语
第 1 阶段仅使用工具——设计依据和第 2 阶段资源计划见
docs/adr/ADR-003-mcp-primitives.md。
🏷️ 工具注解
所有工具都声明了与其行为一致的显式注解:
| 工具 | 只读 | 破坏性 | 幂等 | 开放世界 |
|---|---|---|---|---|
parlament_search_business | ✅ | — | ✅ | ✅ |
parlament_get_business | ✅ | — | ✅ | ✅ |
parlament_search_members | ✅ | — | ✅ | ✅ |
parlament_get_votes | ✅ | — | ✅ | ✅ |
parlament_get_sessions | ✅ | — | ✅ | ✅ |
parlament_search_transcripts | ✅ | — | ✅ | ✅ |
parlament_get_transcript | ✅ | — | ✅ | ✅ |
📈 可观测性
结构化 JSON 日志会写入 stderr(stdout 保留给 stdio 协议使用)。OpenTelemetry 跟踪会包装每次工具调用,并自动检测发出的 HTTP 请求;设置 OTEL_EXPORTER_OTLP_ENDPOINT(并启用 otel-export extra)即可发送跟踪数据。完整的安全态势(Lethal-Trifecta 评估、出站流量允许列表、网关加固)请参阅 docs/security.md。
🛡️ 安全与限制
| 方面 | 详情 |
|---|---|
| 访问权限 | 只读(readOnlyHint: true)——服务无法修改或删除任何数据 |
| 个人数据 | 根据法律(BGÖ),议会事务属于公开记录。不会访问或存储私人数据。 |
| 速率限制 | 内置每次查询上限:最多 100 条结果(议会事务/议员)、50 条(投票)、30 条(会议记录搜索)、10 条(会议)。会议记录全文按次调用设有上限,并采用分页方式——不会意外拉取整场会议的内容。 |
| 超时 | 每次元数据调用 20 秒;读取会议记录 45 秒(逐字搜索开销较大) |
| 身份验证 | 无需 API 密钥——Curia Vista 可公开访问 |
| 数据来源 | 瑞士联邦政府官方数据(Schweizerische Parlamentsdienste) |
| 服务条款 | 受 ws.parlament.ch 的服务条款约束——Schweizerische Parlamentsdienste |
已知限制
通用
- OData
substringof()筛选器对某些字段区分大小写。 - 对于非常近期的会话,API 中的会话名称可能为
null——请使用会话 ID。
记录稿(Amtliches Bulletin) — 已于 2026-07-19 在线验证:
- 时间覆盖范围:仅从 1999-12-06 开始。 结构化的
Transcript实体可追溯至 1999 年 12 月。1891–1999 年的辩论仅存在于扫描版档案文件中(Bundesarchiv / Amtsdruckschriften),未接入此处(OCR 不在范围内)。日期范围完全早于覆盖范围的查询会返回说明性错误,而非空结果。 - 源数据中没有页码。 API 不包含页码或栏号字段,因此无法生成经典的
AB <year> N <page>格式。我们提供稳定、可验证的替代格式——AB <year> <N|S>, <date>, <speaker>——以及权威的source_url(SubjectId)和transcript_id。这是有据可查且坦诚的权衡,并非遗漏。 - 语言行为(重要)。
Language表示的是版本,而非发言语言。工具筛选Language eq 'DE'仅用于去重,将三个字节完全相同的版本(DE/FR/IT)缩减为一份。每篇发言均以其原始措辞返回;法语或意大利语发言不会被隐藏,其实际语言会在language字段中标明(de/fr/it)。响应通过language_note说明了这一点。 - 截断会明确标示,绝不静默处理。 搜索会返回较短的摘录(
snippet,约 320 个字符),并附带is_excerpt、total_length_chars以及获取全文的提示。parlament_get_transcript会将输出限制在max_chars;发生截断时,会设置is_excerpt=True,并返回可用于继续获取的next_offset。 - 仅提供逐字原文,绝不提供摘要。 措辞本身就是产品;工具绝不会用摘要替代实际文本。
- 延迟: 将自由文本
keyword与speaker_name结合使用是最慢的路径(约 40 秒)。添加session_id、business_number或日期范围,可将读取时间控制在约 1–2 秒。
🧪 测试
pip install -e ".[dev]"
# Unit + mocked integration tests (no network), as run in CI:
PYTHONPATH=src pytest tests/ -m "not live"
# Include live tests against the real ws.parlament.ch API:
PYTHONPATH=src pytest tests/ -m live
HTTP 请求使用 respx 模拟;依赖网络的测试标记为
@pytest.mark.live,并通过 -m "not live" 从 CI 中排除。工具定义固定在
tool-hashes.json 中(python -m parlament_mcp.tool_hashes --check)。
贡献
请参阅 CONTRIBUTING.md。
安全
安全政策和安全态势(漏洞报告、Lethal-Trifecta 评估、已接受的风险)请参阅 SECURITY.md。
许可证
MIT © Hayal Oezkan — 请参阅 LICENSE
作者
Hayal Oezkan · github.com/malkreide
安装
通过 uv 的 uvx 运行——无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"parlament-mcp": {
"command": "uvx",
"args": [
"parlament-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。