swiss-statistics-mcp
This server provides AI-native access to Swiss Federal Statistical Office (BFS) data via the STAT-TAB PxWeb API, covering 682 datasets across 21 thematic areas — no authentication required. It offers 9 tools:
Browse statistical themes – List all 21 BFS thematic areas (e.g., Population, Education, Health, Transport) with dataset counts.
Discover datasets by theme – Retrieve all available tables for a specific theme using its 2-digit code.
Search the full catalogue – Full-text keyword search across all 682+ BFS table titles, optionally filtered by theme.
Inspect table structure – Get detailed metadata for any table: variables, dimension codes, and available filter values.
Query statistical data – Fetch actual data from any BFS table with optional dimension filters, language selection, and a configurable row limit (up to 5,000).
Education statistics – Convenience tool for teachers, students, enrollment scenarios, and scholarships, optionally filtered by canton.
Population statistics – Query Swiss resident population by region/canton, year, age, or gender.
Compare cantons – Compare any statistical indicator side-by-side across multiple Swiss cantons simultaneously.
Featured datasets – A curated shortlist of high-value datasets for education planning and public administration.
Key characteristics:
Supports 4 languages: German, French, Italian, and English
All operations are read-only, accessing Open Government Data (OGD)
Includes built-in retry logic, metadata caching (1-hour TTL), and concurrency controls
Supports stdio (Claude Desktop) and Streamable HTTP (cloud) transports
Click on "Deploy 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.
Related MCP server: Swiss Truth MCP
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
📊 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
# 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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
Tool | Description |
| Curated list of highly relevant datasets (focus on education and demographics) |
| Browse the catalogue: all 21 themes (no |
| 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 |
| Resolve a commune by name or BFS number as of a given date (canton, validity, LINDAS URI) |
| Map a historical BFS number onto today's number(s) — re-key old statistics across fusions |
| List all communes of a canton as of a given date |
| Search long-run time series in Historical Statistics of Switzerland (HSSO) |
| New buildings & dwellings per commune (yearly), incl. dwelling room-size mix |
| Building investment & Arbeitsvorrat (leading indicator) by region/canton/commune |
| Construction price index (Baupreisindex, parsed series) / residential property price index (IMPI, source links) |
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
Cube ID | Title | Coverage | Used by |
| Neu erstellte Gebäude mit Wohnungen nach Gemeinde, Gebäudetyp | 2013– |
|
| Neu erstellte Wohnungen nach Gemeinde, Anzahl Zimmer | 2013– |
|
| Bauinvestitionen und Arbeitsvorrat nach Grossregion/Kanton/Gemeinde | 1994– |
|
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.
Index | Source | Returns |
| opendata.swiss dataset Schweizerischer Baupreisindex (Multibasen) → DAM XLSX asset | Parsed national semi-annual index series (Schweiz, Baugewerbe Total), with the base period |
| opendata.swiss dataset Schweizerischer Wohnimmobilienpreisindex (IMPI) → DAM PDF/HTML assets | Official source links only — BFS does not publish a machine-readable IMPI series |
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
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?" |
|
"Which Zurich communes have merged since 2000, and onto which of today's BFS numbers must I re-key old statistics?" |
|
"List all communes of canton Glarus today" |
|
"Find long-run series on population in HSSO" |
|
"How many new dwellings were built in Winterthur since 2018, by room size?" |
|
"What is the building investment and Arbeitsvorrat for canton Zurich?" |
|
"How has the construction price index moved since 2015?" |
|
→ 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 │
└─────────────────┘ │ │ └──────────────────────────┘
│ 15 Tools │
│ + commune/historical ref │
│ + construction (theme 09) │
│ + price indices (DAM/CKAN) │
│ Stdio | Streamable HTTP │
│ │
│ No authentication required │
└──────────────────────────────┘Data Source Characteristics
Source | Protocol | Coverage | Auth | Licence |
BFS STAT-TAB | PxWeb REST API | 682 tables, 21 themes | None | OGD |
BFS AGVCH (commune register) | REST (CSV/XLSX) | Snapshots, mutations, correspondances | None | OGD |
HSSO (historical statistics) | Static XLSX dumps | ~750 long-run tables | None | CC BY-NC-SA 3.0 |
BFS DAM + opendata.swiss (CKAN) | CKAN metadata + DAM XLSX/PDF | Baupreisindex, IMPI | None (custom UA required) | OGD |
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:
Key | What it identifies | Canonical form | Notes |
BFS commune number ( | A political commune | integer, e.g. | The primary join key across statistics, geo, education and health data. Stable LINDAS/Linked-Data URI: |
EGID | A single building (Eidg. Gebäudeidentifikator) | 9-digit integer | The join key for building/dwelling-level data (GWR, energy, addresses). A commune contains many EGIDs; |
Canton abbreviation | A canton | two letters, e.g. | The coarsest geographic key. Derivable from any commune via its |
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
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 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_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-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.
Era | Revision | Who reaches it |
|
| What today's clients speak. The server answers with the revision asked for, or with the |
Per-request envelope |
| A request carrying the |
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. This server builds no ASGI app to send an initialize through, so
the gate asserts the SDK constants rather than a measured response — the
weaker form, named rather than left unsaid.
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
# 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
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):
{
"mcpServers": {
"swiss-statistics-mcp": {
"command": "uvx",
"args": [
"swiss-statistics-mcp"
]
}
}
}Available Tools
15 toolsbfs_browse_catalogARead-onlyIdempotent
Browse the BFS catalogue: the theme list, or the datasets within a theme.
Two modes in one tool (mode in the result says which ran):
Omit
theme_code→ list all 21 statistical themes with their 2-digit codes and dataset counts (the taxonomy of Swiss federal statistics).Provide
theme_code→ list the datasets in that theme (table IDs + titles) to feed bfs_get_table_metadata / bfs_get_data.
Args: params (BrowseCatalogInput): - theme_code (str | None): 2-digit theme code, e.g. '15' for Bildung; omit for the theme list - lang (str): Language code ('de', 'fr', 'it', 'en') - limit (int): Max tables to return (theme mode; default 20)
Returns:
BrowseCatalogResult. mode='themes' populates themes; mode='tables'
populates tables plus theme metadata. On error, error/hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| mode | No | |
| note | No | |
| error | No | |
| tables | No | |
| themes | No | |
| returned | No | |
| next_step | No | |
| theme_code | No | |
| theme_name | No | |
| total_datasets | No | |
| total_in_theme | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, but the description adds valuable context beyond annotations: it discloses the mode field in the result, that error/hint are set on failure, and that theme mode returns dataset counts and theme metadata. It does not cover rate limits or auth, but that is not expected for a read-only catalog browse.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a two-sentence intro, a clear two-mode breakdown, a compact Args list, and a Returns note. Every sentence serves a purpose; no fluff or redundancy. It is concise without sacrificing detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is moderately complex (two modes), and the description fully covers both modes, the output shape (themes vs tables), and error handling. With an output schema present, the description need not explain return types in more detail, but it already covers them sufficiently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the signal says schema description coverage is 0%, the description fully explains all three parameters in the docstring: theme_code (2-digit code, omit for themes), lang (language codes), and limit (max tables). It also gives concrete examples ('15' for Bildung). This compensates for any schema gaps and adds practical meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Browse the BFS catalogue: the theme list, or the datasets within a theme.' It clearly distinguishes two modes and names downstream tools (bfs_get_table_metadata, bfs_get_data), which differentiates it from sibling tools like bfs_search_tables.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is explicit: 'Omit theme_code → list all 21 statistical themes... Provide theme_code → list the datasets in that theme.' It also states the purpose of the output ('to feed bfs_get_table_metadata / bfs_get_data'), giving clear when-to-use guidance and naming alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_compare_cantonsARead-onlyIdempotent
Compare a BFS statistical indicator across multiple Swiss cantons.
Designed for KI-Fachgruppe demos and benchmarking. Fetches the same dataset for multiple cantons simultaneously, enabling direct comparison.
Args: params (CompareCantonsInput): - table_id (str): BFS table ID to query - canton_values (list[str]): Canton value codes to compare. Use '0' for Switzerland total, '1' for Zürich, '2' for Bern, etc. Get codes via bfs_get_table_metadata on any canton-level table. - additional_filters (Optional[list]): Extra dimension filters - lang (str): Language code
Returns: str: JSON with data for all selected cantons side by side.
Example use case: Compare teacher-to-student ratios across ZH, BE, LU, CH total: canton_values=['0', '1', '2', '3']
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| rows | No | |
| year | No | |
| error | No | |
| title | No | |
| topic | No | |
| canton | No | |
| region | No | |
| source | No | |
| updated | No | |
| language | No | |
| table_id | No | |
| breakdown | No | |
| truncated | No | |
| dimensions | No | |
| rows_total | No | |
| canton_filter | No | |
| rows_returned | No | |
| canton_variable | No | |
| cantons_compared | No | |
| topic_description | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and idempotentHint=true. The description adds that it fetches data simultaneously for multiple cantons and returns JSON. This adds useful behavioral context without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph with an integrated example. It states the purpose upfront and every sentence adds information. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity and the presence of annotations (read-only, idempotent), the description covers purpose, parameters, usage, and ties to sibling tools. It lacks mention of error handling or response structure, but an output schema is likely provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for each parameter, but the description adds value by explaining canton code meanings (e.g., '0' for Switzerland total) and including a concrete example in the use case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence clearly states 'Compare a BFS statistical indicator across multiple Swiss cantons', providing a specific verb (compare) and resource (BFS indicator across cantons). This distinguishes it from sibling tools like bfs_get_data which is likely for single-canton queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a usage context: 'Designed for KI-Fachgruppe demos and benchmarking', and provides an example use case. It also instructs to get canton codes via bfs_get_table_metadata. However, it does not explicitly contrast with alternatives like bfs_get_data for single cantons.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_construction_activityARead-onlyIdempotent
Yearly new buildings and new dwellings for a commune, with room-size mix.
Returns the consolidated official annual construction statistics (BFS
STAT-TAB theme 09) for one commune: newly built buildings with dwellings
(px-x-0904030000_106) and newly built dwellings broken down by number of
rooms (px-x-0904030000_105), as a per-year series from since_year.
Note: this is the consolidated official yearly statistic. For up-to-date
building-register states and the construction pipeline (Baugesuche /
Bauvorhaben), see the swiss-housing-mcp server — the overlap is deliberate
so the two sources can be cross-validated.
Args: params (ConstructionActivityInput): - municipality_bfs (int): BFS commune number, e.g. 261 (Zürich) - since_year (int): earliest year, inclusive (default 2015)
Returns:
ConstructionActivityResult with a years series (new_buildings,
new_dwellings, dwellings_by_rooms). On error, error/hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| error | No | |
| years | No | |
| source | No | |
| table_ids | No | |
| provenance | No | |
| since_year | No | |
| cross_validation | No | |
| municipality_bfs | No | |
| municipality_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds valuable context beyond annotations: it returns a per-year series with specific fields, is based on official consolidated data, and sets error/hint fields on failure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a one-line purpose, a clarifying note about alternatives, an Args section, and a Returns section. Every sentence adds value, and it is appropriately sized for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich annotations and output schema, the description is complete: it explains the temporal scope, the one-commune focus, the relationship to an overlapping source, and the expected result shape. Error handling is also disclosed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema includes detailed nested descriptions, the context signal reports 0% top-level schema description coverage. The description compensates with explicit Args bullets for municipality_bfs (including an example) and since_year (inclusive, default 2015), giving agents enough semantic grounding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource statement: 'Yearly new buildings and new dwellings for a commune, with room-size mix.' It names the exact BFS data cubes and clarifies that this is the consolidated official yearly statistic, distinguishing it from related construction and pipeline tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: 'this is the *consolidated official yearly* statistic.' It also gives a clear when-not and alternative: 'For up-to-date building-register states and the construction pipeline (Baugesuche / Bauvorhaben), see the swiss-housing-mcp server.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_construction_investmentARead-onlyIdempotent
Yearly building investment and Arbeitsvorrat for a region/canton/commune.
Returns building investment (Bauinvestitionen, current year) alongside the
Arbeitsvorrat (work on hand for the following year) from BFS STAT-TAB
px-x-0904010000_205, as a per-year series from since_year. The
Arbeitsvorrat is the monetary leading indicator: it signals next year's
construction volume before it is realised.
Args:
params (ConstructionInvestmentInput):
- level (str): 'grossregion', 'kanton', or 'gemeinde'
- code (str): region/canton/commune code matching level
- since_year (int): earliest year, inclusive (default 2015)
Returns:
ConstructionInvestmentResult with a years series (investment,
work_on_hand) in 1000 CHF. On error, error/hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| code | No | |
| hint | No | |
| note | No | |
| unit | No | |
| error | No | |
| level | No | |
| years | No | |
| source | No | |
| table_id | No | |
| provenance | No | |
| since_year | No | |
| region_name | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey read-only, idempotent, non-destructive behavior. The description adds valuable context: output units in 1000 CHF, the per-year series format, the leading-indicator meaning, and error/hint fields. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with logical sections (overview, args, returns) and every sentence contributes meaning. It is slightly wordy but not bloated, earning a high but not perfect score for conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the data source, return series, units, and error behavior. Since an output schema exists, it need not explain returns in detail, but doing so adds completeness. Overall, the tool is fully contextualized for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the schema has detailed descriptions, the tool description includes an Args section covering all parameters (level, code, since_year) with examples and default value. This fully compensates for the low reported schema description coverage and gives clear guidance on how each parameter should be used.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it returns yearly building investment and Arbeitsvorrat for a region/canton/commune, naming the specific BFS STAT-TAB data source. This specific verb+resource combination distinguishes it from siblings like bfs_get_data or bfs_construction_activity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the purpose and highlights the Arbeitsvorrat as a leading indicator, giving a clear context for when the tool is useful. However, it does not explicitly mention when not to use it or name alternative sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_education_statsARead-onlyIdempotent
Retrieve Swiss education statistics — convenience tool for Schulamt context.
Provides direct access to key education datasets without needing to know table IDs or variable codes. Covers teachers, students, enrollment scenarios, and scholarship data, optionally filtered by canton.
Args: params (GetEducationStatsInput): - topic (str): One of: 'teachers', 'students', 'scenarios', 'scholarships' - canton (Optional[str]): Canton name, e.g. 'Zürich'. None = all cantons. - lang (str): Language code
Returns:
DataTableResult with topic, topic_description, canton_filter
on success, plus the data table fields. On error, error and
hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| rows | No | |
| year | No | |
| error | No | |
| title | No | |
| topic | No | |
| canton | No | |
| region | No | |
| source | No | |
| updated | No | |
| language | No | |
| table_id | No | |
| breakdown | No | |
| truncated | No | |
| dimensions | No | |
| rows_total | No | |
| canton_filter | No | |
| rows_returned | No | |
| canton_variable | No | |
| cantons_compared | No | |
| topic_description | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description aligns with annotations (readOnlyHint=true, etc.) and adds detail on return format (DataTableResult with topic, canton_filter, error/hint fields). No contradictions, and it elaborates on parameter effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured with Args/Returns sections, front-loaded purpose, and no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema, annotations, and presence of an output schema, the description covers all essential aspects: purpose, parameters, return shape, and error handling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions already cover all three parameters. The description restates them but adds little new beyond the schema. High schema coverage sets baseline at 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states it retrieves Swiss education statistics as a convenience tool for the Schulamt context, listing specific topics (teachers, students, scenarios, scholarships) and filtering by canton. It differentiates from siblings like bfs_get_data by noting no need for table IDs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates this is for common education topics without table IDs, implying use over bfs_get_data. However, it does not explicitly state when not to use it or provide alternative tool names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_featured_datasetsARead-onlyIdempotent
Return a curated list of high-value BFS datasets for Schulamt and public administration.
Provides a shortlist of the most relevant datasets for education planning, demographic analysis, and political context — ideal as a starting point.
Args: params (ListThemesInput): - lang (str): Language code
Returns: FeaturedDatasetsResult with curated table IDs, titles, themes, and recommended use cases.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| error | No | |
| total | No | |
| quick_start | No | |
| featured_datasets | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. The description adds valuable behavioral context by noting the tool returns a curated shortlist with recommended use cases and specific output fields, which goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is succinct with front-loaded primary purpose, followed by contextual details and a minimal Args section. No redundant sentences; every part contributes to understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has only one parameter, rich annotations, and an output schema, the description adequately covers usage context (target audience, use cases, output contents) without needing to detail return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate. However, it only restates 'lang (str): Language code' without adding value beyond the schema's already detailed description (default, pattern, allowed values). This fails to provide additional meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Return' and the resource 'curated list of high-value BFS datasets' targeted at Schulamt and public administration. It differentiates from siblings like bfs_list_tables_by_theme by emphasizing curation and high-value selection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use the tool: as a starting point for education planning, demographic analysis, and political context. It does not provide explicit when-not or alternative tools, but the context from sibling names implies appropriate alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_get_dataARead-onlyIdempotent
Query statistical data from a BFS table with optional filters.
Fetches actual data values from a STAT-TAB table. Always call bfs_get_table_metadata first to understand available variables and values.
Args: params (GetDataInput): - table_id (str): BFS table ID - filters (Optional[list]): Dimension filters to narrow results. Each filter: {"code": "VariableCode", "values": ["val1", "val2"]} Without filters, all data is returned (may be very large). - lang (str): Language for labels - max_rows (int): Safety limit on returned rows (default 500)
Returns:
DataTableResult with dimensions, rows, plus truncated,
rows_total, rows_returned for machine-readable capping.
On error, error and hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| rows | No | |
| year | No | |
| error | No | |
| title | No | |
| topic | No | |
| canton | No | |
| region | No | |
| source | No | |
| updated | No | |
| language | No | |
| table_id | No | |
| breakdown | No | |
| truncated | No | |
| dimensions | No | |
| rows_total | No | |
| canton_filter | No | |
| rows_returned | No | |
| canton_variable | No | |
| cantons_compared | No | |
| topic_description | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false, so the description's claim of querying data is consistent. The description adds behavioral context about the safety limit max_rows and the potential for large datasets when no filters are applied. It also describes error handling in the return (error and hint fields). This fills gaps beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a clear purpose statement, a critical prerequisite, and then a bullet-point list of parameters with their roles. Every sentence adds value, and the most important information (what the tool does and the precondition) is front-loaded. There is no unnecessary verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists (DataTableResult), the description does not need to detail return values, but it does mention key fields (dimensions, rows, truncated, etc.). It covers prerequisites, filtering, language, and safety limits. The tool is a simple query with clear inputs and outputs, and the description addresses all relevant aspects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides detailed descriptions for each parameter (table_id, filters, lang, max_rows), so the description's summary in Args adds only marginal value. The description does include practical examples (e.g., '['1', '2'] for Zürich and Bern') in the schema itself, but the tool description restates key points concisely. Since schema coverage is high, the description does not significantly enhance parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it queries statistical data from a BFS table with optional filters, distinguishing it from sibling tools like bfs_get_table_metadata (which fetches metadata) and bfs_search_tables (which searches for tables). The verb 'Query' and resource 'data values from a STAT-TAB table' are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises calling bfs_get_table_metadata first to understand available variables and values, which is a clear prerequisite. It also notes that without filters, all data is returned (may be very large), implying when to use filters. However, it does not explicitly state when not to use this tool or list alternatives, but the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_get_table_metadataARead-onlyIdempotent
Get metadata for a BFS table: title, variables, and available filter values.
Essential step before calling bfs_get_data. Returns all dimension variables with their codes and value labels needed to construct data queries.
Args: params (GetTableMetadataInput): - table_id (str): BFS table ID, e.g. 'px-x-1504000000_173' - lang (str): Language for labels
Returns: str: JSON with table title, source, update date, and all variables with their codes and value options. Use variable codes in bfs_get_data filters.
Example output structure: { "title": "Lehrkräfte nach Schuljahr, Kanton...", "variables": [ { "code": "Schuljahr", "label": "Schuljahr", "n_values": 14, "values": [{"code": "0", "label": "2010/11"}, ...] } ] }
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| error | No | |
| title | No | |
| source | No | |
| language | No | |
| table_id | No | |
| variables | No | |
| theme_code | No | |
| theme_name | No | |
| usage_hint | No | |
| n_variables | No | |
| last_updated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and idempotent behavior. The description adds valuable context about the return format (JSON with title, source, update date, variables with codes and value options) and provides an example output structure. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections: purpose, workflow position, args, returns, and example. The purpose is front-loaded. The Args section duplicates schema descriptions, slightly bloating length, but the overall structure and example justify the size.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, when to use, return structure, and example output. It does not mention error cases or size limitations, but the output schema (present) and annotations reduce the need for such details. It is sufficiently complete for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description's Args section restates the schema's parameter info (table_id and lang) with no additional semantic depth. The example ID and language codes already exist in the schema. With schema description coverage at 0%, the description fails to compensate by offering new meaning or richer explanations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get metadata for a BFS table: title, variables, and available filter values,' using a specific verb and resource. It also distinguishes itself from siblings by positioning as an 'Essential step before calling bfs_get_data,' making it distinct from data retrieval and search/browse tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Essential step before calling bfs_get_data,' giving clear when-to-use context within the BFS workflow. It does not explicitly mention alternatives or when not to use, but the reference to bfs_get_data implies the intended usage pattern.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_populationARead-onlyIdempotent
Retrieve Swiss population statistics by region, year, and breakdown.
Accesses the core BFS population dataset (ständige Wohnbevölkerung) with flexible filtering by canton/municipality, year, age, and gender. Critical for school space planning and demographic projections.
Args: params (GetPopulationInput): - region (str): 'Schweiz', or canton name like 'Zürich' - year (Optional[str]): Year filter, e.g. '2024' - breakdown (str): 'total', 'age', or 'gender'
Returns: str: JSON with population figures for the selected region and breakdown.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| rows | No | |
| year | No | |
| error | No | |
| title | No | |
| topic | No | |
| canton | No | |
| region | No | |
| source | No | |
| updated | No | |
| language | No | |
| table_id | No | |
| breakdown | No | |
| truncated | No | |
| dimensions | No | |
| rows_total | No | |
| canton_filter | No | |
| rows_returned | No | |
| canton_variable | No | |
| cantons_compared | No | |
| topic_description | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint, destructiveHint, idempotentHint. Description adds context about 'flexible filtering' and dataset source, but does not disclose behavioral traits beyond what annotations provide. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is front-loaded with main purpose, followed by details in a structured Args/Returns format. Every sentence adds value; no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema and the description covers parameters, return type, and use case, it is complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite schema description coverage of 0%, the description includes an Args section that explains each parameter (region, year, breakdown) with types and examples. This compensates for the missing schema descriptions, though it could be more detailed on year format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it retrieves Swiss population statistics by region, year, and breakdown. It mentions the specific dataset and use cases (school space planning), distinguishing it from siblings like bfs_compare_cantons or bfs_education_stats.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage for demographic projections, but does not explicitly state when not to use or compare to alternatives like bfs_compare_cantons. No exclusions or conditions provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_price_indexARead-onlyIdempotent
Swiss price indices not carried by STAT-TAB: Baupreisindex & IMPI.
baupreisindex: the construction price index — returns the national semi-annual index series (Schweiz, Baugewerbe Total), parsed from the BFS DAM XLSX selected via opendata.swiss (CKAN) metadata.impi: the residential property price index — BFS publishes this only as PDF/HTML, so this returns the official source links plus an explicit limitation rather than parsed values.
Data flows through opendata.swiss (CKAN), which rejects default User-Agents with HTTP 403; a custom User-Agent is always sent. Results are cached for 24h.
Args: params (PriceIndexInput): - index (str): 'baupreisindex' or 'impi' - since_year (int | None): optional earliest year to include
Returns:
PriceIndexResult with series (baupreisindex) or source_links (impi).
On error, error/hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| base | No | |
| hint | No | |
| note | No | |
| error | No | |
| index | No | |
| title | No | |
| series | No | |
| source | No | |
| dataset | No | |
| coverage | No | |
| provenance | No | |
| source_links | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds substantial context: data flows via opendata.swiss (CKAN), default user agents are rejected (403) requiring a custom UA, results are cached 24h, and IMPI returns only source links due to publication format. It also notes error handling, exceeding the annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with a short intro, bullet points for each index, a note on data flow, and clear Args/Returns sections. Every sentence provides distinct value, and the structure makes it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one input object and an output schema, the description fully explains the two operational modes, return types, caching behavior, and error handling. Combined with the existing annotations and output schema, the description is complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for `index` and `since_year`, covering accepted values and meaning. The description's Args section largely repeats this information, adding little beyond the schema. Since schema coverage for the nested parameters is strong, a baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description immediately identifies the tool's purpose: providing Swiss price indices (Baupreisindex and IMPI) not available in STAT-TAB. It clearly distinguishes between the two index variants and explains what each returns, setting it apart from sibling tools that handle tables, metadata, or other construction statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states a clear scope ('not carried by STAT-TAB') and distinguishes between the two index modes, including the IMPI limitation (PDF/HTML only). However, it does not explicitly mention alternatives or when not to use this tool, though the scope implies when it is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bfs_search_tablesARead-only
Search for BFS statistical tables by keyword in their titles.
Performs a full-text search across all 682+ BFS table titles. Results include table IDs needed for bfs_get_table_metadata and bfs_get_data.
Note: First call builds a catalog (~682 API requests). Subsequent calls within 1 hour use the cached catalog and are instant.
Args: params (SearchTablesInput): - query (str): Search keywords, e.g. 'Lehrkräfte', 'Schüler Kanton' - theme_code (Optional[str]): Filter by theme, e.g. '15' - lang (str): Language for table titles - limit (int): Max results (default 10)
Returns:
SearchTablesResult with matching tables. On error, error and
hint are set and results is None.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| error | No | |
| query | No | |
| results | No | |
| next_step | No | |
| total_matches | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable context: first call makes ~682 API requests, subsequent calls within 1 hour are instant, and error handling behavior (error and hint fields). Does not mention potential rate limits or result size.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections: purpose, details, caching note, parameter listing, and return info. Every sentence is informative. Front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a search tool with an output schema. Covers purpose, parameters, caching, and error handling. Mentions that results include table IDs for other tools, which aids in task chaining.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Description provides explicit parameter explanations, including examples for query (e.g., 'Lehrkräfte'), description of theme_code filter, lang, and limit. This adds significant value beyond the schema's descriptions, even though schema has descriptions. The examples help understand usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it searches BFS statistical tables by keyword in titles, distinguishing from sibling tools like bfs_list_tables_by_theme. Mentions relevance to downstream tools (bfs_get_table_metadata, bfs_get_data).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains that it performs full-text search across all tables and describes caching behavior (first call slow, subsequent instant). Implicitly guides when to use for keyword-based search, but doesn't explicitly contrast with other search tools or mention exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_communesARead-onlyIdempotent
List all communes of a canton, as of a given date.
Canton membership is derived from the snapshot's Parent chain
(commune → district → canton), so this reflects the official division
on valid_at_date. Each entry carries its BFS number and LINDAS URI.
Args: params (ListCommunesInput): - canton (str): abbreviation ('ZH') or name ('Zürich') - valid_at_date (str): ISO date; default today
Returns:
ListCommunesResult with the canton's communes, sorted by BFS
number. On error, error and hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| error | No | |
| total | No | |
| canton | No | |
| source | No | |
| communes | No | |
| provenance | No | |
| canton_abbr | No | |
| valid_at_date | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds meaningful behavior beyond annotations: explains how canton membership is derived from the Parent chain, states sorting by BFS number, and discloses error/hint fields. No contradiction with readOnly/idempotent/destructive hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in first sentence; the remaining sentences explain derivation, output fields, params, and return behavior in a compact structured Args/Returns layout. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list tool with output schema and readOnly annotations, the description covers scope, date semantics, output sorting, and error behavior. It is self-sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at 0%, the description compensates by documenting both params: canton accepts abbreviation or name with examples, and valid_at_date is ISO date defaulting to today. It adds practical format details beyond bare property names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb+resource ('List all communes of a canton, as of a given date') and specifies output contents (BFS number, LINDAS URI). It clearly distinguishes from sibling single-commune/table tools by emphasizing 'all communes' and official division by date.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: use when you need all communes for a canton at a specific date, with membership based on the snapshot's Parent chain. It does not explicitly name alternatives/exclusions, so not a 5, but it gives enough context for appropriate selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookup_communeARead-onlyIdempotent
Resolve a Swiss commune by name or BFS number, as of a given date.
The BFS commune number is the portfolio's join key. This tool returns
the official register entry — BFS number, name, canton, validity dates
and the stable LINDAS URI — for a commune as it existed on valid_at_date.
Args: params (LookupCommuneInput): - name_or_bfs_number (str): name/substring or BFS number - valid_at_date (str): ISO date; commune state as of this date
Returns:
LookupCommuneResult with matching communes (BFS number, canton,
validity, LINDAS URI). On error, error and hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| error | No | |
| query | No | |
| source | No | |
| communes | No | |
| provenance | No | |
| total_matches | No | |
| valid_at_date | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive. The description adds valuable behavioral context: it specifies the exact return fields (BFS number, canton, validity, LINDAS URI), explains the date-sensitive state of the commune, and discloses error handling (error and hint fields are set). This goes beyond the annotations to clarify expected outputs and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with an opening purpose statement, a brief context paragraph, and clearly labeled Args/Returns sections. While slightly verbose with the join key explanation, every sentence contributes meaningful context. It is front-loaded with the main purpose and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the presence of an output schema, and strong annotations, the description covers all necessary aspects: what it does, key parameters, return structure, and error behavior. It is complete enough for an agent to understand when and how to use it without further documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides rich descriptions for both parameters, including examples and matching behavior for name_or_bfs_number and the ISO date format for valid_at_date. The description's Args section merely repeats this information without adding new semantic depth, so it adds little beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Resolve a Swiss commune by name or BFS number, as of a given date.' It clearly states the tool's scope and output (official register entry with BFS number, name, canton, validity, LINDAS URI), distinguishing it from siblings like list_communes or resolve_historical_commune by emphasizing temporal resolution and the portfolio's join key.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides contextual hints—'as of a given date' and 'portfolio's join key'—but does not explicitly state when to use this tool over alternatives like resolve_historical_commune or list_communes. There are no stated exclusions or alternative naming, so the usage guidance is only implied, not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_historical_communeARead-onlyIdempotent
Map a historical BFS commune number onto today's number(s).
This is the core value of the reference layer: when old statistics are
keyed on a BFS number that has since been merged or renamed, this tool
returns which of today's commune(s) that number resolves to, plus the
mutation path (fusions/renamings with dates). Use resolves_to to
re-key (umschlüsseln) old figures onto the current municipal division.
Args: params (ResolveHistoricalCommuneInput): - bfs_number (int): historical BFS number - from_date (str): ISO date the old data belongs to - to_date (str): ISO target date (default today)
Returns:
ResolveHistoricalCommuneResult with resolves_to (today's BFS
number/name/LINDAS URI) and mutation_path. On error, error/hint.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| error | No | |
| source | No | |
| to_date | No | |
| from_date | No | |
| unchanged | No | |
| bfs_number | No | |
| provenance | No | |
| resolves_to | No | |
| mutation_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and the description adds meaningful behavioral context: it returns a mutation path (fusions/renamings with dates), resolves to today's BFS number/name/LINDAS URI, and provides error/hint fields. This goes beyond the annotations and clarifies the tool's behavior accurately.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear opening sentence, purpose elaboration, and Args/Returns sections. It is slightly verbose with phrases like 'core value of the reference layer' but each sentence contributes useful context. The front-loaded summary is strong, making it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a relatively specialized historical resolution tool, the description covers the core use case, the output structure (resolves_to and mutation_path), error handling, and how to apply it for re-keying. Combined with the output schema, the description is complete and sufficient for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides detailed descriptions for all three parameters (bfs_number, from_date, to_date) including examples and constraints. The description's Args section repeats this information without adding much new semantic value. Since schema coverage is high, the baseline is 3; the description doesn't significantly enhance parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb 'Map a historical BFS commune number onto today's number(s)', clearly identifying the resource (historical commune numbers) and the action (mapping to current numbers). It also distinguishes itself from siblings by focusing on mutation paths and re-keying old statistics, which is unique among the listed tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: 'when old statistics are keyed on a BFS number that has since been merged or renamed'. It explains the use case for re-keying old figures. However, it doesn't explicitly list when not to use this tool or mention alternative sibling tools like search_historical_series or lookup_commune, so it lacks explicit exclusions/alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_historical_seriesARead-onlyIdempotent
Search long-run historical time series (HSSO) by topic.
Historical Statistics of Switzerland provides long-run series (roughly 19th–20th century) as static XLSX tables. This tool searches the table catalogue by keyword and returns each match with its page and a stable XLSX download URL.
Licence: HSSO is CC BY-NC-SA 3.0 — attribution required, NonCommercial.
Every response carries that notice in licence_note.
Args: params (SearchHistoricalSeriesInput): - topic (str): keyword(s); all must match the title - period (str): optional period hint (informational only)
Returns:
SearchHistoricalSeriesResult with matching series (code, title,
page URL, XLSX URL). On error, error and hint are set.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| note | No | |
| error | No | |
| topic | No | |
| period | No | |
| series | No | |
| source | No | |
| provenance | No | |
| licence_note | No | |
| total_matches | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description goes beyond this by disclosing the licence (CC BY-NC-SA 3.0), that every response includes a licence notice, and that the period parameter is informational only because HSSO does not support per-table filtering. It also notes the error/ hint fields, adding useful behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded purpose, a brief resource context, licence notice, and an Args/Returns layout. Every sentence contributes necessary information without redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides complete context for a read-only search tool: resource, input semantics, output shape, error behavior, and licensing. Since an output schema exists, the return values need not be exhaustively described, and the description covers all other relevant aspects adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Context reports schema description coverage at 0%, so the description must compensate. It explains that topic is a keyword that all must match the title, and that period is optional and informational only. This is sufficient semantic guidance even though the nested schema actually contains detailed descriptions; the description adds compact, accessible meaning for the agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource-scope statement: 'Search long-run historical time series (HSSO) by topic.' It clearly distinguishes this tool from the BFS sibling tools by focusing on HSSO's static XLSX table catalogue, and it states what is returned (page and XLSX URL). No ambiguity about the tool's purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by explaining that this searches the HSSO catalogue of long-run 19th–20th century series, which distinguishes it from BFS-oriented siblings. It does not explicitly name alternatives or state when not to use it, but the resource scope ('Historical Statistics of Switzerland', 'HSSO') makes the usage context evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
11 tool updates
v0.7.0- Added
bfs_browse_catalog - Added
bfs_construction_activity - Added
bfs_construction_investment - Changed
bfs_get_table_metadata1 field changed- changed
Input schema / $defs / GetTableMetadataInput / properties / table_id / descriptionPrevious value: -"BFS table/database ID, e.g. 'px-x-1504000000_173'. Obtain from bfs_search_tables or bfs_list_tables_by_theme."New value: +"BFS table/database ID, e.g. 'px-x-1504000000_173'. Obtain from bfs_search_tables or bfs_browse_catalog."
- Removed
bfs_list_tables_by_theme - Removed
bfs_list_themes - Added
bfs_price_index - Added
list_communes - Added
lookup_commune - Added
resolve_historical_commune - Added
search_historical_series
9 tool updates
v0.2.0- First observed
bfs_compare_cantons - First observed
bfs_education_stats - First observed
bfs_featured_datasets - First observed
bfs_get_data - First observed
bfs_get_table_metadata - First observed
bfs_list_tables_by_theme - First observed
bfs_list_themes - First observed
bfs_population - First observed
bfs_search_tables
TDQS
Scored across 15 tools
Most tools have distinct purposes, but some overlap exists among dataset discovery tools (bfs_browse_catalog, bfs_search_tables, bfs_featured_datasets) and data retrieval tools (bfs_get_data vs. bfs_education_stats, bfs_population, bfs_compare_cantons). The detailed descriptions help an agent differentiate them, so confusion is unlikely but possible.
The tool names are uniformly snake_case with a strong 'bfs_' prefix for BFS data tools, and many use a verb_noun pattern (bfs_get_data, bfs_compare_cantons, lookup_commune). However, several convenience tools break the pattern with noun-only names (bfs_population, bfs_construction_activity, bfs_price_index), making the naming slightly inconsistent.
With 15 tools, the server sits at the upper boundary of the ideal range. Each tool serves a clear purpose in the statistical workflow, from catalog discovery and metadata retrieval to specialized data extractions and commune reference lookups. No superfluous tools.
The server covers the full statistical query lifecycle: browsing/searching for tables, retrieving metadata, fetching filtered data, and convenience wrappers for key domains (education, population, construction, prices). It also includes essential commune reference tools for re-keying historical data. No significant gaps are apparent.
Maintenance
Related MCP Connectors
Swiss federal law (Fedlex) and political data (LINDAS) for agents, every answer with sources
Swiss customs (TARES), FINMA registry & NOGA/NACE/ISIC classifications. 9 MCP tools, free tier.
Official Swiss living-cost & relocation data for all 26 cantons — taxes, rent, premiums, jobs.
IBGE: geography, census, economy and health from the official APIs, with provenance. 23 tools.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides AI assistants access to 1.6 million Swiss health insurance premium records from 55 insurers across 11 years (2016-2026), enabling price comparisons, historical analysis, and finding the cheapest insurance options based on location, age, and coverage preferences.418 npm1MIT
- AlicenseNot gradedqualityDmaintenanceVerified knowledge base for AI agents. Stop hallucinations with certified, source-backed facts. Covers Swiss law, health, finance, climate, AI/ML, and more. 8 tools, no API key needed, public and free.MIT
- AlicenseAqualityAmaintenanceEnables AI models to query Swiss National Bank data including exchange rates, balance sheet, interest rates, SARON, monetary aggregates, banking statistics, and balance of payments via the SNB public API.1117 PyPIMIT
- FlicenseAqualityCmaintenanceEnables LLMs to query structured statistical data from the Swiss Federal Archives' Linked Data platform (LINDAS) by translating natural language questions into SPARQL queries against RDF data cubes.8-