swiss-statistics-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@swiss-statistics-mcpWhat is the population of Zurich in 2023?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π¨π Part of the Swiss Public Data MCP Portfolio
π swiss-statistics-mcp
MCP Server for Swiss Federal Statistical Office (BFS) data via STAT-TAB PxWeb API β 682 datasets across 21 themes, no authentication required
Demo
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
mainProduction 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:
Property | Details |
API | STAT-TAB PxWeb API v1 |
Endpoint |
|
Provider | Swiss Federal Statistical Office (BFS) |
Datasets | 682 tables across 21 thematic areas |
Languages | German ( |
Licence | Open Government Data (OGD) β BFS Terms of Use |
Authentication | None β fully public |
Anchor demo query: "How many students attended lower secondary schools in the canton of Zurich in 2024?" β real BFS figures, no hallucination.
Features
π 9 tools across 21 statistical themes (682 datasets)
π Full-text search across the entire BFS data catalogue
π Convenience tools for education statistics and population data
ποΈ 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
# 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 .Or with uvx (no permanent installation):
uvx swiss-statistics-mcpQuickstart
# 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 8000Try 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):
{
"mcpServers": {
"swiss-statistics": {
"command": "python",
"args": ["-m", "swiss_statistics_mcp.server"]
}
}
}Or with uvx:
{
"mcpServers": {
"swiss-statistics": {
"command": "uvx",
"args": ["swiss-statistics-mcp"]
}
}
}Config file locations:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%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.jsongloballyWindsurf:
~/.codeium/windsurf/mcp_config.jsonVS 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.0Set start command:
python -m swiss_statistics_mcp.server --http --port 8000In 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.
# 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) # TrueEvery 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.
Tool | Result type |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Available Tools
Tool | Description |
| Curated list of highly relevant datasets (focus on education and demographics) |
| All 21 BFS themes with number of available datasets |
| All tables for a given theme (e.g. |
| Full-text search across the entire data catalogue (682 datasets) |
| Variables, values and metadata for a specific table |
| Data retrieval with optional filters by dimensions and values |
| Convenience tool: teachers, pupils, demographic scenarios, scholarships |
| Resident population by canton, year, age structure or sex |
| Cross-cantonal comparison for any table and any variable |
Example Use Cases
Query | Tool |
"How many teachers worked in Zurich in 2023?" |
|
"How will upper secondary enrolment develop until 2031?" |
|
"What is the population of canton Zurich by age?" |
|
"Compare the social assistance rate across all cantons" |
|
"Is there data on school buildings?" |
|
β More use cases by audience β
Themes
Code | Theme | Code | Theme |
01 | Population | 12 | Money, banks, insurance |
02 | Territory and environment | 13 | Social security |
03 | Work and income | 14 | Health |
04 | National economy | 15 | Education and science |
05 | Prices | 16 | Culture, media, information society |
06 | Industry and services | 17 | Politics |
07 | Agriculture and forestry | 18 | General government |
08 | Energy | 19 | Crime and criminal justice |
09 | Construction and housing | 20 | Economic and social situation |
10 | Tourism | 21 | Sustainable development |
11 | Mobility and transport |
Architecture
βββββββββββββββββββ ββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
β Claude / AI ββββββΆβ Swiss Statistics MCP ββββββΆβ BFS STAT-TAB β
β (MCP Host) βββββββ (MCP Server) βββββββ PxWeb API v1 β
βββββββββββββββββββ β β ββββββββββββββββββββββββββββ
β 9 Tools β
β 682 datasets Β· 21 themes β
β Stdio | Streamable HTTP β
β β
β No authentication required β
ββββββββββββββββββββββββββββββββData Source Characteristics
Source | Protocol | Coverage | Auth |
BFS STAT-TAB | PxWeb REST API | 682 tables, 21 themes | None |
Project Structure
swiss-statistics-mcp/
βββ src/swiss_statistics_mcp/
β βββ __init__.py # Package
β βββ server.py # 9 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
βββ LICENSE
βββ README.md # This file (English)
βββ README.de.md # German versionObservability
The server emits one JSON log line per tool call on stderr:
{"ts": "2026-05-20T04:02:28", "level": "INFO", "logger": "swiss_statistics_mcp",
"event": "tool_start", "tool": "bfs_list_themes", "rid": "1091cb73", "params_keys": ["lang"]}
{"ts": "2026-05-20T04:02:28", "level": "INFO", "logger": "swiss_statistics_mcp",
"event": "tool_end", "tool": "bfs_list_themes", "rid": "1091cb73", "status": "ok", "duration_ms": 303}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_list_tables_by_themerun 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
Testing
# Unit tests (no API key required)
PYTHONPATH=src pytest tests/ -m "not live"
# Integration tests (live API calls)
pytest tests/ -m "live"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
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
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/malkreide/swiss-statistics-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server