关于 swiss-statistics-mcp
swiss-statistics-mcp 通过 BFS 的 STAT-TAB PxWeb API,为研究者和公共数据分析者提供瑞士官方统计数据。它支持目录检索、数据筛选、跨州比较,以及市镇历史、建筑和价格指数相关查询,且无需 API 密钥。
主要功能
- 01检索 21 个主题的统计目录
- 02筛选表格并获取数据
- 03比较各州统计数据
- 04查询市镇与历史统计系列
- 05获取建筑活动、投资和价格指数
适用场景
- 01比较各州的人口或社会指标
- 02查找教育统计并提取指定数据
- 03处理市镇合并前后的历史数据
- 04查询建筑活动、投资或价格指数
MCP 相关
作为 MCP 服务,它通过工具向客户端提供 BFS STAT-TAB 和相关公开统计数据,包括目录浏览、数据查询与跨州比较。无需认证,支持 stdio 和 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
📊 swiss-statistics-mcp
通过 STAT-TAB PxWeb API 获取瑞士联邦统计局(BFS)数据的 MCP 服务——涵盖 21 个主题的 682 个数据集,无需身份验证
演示
成熟度
根据 PyPI 分类器,此服务处于 Alpha(0.x) 阶段。在 1.0 版本发布前:
- 工具名称、输入架构和输出 JSON 键可能会在次版本之间变更
- 云端部署应固定到特定的 git 标签,而非
main - 只读开放数据场景可用于生产环境;面向用户的场景则应视为实验性用途
有关破坏性变更,请参阅 CHANGELOG.md。
概述
swiss-statistics-mcp 可通过 STAT-TAB PxWeb API 访问瑞士联邦统计局(BFS)数据,无需身份验证:
| 属性 | 详情 |
|---|---|
| API | STAT-TAB PxWeb API v1 |
| 端点 | https://www.pxweb.bfs.admin.ch/api/v1/ |
| 提供方 | 瑞士联邦统计局(BFS) |
| 数据集 | 21 个主题领域中的 682 张表 |
| 语言 | 德语(de)、法语(fr)、意大利语(it)、英语(en) |
| 许可 | 开放政府数据(OGD)——BFS 使用条款 |
| 身份验证 | 无——完全公开 |
示例查询: “2024 年苏黎世州有多少学生就读于初中?”——提供真实的 BFS 数据,不会产生幻觉。
功能
- 📊 15 个工具:覆盖 21 个统计主题(682 个数据集)的 8 个工具 + 4 个市镇/历史参考层工具 + 2 个建筑/房地产工具 + 1 个价格指数工具
- 🔍 对整个 BFS 数据目录进行全文搜索
- 🎓 用于教育统计和人口数据的便捷工具
- 🏗️ 建筑统计——新建建筑/住宅和建筑投资,包括 Arbeitsvorrat 领先指标
- 🏠 价格指数——通过 BFS DAM/CKAN 数据源获取建筑价格指数(Baupreisindex,解析序列)和住宅物业价格指数(IMPI)
- 🏔️ 对任意表和变量进行跨州比较
- 🔓 无需 API 密钥——所有数据均采用开放许可
- ☁️ 双传输方式——stdio(Claude Desktop)+ Streamable HTTP(云端)
前置条件
- Python 3.11+
- uv(推荐)或 pip
安装
# Clone the repository
git clone https://github.com/malkreide/swiss-statistics-mcp.git
cd swiss-statistics-mcp
# Install
pip install -e .
# or with uv:
uv pip install -e .
也可使用 uvx(无需永久安装):
uvx swiss-statistics-mcp
快速开始
# stdio (for Claude Desktop)
python -m swiss_statistics_mcp.server
# Streamable HTTP, loopback only (default: host=127.0.0.1, port=8000)
python -m swiss_statistics_mcp.server --http --port 8000
# Streamable HTTP, all interfaces (only behind a reverse proxy with access control)
MCP_HOST=0.0.0.0 python -m swiss_statistics_mcp.server --http --port 8000
# or
python -m swiss_statistics_mcp.server --http --host 0.0.0.0 --port 8000
立即在 Claude Desktop 中试用:
“2023 年苏黎世州有多少教师在工作?” “伯尔尼州的人口按年龄划分是多少?” “比较 2022 年所有州的社会救助率。”
配置
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):
{
"mcpServers": {
"swiss-statistics": {
"command": "python",
"args": ["-m", "swiss_statistics_mcp.server"]
}
}
}
也可使用 uvx:
{
"mcpServers": {
"swiss-statistics": {
"command": "uvx",
"args": ["swiss-statistics-mcp"]
}
}
}
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Cursor / Windsurf / VS Code + Continue
配置语法与 Claude Desktop 完全相同。文件名取决于客户端:
- Cursor: 项目文件夹中的
.cursor/mcp.json,或全局的~/.cursor/mcp.json - Windsurf:
~/.codeium/windsurf/mcp_config.json - VS Code + Continue:
.continue/config.json
云端部署(用于浏览器访问的 SSE)
用于通过浏览器中的 claude.ai 使用(例如,在没有本地软件的受管工作站上)。
⚠️ 安全提示 — 此服务没有身份验证。 公开 URL 会使其成为通往你部署所在 IP 上 BFS API 的开放代理。任何拥有该 URL 的客户端都能调用这些工具、消耗你的平台配额,并让流量归属到你的 IP。以下是两种缓解措施,按优先顺序排列:
- 在其前面设置访问控制 — 使用 Render 的「Private Service」、Cloudflare Access,或在容器前放置带有 Basic-Auth / IP 允许列表的反向代理。
- 将其作为公开的开放数据代理接受 — 只有在所有数据均为 BFS OGD(公共开放数据)且工具为只读时,这才可以接受。
服务默认绑定到
127.0.0.1。要在容器端口上公开服务,必须显式设置MCP_HOST=0.0.0.0(例如,设为 Render 环境变量),或传入--host 0.0.0.0。若未采取上述任一缓解措施,请勿这样做。
Render.com:
- 将仓库推送到 GitHub 或在 GitHub 上复刻仓库
- 在 render.com 上:New Web Service → 连接 GitHub 仓库
- 设置环境变量:
MCP_HOST=0.0.0.0 - 设置启动命令:
python -m swiss_statistics_mcp.server --http --port 8000 - 在 claude.ai 的 Settings → MCP Servers 下,添加:
https://your-app.onrender.com/sse
💡 “开发者笔记本用 stdio,浏览器用 SSE。”
输出架构
从 v0.2.0 开始,每个工具返回的都是类型化的 Pydantic 模型,而不是 JSON
字符串。FastMCP 会将其序列化为结构化内容,以便 MCP 客户端直接读取字段。
# Old (pre-0.2.0)
result = await bfs_get_data(...) # str
data = json.loads(result) # dict
print(data["rows_total"])
# New (>= 0.2.0)
result = await bfs_get_data(...) # DataTableResult
print(result.rows_total) # 1000
print(result.truncated) # True
每个结果的顶层都包含 error: str | None 和 hint: str | None ——
result.error is None 表示成功。返回数据的工具
(bfs_get_data、bfs_education_stats、bfs_population、
bfs_compare_cantons)还会提供 truncated: bool、
rows_total: int 和 rows_returned: int,以便以机器可读的方式检测是否触及上限。
| 工具 | 结果类型 |
|---|---|
bfs_browse_catalog | BrowseCatalogResult |
bfs_search_tables | SearchTablesResult |
bfs_get_table_metadata | TableMetadataResult |
bfs_get_data | DataTableResult |
bfs_education_stats | DataTableResult |
bfs_population | DataTableResult |
bfs_compare_cantons | DataTableResult |
bfs_featured_datasets | FeaturedDatasetsResult |
lookup_commune | LookupCommuneResult |
resolve_historical_commune | ResolveHistoricalCommuneResult |
list_communes | ListCommunesResult |
search_historical_series | SearchHistoricalSeriesResult |
bfs_construction_activity | ConstructionActivityResult |
bfs_construction_investment | ConstructionInvestmentResult |
bfs_price_index | PriceIndexResult |
参考层结果还会包含 source(来源标注)和 provenance(live_api | cached);SearchHistoricalSeriesResult 还包含 licence_note,其中注明了必需的 HSSO 非商业用途声明。建筑和价格指数结果也会按照相同的封装模式包含 source + provenance。
可用工具
| 工具 | 描述 |
|---|---|
bfs_featured_datasets | 精选的高度相关数据集(侧重教育和人口统计) |
bfs_browse_catalog | 浏览目录:全部 21 个主题(不指定 theme_code),或某个主题中的所有表格(例如,theme_code="15" = 教育与科学) |
bfs_search_tables | 在整个数据目录(682 个数据集)中进行全文搜索 |
bfs_get_table_metadata | 获取特定表格的变量、取值和元数据 |
bfs_get_data | 获取数据,可按维度和取值进行筛选 |
bfs_education_stats | 便捷工具:教师、学生、人口统计情景、奖学金 |
bfs_population | 按州、年份、年龄结构或性别查询常住人口 |
bfs_compare_cantons | 对任意表格和变量进行跨州比较 |
lookup_commune | 根据指定日期的名称或 BFS 编号解析市镇(州、有效性、LINDAS URI) |
resolve_historical_commune | 将历史 BFS 编号映射到现行编号 — 在市镇合并后重新关联旧统计数据 |
list_communes | 列出指定日期某个州的所有市镇 |
search_historical_series | 在《瑞士历史统计》(HSSO)中搜索长期时间序列 |
bfs_construction_activity | 按市镇查询新建建筑和住宅(年度数据),包括住宅房间数构成 |
bfs_construction_investment | 按大区、州或市镇查询建筑投资和待完成工作量(领先指标) |
bfs_price_index | 建筑价格指数(Baupreisindex,已解析序列)/ 住宅房地产价格指数(IMPI,来源链接) |
其中四个工具构成了该工具集的参考层(见 关联键):它们将 BFS 官方市镇编号转换为可靠的关联键,并可重新关联早于市镇合并的统计数据。两个 bfs_construction_* 工具涵盖 STAT-TAB 主题 09(建筑与住房)——见 建筑数据来源。bfs_price_index 涵盖 不在 STAT-TAB 中的价格指数——见 价格指数来源。
建筑数据来源
| 立方体 ID | 标题 | 覆盖范围 | 使用工具 |
|---|---|---|---|
px-x-0904030000_106 | 按市镇和建筑类型划分的新建住宅建筑 | 2013– | bfs_construction_activity |
px-x-0904030000_105 | 按市镇和房间数划分的新建住宅 | 2013– | bfs_construction_activity |
px-x-0904010000_205 | 按大区/州/市镇划分的建筑投资和待完成工作量 | 1994– | bfs_construction_investment |
2013 年以前按市镇统计的建筑时间序列存放在已停用的立方体
px-x-0904030000_101/_104(1995–2012)中,这些立方体使用不同的地理编码,且这些工具不会查询它们。建筑/住宅数据是经汇总的官方年度统计数据——如需了解最新的登记状态和建筑项目储备,请与swiss-housing-mcp交叉验证(这是有意设置的冗余)。
价格指数来源
bfs_price_index 涵盖两个未通过 STAT-TAB 发布的指数。其数据集托管在 opendata.swiss(CKAN)上;数据文件本身是 BFS DAM 资源。
| 指数 | 来源 | 返回内容 |
|---|---|---|
baupreisindex | opendata.swiss 数据集 Schweizerischer Baupreisindex (Multibasen) → DAM XLSX 资源 | 解析后的全国半年期指数序列(Schweiz, Baugewerbe Total),包含基期 |
impi | opendata.swiss 数据集 Schweizerischer Wohnimmobilienpreisindex (IMPI) → DAM PDF/HTML 资源 | 仅官方来源链接 — BFS 不发布机器可读的 IMPI 序列 |
我们为你处理了两个特殊情况:
ckan.opendata.swiss会向默认 User-Agent 返回 HTTP 403,因此每次调用都会发送自定义的swiss-statistics-mcp/<version>User-Agent;DAM 资源的格式混杂,因此通过验证响应的content-type来选择 XLSX(跳过 PDF)。结果会缓存 24 小时。
示例用例
| 查询 | 工具 |
|---|---|
| “2023 年苏黎世有多少教师?” | bfs_education_stats |
| “高中阶段入学人数到 2031 年将如何变化?” | bfs_education_stats |
| “苏黎世州按年龄划分的人口是多少?” | bfs_population |
| “比较所有州的社会救助率” | bfs_compare_cantons |
| “是否有学校建筑相关数据?” | bfs_search_tables |
| “自 2000 年以来,苏黎世哪些市镇合并过?我必须将旧统计数据重新对应到哪些现今的 BFS 编号?” | resolve_historical_commune |
| “列出格拉鲁斯州现今的所有市镇” | list_communes |
| “在 HSSO 中查找人口长期序列” | search_historical_series |
| “自 2018 年以来,温特图尔新建了多少套住宅?按房间大小划分” | bfs_construction_activity |
| “苏黎世州的建筑投资和 Arbeitsvorrat 是多少?” | bfs_construction_investment |
| “自 2015 年以来,建筑价格指数如何变化?” | bfs_price_index |
主题
| 代码 | 主题 | 代码 | 主题 |
|---|---|---|---|
| 01 | 人口 | 12 | 货币、银行、保险 |
| 02 | 国土与环境 | 13 | 社会保障 |
| 03 | 工作与收入 | 14 | 健康 |
| 04 | 国民经济 | 15 | 教育与科学 |
| 05 | 价格 | 16 | 文化、媒体、信息社会 |
| 06 | 工业与服务业 | 17 | 政治 |
| 07 | 农业与林业 | 18 | 一般政府 |
| 08 | 能源 | 19 | 犯罪与刑事司法 |
| 09 | 建筑与住房 | 20 | 经济与社会状况 |
| 10 | 旅游 | 21 | 可持续发展 |
| 11 | 交通与运输 |
架构
┌─────────────────┐ ┌──────────────────────────────┐ ┌──────────────────────────┐
│ Claude / AI │────▶│ Swiss Statistics MCP │────▶│ BFS STAT-TAB │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ PxWeb API v1 │
└─────────────────┘ │ │ └──────────────────────────┘
│ 15 Tools │
│ + commune/historical ref │
│ + construction (theme 09) │
│ + price indices (DAM/CKAN) │
│ Stdio | Streamable HTTP │
│ │
│ No authentication required │
└──────────────────────────────┘
数据源特征
| 来源 | 协议 | 覆盖范围 | 身份验证 | 许可 |
|---|---|---|---|---|
| BFS STAT-TAB | PxWeb REST API | 682 个表,21 个主题 | 无 | OGD |
| BFS AGVCH(市镇登记册) | REST(CSV/XLSX) | 快照、变更、对应关系 | 无 | OGD |
| HSSO(历史统计) | 静态 XLSX 数据转储 | 约 750 个长期序列表 | 无 | CC BY-NC-SA 3.0 |
| BFS DAM + opendata.swiss(CKAN) | CKAN 元数据 + DAM XLSX/PDF | Baupreisindex、IMPI | 无(需要自定义 UA) | OGD |
架构决策
- AGVCH 市镇名录 → 架构 A(仅实时 API)。 官方 REST 服务(
snapshot/correspondances/mutations/levels)是一个清晰、带版本且无需身份验证的 API——已于 2026-07-19 通过实时验证——因此市镇工具会直接查询该服务,并使用 24 小时内存缓存和共享重试策略。无需回退到数据转储。**发现:**实时快照 CSV 的表头使用Inscription,Radiation,Rec_Type_fr(而非 API PDF 中列出的Einschreibung,Streichung),并且HistoricalCode并非跨级别全局唯一——推导市镇所属州时,会按级别区分Parent链接。 - HSSO → 架构 C(仅数据转储)。 HSSO 不提供 API,只有稳定 URL 上每个表格对应的静态 XLSX 文件(
/get/{CHAPTER}.{NN}{suffix}.xlsx)。search_historical_series会根据各章节页面建立带缓存的标题索引,并返回稳定的下载 URL。HSSO 采用 **CC BY-NC-SA 3.0(非商业用途)**许可——与本服务的 OGD 基准许可不同——因此每条 HSSO 响应都会在licence_note中明确注明非商业用途限制。
关联键
此参考层的作用是让 瑞士公共数据 MCP 组合 中不同服务的数据能够可靠地关联。以下三个标识符是整个组合通用的键:
| 键 | 标识对象 | 标准形式 | 说明 |
|---|---|---|---|
BFS 市镇编号(BfsCode) | 一个政治市镇 | 整数,例如 261(苏黎世) | 统计、地理、教育和健康数据的主要关联键。稳定的 LINDAS/Linked-Data URI:https://ld.admin.ch/municipality/{BfsCode}。并非始终不变——市镇合并后会分配新编号,因此历史数据必须通过 resolve_historical_commune 重新关联。 |
| EGID | 单栋建筑(Eidg. Gebäudeidentifikator) | 9 位整数 | 建筑物/住宅级数据(GWR、能源、地址)的关联键。一个市镇包含多个 EGID;每个 EGID 所属的市镇由 BfsCode 表示。 |
| 州缩写 | 一个州 | 两个字母,例如 ZH | 最粗粒度的地理键。可通过任意市镇的 Parent 链推导(以 canton_abbr 暴露)。 |
重新关联为何重要。 市镇合并、拆分或变更所属州时,BFS 市镇编号会发生变化。合并前发布的统计数据使用旧编号;如果不重新关联就将其与当前数据关联,相关行会被悄然丢弃或错误归属。resolve_historical_commune(bfs_number, from_date, to_date) 会返回 resolves_to 集合——旧数据应汇总到的当前编号——以及 mutation_path(包含日期的合并/更名记录)。组合中的其他服务也应在概念上遵循这一约定,以确保同一个键在各处都以相同方式解析。
示例(锚点查询)。 “自 2000 年以来,苏黎世有哪些市镇发生了合并?”——例如,旧编号 132 Hirzel 和 133 Horgen 都重新关联到当前编号 295 Horgen;134/140/142 则关联到 293 Wädenswil。
项目结构
swiss-statistics-mcp/
├── src/swiss_statistics_mcp/
│ ├── __init__.py # Package
│ └── server.py # 15 tools
├── tests/
│ └── test_server.py # Unit + integration tests (mocked HTTP)
├── .github/workflows/ci.yml # GitHub Actions (Python 3.11/3.12/3.13)
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md # English
├── CONTRIBUTING.de.md # German version
├── SECURITY.md # English
├── SECURITY.de.md # German version
├── LICENSE
├── README.md # This file (English)
└── README.de.md # German version
可观测性
服务会在 stderr 上针对每次工具调用输出一行 JSON 日志:
{"ts": "2026-05-20T04:02:28", "level": "INFO", "logger": "swiss_statistics_mcp",
"event": "tool_start", "tool": "bfs_browse_catalog", "rid": "1091cb73", "params_keys": ["theme_code", "lang", "limit"]}
{"ts": "2026-05-20T04:02:28", "level": "INFO", "logger": "swiss_statistics_mcp",
"event": "tool_end", "tool": "bfs_browse_catalog", "rid": "1091cb73", "status": "ok", "duration_ms": 303}
rid— 8 字符的关联 ID,用于关联同一次调用的tool_start和tool_endparams_keys— 输入字段名称的排序列表(不含字段值或个人身份信息)duration_ms—tool_end事件中的单次调用延迟status—"ok"或"error";工具引发异常时会添加error_type
Render 和其他云平台可以直接为这些日志编制索引,用于构建按工具划分的延迟
仪表板和错误率告警。设置 MCP_LOG_LEVEL=DEBUG 可输出详细日志,
设置为 WARNING 则可抑制单次调用事件。
ℹ️ 日志会写入 stderr,因此不会与 MCP 通过 stdio 传输的协议数据冲突 (协议数据使用 stdout)。
韧性
在瞬时的 BFS-API 故障传递到 LLM 之前,服务会先行处理:
- 重试 — 对
5xx、429和网络错误最多重试 3 次,并采用指数退避(0.5s → 4s)。4xx错误会立即显示,以免掩盖客户端错误。可通过MCP_RETRY_MAX_ATTEMPTS、MCP_RETRY_WAIT_INITIAL、MCP_RETRY_WAIT_MAX环境变量调整。 - 元数据缓存 — 表元数据(变量、值域、last_updated)会按
(table_id, lang)在内存中缓存 1h。首次列表/详情流程会预热缓存;后续调用会即时返回。 - 并发上限 —
bfs_browse_catalog(主题模式)中的元数据扇出获取会并行执行,并受FANOUT_CONCURRENCY = 5限制。对于limit=20,这会将耗时从顺序执行时的约 20s 缩短到约 4s,同时避免给上游 API 带来过大压力。
已知限制
- PxWeb API: 快速连续查询可能会触发速率限制;服务会将目录索引缓存 1 小时,并将表元数据缓存 1 小时
- 语言: 数据集标题和维度值默认使用德语;法语、意大利语和英语的覆盖情况因表而异
- JSON-STAT2: 部分复杂交叉表可能返回大型结果集;请使用维度筛选器缩小查询范围
- 市镇登记册 (AGVCH): 实时快照 CSV 标头使用
Inscription/Radiation/Rec_Type_fr(而非 API PDF 中的Einschreibung/Streichung名称);HistoricalCode在不同层级间并非全局唯一,因此州须通过逐级遍历Parent链来推导。快照/变更会缓存 24 h。 - HSSO: 许可为 CC BY-NC-SA 3.0 (NonCommercial) — 必须署名,不得用于商业用途;每个响应都会在
licence_note中包含此信息。HSSO 不提供按表筛选时期的功能,因此search_historical_series的period参数仅供参考 — 请在 XLSX 中核实实际时间跨度。search_historical_series返回稳定的 XLSX 下载 URL,而不是解析后的序列值。 - PxWeb 中的市镇代码在不同数据立方体间并不一致。 在
px-x-0904030000_106/_107中,值代码就是补零后的 BFS 编号(0261);在px-x-0904030000_105中,它是一个不透明的顺序 ID(160),BFS 编号仅出现在标签中(......0261 Zürich)。bfs_construction_activity会通过匹配标签中嵌入的 BFS 编号,使用每个数据立方体自身的实时维度值进行解析,绝不会猜测代码。 - 建筑业数据覆盖范围: 当前市镇级建筑系列从 2013 年开始;因此
bfs_construction_activity接受since_year >= 2013。数值为合并后的官方年度统计数据。建筑投资值(bfs_construction_investment)以 1000 CHF 为单位;Arbeitsvorrat是下一年的建筑工程量(一项货币先行指标)。 - 价格指数(
bfs_price_index): IMPI(住宅房地产价格指数)仅由 BFS 以 PDF/HTML 形式发布 — 没有机器可读的序列 — 因此index="impi"会返回官方来源链接和明确的限制说明,而非数值。Baupreisindex XLSX 会被解析为全国半年期序列(Schweiz,Baugewerbe Total);源 XLSX 中存在区域/对象类型细分数据,但不会返回。DAM 资源 ID 会从 CKAN 元数据中实时解析(绝不硬编码),因为它们会在重新发布时更改;如果上游 XLSX 结构发生变化,该工具会明确报错,而不会返回错误数值。
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_modern_wire.py 则通过 HTTP 驱动 streamable_http_app() 中的 ASGI 应用,验证 server/discover、serverInfo 标记、2026-07-28 要求的 resultType、SEP-2549 新鲜度提示,以及对未完整封装的明确拒绝。
两种形式都要保留。对连接进行测量只能得知当前协商的修订版本——如果 SDK 升级提高了上限,它就会悄然测出新的上限。只有固定常量的测试才能捕获这一变化。两者断言的内容不同,不能互相取代。
服务身份
现代时代会将 serverInfo 写入每个结果的 _meta,而不只是每个连接写入一次;SDK 不会替换任何内容:"未指定版本的服务会报告一个空的 version。" 因此,此服务在构造时会声明 title、version、description 和 website_url,使每个响应都携带与 server.json 中发布信息相同的身份。
version、description 和 website_url 从软件包元数据中读取,而不是写成字面值:这里的字面值会成为 pyproject.toml 和 server.json 之外的第三份副本,而且是唯一一份没人会更新的副本,因为它无处可见。title 则保留为字面值——显示名称不属于软件包元数据。
有意不设置 icons——此仓库不托管图标资源,编造一个背后没有任何内容的 URL,还不如省略该字段。出于同样的原因,字段缺失优于字段为空:website_url 的类型是 str | None,不做 URL 验证;标记会使用 exclude_none 导出,因此 None 会省略该字段,而 "" 则会向每个调用方发送 "websiteUrl": ""。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时代的别名,而不是握手时代的别名——仅依据它固定版本,会让当前客户端实际协商的时代可以悄然漂移。
更新策略。 门禁测试失败时,不要盲目修改常量:阅读两个修订版本之间的规范变更日志,确认服务仍正常工作,然后一并更新常量、本节、README.de.md 和 CHANGELOG.md。
测试
# Unit tests (no API key required)
PYTHONPATH=src pytest tests/ -m "not live"
# Integration tests (live API calls)
pytest tests/ -m "live"
安全与限制
- 只读: 所有工具仅执行 HTTP GET 请求,不会写入、修改或删除任何数据。
- 无个人数据: STAT-TAB 返回汇总统计数据集。此服务不会处理或存储任何个人身份信息(PII)。
- 速率限制: PxWeb API 是没有公开文档说明速率限制的公共端点;请避免对包含 682 张表的完整目录进行密集循环查询。此服务对每个请求强制实施 30s 超时,并将目录索引缓存 1 小时。
- 数据时效性: BFS 会定期发布更新后的数据(并非实时数据)。数据反映查询时上游数据库中的状态。
- 服务条款: 数据受 BFS 使用条款(OGD)约束。所有 STAT-TAB 数据均以开放政府数据形式发布,可在注明来源的情况下自由使用。
- 不作保证: 此服务是社区项目,与瑞士联邦统计局无关联。服务可用性取决于上游 BFS API。
更新日志
请参阅 CHANGELOG.md
参与贡献
请参阅 CONTRIBUTING.md
安全
只读、不含 PII、无需身份验证,仅使用一个固定的 BFS 端点。完整的安全态势和已接受风险的决策,请参阅 SECURITY.md。
许可证
MIT License — 请参阅 LICENSE
作者
Hayal Oezkan · malkreide
致谢与相关项目
- BFS: www.bfs.admin.ch — 瑞士联邦统计局
- STAT-TAB: www.pxweb.bfs.admin.ch — PxWeb 数据库界面
- 协议: Model Context Protocol — Anthropic / Linux Foundation
- 相关项目: swiss-cultural-heritage-mcp — SIK-ISEA、Nationalmuseum、Nationalbibliothek
- 相关项目: fedlex-mcp — 通过 Fedlex SPARQL 获取瑞士联邦法律
- 相关项目: zurich-opendata-mcp — CKAN、天气、空气质量、苏黎世市
- 相关项目: swiss-transport-mcp — OJP 行程规划、SIRI-SX 服务中断信息
- 相关项目: global-education-mcp — UNESCO UIS 和 OECD《教育概览》
- 作品集: Swiss Public Data MCP Portfolio
安装
通过 uv 的 uvx 运行,无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"swiss-statistics-mcp": {
"command": "uvx",
"args": [
"swiss-statistics-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。