
Swiss Statistics Mcp
io.github.malkreide由 GitHub 帳號 malkreide 發布v0.8.0更新於 Oct 27, 2026
BFS STAT-TAB PxWeb API for official Swiss statistics
概覽
唯讀 MCP 伺服器,讓助理透過公開的 STAT-TAB PxWeb API 存取瑞士聯邦統計局(BFS)的官方統計資料。
- 可以做什麼
- 瀏覽並全文檢索 BFS 目錄中 21 個主題下的 682 個資料集,讀取表格中繼資料
- 依維度篩選取得統計資料,並提供教育統計與依邦、年份、年齡或性別查詢常住人口的便利工具
- 對任一表格與變數進行跨邦比較
- 依名稱或 BFS 編號解析市鎮、列出某邦所有市鎮,並將歷史市鎮編號對應到合併後的現行編號
- 檢索瑞士歷史統計的長期時間序列並回傳其下載連結
- 查詢建築活動、建築投資以及建築或住宅價格指數
- 適用情境
- 需要可查證的瑞士官方統計資料(人口、教育、建築、社會指標)而非模型臆測時適用,也適合以官方市鎮編號串接瑞士資料或進行跨邦比較。
- 執行需求
- 以本機 Python 套件執行(需 Python 3.11+,uv 或 pip;uvx swiss-statistics-mcp 無需長期安裝)。不需 API 金鑰或帳號。需要能連線 BFS STAT-TAB API 及相關 BFS 開放資料來源。可選環境變數可調整日誌、重試與 HTTP 綁定位址。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Swiss Statistics Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
🇨🇭 Part of the Swiss Public Data MCP Portfolio
📊 swiss-statistics-mcp
[Version] [License: MIT] [Python 3.11+] [MCP] [No Auth Required] [CI]
MCP Server for Swiss Federal Statistical Office (BFS) data via STAT-TAB PxWeb API — 682 datasets across 21 themes, no authentication required
Demo
[Demo: Claude using bfs_education_stats]
Maturity
This server is Alpha (0.x) as per the PyPI classifier. Until 1.0:
- Tool names, input schemas, and output JSON keys MAY change between minor versions
- Pin cloud deployments to a specific git tag, not
main - Production use is acceptable for read-only Open Data scenarios; consider it experimental for anything user-facing
See CHANGELOG.md for breaking changes.
Overview
swiss-statistics-mcp provides AI-native access to the Swiss Federal Statistical Office (BFS) via the STAT-TAB PxWeb API, without authentication:
Anchor demo query: "How many students attended lower secondary schools in the canton of Zurich in 2024?" — real BFS figures, no hallucination.
Features
- 📊 15 tools: 8 across 21 statistical themes (682 datasets) + a 4-tool commune/historical reference layer + 2 construction/real-estate tools + a price-index tool
- 🔍 Full-text search across the entire BFS data catalogue
- 🎓 Convenience tools for education statistics and population data
- 🏗️ Construction statistics — new buildings/dwellings and building investment incl. the Arbeitsvorrat leading indicator
- 🏠 Price indices — construction price index (Baupreisindex, parsed series) and residential property price index (IMPI) via the BFS DAM/CKAN sources
- 🏔️ Cross-cantonal comparison for any table and variable
- 🔓 No API key required — all data under open licences
- ☁️ Dual transport — stdio (Claude Desktop) + Streamable HTTP (cloud)
Prerequisites
- Python 3.11+
- uv (recommended) or pip
Installation
Or with uvx (no permanent installation):
Quickstart
Try it immediately in Claude Desktop:
"How many teachers worked in the canton of Zurich in 2023?" "What is the population of canton Bern broken down by age?" "Compare the social assistance rate across all cantons for 2022."
Configuration
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
Or with uvx:
Config file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Cursor / Windsurf / VS Code + Continue
The configuration syntax is identical to Claude Desktop. The file name depends on the client:
- Cursor:
.cursor/mcp.jsonin the project folder, or~/.cursor/mcp.jsonglobally - Windsurf:
~/.codeium/windsurf/mcp_config.json - VS Code + Continue:
.continue/config.json
Cloud Deployment (SSE for browser access)
For use via claude.ai in the browser (e.g. on managed workstations without local software).
⚠️ Security note — this server has no authentication. A public URL turns it into an open proxy to the BFS API on your deployment's IP. Any client with the URL can drive the tools, consume your platform quota, and attribute traffic to your IP. Two mitigations, in order of preference:
- Put it behind access control — Render's «Private Service», Cloudflare Access, or a reverse proxy with Basic-Auth / IP allowlist in front of the container.
- Accept it as a public open-data proxy — only acceptable because all data is BFS OGD (Public Open Data) and tools are read-only.
The server binds to
127.0.0.1by default. To expose it on a container port you must explicitly setMCP_HOST=0.0.0.0(e.g. as a Render env var) or pass--host 0.0.0.0. Do not do this without one of the mitigations above.
Render.com:
- Push/fork the repository to GitHub
- On render.com: New Web Service → connect GitHub repo
- Set environment variable:
MCP_HOST=0.0.0.0 - Set start command:
python -m swiss_statistics_mcp.server --http --port 8000 - In claude.ai under Settings → MCP Servers, add:
https://your-app.onrender.com/sse
💡 "stdio for the developer laptop, SSE for the browser."
Output Schema
Since v0.2.0, every tool returns a typed Pydantic model rather than a JSON
string. FastMCP serializes these as structured content so MCP clients can
read fields directly.
Every result carries error: str | None and hint: str | None at the top
level — result.error is None means success. Data-returning tools
(bfs_get_data, bfs_education_stats, bfs_population,
bfs_compare_cantons) additionally expose truncated: bool,
rows_total: int, and rows_returned: int for machine-readable cap
detection.
Reference-layer results additionally carry source (attribution) and provenance (live_api | cached); SearchHistoricalSeriesResult also carries licence_note with the mandatory HSSO NonCommercial notice. The construction and price-index results carry source + provenance on the same envelope pattern.
Available Tools
Four of these tools form the reference layer of the portfolio (see Join Keys): they turn official BFS commune numbers into a reliable join key and let you re-key statistics that predate a municipal merger. The two bfs_construction_* tools cover STAT-TAB theme 09 (Bau- und Wohnungswesen) — see Construction sources. bfs_price_index covers price indices that are not in STAT-TAB — see Price-index sources.
Construction sources
The pre-2013 Gemeinde-level building series lives in the discontinued cubes
px-x-0904030000_101/_104(1995–2012), which use a different geo coding and are not queried by these tools. Building/dwelling figures are the consolidated official yearly statistics — for up-to-date register states and the construction pipeline, cross-validate againstswiss-housing-mcp(deliberate redundancy).
Price-index sources
bfs_price_index covers two indices that are not published via STAT-TAB. Their datasets live on opendata.swiss (CKAN); the data files themselves are BFS DAM assets.
Two quirks are handled for you:
ckan.opendata.swissreturns HTTP 403 to default User-Agents, so every call sends a customswiss-statistics-mcp/<version>User-Agent; and DAM assets mix formats, so the XLSX is selected by verifying the responsecontent-type(PDFs are skipped). Results are cached for 24 h.
Example Use Cases
→ More use cases by audience →
Themes
Architecture
Data Source Characteristics
Architecture decision
- AGVCH commune register → Architecture A (live-API-only). The official REST service (
snapshot/correspondances/mutations/levels) is a clean, versioned, no-auth API — verified live on 2026-07-19 — so the commune tools query it directly with a 24 h in-memory cache and the shared retry policy. No dump fallback is needed. Finding: the live snapshot CSV header usesInscription,Radiation,Rec_Type_fr(not theEinschreibung,Streichungnames printed in the API PDF), andHistoricalCodeis not globally unique across levels — theParentlink is disambiguated by tier when deriving a commune's canton. - HSSO → Architecture C (dump-only). HSSO offers no API, only static per-table XLSX at stable URLs (
/get/{CHAPTER}.{NN}{suffix}.xlsx).search_historical_seriesbuilds a cached title index from the chapter pages and returns the stable download URL. HSSO is licensed CC BY-NC-SA 3.0 (NonCommercial) — different from this server's OGD baseline — so every HSSO response carries an explicit NonCommercial notice inlicence_note.
Join Keys
The reference layer exists so that data from different servers in the Swiss Public Data MCP Portfolio can be joined reliably. Three identifiers are the portfolio-wide keys:
Why re-keying matters. BFS commune numbers change whenever communes merge, split, or move canton. Statistics published before a merger use the old number; joining them to today's data without re-keying silently drops or misattributes rows. resolve_historical_commune(bfs_number, from_date, to_date) returns the resolves_to set — the current number(s) old figures must be aggregated onto — plus the mutation_path (the fusions/renamings, with dates). Other portfolio servers are meant to mirror this contract conceptually so the same key resolves the same way everywhere.
Example (anchor query). "Which Zurich communes have merged since 2000?" — e.g. old 132 Hirzel and 133 Horgen both re-key onto today's 295 Horgen; 134/140/142 onto 293 Wädenswil.
Project Structure
Observability
The server emits one JSON log line per tool call on stderr:
rid— 8-char correlation id linkingtool_startandtool_endfor the same callparams_keys— sorted list of input field names (no values, no PII)duration_ms— per-call latency on thetool_endeventstatus—"ok"or"error";error_typeis added when a tool raises
Render and other cloud platforms can index these directly for per-tool latency
dashboards and error-rate alerts. Set MCP_LOG_LEVEL=DEBUG for verbose output
or WARNING to suppress per-call events.
ℹ️ Logs go to stderr so they never collide with the MCP protocol on stdio transport (which uses stdout).
Resilience
The server absorbs transient BFS-API hiccups before they reach the LLM:
- Retries —
5xx,429, and network errors are retried up to 3 times with exponential backoff (0.5s → 4s).4xxerrors surface immediately so client bugs aren't masked. Tunable viaMCP_RETRY_MAX_ATTEMPTS,MCP_RETRY_WAIT_INITIAL,MCP_RETRY_WAIT_MAXenv vars. - Metadata cache — Table metadata (variables, value domains, last_updated)
is cached in-memory per
(table_id, lang)for 1h. Cold list/detail flows warm the cache; subsequent calls return instantly. - Concurrency cap — Fan-out metadata fetches in
bfs_browse_catalog(theme mode) run in parallel bounded byFANOUT_CONCURRENCY = 5. Forlimit=20this cuts wall-clock from ~20s sequential to ~4s, without overwhelming the upstream API.
Known Limitations
- PxWeb API: Rate limiting may apply for rapid successive queries; the server uses a 1-hour cache for the catalogue index and a 1-hour cache for table metadata
- Language: Dataset titles and dimension values are in German by default; French, Italian and English coverage varies by table
- JSON-STAT2: Some complex cross-tabulations may return large result sets; use dimension filters to narrow queries
- Commune register (AGVCH): Live snapshot CSV headers use
Inscription/Radiation/Rec_Type_fr(not theEinschreibung/Streichungnames in the API PDF);HistoricalCodeis not globally unique across levels, so the canton is derived by walking theParentchain one tier at a time. Snapshots/mutations are cached for 24 h. - HSSO: Licensed CC BY-NC-SA 3.0 (NonCommercial) — attribution required, no commercial use; every response carries this in
licence_note. HSSO exposes no per-table period filter, sosearch_historical_series'speriodargument is an informational hint only — verify the actual span in the XLSX.search_historical_seriesreturns the stable XLSX download URL, not the parsed series values. - PxWeb commune codes are not consistent across cubes. In
px-x-0904030000_106/_107the value code IS the zero-padded BFS number (0261); inpx-x-0904030000_105it is an opaque sequential id (160) and the BFS number appears only in the label (......0261 Zürich).bfs_construction_activityresolves each cube against its own live dimension values by matching the label-embedded BFS number, never by guessing the code. - Construction coverage: the current Gemeinde-level building series starts in 2013;
bfs_construction_activitytherefore acceptssince_year >= 2013. Values are the consolidated official yearly statistics. Building investment values (bfs_construction_investment) are in 1000 CHF; theArbeitsvorratis the following year's building volume (a monetary leading indicator). - Price indices (
bfs_price_index): the IMPI (residential property price index) is published by BFS only as PDF/HTML — there is no machine-readable series — soindex="impi"returns the official source links plus an explicit limitation, not values. The Baupreisindex XLSX is parsed to the national semi-annual series (Schweiz, Baugewerbe Total); regional/object-type breakdowns exist in the source XLSX but are not returned. The DAM asset ids are resolved live from CKAN metadata (never hard-coded), because they change on republish; if the upstream XLSX structure changes, the tool degrades to a clear error rather than returning wrong values.
MCP Protocol Version
This server speaks two protocol eras over the same endpoint. The client's first request on a connection decides which one applies; a later claim from the other era is refused.
Both revisions are pinned in
tests/test_protocol_version.py and asserted
against the installed SDK, so a Dependabot bump of mcp cannot move either one
silently. The same file also reads the negotiated revision off a real
connection, and tests/test_modern_wire.py drives
the ASGI app from streamable_http_app() over HTTP: server/discover, the
serverInfo stamp, the resultType that 2026-07-28 makes mandatory, the
SEP-2549 freshness hint, and the named rejection of a half-built envelope.
Both forms stay. A measured connection says which revision was negotiated today — if an SDK bump moves the ceiling, it silently measures the new one. Only the constant pin catches that. They assert different things; neither replaces the other.
Server identity
The modern era stamps serverInfo into the _meta of every result, not
once per connection, and the SDK substitutes nothing: "An unversioned server
reports an empty version." This server therefore declares title,
version, description and website_url at construction, so every response
carries the same identity that server.json publishes.
version, description and website_url are read from the package metadata
rather than written as literals: a literal here would be a third copy beside
pyproject.toml and server.json, and the only one nobody keeps current
because it is visible nowhere. title stays a literal — a display name is not
package metadata.
icons is deliberately unset — this repository hosts no icon assets, and
inventing a URL with nothing behind it is worse than omitting the field. For the
same reason an absent field beats an empty one: website_url is str | None
with no URL validation, and the stamp is dumped with exclude_none, so None
omits the field while "" ships "websiteUrl": "" to every caller.
Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern
era, not for the handshake era — pinning against it alone would leave the era
that current clients actually negotiate free to drift.
Update policy. When the gate fails, do not edit the constant blindly: read
the spec changelog between the two revisions, verify the server still behaves,
then move the constant, this section, README.de.md and
CHANGELOG.md together.
Testing
Safety & Limits
- Read-only: All tools perform HTTP GET requests only — no data is written, modified, or deleted.
- No personal data: STAT-TAB returns aggregated statistical datasets. No personally identifiable information (PII) is processed or stored by this server.
- Rate limits: The PxWeb API is a public endpoint without documented rate limits; avoid tight loops over the full 682-table catalogue. The server enforces a 30s timeout per request and caches the catalogue index for 1 hour.
- Data freshness: BFS publishes updated figures periodically (not real-time). Figures reflect the state of the upstream database at query time.
- Terms of service: Data is subject to the BFS Terms of Use (OGD). All STAT-TAB data is published as Open Government Data and may be freely used with attribution.
- No guarantees: This server is a community project, not affiliated with the Swiss Federal Statistical Office. Availability depends on the upstream BFS API.
Changelog
See CHANGELOG.md
Contributing
See CONTRIBUTING.md
Security
Read-only, no PII, no authentication, single fixed BFS endpoint. See SECURITY.md for the full security posture and accepted-risk decisions.
License
MIT License — see LICENSE
Author
Hayal Oezkan · malkreide
Credits & Related Projects
- BFS: www.bfs.admin.ch — Swiss Federal Statistical Office
- STAT-TAB: www.pxweb.bfs.admin.ch — PxWeb database interface
- Protocol: Model Context Protocol — Anthropic / Linux Foundation
- Related: swiss-cultural-heritage-mcp — SIK-ISEA, Nationalmuseum, Nationalbibliothek
- Related: fedlex-mcp — Swiss federal law via Fedlex SPARQL
- Related: zurich-opendata-mcp — CKAN, weather, air quality, City of Zurich
- Related: swiss-transport-mcp — OJP journey planning, SIRI-SX disruptions
- Related: global-education-mcp — UNESCO UIS and OECD Education at a Glance
- Portfolio: Swiss Public Data MCP Portfolio
Installation
Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):
來源:README.md,提交 2c685b9
工具
0版本歷史
2- v0.8.0最新Sep 26, 2026
- v0.7.2Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分