swisstopo-mcp

swisstopo-mcp

MCP server for Swiss federal geodata -- maps, elevation, geocoding, cadastral extracts, and downloadable datasets via Swisstopo APIs.

Category
Visit Server

README

Part of the Swiss Public Data MCP Portfolio

swisstopo-mcp

Version License: MIT Python 3.11+ MCP No Auth Required CI

MCP server for Swiss federal geodata -- maps, elevation, geocoding, cadastral extracts, and downloadable datasets via Swisstopo APIs

Deutsche Version


Overview

swisstopo-mcp gives AI assistants access to Switzerland's official geodata infrastructure through 13 tools across 6 API families, all without authentication:

Source Data API
Swisstopo REST API 500+ geodata layers (buildings, boundaries, land use) REST/JSON
Geocoding Official addresses, place names, postal codes REST/JSON
Height Service Elevation above sea level, elevation profiles REST/JSON
STAC Catalog Orthophotos, elevation models, 3D buildings STAC 0.9
WMTS National maps, aerial images, zoning maps URL builder
OEREB Cadastre Public-law restrictions, parcels REST/JSON (cantonal)

Anchor demo query: "What land-use restrictions apply to the parcel at Musterstrasse 5, Zurich? Show me the location on a map." β†’ More use cases by audience β†’


Features

  • πŸ—ΊοΈ 13 tools across 6 API families (REST, Geocoding, Height, STAC, WMTS, OEREB)
  • πŸ” Geocode Swiss addresses and reverse-geocode coordinates
  • πŸ”οΈ Query elevation and compute elevation profiles
  • πŸ“¦ Discover and download geodatasets (orthophotos, 3D buildings, historical maps)
  • πŸ—οΈ Identify map features at coordinates across 500+ Swisstopo layers
  • πŸ”— Generate shareable map.geo.admin.ch links
  • πŸ“‹ Look up cadastral property IDs (EGRID) and retrieve OEREB extracts
  • πŸ”“ No API key required for 11 of 13 tools
  • ☁️ 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/swisstopo-mcp.git
cd swisstopo-mcp

# Install
pip install -e .
# or with uv:
uv pip install -e .

Or with uvx (no permanent installation):

uvx swisstopo-mcp

Quickstart

# stdio (for Claude Desktop)
python -m swisstopo_mcp.server

# Streamable HTTP (port 8000)
python -m swisstopo_mcp.server --http --port 8000

Try it immediately in Claude Desktop:

"Where is Bahnhofstrasse 1, Zurich? Give me the coordinates." "What is the elevation at the Uetliberg summit?" "What buildings are at coordinates 2683500, 1247500 (LV95)?"


Configuration

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "swisstopo": {
      "command": "python",
      "args": ["-m", "swisstopo_mcp.server"]
    }
  }
}

Or with uvx:

{
  "mcpServers": {
    "swisstopo": {
      "command": "uvx",
      "args": ["swisstopo-mcp"]
    }
  }
}

Config file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Cloud Deployment (SSE for browser access)

For use via claude.ai in the browser (e.g. on managed workstations without local software):

Render.com (recommended):

  1. Push/fork the repository to GitHub
  2. On render.com: New Web Service -> connect GitHub repo
  3. Set start command: python -m swisstopo_mcp.server --http --port 8000
  4. In claude.ai under Settings -> MCP Servers, add: https://your-app.onrender.com/sse

Available Tools

REST API (Layer & Feature Queries)

Tool Description
swisstopo_search_layers Search the Swisstopo layer catalog (500+ layers) by keyword
swisstopo_identify_features Find map features at a specific coordinate (spatial query)
swisstopo_find_features Search features by attribute value within a layer (e.g. buildings by EGID)
swisstopo_get_feature Retrieve full attributes and geometry for a feature by ID

Geocoding

Tool Description
swisstopo_geocode Convert Swiss addresses, place names, or postal codes to coordinates
swisstopo_reverse_geocode Find the nearest address for given coordinates

Height Service

Tool Description
swisstopo_get_height Get elevation above sea level (m a.s.l.) at a coordinate
swisstopo_elevation_profile Compute an elevation profile along a line

STAC Catalog (Geodata Downloads)

Tool Description
swisstopo_search_geodata Search the STAC catalog for downloadable geodatasets
swisstopo_get_collection Get details and download links for a STAC collection

WMTS (Map URLs)

Tool Description
swisstopo_map_url Generate a map.geo.admin.ch URL for browser display

OEREB Cadastre

Tool Description
swisstopo_get_egrid Resolve a cadastral property ID (EGRID) from coordinates
swisstopo_get_oereb_extract Retrieve public-law land-use restrictions (OEREB) for a parcel

Example Use Cases

Query Tool
"Where is Bahnhofstrasse 1, Zurich?" swisstopo_geocode
"What is the elevation at the Uetliberg summit?" swisstopo_get_height
"What buildings are at coordinates 2683500, 1247500?" swisstopo_identify_features
"Find orthophoto datasets for download" swisstopo_search_geodata
"Show me a map of Bern at zoom level 10" swisstopo_map_url
"What restrictions apply to parcel at Musterstrasse 5?" swisstopo_get_egrid + swisstopo_get_oereb_extract

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Claude / AI   │────▢│  swisstopo-mcp               │────▢│  Swisstopo REST API      β”‚
β”‚   (MCP Host)    │◀────│  (MCP Server)                │◀────│  api3.geo.admin.ch       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚                              β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                        β”‚  13 Tools                    │────▢│  Geocoding               β”‚
                        β”‚  Stdio | Streamable HTTP     │◀────│  api3.geo.admin.ch       β”‚
                        β”‚                              β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                        β”‚  No authentication required  │────▢│  STAC Catalog            β”‚
                        β”‚  (11 of 13 tools)            │◀────│  data.geo.admin.ch       β”‚
                        β”‚                              β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                        β”‚                              │────▢│  OEREB Cadastre          β”‚
                        β”‚                              │◀────│  (cantonal endpoints)    β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

swisstopo-mcp/
β”œβ”€β”€ src/swisstopo_mcp/
β”‚   β”œβ”€β”€ __init__.py              # Package version
β”‚   β”œβ”€β”€ server.py                # MCP server wiring (tool registrations)
β”‚   β”œβ”€β”€ api_client.py            # Shared HTTP client (httpx + error handling)
β”‚   β”œβ”€β”€ geocoding.py             # swisstopo_geocode, swisstopo_reverse_geocode
β”‚   β”œβ”€β”€ rest_api.py              # swisstopo_search_layers, identify, find, get_feature
β”‚   β”œβ”€β”€ height.py                # swisstopo_get_height, swisstopo_elevation_profile
β”‚   β”œβ”€β”€ stac.py                  # swisstopo_search_geodata, swisstopo_get_collection
β”‚   β”œβ”€β”€ wmts.py                  # swisstopo_map_url
β”‚   └── oereb.py                 # swisstopo_get_egrid, swisstopo_get_oereb_extract
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_api_client.py
β”‚   β”œβ”€β”€ test_geocoding.py
β”‚   β”œβ”€β”€ test_height.py
β”‚   β”œβ”€β”€ test_oereb.py
β”‚   β”œβ”€β”€ test_rest_api.py
β”‚   β”œβ”€β”€ test_stac.py
β”‚   └── test_wmts.py
β”œβ”€β”€ .github/workflows/ci.yml     # GitHub Actions (Python 3.11/3.12/3.13)
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ CONTRIBUTING.md
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md                    # This file (English)
└── README.de.md                 # German version

Security & Compliance

Phase

This server is in Phase 1 β€” Read-only wrapper. All 13 tools are readOnlyHint: true / destructiveHint: false; there are no write or send capabilities. See docs/roadmap.md for later phases.

Lethal Trifecta assessment

Capability Status Rationale
Access to private data ❌ No Public Open Data only (federal/cantonal geodata)
Exposure to untrusted content ⚠️ Limited Reads only from a fixed allow-list of trusted geo.admin / OEREB hosts
External communication (write/send) ❌ No Read-only; no mail/webhook/write tools

Trifecta score: at most 1 of 3 β€” safe by design.

Egress

Outbound requests are restricted to an explicit code-layer allow-list and redirects are disabled β€” see docs/network-egress.md.

Container deployment

For containerised HTTP deployments, a hardened Dockerfile and Kubernetes manifests (non-root, read-only root filesystem, dropped capabilities, egress NetworkPolicy) are provided β€” see docs/deployment.md.

MCP Protocol Version

The MCP protocol version is negotiated by the mcp SDK, which is pinned to the 1.x major in pyproject.toml so an update cannot silently change the negotiated version. SDK bumps are proposed monthly via Dependabot and tracked in CHANGELOG.md.

Sessions & Authentication

The server is unauthenticated by design β€” it serves only public open data. Over HTTP, session IDs are managed entirely by the FastMCP framework; there is no per-user state, so there is nothing user-specific to bind a session to. If an authenticated deployment is ever introduced, session IDs must be bound to the validated user identity (audit finding SEC-009).

Error handling

  • Execution errors (upstream failure, invalid value) are returned as a ToolResponse with is_error: true and a user-friendly summary; raw exception text is never leaked to the client (it is logged to stderr instead).
  • Protocol errors (unknown tool, malformed/invalid arguments) are emitted by the MCP SDK as JSON-RPC errors with standard codes (e.g. -32602 invalid params). Input validation happens at the Pydantic boundary (SEC-018).

MCP Primitives

This server intentionally exposes Tools only (no Resources or Prompts): it is a Phase-1 read-only wrapper, and every result is a live, parameterised API query rather than a static addressable document. Resources/Prompts may be added in a later phase if stable URI schemes emerge.

Tool workflows

Most tools return a thought-complete result in a single call. Two domains use a short, documented discovery chain (each tool's description states the next step):

  • Feature query: swisstopo_search_layers (find layer IDs) β†’ swisstopo_identify_features / swisstopo_find_features β†’ swisstopo_get_feature (full detail).
  • Cadastre: swisstopo_geocode β†’ swisstopo_get_egrid β†’ swisstopo_get_oereb_extract.
  • Downloads: swisstopo_search_geodata β†’ swisstopo_get_collection.

Response Format

Every tool returns a structured ToolResponse (FastMCP emits it as structured content with an output schema, plus a JSON text block):

Field Meaning
summary Human-readable Markdown summary
results Machine-readable structured records
count Number of results
match_type exact / fuzzy / none (search-style tools)
source / license Data attribution (OGD-CH, CC/OGD terms)
provenance / retrieved_at How and when the data was obtained
is_error true for handled errors

Known Limitations

  • OEREB tools require a canton parameter; not all cantons expose the same API format
  • STAC catalog uses Swisstopo's v0.9 endpoint; some collections may lack complete metadata
  • Geocoding covers Swiss addresses only (no Liechtenstein)
  • Rate limits are enforced by Swisstopo; high-frequency usage may be throttled

Testing

# Unit tests (no network required)
pytest tests/ -m "not live"

# Integration tests (live API calls)
pytest tests/ -m "live"

Changelog

See CHANGELOG.md


Contributing

See CONTRIBUTING.md


License

MIT License -- see LICENSE

Data provided by swisstopo under Open Government Data terms.


Author

Hayal Oezkan Β· malkreide


Credits & Related Projects

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured