The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Swiss Energy MCP listing page.
🇨🇭 Part of the Swiss Public Data MCP Portfolio
MCP server for Swiss energy data from the Federal Office of Energy (SFOE/BFE) via GeoAdmin REST API and opendata.swiss — no API key required.
swiss-energy-mcp gives AI assistants structured, location-based access to Switzerland's energy infrastructure. Built on open geodata from the Swiss Federal Office of Energy (SFOE/BFE) via the GeoAdmin REST API and the opendata.swiss catalogue — completely authentication-free.
The server is part of a growing portfolio of Swiss open data MCP servers. Think of it as the energy atlas counterpart to swiss-road-mobility-mcp: while the latter maps mobility, this server maps where Switzerland produces electricity, where solar potential exists, and which municipalities hold the "Energiestadt" label.
Anchor demo query: "Which power plants are within 20 km of the school in Wädenswil — and is the municipality an Energiestadt?"
uv (recommended) or pipAdd to your claude_desktop_config.json:
Config file locations:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonFor use via claude.ai in the browser (e.g. on managed workstations without local software):
💡 "stdio for the developer laptop, HTTP for the browser."
Once connected in Claude Desktop, try:
| Tool | Description |
|---|---|
energy_find_power_plants | All electricity generation plants within a radius (optional category filter) |
energy_find_wind_turbines | Wind turbines with manufacturer, model, hub height |
energy_find_hydro_plants | Hydropower plants with capacity and expected output |
energy_find_pv_installations | Large PV installations with annual/winter production |
energy_find_biogas_plants | Biogas plants |
energy_find_energy_cities | Municipalities with "Energiestadt" label |
energy_solar_potential | Solar suitability of roof segments at a location |
energy_location_profile | Combined energy profile (5 layers) for a location |
energy_search_bfe_datasets | Full-text search over SFOE datasets on opendata.swiss |
energy_check_status | Check availability of GeoAdmin and opendata.swiss APIs |
All tools accept WGS84 coordinates (lat/lon). Conversion to Swiss LV95 is handled internally.
| Query | Tool |
|---|---|
| "Power plants near Bern (20 km radius)?" | energy_find_power_plants |
| "Wind turbines in the Jura?" | energy_find_wind_turbines |
| "Is Zürich an Energiestadt?" | energy_find_energy_cities |
| "Solar potential of rooftops near lat=47.37, lon=8.54?" | energy_solar_potential |
| "Full energy profile for Lucerne region?" | energy_location_profile |
| "SFOE datasets on hydropower?" | energy_search_bfe_datasets |
→ More use cases by audience →
| Source | URL | Auth |
|---|---|---|
| GeoAdmin REST API (swisstopo) | api3.geo.admin.ch | None |
| opendata.swiss CKAN API | opendata.swiss/api/3/action | None |
BFE Layers used:
ch.bfe.elektrizitaetsproduktionsanlagench.bfe.windenergieanlagench.bfe.statistik-wasserkraftanlagench.bfe.photovoltaik-grossanlagench.bfe.biogasanlagench.bfe.energiestaedtech.bfe.solarenergie-eignung-daecherAll variables use the SWISS_ENERGY_ prefix and are validated at startup.
| Environment variable | Default | Description |
|---|---|---|
SWISS_ENERGY_TRANSPORT | stdio | Transport mode: stdio or http |
SWISS_ENERGY_HOST | 127.0.0.1 | Host for HTTP transport. Bind 0.0.0.0 only inside a container. |
SWISS_ENERGY_PORT | 8000 | Port for HTTP transport |
SWISS_ENERGY_CORS_ORIGINS | https://claude.ai | Comma-separated allowed CORS origins (HTTP transport) |
SWISS_ENERGY_ALLOWED_HOSTS | (empty) | Comma-separated inbound Host allow-list. Only needed for a non-loopback bind. |
SWISS_ENERGY_LOG_LEVEL | INFO | Log level: DEBUG / INFO / WARNING / ERROR |
SWISS_ENERGY_HTTP_TIMEOUT | 20 | Upstream HTTP timeout in seconds |
Both list-valued variables also accept a JSON array — ["https://a.test"] —
in addition to the comma-separated form.
See .env.example for a template.
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 |
|---|---|---|
initialize handshake | 2024-11-05 … 2025-11-25 | What today's clients speak. The server answers with the revision asked for, or with the 2025-11-25 ceiling when the request asks for something newer. |
| Per-request envelope | 2026-07-28 | A request carrying the 2026-07-28 _meta envelope opens a modern connection. |
Both revisions are pinned in
tests/test_protocol_version.py and asserted
against the installed SDK, so a Dependabot bump of mcp cannot move either one
silently. The handshake ceiling is measured against a live initialize through
the assembled ASGI stack, not read off a constant name.
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.
The server uses all three MCP primitives:
EnergyResponse envelope: structured results plus a Markdown summary,
explicit source / license attribution, and a match_type field.energy://layers, the static catalogue of BFE GeoAdmin layers.energy_site_assessment, a guided location-analysis template.The server is in Phase 1 (read-only). See docs/roadmap.md for the phased architecture and docs/security.md for the egress allow-list, SSRF protection and trifecta assessment.
| Aspect | Details |
|---|---|
| Access | Read-only (readOnlyHint: true) — the server cannot modify or delete any data |
| Personal data | No personal data — all sources are aggregated, public infrastructure data |
| Rate limits | Built-in per-query caps (max 50 search results, default 5 km radius) |
| Timeout | 20 seconds per API call |
| Authentication | No API keys required — both APIs are publicly accessible |
| Licenses | All data under open licenses via opendata.swiss (OGD) |
| Terms of Service | Subject to ToS of the respective data sources: GeoAdmin, opendata.swiss, SFOE/BFE |
| Component | Metaphor | Function |
|---|---|---|
api_client.py | Switchboard | Handles HTTP requests, coordinate conversion, error handling |
| LV95 converter | Translator | Converts WGS84 (lat/lon) to Swiss coordinate system |
server.py | Storefront | Exposes all 10 tools via FastMCP |
ch.bfe.solarenergie-eignung-daecher covers building footprints — not all roof types are classifiedSee CHANGELOG.md
See CONTRIBUTING.md (🇩🇪 Deutsch)
See SECURITY.md (🇩🇪 Deutsch) for the security policy and posture summary, and docs/security.md for the full technical security model.
MIT License — see LICENSE
Hayal Oezkan · malkreide
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):