关于 zurich-opendata-mcp
zurich-opendata-mcp 为研究者、居民及公共部门用户提供苏黎世市开放数据查询,覆盖数据集、实时环境与交通、地理信息和市政事务。它将多个城市数据源汇集为 MCP 工具与资源。
主要功能
- 01搜索并查询开放数据集
- 02实时天气、空气和水情
- 03实时停车与客流信息
- 04地理图层及 GeoJSON 要素
- 05议会、市政决议与旅游数据
适用场景
- 01查找苏黎世学校相关数据集
- 02查询当前天气、空气质量或停车位
- 03获取学校设施或游乐场地理数据
- 04检索议会记录和市政决议
MCP 相关
该 MCP 服务向兼容客户端提供城市开放数据查询工具和资源,包括数据集元数据、停车信息、地理数据及旅游分类。默认使用 stdio,也可通过 Streamable HTTP 提供服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
26收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| params | any | 是 |
详细介绍
🇨🇭 属于瑞士公共数据 MCP 组合
🏙️ 苏黎世开放数据 MCP 服务
🌐 英语 | 德语
一个 MCP(Model Context Protocol)服务,提供 AI 驱动的方式来访问瑞士苏黎世市的开放数据。
让 Claude、ChatGPT 及其他兼容 MCP 的 AI 助手可以直接查询苏黎世市的 900 多个数据集、地理数据、议会会议记录、市议会决议、旅游数据、关联数据,以及实时环境和交通信息。23 个工具(另有 3 个已弃用的别名)、5 个资源、6 个 API。
演示
✨ 功能
CKAN 开放数据(data.stadt-zuerich.ch)
zurich_search_datasets– 使用 Solr 语法对 900 多个数据集进行全文搜索zurich_get_dataset– 获取数据集的完整元数据和下载 URLzurich_datastore_query– 直接查询表格数据(筛选、排序)zurich_datastore_sql– 在 DataStore 上执行 SQL 查询zurich_list_categories– 浏览 19 个主题类别zurich_list_tags– 按标签进行主题搜索
实时环境数据
zurich_weather_live– 🌤️ 当前天气(温度、湿度、气压、降雨),数据来自 4 个 UGZ 站点zurich_air_quality– 🌬️ 实时空气质量(NO₂、O₃、PM10、PM2.5),附 WHO 阈值zurich_water_weather– 🌊 苏黎世湖数据(水温、水位、风况),每 10 分钟更新一次
实时交通数据
zurich_pedestrian_traffic– 🚶 班霍夫大街的行人计数(3 个地点,按小时统计)zurich_vbz_passengers– 🚊 VBZ 公共交通客流量(800,000 多条记录,覆盖所有线路和站点)zurich_parking_live– 🅿️ 36 个停车场的实时占用情况(ParkenDD)
地理门户(WFS 地理数据)
zurich_geo_layers– 📍 列出 14 个可用的地理数据图层zurich_geo_features– 📍 获取 GeoJSON 要素(学校、城区、游乐场、气候数据等)
市议会(Paris API)
zurich_parliament_search– 🏛️ 搜索议会会议记录(质询、动议、提案)zurich_parliament_members– 🏛️ 搜索议员(政党、委员会、职务)
苏黎世旅游
zurich_tourism– 🏨 景点、餐厅、酒店、活动(Schema.org 数据,支持 4 种语言)
关联数据(SPARQL)
zurich_sparql– 📊 在统计关联数据端点上执行 SPARQL 查询*(该端点尚未投入生产使用——默认情况下不会注册此工具;可通过环境变量ZURICH_OPENDATA_ENABLE_SPARQL=1启用)*
市议会决议
zurich_strb_search– 📜 对公开的市议会决议进行全文搜索(标题、部门、日期范围)zurich_strb_by_department– 📜 列出某个部门的所有决议(例如SSD、FD、PRD)zurich_strb_detail– 📜 按NNNN/YYYY编号查询单项决议
(此前使用的名称 search_stadtratsbeschluesse、get_beschluesse_by_departement 和 get_stadtratsbeschluss_detail 将继续作为已弃用的别名提供,直至下一个主版本发布。)
分析工具
zurich_analyze_datasets– 综合分析:相关性、时效性、数据结构zurich_catalog_stats– 包含统计数据的目录概览zurich_find_school_data– 精选搜索教育相关数据集
MCP 资源
zurich://dataset/{name}– 数据集元数据zurich://category/{group_id}– 类别详情zurich://parking– 当前停车数据zurich://geo/{layer_id}– GeoJSON 地理数据(14 个图层)zurich://tourism/categories– 旅游类别
🚀 安装
先决条件
- Python 3.11+
- pip 或 uv
mcp[cli]2.x — 自动安装;服务使用 2.x API (mcp.server.mcpserver),无法在mcp1.x 上运行
请使用 0.6.0 或更高版本。 Release
0.5.1声明了mcp[cli]>=1.28.1,但没有 设定上限。mcp2.0.0 移除了mcp.server.fastmcp后,所有全新安装的0.5.1都会解析到 2.0.0,并在导入时因ModuleNotFoundError而失败。0.6.0使用 2.x API,并将版本固定为>=2.0.0,<3。 如果你使用的是0.5.1,请升级——该版本已不存在可用的配置。
安装
# Clone
git clone https://github.com/malkreide/zurich-opendata-mcp.git
cd zurich-opendata-mcp
# Install
pip install -e .
# Or with uv
uv pip install -e .
⚙️ 配置
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS):
{
"mcpServers": {
"zurich-opendata": {
"command": "python",
"args": ["-m", "zurich_opendata_mcp.server"],
"env": {}
}
}
}
也可以使用已安装的命令:
{
"mcpServers": {
"zurich-opendata": {
"command": "zurich-opendata-mcp"
}
}
}
Claude Code(CLI)
claude mcp add zurich-opendata -- python -m zurich_opendata_mcp.server
Cursor / VS Code
添加到 .vscode/settings.json:
{
"mcpServers": {
"zurich-opendata": {
"command": "python",
"args": ["-m", "zurich_opendata_mcp.server"]
}
}
}
💬 示例查询
配置完成后,你可以向 Claude 提问:
开放数据
- “苏黎世有哪些关于学校的数据集?”
- “显示公立学校的学校假期”
- “分析可用的地理数据”
实时数据
- “苏黎世当前的气温是多少?” →
zurich_weather_live - “今天的空气质量怎么样?” →
zurich_air_quality - “苏黎世湖的水温是多少?” →
zurich_water_weather - “现在有多少个空闲停车位?” →
zurich_parking_live - “现在有多少人在班霍夫大街上?” →
zurich_pedestrian_traffic
地理数据
- “以 GeoJSON 格式显示苏黎世的所有学校设施” →
zurich_geo_features - “有哪些可用的地理数据图层?” →
zurich_geo_layers - “苏黎世的游乐场在哪里?”
市议会
- “有哪些关于学校的议会动议提交过?” →
zurich_parliament_search - “哪些议员属于 SP 党?” →
zurich_parliament_members
市议会决议(Stadtratsbeschlüsse)
- “查找 2025 年关于 Volksschule 的市议会决议” →
zurich_strb_search - “列出 2025 年所有 SSD 决议” →
zurich_strb_by_department - “显示市议会决议 1203/2025” →
zurich_strb_detail
旅游
- “苏黎世旅游局推荐了哪些餐厅?” →
zurich_tourism
🔗 数据来源
| API | Endpoint | 数据 |
|---|---|---|
| CKAN | data.stadt-zuerich.ch/api/3/ | 900 多个开放数据集 |
| Geoportal WFS | ogd.stadt-zuerich.ch/wfs/geoportal | 14 个地理数据图层(GeoJSON) |
| Paris API | gemeinderat-zuerich.ch/api | 议会会议记录和议员 |
| Zurich Tourism | zuerich.com/en/api/v2/data | 景点、餐厅、酒店 |
| SPARQL | ld.stadt-zuerich.ch/query | 关联开放数据 / 统计数据 |
| ParkenDD | api.parkendd.de/Zuerich | 实时停车占用情况 |
📊 可用数据类别
| 类别 | ID |
|---|---|
| 就业 | arbeit-und-erwerb |
| 底图 | basiskarten |
| 建设与住房 | bauen-und-wohnen |
| 人口 | bevolkerung |
| 教育 | bildung |
| 能源 | energie |
| 财政 | finanzen |
| 休闲 | freizeit |
| 健康 | gesundheit |
| 犯罪 | kriminalitat |
| 文化 | kultur |
| 出行 | mobilitat |
| 政治 | politik |
| 价格 | preise |
| 社会事务 | soziales |
| 旅游 | tourismus |
| 环境 | umwelt |
| 行政管理 | verwaltung |
| 经济 | volkswirtschaft |
📍 可用的地理图层
权威来源:src/zurich_opendata_mcp/config.py 中的 GEOPORTAL_LAYERS。
| 图层 ID | 说明 |
|---|---|
schulanlagen | 学校设施(幼儿园、学校、课后托管) |
schulkreise | 学区边界(多边形) |
schulwege | 上学路线交叉点和危险点 |
stadtkreise | 城市区边界(多边形) |
spielplaetze | 公共游乐场 |
kreisbuero | 城市区办事处 |
sammelstelle | 废弃物收集点 |
sport | 体育设施 |
klimadaten | 气候数据(栅格、温度、热岛) |
lehrpfade | 教育步道 |
stimmlokale | 投票站 |
sozialzentrum | 社会服务中心 |
velopruefstrecken | 学校自行车考试路线 |
familienberatung | 家庭咨询会面点 |
🏗️ 项目结构
zurich-opendata-mcp/
├── src/zurich_opendata_mcp/
│ ├── __init__.py
│ ├── app.py # Shared FastMCP instance
│ ├── server.py # Console entry + back-compat re-exports
│ ├── config.py # Endpoints, layer maps, resource IDs
│ ├── http_client.py # Shared httpx client + CKAN wrapper
│ ├── formatters.py # CKAN→model mapping + Markdown rendering
│ ├── models.py # Pydantic structured-output models
│ ├── clients/ # API clients: paris, sparql, tourism, wfs
│ └── tools/ # @mcp.tool implementations:
│ # catalog, datastore, geo, parliament,
│ # realtime, sparql, strb, tourism,
│ # resources (zurich:// URIs)
├── tests/ # respx round-trip, unit and live-marked tests
├── audits/ # Code-audit reports
├── .github/workflows/ # ci.yml + publish.yml (Trusted Publisher)
├── pyproject.toml
├── README.md / README.de.md
├── CONTRIBUTING.md / .de.md
├── SECURITY.md / .de.md
├── CHANGELOG.md
├── CLAUDE.md # Project conventions for Claude
├── LICENSE
└── claude_desktop_config.json
🧪 开发
# Install dev dependencies
pip install -e ".[dev]"
# Unit + validation tests (no network)
pytest tests/ -m "not live"
# Live integration tests (against live APIs — opt-in)
pytest tests/ -m live
# Linting
ruff check src/ tests/
🌐 HTTP 传输
默认情况下,服务通过 stdio 使用 MCP。使用 --http 后则改为提供 Streamable HTTP:
zurich-opendata-mcp --http --port 8000 # binds 127.0.0.1 (default)
zurich-opendata-mcp --http --host 0.0.0.0 --port 8000
| 选项 | 含义 | 默认值 |
|---|---|---|
--http | 提供 Streamable HTTP,而非 stdio | (关闭 → stdio) |
--host | 绑定地址 | 127.0.0.1 |
--port | 绑定端口(1–65535) | 8000 |
MCP_ALLOWED_HOSTS | 以逗号分隔的此服务可通过其访问的名称,包括端口(例如 zurich.example.ch:8000)。任何其他 Host 下的请求都会收到 421;允许环回地址,以便容器健康检查继续正常运行。 | (未设置) |
默认使用环回地址是有意为之。 绑定到 0.0.0.0 会让所有能够访问这台机器的人都能通过每个网络接口访问服务——它前面没有身份验证。
绑定到环回地址之外的地址时,请设置 MCP_ALLOWED_HOSTS。 这可以防范 DNS 重绑定:网络中的某个网页将自己的主机名解析到此服务的地址,然后从浏览器与其通信。从浏览器的角度看,该请求属于同源请求,因此没有任何源规则会阻止它——只有 Host 检查可以做到。
若绑定到非环回地址但未设置此变量,检查会保持关闭,并记录警告。只有当前置组件会验证 Host 时,这才是合适的默认行为。这里不会尝试猜测:在 0.0.0.0 上,进程无法知道可访问的名称;猜错了,就会用 421 拒绝所有请求,反而影响它原本要保护的部署。
MCP 协议版本
此服务在同一端点上支持两个协议时代。客户端在连接上的首个请求决定适用哪个时代;之后若声称属于另一个时代,则会被拒绝。
| 时代 | 修订版本 | 可连接的客户端 |
|---|---|---|
initialize 握手 | 2024-11-05 … 2025-11-25 | 当前客户端所使用的版本。服务会以请求指定的修订版本作答;若请求的是更新版本,则使用 2025-11-25 这一上限。 |
| 每请求信封 | 2026-07-28 | 携带 2026-07-28 _meta 信封的请求会建立现代连接。 |
这两个修订版本固定在 tests/test_protocol_version.py 中,门禁会对它们进行双重检查:它会测量进程内 mcp.Client 实际与此服务协商出的修订版本(涵盖两个时代,通过内存传输——不经过 ASGI,也不经过网络),并且会读取 SDK 常量,确保 Dependabot 对 mcp 的升级不会悄悄改变任一版本。测量部分是关键保障:即使某个时代停止提供服务,而其常量保持不变,测试仍会失败。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是指向现代时代的别名,而不是握手时代的别名——仅依靠它来固定版本,会让当前客户端实际协商的时代版本悄然漂移。
此服务器在 2026-07-28 的原生行为
修订版不只是 SDK 采用的一个数字。其中三项变更对服务器本身提出了要求,而此版本都已满足:
| 规范变更 | 此服务器的行为 |
|---|---|
SEP-2549 — 列表方法中的 ttlMs / cacheScope | tools/list、resources/list、resources/templates/list 和 server/discover 均携带 ttlMs 300000、cacheScope public。如果没有这些字段,SDK 就会对导入时已固定的目录回复“已过期,绝不共享”。resources/read 特意不携带提示:那将是对内容而非目录的承诺。 |
SEP-2575 — 不调用 initialize,因此每个结果都携带身份信息 | 每个结果的 _meta 都带有 io.modelcontextprotocol/serverInfo,其中包含名称、标题、版本、描述和 websiteUrl。未设置 version= 的 MCPServer 会在每个答复中写入空字符串,而 SDK 不会自行替换。 |
SEP-2575 — server/discover 是唯一可以提供说明的地方 | 服务器提供 instructions;即使无状态调用方从未发送 initialize,也能了解目录 → 资源 UUID → DataStore 的顺序,以及实时读数的有效时长。 |
次要变更 #3(tools/list SHOULD 按确定顺序排列)由工具管理器的插入顺序满足;该顺序遵循 server.py 中固定的导入顺序。测试会将线路上的顺序与之比较。
有一项能力属于 SDK,而非此服务器:由于提供了 subscriptions/listen,能力区块会声明 listChanged 和 resources.subscribe。此服务器的目录在导入时固定,且从不发出变更通知。我们已对此进行测量,并保持现状——能力声明的是该方法已提供,这确实属实。
更新策略。 如果检查未通过,不要盲目修改常量:先阅读两个修订版之间的规范变更日志,确认服务器仍按预期运行,然后同步更新常量、本节、README.de.md 和 CHANGELOG.md。
安全与限制
- 只读: 所有工具仅执行 HTTP GET 请求,不会写入、修改或删除数据。
- 不涉及个人数据: 这些 API 返回开放的城市数据集(停车位占用情况、天气读数、议会会议记录)。此服务器不会处理或存储任何个人身份信息(PII)。
- 速率限制: CKAN Solr 搜索和 ParkenDD 是未记录速率限制的公共 API;请谨慎使用
rows和limit参数。服务器会对每个请求施加 30s 超时;上游暂时性错误(连接失败、HTTP 502/503/504)会在短暂退避后重试一次。 - 数据新鲜度: 实时工具(停车、天气、空气质量)会反映查询时上游来源的数据。测量数据绝不会缓存;只有当前年度 UGZ 资源 ID(天气/空气质量)的查询会在进程内缓存 24h。
- 服务条款: 数据受各来源的服务条款约束 — data.stadt-zuerich.ch、ParkenDD、gemeinderat-zuerich.ch。苏黎世市的所有数据均以 CC0 发布(自 2021 年起默认开放)。
- 不作保证: 此服务器是社区项目,与苏黎世市或任何 API 提供方均无关联。服务可用性取决于上游 API。
🤝 参与贡献
欢迎贡献 — 参见 CONTRIBUTING.md(Deutsch)。
🔒 安全
只读、不涉及 PII、无需身份验证,且仅使用一组固定的公共数据端点。完整的安全状况和已接受风险的决策,参见 SECURITY.md(Deutsch)。
📜 许可证
MIT License — 参见 LICENSE。使用的所有数据均以开放许可证发布(CC0/自 2021 年起默认开放)。
👤 作者
Hayal Oezkan · malkreide
由 Model Context Protocol 提供支持 • 6 个 API • 23 个工具 • 5 个资源
安装
通过 uv 的 uvx 运行,无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"zurich-opendata-mcp": {
"command": "uvx",
"args": [
"zurich-opendata-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。