关于 sbb-opendata-mcp
sbb-opendata-mcp 通过 OpenDataSoft API 向 AI 应用和兼容 MCP 的客户端提供瑞士联邦铁路公开数据。数据涵盖铁路运营、车站、基础设施和房地产,并同时返回结构化结果与可读内容。
主要功能
- 01按车站查询客流
- 02获取当前铁路中断信息
- 03查询基建与房地产项目
- 04查询列车数量和站台数据
- 05比较车站并搜索停靠点
- 06浏览数据集目录
适用场景
- 01查看瑞士铁路当前中断情况
- 02比较主要车站的客流
- 03查找站台信息和附近停靠点
MCP 相关
提供读取 SBB 开放数据的 MCP 工具,支持 stdio 和 Streamable HTTP 传输。结果包含结构化内容,并可输出 Markdown 或 JSON。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
9收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| params | any | 是 |
详细介绍
🚆 sbb-opendata-mcp
🇨🇭 属于 瑞士公共数据 MCP 项目组合
将 AI 模型连接到瑞士联邦铁路(SBB)开放数据的 MCP 服务——包括客流量、铁路实时中断、基础设施与房地产项目、列车数量、站台数据、车辆信息,以及来自 data.sbb.ch 的车站搜索。无需 API 密钥。
演示
概述
sbb-opendata-mcp 让 Claude 等 AI 助手能够直接访问 SBB 公共数据,无需复制粘贴或手动调用 API。诸如 “2024 年每天有多少乘客经过 Zürich HB?” 这样的问题,可以通过真实测量数据得到解答。
SBB 开放数据门户使用 OpenDataSoft REST API(v2.1)。此服务会将数据转换为简洁的 Markdown 和 JSON,供 AI 模型使用;还会在便于阅读的文本之外提供 MCP structuredContent,让程序化客户端无需重新解析即可使用底层记录。此服务与模型无关,可与任何兼容 MCP 的客户端配合使用。
示例查询: “比较 Zürich HB、Bern 和 Basel SBB 的客流量与站台容量。” → 按受众分类的更多使用场景 →
功能
- 📊 客流量 – 按车站和年份统计上车/下车人数(日均值)
- 🚨 铁路实时中断 – 交通通知,每 5 分钟更新一次
- 🏗️ 基础设施项目 – 车站和线路建设
- 🏢 房地产项目 – SBB 房地产开发(每日更新)
- 🚆 分路段列车数量 – 按线路统计列车数量(SBB、BLS、SOB 等)
- 🛤️ 站台数据 – 长度、类型、面积、无障碍通行
- 🚃 车辆信息 – 运力和建造年份
- 🔁 车站对比 – 跨多个数据集比较多达 10 个车站
- 🔍 车站搜索 – 瑞士 DiDok 注册库(覆盖整个瑞士)
- 📦 数据集目录 – 列出全部约 89 个 SBB 开放数据集
- 🔑 无需 API 密钥 – 所有数据均为公开数据,可免费使用
- ☁️ 双传输方式 – 使用 stdio 连接 Claude Desktop,使用 Streamable HTTP 部署到云端
前提条件
- Python 3.11+
- 无需 API 密钥——所有数据均来自公共门户 data.sbb.ch
安装 uv(推荐):
curl -LsSf https://astral.sh/uv/install.sh | sh
安装
从 PyPI 安装:
pip install sbb-opendata-mcp
或使用 uvx(无需永久安装):
uvx sbb-opendata-mcp
进行本地开发时,从克隆的仓库以可编辑模式安装:
git clone https://github.com/malkreide/sbb-opendata-mcp.git
cd sbb-opendata-mcp
pip install -e ".[dev]"
快速开始
# Start the server (stdio mode for Claude Desktop)
sbb-opendata-mcp
在 Claude Desktop 中立即试用:
“2024 年每天有多少人在 Zürich HB 上车?” “瑞士铁路网络当前是否有中断?”
配置
环境变量
服务器通过 stdio 运行时无需配置。以下变量用于调整可选的 Streamable HTTP 传输、日志和可观测性。
| 变量 | 作用 | 默认值 |
|---|---|---|
MCP_HOST | HTTP 传输的绑定主机。在本地使用时保持为 127.0.0.1;只有在受控的容器/云环境中才绑定到 0.0.0.0。 | 127.0.0.1 |
MCP_PORT | HTTP 传输的端口。 | 8000 |
MCP_ALLOWED_HOSTS | 以逗号分隔的主机允许列表,用于防范 DNS 重绑定(例如 your-app.onrender.com,your-app.onrender.com:*)。 | 仅 localhost |
MCP_ALLOWED_ORIGINS | 以逗号分隔的浏览器来源允许列表(例如 https://your-app.onrender.com)。 | (none) |
LOG_LEVEL | 日志详细程度(DEBUG/INFO/WARNING/…)。 | INFO |
LOG_FORMAT | 使用 json 输出结构化日志;其他值则输出便于阅读的文本。始终写入 stderr。 | text |
🔒 DNS 重绑定/Origin 防护始终启用;localhost 已加入允许列表,因此本地 HTTP 开发开箱即用。日志写入 stderr——stdout 留作 stdio JSON-RPC 通道使用。
Claude Desktop 配置
{
"mcpServers": {
"sbb-opendata": {
"command": "uvx",
"args": ["sbb-opendata-mcp"]
}
}
}
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
重启 Claude Desktop——首次使用时会自动下载服务器。
其他 MCP 客户端
适用于 Cursor、Windsurf、VS Code + Continue、LibreChat、Cline,以及通过 mcp-proxy 使用的可自托管模型——配置与上述相同。
云端部署(Streamable HTTP)
适用于通过浏览器中的 claude.ai 或远程服务使用(例如 Render.com)。云端传输使用 Streamable HTTP(端点 /mcp)。
Docker(推荐):
# Build + run with explicit resource limits (see docker-compose.yml)
docker compose up --build
# → http://127.0.0.1:8000/mcp
该镜像采用多阶段构建,并以非 root 用户身份运行;docker-compose.yml 添加了 read_only、no-new-privileges 以及内存/CPU/PID 限制。
手动部署/Render.com:
pip install -e .
# Bind publicly (behind a rate-limiting reverse proxy) and configure
# DNS-rebinding / Origin protection for your hostname:
export MCP_HOST=0.0.0.0
export MCP_ALLOWED_HOSTS="your-app.onrender.com,your-app.onrender.com:*"
export MCP_ALLOWED_ORIGINS="https://your-app.onrender.com"
python -m sbb_opendata_mcp.server --http --port 8000
⚠️ 绑定: 在网络传输中,服务器默认绑定到
127.0.0.1,因此本地启动的服务器不会暴露给整个网络。仅在容器/云环境中,当确实需要绑定所有接口时,才设置MCP_HOST=0.0.0.0(Docker 镜像会自动设置此项),并将服务器置于实施速率限制的反向代理之后(若端点不应公开,还需进行身份验证)。详见SECURITY.md。
可用工具
| 工具 | 描述 | 数据更新频率 |
|---|---|---|
sbb_get_passenger_frequency | 按车站和年份统计的上下车人数(每日平均值) | 每年 |
sbb_get_rail_disruptions | 实时铁路交通消息 | 每 5 分钟 |
sbb_get_real_estate_projects | SBB 房地产开发项目 | 每日 |
sbb_get_trains_per_segment | 按路线区段统计的列车数量(SBB、BLS、SOB …) | 每年 |
sbb_get_platform_data | 站台数据(长度、类型、面积) | 持续更新 |
sbb_get_rolling_stock | 车辆数据(载客量、建造年份) | 持续更新 |
sbb_compare_stations | 比较最多 10 个车站(多数据集) | – |
sbb_search_stations | 搜索站点(瑞士 DiDok 登记册,涵盖全瑞士) | 持续更新 |
sbb_list_datasets | 列出全部约 89 个 SBB 开放数据集 | – |
所有工具都支持 response_format: "markdown"(便于阅读)和 "json"(便于机器读取),并支持分页。每个工具还会在渲染后的文本旁返回 MCP structuredContent(底层记录/元数据),并通过 outputSchema 声明其结构。错误结果会设置 isError: true,并返回 {error, upstream_unavailable}。
示例用例
| 查询 | 工具 |
|---|---|
| “2024 年每天有多少人在 Zürich HB 上车?” | sbb_get_passenger_frequency |
| “瑞士铁路网目前有哪些运营中断?” | sbb_get_rail_disruptions |
| “比较 Zürich HB、Bern 和 Basel SBB” | sbb_compare_stations |
| “SBB 有哪些正在进行的房地产建设项目?” | sbb_get_real_estate_projects |
| “Zürich–Winterthur 路线上每年有多少列火车运行?” | sbb_get_trains_per_segment |
| “Wädenswil 有哪些站点?” | sbb_search_stations |
架构
┌─────────────────┐ ┌───────────────────────────┐ ┌──────────────────────────┐
│ Claude / AI │────▶│ SBB Open Data MCP │────▶│ data.sbb.ch │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ │
└─────────────────┘ │ │ │ OpenDataSoft REST v2.1 │
│ 9 Tools │ │ (public, no API key) │
│ Stdio | Streamable HTTP │ │ │
│ │ │ passagierfrequenz │
│ Shared httpx client │ │ rail-traffic-information │
│ (pooled, lifespan-managed)│ │ construction-projects │
│ ODSQL escaping + Pydantic │ │ perron · rollmaterial │
│ validation │ │ zugzahlen · dienststellen│
└───────────────────────────┘ └──────────────────────────┘
项目结构
sbb-opendata-mcp/
├── src/sbb_opendata_mcp/
│ ├── __init__.py
│ └── server.py # FastMCP server, all 10 tool definitions
├── tests/
│ └── test_server.py # Unit + live API smoke tests
├── audits/ # MCP best-practice audit evidence
├── docs/assets/demo.svg # README demo asset
├── .github/workflows/ci.yml # GitHub Actions (Python 3.11/3.12/3.13)
├── Dockerfile # Multi-stage, non-root runtime image
├── docker-compose.yml # Local run with resource limits
├── claude_desktop_config.json # Example Claude Desktop config
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── SECURITY.md
├── EXAMPLES.md
├── LICENSE
├── README.md # This file (English)
└── README.de.md # German version
安全与限制
- **只读:**所有 9 个工具都只执行只读 HTTP GET 请求,不会在上游写入、修改或删除数据。
- **不涉及个人数据:**查询仅临时处理,不会存储。门户返回的是汇总统计、基础设施和运营元数据,不会处理或保留 PII。
- **无需 API 密钥:**数据公开且免费,无需身份验证,也无需管理密钥。
- 防注入:
year/canton会经过正则表达式验证,插入 ODSQLwhere子句的每个值都会通过中央辅助函数进行转义。 - **数据时效性:**实时工具(运营中断)会反映查询时的上游数据源;统计数据集每年/每天更新(参见工具表)。
- **服务条款:**数据依据 data.sbb.ch 许可证发布(允许非商业用途、允许商业用途、要求注明出处)。
- **不作保证:**此服务是社区项目,与 SBB 无关联。服务可用性取决于上游 API。
完整的安全说明请参阅 SECURITY.md。
已知限制
- **客流量:**每年更新;最新完整年度的数据可能会延迟数月。
- **铁路运营中断:**返回所有当前的瑞士铁路消息 → 使用
limit和分页。 - **区间列车数量:**数量为年度汇总数据,并非实时数据。
- **车站搜索:**覆盖完整的瑞士 DiDok 注册表(所有运营商),而不仅仅是 SBB。
- **自身不进行速率限制:**请将公开的 HTTP 部署置于具备速率限制功能的反向代理之后。
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 时不会悄然改变其中任一版本。两项线上协议测试会通过 mcp.streamable_http_app()(--http 提供的应用)针对每个时代发送真实请求,并从响应中读取修订版本:一项是无会话的 2026-07-28 server/discover POST,另一项是请求 2026-07-28 的 initialize,其响应会限制在 2025-11-25。
除了 SDK 自身的功能外,此服务为 2026-07-28 提供的内容固定在
tests/test_spec_2026_07_28.py 中:完整的 serverInfo(现代时代会在每个结果中附上此信息;如果没有 version,读取结果就是 "")、每个工具顶层的 title、每个工具的 outputSchema(服务和 SDK 客户端都会根据它进行验证),以及列表方法上的 ttlMs/cacheScope。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时代的别名,而不是握手时代的别名——若只根据它固定版本,当前客户端实际协商的时代仍会任其漂移。
更新策略。 门禁失败时,不要盲目修改常量:先阅读两个修订版本之间的规范变更日志,确认服务仍正常运行,然后一并更新常量、本节、README.de.md 和
CHANGELOG.md。
测试
无需 API 密钥。
# Unit tests (no network required)
PYTHONPATH=src pytest tests/ -m "not live"
# Live API smoke tests (require network access to data.sbb.ch)
PYTHONPATH=src pytest tests/ -m live
# Re-record the fixtures from data.sbb.ch (writes tests/fixtures/PROVENANCE.md)
python scripts/record_fixtures.py
单元测试的负载均为实录,并非杜撰。每个文件的来源、检索日期、筛选规则和 SHA-256 值记录在
tests/fixtures/PROVENANCE.md 中。
tests/fixtures/dataset_fields.json 不是数据摘录,而是契约:
Explore v2.1 API 会声明每个数据集的字段名称;如果 select 或 order_by 使用了该数据集不存在的字段,API 会返回 HTTP 400,而不是减少列数。TestFieldContract 会根据这份声明核对服务使用的每个字段名称,因此下一次重命名会导致测试失败,而不是让用户的请求失败。截至 2026-08-08,十个工具中有三个正是因此一直无法正常工作。
CI 不会运行线上测试(
-m "not live")。这三个故障工具中有两个曾经有覆盖它们的线上测试——test_live_search_waedenswil和test_live_list_datasets。测试覆盖确实存在,但测试并未运行。
更新日志
参见 CHANGELOG.md
贡献
安全
有关安全状况和漏洞报告方式,请参见 SECURITY.md (Deutsch)。
许可证
MIT License — 参见 LICENSE
作者
Hayal Oezkan · github.com/malkreide
致谢与相关项目
- 数据: data.sbb.ch – 瑞士联邦铁路(SBB)开放数据,OpenDataSoft REST API v2.1
- 协议: Model Context Protocol – Anthropic / Linux Foundation
- 相关项目:
- swiss-transport-mcp – 实时班次、行程与服务中断信息(opentransportdata.swiss)
- swiss-road-mobility-mcp – 微出行与电动汽车充电
- zurich-opendata-mcp – 用于苏黎世市开放数据的 MCP 服务
- 作品集: Swiss Public Data MCP Portfolio
安装
通过 uv 的 uvx 运行——无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"sbb-opendata-mcp": {
"command": "uvx",
"args": [
"sbb-opendata-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。