关于 swiss-democracy-mcp
swiss-democracy-mcp 为 MCP 客户端提供瑞士联邦公投、选举及相关统计数据,面向民主研究和公共数据分析。它整合 Swissvotes、BFS 和 SRGSSR Polis;多数数据无需认证,Polis 工具需要凭据。
主要功能
- 01搜索 1848 年以来的联邦公投
- 02查询政党立场与州级结果
- 03获取 BFS 实时及历史投票结果
- 04查询 Polis 公投与选举记录
适用场景
- 01分析特定公投的全国和州级结果
- 02比较政党对提案的建议立场
- 03查询市镇级历史投票或选举数据
MCP 相关
作为 MCP 服务,它向客户端提供只读工具,不提供资源或提示词。工具读取 Swissvotes、BFS 和 SRGSSR Polis 数据;Polis 工具需要 OAuth2 凭据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
10收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| params | any | 是 |
详细介绍
🗳️ swiss-democracy-mcp
🇨🇭 属于 Swiss Public Data MCP Portfolio — 将 AI 模型连接至瑞士机构数据源。
🌐 English | 🇩🇪 德语版
一个 MCP 服务,提供访问瑞士直接民主数据的能力,涵盖自 1848 年以来的所有联邦全民投票,以及自 1900 年以来的选举。
演示查询
«Wie hat der Kanton Zürich bei der AHV 21 Initiative 2022 abgestimmt,
und welche Parteien unterstützten die Vorlage?»
→ democracy_search_votes(keyword="AHV 21", year_from=2022)
→ democracy_get_cantonal_results(vote_number="551")
→ democracy_get_party_positions(vote_number="551")
→ 按受众分类查看更多用例 →
数据源
| 来源 | 覆盖范围 | 身份验证 |
|---|---|---|
| Swissvotes(伯尔尼大学) | 自 1848 年以来的所有联邦投票 · 874 列 · 政党立场 · 州级结果 | 无需 ✓ |
| BFS / opendata.swiss | 实时数据和档案(自 1981 年起)· 市镇级 | 无需 ✓ |
| SRGSSR Polis | 自 1900 年以来的投票和选举 · 市镇级详情 | OAuth2 密钥 |
工具
阶段 1 — Swissvotes(无需身份验证)
| 工具 | 描述 |
|---|---|
democracy_search_votes | 按关键词、日期范围、法律形式、结果、政策领域搜索自 1848 年以来的所有联邦全民投票 |
democracy_get_vote_detail | 查看特定投票的完整详情:官方标题、议会立场、全国结果、签名数 |
democracy_get_party_positions | 政党建议(FDP、SP、SVP、Die Mitte、GPS、GLP 等)及竞选资金数据 |
democracy_get_cantonal_results | 查看全部 26 个州的结果:赞成比例、投票率、通过标记 |
democracy_list_vote_dates | 列出所有投票日期及每个日期的提案数量 |
阶段 2 — BFS 实时数据(无需身份验证)
| 工具 | 描述 |
|---|---|
democracy_bfs_list_vote_dates | 列出所有 BFS 投票日期(档案和当前数据) |
democracy_bfs_get_vote_results | 查看全国、州或市镇级别的实时或存档结果 |
阶段 3 — SRGSSR Polis(需要 API 密钥)
| 工具 | 描述 |
|---|---|
democracy_polis_list_votations | 查看自 1900 年以来的历史投票及市镇级数据 |
democracy_polis_get_votation_detail | 查看完整的 Polis 详情,可选包含所有市镇结果 |
democracy_polis_list_elections | 查看自 1900 年以来的国民院、联邦院和州级选举 |
安装
Claude Desktop(stdio)
添加到 claude_desktop_config.json:
{
"mcpServers": {
"swiss-democracy": {
"command": "uvx",
"args": ["swiss-democracy-mcp"],
"env": {
"SRGSSR_CONSUMER_KEY": "your_key_here",
"SRGSSR_CONSUMER_SECRET": "your_secret_here"
}
}
}
}
SRGSSR_*变量为可选项。不设置这些变量时,所有 Swissvotes 和 BFS 工具仍可正常使用。只有 Polis 工具需要凭据。
云端 / Render.com(Streamable HTTP)
pip install swiss-democracy-mcp
# Bind to all interfaces ONLY inside a container/cloud environment:
MCP_TRANSPORT=streamable_http MCP_HOST=0.0.0.0 MCP_PORT=8000 python -m swiss_democracy_mcp.server
MCP_HOST 默认为 127.0.0.1(环回地址)。仅在沙盒容器/云端部署中设置 MCP_HOST=0.0.0.0 — 切勿在本地机器上设置,否则会使整个网络都能访问该服务。
架构
┌─────────────────────────────────────────────┐
│ Claude / LLM Host │
└──────────────┬──────────────────────────────┘
│ MCP (stdio / Streamable HTTP)
┌──────────────▼──────────────────────────────┐
│ swiss-democracy-mcp │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ Swissvotes CSV Cache (24h TTL) │ │
│ │ All 874 columns, since 1848 │ │
│ └──────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────▼──────────────────────┐ │
│ │ BFS / opendata.swiss (no auth) │ │
│ │ Real-time & archive since 1981 │ │
│ └──────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────▼──────────────────────┐ │
│ │ SRGSSR Polis (OAuth2, optional) │ │
│ │ Votes & elections since 1900 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
传输方式: Claude Desktop 使用 stdio · 云端/Render.com 使用 Streamable HTTP
认证模式: 优先免认证——Swissvotes 和 BFS 无需任何凭据即可使用
缓存: Swissvotes CSV 在启动时加载一次,并缓存 24 小时
配置
所有配置均通过环境变量完成(参见 .env.example):
| 变量 | 默认值 | 用途 |
|---|---|---|
MCP_TRANSPORT | stdio | stdio(本地)或 streamable_http(云端) |
MCP_HOST | 127.0.0.1 | HTTP 绑定地址——仅在容器中设置为 0.0.0.0 |
MCP_PORT | 8000 | HTTP 端口 |
LOG_LEVEL | INFO | 结构化 JSON 日志写入 stderr |
MCP_CORS_ORIGINS | — | HTTP 传输的 CORS 允许来源列表,以逗号分隔。留空表示不允许任何浏览器客户端;* 允许任何来源,并会记录一条警告。stdio 客户端不受影响 |
MCP_ALLOWED_HOSTS | — | 入站 Host 允许列表,以逗号分隔。仅在绑定地址非回环地址时需要 |
SRGSSR_CONSUMER_KEY / SRGSSR_CONSUMER_SECRET | — | 可选,仅用于 democracy_polis_* 工具 |
密钥以 SecretStr 类型保存,绝不会写入日志。请参阅
docs/secret-management.md 和
docs/security.md。
MCP 原语
此服务有意仅公开工具(不提供资源或提示词)。它是一个第 1 阶段的只读数据封装器(参见 docs/roadmap.md);工具集规模较小(10 个面向用例的工具),且每条响应都包含完整的来源信息。资源(例如 vote://{anr})可作为后续阶段的候选方案,待 URI 方案稳定后再考虑。
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 时不会悄然更改任一版本。在这两个文件旁边,
tests/test_server_identity.py 会通过组装好的 ASGI 应用发送真实请求:按请求封套会收到工具列表作为响应,而即使 initialize 提供了现代修订版,也仍会收到握手上限版本。常量表明 SDK 知晓哪些修订版;实测则表明此服务实际提供哪些修订版。
服务身份。 在握手时代,serverInfo 只在 initialize 响应中声明一次。现代时代没有握手,而是在每条响应中添加身份信息,具体为
_meta["io.modelcontextprotocol/serverInfo"]。Implementation.version 是必填的架构字段;如果构造函数中省略该字段,SDK 会预先填入 "",因此版本未设置并非缺失,而是线上传输的一个值——绿色的测试套件也不会显示这一点。此服务会显式传入其发行版本;test_server_identity.py 会在两种协议线上测量该版本,并以一个未经特殊处理的 MCPServer 作为负向对照。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时代的别名,而非握手时代的别名——若只针对它固定版本,当前客户端实际协商的时代就会任其漂移。
更新策略。 门禁失败时,不要盲目编辑常量:阅读两个修订版之间的规范变更日志,验证服务仍能正常运行,然后同步更新常量、本节、README.de.md 和
CHANGELOG.md。
组合使用
与瑞士公共数据 MCP 组合中的其他服务搭配使用:
- zurich-opendata-mcp — 为投票分析添加苏黎世市级统计数据
- swiss-statistics-mcp — 使用按州划分的 BFS 人口统计数据进行补充
- srgssr-mcp — 将 SRF 新闻档案内容关联到具体投票日期
多服务查询示例:
«Vergleiche die Abstimmungsresultate zur AHV-Reform mit der Altersstruktur der Kantone»
→ swiss-democracy-mcp + swiss-statistics-mcp
安全与限制
- 只读: 所有工具仅执行 HTTP GET 请求 — 不会在上游写入、修改或删除任何数据。
- 出站访问允许列表(SSRF 防护): 出站请求仅限固定的可信主机允许列表(
swissvotes.ch、opendata.swiss、*.bfs.admin.ch、api.srgssr.ch),且仅允许 HTTPS。调用方提供的 URL(BFSresult_url)还会经过解析;若指向私有、环回或云元数据 IP 地址段,则会被拒绝。 - 无个人数据: Swissvotes、BFS 和 SRGSSR Polis 提供民主数据汇总信息(投票结果、政党立场、州/市镇统计)。此服务不会处理或存储任何个人身份信息(PII)。
- 速率限制: Swissvotes 是单个 CSV,每 24 小时下载一次并缓存在内存中。BFS / opendata.swiss 和 SRGSSR Polis 是未公布速率限制的公共 API — 请谨慎设置
limit和日期范围。此服务会为每个请求强制设置 30 秒超时。 - 数据时效性: BFS 实时结果反映查询时的上游数据源(不进行本地缓存)。Swissvotes 每 24 小时从伯尔尼大学镜像站刷新一次。
- 服务条款: 数据受各来源的服务条款约束 — swissvotes.ch(CC BY 4.0,伯尔尼大学)、opendata.swiss(大多采用 CC-BY / Open by Default)、SRGSSR Polis(免费套餐,仅限非商业用途)。请始终在下游产品中注明上游来源。
- 不作保证: 此服务是一个社区项目,与伯尔尼大学、联邦统计局或 SRG SSR 均无关联。服务可用性取决于上游 API。
已知限制
- Swissvotes 覆盖范围: 州级结果自 1848 年起可用;市镇级结果仅通过 SRGSSR Polis 提供(自约 1990 年代起,具体取决于投票)。
- BFS 档案: 实时服务仅涵盖自 1981 年起的联邦投票。
- Polis 工具: 需要在 developer.srgssr.ch 免费注册。仅限非商业用途。
- CSV 缓存: Swissvotes 数据集约有数 MB,并在内存中缓存 24 小时。因此,其内存占用高于仅使用 API 的服务。
测试
# Unit tests (no network required)
PYTHONPATH=src pytest tests/ -m "not live" -v
# Live tests (require network access)
PYTHONPATH=src pytest tests/ -m "live" -v
测试数据的来源
tests/fixtures/ 下的测试固件记录自在线数据源,并标注了日期。每个文件的来源、获取日期、筛选规则和 SHA-256 值见:
tests/fixtures/PROVENANCE.md。
python scripts/record_fixtures.py # re-record
这里的关键在于筛选规则。 Swissvotes 数据集包含 714 行
和 874 列,记录的行是按属性而非位置选取的。“前 N 行”的做法
会恰好删掉测试固件所要验证的单元格:占位符 9999(“无
信息”)和 .(“不适用”),它们出现在 714 次投票中的 667 次里。没有这些值的测试固件看起来会很干净,却无法证明任何问题 — 而这正是没人注意到这些工具一直把它们当作实际值传递的原因。
文件中也保留了字节顺序标记,因为源文件包含该标记,而服务会显式移除它。没有这个标记,测试固件就无法证明服务需要执行这一步。
SRGSSR Polis 需要 OAuth 凭据,因此在 PROVENANCE.md 中列为 NOT RECORDED,而不是为其编造一个并不存在的日期。
贡献
请参阅 CONTRIBUTING.md(🇩🇪 Deutsch)。
安全
请参阅 SECURITY.md(🇩🇪 Deutsch),了解安全状况和漏洞报告方式。
许可证
MIT — 请参阅 LICENSE。
数据许可:
- Swissvotes:知识共享署名 4.0
- BFS / opendata.swiss:开放使用
- SRGSSR Polis:仅限非商业用途 — 请参阅 developer.srgssr.ch
作者
Hayal Oezkan · github.com/malkreide
安装
通过 uv 的 uvx 运行——无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"swiss-democracy-mcp": {
"command": "uvx",
"args": [
"swiss-democracy-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。