Schwaizer BFS MCP Server
About Schwaizer
SHAPING SWITZERLAND'S AI FUTURE
Empowering Swiss businesses and society through responsible AI adoption.
Founded in 2025, Schwaizer is a non-profit organization dedicated to accelerating the responsible adoption of artificial intelligence across Switzerland.
Website: https://www.schwaizer.ch
Overview
The Schwaizer BFS MCP Server provides programmatic access to statistical data from the Swiss Federal Statistical Office (Bundesamt fΓΌr Statistik / Office fΓ©dΓ©ral de la statistique) through the Model Context Protocol (MCP).
This server integrates with three BFS APIs:
PXWEB API - Main statistical data API with comprehensive datasets
Swiss Stats Explorer (SSE) API - Modern SDMX-based API for time-series data
DAM API - Data Asset Management catalog for searching and discovering datasets
Features
π Search datasets by keywords, themes, and spatial divisions
π Retrieve statistical data with flexible filtering options
π Multi-language support (German, French, Italian, English)
π Time-series data access via Swiss Stats Explorer API
ποΈ Browse catalog with 21 statistical themes
π§ Metadata exploration to understand dataset structure
β‘ Rate limiting handling with automatic retries
π Structured logging for debugging
Installation
Prerequisites
Node.js 20.0.0 or higher
npm or pnpm
Install Dependencies
npm installConfiguration
Copy the example environment file:
cp .env.example .envEdit .env to customize settings (optional):
# Logging level (debug, info, warn, error)
LOG_LEVEL=info
# Optional: Rate limiting
BFS_REQUEST_DELAY=0
BFS_MAX_RETRIES=3Usage
Running the Server
npm startThe server runs via stdio and can be integrated with any MCP-compatible client.
Available Tools
Catalog Tools
search_datasets
Search for statistical datasets in the BFS catalog.
Parameters:
language(optional): Language for results (de, fr, it, en) - default: enquery(optional): Search term to find in titles and descriptionstheme(optional): Filter by theme (prodima number)spatialDivision(optional): Filter by spatial division levelpublishingYearStart(optional): Filter by publishing year startpublishingYearEnd(optional): Filter by publishing year endlimit(optional): Maximum results (1-1000) - default: 50
Example:
{
"language": "en",
"query": "students",
"theme": 900212,
"limit": 10
}list_themes
List all available statistical themes (categories).
Parameters:
language(optional): Language for theme names - default: en
Returns: List of 21 themes with prodima numbers and codes.
get_dataset_info
Get detailed information about a specific dataset.
Parameters:
numberBfs(optional): BFS number (e.g., "px-x-1502040100_131")numberAsset(optional): Asset numberlanguage(optional): Language for results - default: en
Note: Provide either numberBfs or numberAsset. The BFS number is different for PXWEB and SSE datasets.
Data Tools
get_statistical_data
Retrieve statistical data from the PXWEB API.
Parameters:
numberBfs(required): BFS number of the datasetlanguage(optional): Language for results - default: enquery(optional): Dimension filters as key-value pairsformat(optional): Response format (json-stat, json, csv) - default: json-stat
Example:
{
"numberBfs": "px-x-1502040100_131",
"language": "en",
"query": {
"Jahr": ["40", "41"],
"Studienstufe": ["2", "3"]
}
}get_sse_data
Retrieve time-series data from the Swiss Stats Explorer API.
Parameters:
numberBfs(required): SSE dataset identifier (e.g., "DF_LWZ_1")language(optional): Language for results - default: enquery(optional): Dimension filtersstartPeriod(optional): Start period (e.g., "2020")endPeriod(optional): End period (e.g., "2023")
Note: The BFS number for SSE datasets is different from the PXWEB datasets.
Example:
{
"numberBfs": "DF_PASTA_552_MONTHLY",
"language": "en",
"query": {
"FREQ": "M",
"ACCOMMODATION_TYPE": ["552001"],
"COUNTRY_ORIGIN": ["CH", "AUSL"]
},
"startPeriod": "2020",
"endPeriod": "2023"
}Metadata Tools
get_dataset_metadata
Get complete metadata structure for a PXWEB dataset.
Parameters:
numberBfs(required): BFS number of the datasetlanguage(optional): Language for labels - default: en
Returns: Complete dimension structure with all codes and values.
get_sse_metadata
Get metadata for a Swiss Stats Explorer dataset.
Parameters:
numberBfs(required): SSE dataset identifierlanguage(optional): Language for labels - default: en
get_dataset_dimensions
Get a simplified view of available dimensions for filtering.
Parameters:
numberBfs(required): BFS number of the datasetlanguage(optional): Language for labels - default: en
Returns: Dimension codes with sample values for quick reference.
Typical Workflow
1. Discover Datasets
// Search for datasets about students
search_datasets({
"query": "students",
"language": "en",
"theme": 900212 // Education theme
})2. Explore Dataset Structure
// Get metadata to understand available dimensions
get_dataset_metadata({
"numberBfs": "px-x-1502040100_131",
"language": "en"
})3. Retrieve Data
// Get filtered data
get_statistical_data({
"numberBfs": "px-x-1502040100_131",
"language": "en",
"query": {
"Jahr": ["40", "41"], // Years 2020/21, 2021/22
"Geschlecht": ["0", "1"] // All genders
}
})Example Use Case: Demographic Analysis
This section demonstrates a complete workflow for finding and retrieving specific demographic data.
Goal: Find the total permanent resident population of Zurich (ZH), Bern (BE), and Vaud (VD) for the years 2020-2024.
Step 1: Search for Relevant Datasets
First, search for datasets related to population at the cantonal level.
search_datasets({
"language": "en",
"query": "population",
"spatialDivision": "Cantons"
})This returns a list of datasets. We identify "px-x-0102010000_102" ("Permanent and non-permanent resident population by canton, sex, marital status and age, 2010-2024") as the most relevant one.
Step 2: Get Dataset Metadata
Next, get the metadata to understand the dataset's structure and find the codes for filtering.
get_dataset_metadata({
"numberBfs": "px-x-0102010000_102",
"language": "en"
})From the metadata, we identify the following codes:
Cantons:
ZH,BE,VDPopulation Type:
1(Permanent resident population)Sex:
-99999(Total)Marital Status:
-99999(Total)Age:
-99999(Total)
Step 3: Retrieve the Data
Finally, use the codes to query the specific data points.
get_statistical_data({
"language": "en",
"numberBfs": "px-x-0102010000_102",
"query": {
"Jahr": ["2020", "2021", "2022", "2023", "2024"],
"Kanton": ["ZH", "BE", "VD"],
"BevΓΆlkerungstyp": "1",
"Geschlecht": "-99999",
"Zivilstand": "-99999",
"Alter": "-99999"
},
"format": "json"
})Step 4: Analyze the Results
The query returns the following data, which can then be used for analysis or visualization.
Year | Canton | Population |
2020 | Zurich | 1,553,423 |
2020 | Bern | 1,043,081 |
2020 | Vaud | 814,762 |
2021 | Zurich | 1,564,662 |
2021 | Bern | 1,047,422 |
2021 | Vaud | 822,968 |
2022 | Zurich | 1,579,967 |
2022 | Bern | 1,051,437 |
2022 | Vaud | 830,431 |
2023 | Zurich | 1,605,508 |
2023 | Bern | 1,063,533 |
2023 | Vaud | 845,870 |
2024 | Zurich | 1,620,020 |
2024 | Bern | 1,071,216 |
2024 | Vaud | 855,106 |
This workflow demonstrates how to efficiently navigate the BFS data catalog and retrieve precise data for analysis.
BFS Themes
The BFS organizes data into 21 thematic areas:
Code | Theme | Prodima |
00 | Statistical basis and overviews | 900001 |
01 | Population | 900010 |
02 | Territory and environment | 900035 |
03 | Work and income | 900051 |
04 | National economy | 900075 |
05 | Prices | 900084 |
06 | Industry and services | 900092 |
07 | Agriculture and forestry | 900104 |
08 | Energy | 900127 |
09 | Construction and housing | 900140 |
10 | Tourism | 900160 |
11 | Mobility and transport | 900169 |
12 | Money, banks and insurance | 900191 |
13 | Social security | 900198 |
14 | Health | 900210 |
15 | Education and science | 900212 |
16 | Culture, media, information society, sports | 900214 |
17 | Politics | 900226 |
18 | General Government and finance | 900239 |
19 | Crime and criminal justice | 900257 |
20 | Economic and social situation of the population | 900269 |
21 | Sustainable development, regional disparities | 900276 |
Rate Limiting
The BFS PXWEB API has rate limits. If you encounter HTTP 429 errors:
Add delays between requests: Set
BFS_REQUEST_DELAYin.envQuery specific dimensions: Instead of requesting all data, filter by specific dimensions
Use smaller datasets: Break large queries into smaller chunks
API Documentation
PXWEB API
Base URL:
https://www.pxweb.bfs.admin.ch/api/v1Documentation: PXWEB API Guide
Swiss Stats Explorer (SSE)
Base URL:
https://stats.swiss/api/v1Format: SDMX-based XML responses
DAM API
Base URL:
https://dam-api.bfs.admin.ch/hub/apiPurpose: Dataset catalog and metadata
Error Handling
The server provides clear error messages for common issues:
404 Not Found: Dataset doesn't exist - check the BFS number
429 Too Many Requests: Rate limit exceeded - add delay or reduce query size
400 Bad Request: Invalid query parameters - check dimension codes and values
No records found: Query filters don't match any data - adjust filters or time period
Development
Project Structure
schwaizer-bfs-mcp/
βββ src/
β βββ index.js # MCP server entry point
β βββ config.js # Configuration loader
β βββ api/ # API clients
β β βββ pxweb-client.js # PXWEB API
β β βββ sse-client.js # Swiss Stats Explorer
β β βββ dam-client.js # DAM catalog
β βββ tools/ # MCP tool implementations
β β βββ catalog-tools.js # Search & discovery
β β βββ data-tools.js # Data retrieval
β β βββ metadata-tools.js # Metadata access
β βββ utils/ # Utilities
β βββ logger.js # Logging
β βββ formatting.js # Helpers
βββ tests/ # Test files
βββ docs/ # Documentation
βββ .env.example # Environment template
βββ package.json # Dependencies
βββ README.md # This fileScripts
npm start- Start the MCP servernpm run dev- Start with auto-reload on file changesnpm test- Run tests (when implemented)npm run lint- Run ESLintnpm run format- Format code with Prettier
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License - See LICENSE file for details
Disclaimer
This is an unofficial community project and is not affiliated with or endorsed by the Swiss Federal Statistical Office (BFS/OFS/UST/UFS).
Resources
Support
For issues and questions, please open an issue on the project's GitHub repository.
Built with β€οΈ by Schwaizer for the Swiss AI community
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/ishumilin/schwaizer-bfs-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server