Zurich Open Data MCP Server

Permite a Claude, ChatGPT y otros asistentes de IA compatibles con MCP consultar directamente más de 900 conjuntos de datos, geodatos, actas parlamentarias, datos turísticos, datos enlazados e información ambiental y de movilidad en tiempo real de la Ciudad de Zúrich. 20 herramientas, 6 recursos, 6 API.

Documentación

🇨🇭 Parte del Portafolio Suizo de MCP de Datos Públicos

🏙️ Servidor MCP de Datos Abiertos de Zúrich

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

🌐 Español | Deutsch

Un servidor MCP (Protocolo de Contexto de Modelo) que proporciona acceso impulsado por IA a Datos Abiertos de la Ciudad de Zúrich, Suiza.

Permite a Claude, ChatGPT y otros asistentes de IA compatibles con MCP consultar directamente más de 900 conjuntos de datos, geodatos, actas parlamentarias, resoluciones del consejo, datos turísticos, datos enlazados e información ambiental y de movilidad en tiempo real de la Ciudad de Zúrich. 23 Herramientas (+3 alias obsoletos), 5 Recursos, 6 APIs.

Demo

Demo: Claude using zurich_parking_live and zurich_air_quality

✨ Características

Datos Abiertos CKAN (data.stadt-zuerich.ch)

  • zurich_search_datasets – Búsqueda de texto completo con sintaxis Solr en más de 900 conjuntos de datos
  • zurich_get_dataset – Metadatos completos y URL de descarga para un conjunto de datos
  • zurich_datastore_query – Consulta directa de datos tabulares (filtros, ordenación)
  • zurich_datastore_sql – Consultas SQL en el DataStore
  • zurich_list_categories – Explorar 19 categorías temáticas
  • zurich_list_tags – Búsqueda temática basada en etiquetas

Datos Ambientales en Tiempo Real

  • zurich_weather_live – 🌤️ Clima actual (temperatura, humedad, presión, lluvia) de 4 estaciones UGZ
  • zurich_air_quality – 🌬️ Calidad del aire en vivo (NO₂, O₃, PM10, PM2.5) con umbrales de la OMS
  • zurich_water_weather – 🌊 Datos del Lago de Zúrich (temperatura del agua, nivel, viento) cada 10 minutos

Datos de Movilidad en Tiempo Real

  • zurich_pedestrian_traffic – 🚶 Conteo de peatones en Bahnhofstrasse (3 ubicaciones, por hora)
  • zurich_vbz_passengers – 🚊 Afluencia del transporte público VBZ (más de 800,000 registros, todas las líneas/paradas)
  • zurich_parking_live – 🅿️ Ocupación en tiempo real de 36 estacionamientos (ParkenDD)

Geoportal (Geodatos WFS)

  • zurich_geo_layers – 📍 Listar 14 capas de geodatos disponibles
  • zurich_geo_features – 📍 Obtener características GeoJSON (escuelas, distritos, parques infantiles, datos climáticos, etc.)

Parlamento de la Ciudad (API Paris)

  • zurich_parliament_search – 🏛️ Buscar actas parlamentarias (interpelaciones, mociones, postulados)
  • zurich_parliament_members – 🏛️ Buscar miembros del consejo (partido, comisiones, mandatos)

Turismo de Zúrich

  • zurich_tourism – 🏨 Atracciones, restaurantes, hoteles, eventos (datos Schema.org, 4 idiomas)

Datos Enlazados (SPARQL)

  • zurich_sparql – 📊 Consultas SPARQL en el endpoint de datos enlazados estadísticos (el endpoint aún no está productivo — la herramienta no está registrada por defecto; actívela con la variable de entorno ZURICH_OPENDATA_ENABLE_SPARQL=1)

Stadtratsbeschlüsse (Resoluciones del Consejo)

  • zurich_strb_search – 📜 Búsqueda de texto completo de resoluciones públicas del consejo (título, departamento, rango de fechas)
  • zurich_strb_by_department – 📜 Listar todas las resoluciones de un departamento (p. ej., SSD, FD, PRD)
  • zurich_strb_detail – 📜 Resolución individual por número NNNN/YYYY

(Los nombres anteriores search_stadtratsbeschluesse, get_beschluesse_by_departement y get_stadtratsbeschluss_detail permanecen disponibles como alias obsoletos hasta la próxima versión principal.)

Herramientas de Análisis

  • zurich_analyze_datasets – Análisis integral: relevancia, actualidad, estructura de datos
  • zurich_catalog_stats – Resumen del catálogo con estadísticas
  • zurich_find_school_data – Búsqueda curada para conjuntos de datos relacionados con educación

Recursos MCP

  • zurich://dataset/{name} – Metadatos de conjuntos de datos
  • zurich://category/{group_id} – Detalles de categorías
  • zurich://parking – Datos actuales de estacionamiento
  • zurich://geo/{layer_id} – Geodatos GeoJSON (14 capas)
  • zurich://tourism/categories – Categorías turísticas

🚀 Instalación

Requisitos previos

  • Python 3.11+
  • pip o uv
  • mcp[cli] 2.x — se instala automáticamente; el servidor utiliza la API 2.x (mcp.server.mcpserver) y no puede ejecutarse en mcp 1.x

Use 0.6.0 o más reciente. La versión 0.5.1 declaró mcp[cli]>=1.28.1 sin límite superior. Una vez que mcp 2.0.0 eliminó mcp.server.fastmcp, cada instalación nueva de 0.5.1 se resolvió a 2.0.0 y falló en la importación con ModuleNotFoundError. 0.6.0 se ejecuta en la API 2.x y fija >=2.0.0,<3. Si está fijado a 0.5.1, actualice — no queda ninguna configuración funcional de esa versión.

Instalar

# Clone
git clone https://github.com/malkreide/zurich-opendata-mcp.git
cd zurich-opendata-mcp

# Install
pip install -e .

# Or with uv
uv pip install -e .

⚙️ Configuración

Claude Desktop

Edite ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "zurich-opendata": {
      "command": "python",
      "args": ["-m", "zurich_opendata_mcp.server"],
      "env": {}
    }
  }
}

Alternativamente, usando el comando instalado:

{
  "mcpServers": {
    "zurich-opendata": {
      "command": "zurich-opendata-mcp"
    }
  }
}

Claude Code (CLI)

claude mcp add zurich-opendata -- python -m zurich_opendata_mcp.server

Cursor / VS Code

Agregue a .vscode/settings.json:

{
  "mcpServers": {
    "zurich-opendata": {
      "command": "python",
      "args": ["-m", "zurich_opendata_mcp.server"]
    }
  }
}

💬 Consultas de Ejemplo

Una vez configurado, puede preguntarle a Claude:

Datos Abiertos

  • "¿Qué conjuntos de datos están disponibles sobre escuelas en Zúrich?"
  • "Muéstrame las vacaciones escolares para escuelas públicas"
  • "Analiza los geodatos disponibles"

Datos en Tiempo Real

  • "¿Cuál es la temperatura actual en Zúrich?"zurich_weather_live
  • "¿Cómo está la calidad del aire hoy?"zurich_air_quality
  • "¿Cuál es la temperatura del agua en el Lago de Zúrich?"zurich_water_weather
  • "¿Cuántos espacios de estacionamiento están libres ahora mismo?"zurich_parking_live
  • "¿Cuántas personas hay en Bahnhofstrasse ahora mismo?"zurich_pedestrian_traffic

Geodatos

  • "Muéstrame todas las instalaciones escolares en Zúrich como GeoJSON"zurich_geo_features
  • "¿Qué capas de geodatos están disponibles?"zurich_geo_layers
  • "¿Dónde están los parques infantiles en Zúrich?"

Parlamento de la Ciudad

  • "¿Qué mociones parlamentarias sobre escuelas se presentaron?"zurich_parliament_search
  • "¿Qué miembros del consejo pertenecen al partido SP?"zurich_parliament_members

Resoluciones del Consejo (Stadtratsbeschlüsse)

  • "Encuentra resoluciones del consejo sobre Volksschule de 2025"zurich_strb_search
  • "Lista todas las resoluciones SSD en 2025"zurich_strb_by_department
  • "Muestra la resolución del consejo 1203/2025"zurich_strb_detail

Turismo

  • "¿Qué restaurantes recomienda Turismo de Zúrich?"zurich_tourism

🔗 Fuentes de Datos

APIEndpointDatos
CKANdata.stadt-zuerich.ch/api/3/Más de 900 conjuntos de datos abiertos
Geoportal WFSogd.stadt-zuerich.ch/wfs/geoportal14 capas de geodatos (GeoJSON)
API Parisgemeinderat-zuerich.ch/apiActas parlamentarias y miembros
Turismo de Zúrichzuerich.com/en/api/v2/dataAtracciones, restaurantes, hoteles
SPARQLld.stadt-zuerich.ch/queryDatos enlazados abiertos / estadísticas
ParkenDDapi.parkendd.de/ZuerichOcupación de estacionamientos en tiempo real

📊 Categorías de Datos Disponibles

CategoríaID
Empleoarbeit-und-erwerb
Mapas Basebasiskarten
Construcción y Viviendabauen-und-wohnen
Poblaciónbevolkerung
Educaciónbildung
Energíaenergie
Finanzasfinanzen
Ociofreizeit
Saludgesundheit
Delincuenciakriminalitat
Culturakultur
Movilidadmobilitat
Políticapolitik
Preciospreise
Asuntos Socialessoziales
Turismotourismus
Medio Ambienteumwelt
Administraciónverwaltung
Economíavolkswirtschaft

📍 Capas Geo Disponibles

Fuente de verdad: GEOPORTAL_LAYERS en src/zurich_opendata_mcp/config.py.

ID de CapaDescripción
schulanlagenInstalaciones escolares (jardines de infancia, escuelas, cuidado extraescolar)
schulkreiseLímites de distritos escolares (polígonos)
schulwegeCruces de rutas escolares y puntos de peligro
stadtkreiseLímites de distritos de la ciudad (polígonos)
spielplaetzeParques infantiles públicos
kreisbueroOficinas de distrito de la ciudad
sammelstellePuntos de recogida de residuos
sportInstalaciones deportivas
klimadatenDatos climáticos (raster, temperaturas, islas de calor)
lehrpfadeSenderos educativos
stimmlokaleColegios electorales
sozialzentrumCentros sociales
velopruefstreckenRutas de examen de bicicleta para escuelas
familienberatungPuntos de encuentro de asesoramiento familiar

🏗️ Estructura del Proyecto

zurich-opendata-mcp/
├── src/zurich_opendata_mcp/
│   ├── __init__.py
│   ├── app.py               # Shared FastMCP instance
│   ├── server.py            # Console entry + back-compat re-exports
│   ├── config.py            # Endpoints, layer maps, resource IDs
│   ├── http_client.py       # Shared httpx client + CKAN wrapper
│   ├── formatters.py        # CKAN→model mapping + Markdown rendering
│   ├── models.py            # Pydantic structured-output models
│   ├── clients/             # API clients: paris, sparql, tourism, wfs
│   └── tools/               # @mcp.tool implementations:
│                            #   catalog, datastore, geo, parliament,
│                            #   realtime, sparql, strb, tourism,
│                            #   resources (zurich:// URIs)
├── tests/                   # respx round-trip, unit and live-marked tests
├── audits/                  # Code-audit reports
├── .github/workflows/       # ci.yml + publish.yml (Trusted Publisher)
├── pyproject.toml
├── README.md / README.de.md
├── CONTRIBUTING.md / .de.md
├── SECURITY.md / .de.md
├── CHANGELOG.md
├── CLAUDE.md                # Project conventions for Claude
├── LICENSE
└── claude_desktop_config.json

🧪 Desarrollo

# Install dev dependencies
pip install -e ".[dev]"

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

# Live integration tests (against live APIs — opt-in)
pytest tests/ -m live

# Linting
ruff check src/ tests/

🌐 Transporte HTTP

Por defecto, el servidor habla MCP sobre stdio. --http sirve Streamable HTTP en su lugar:

zurich-opendata-mcp --http --port 8000              # binds 127.0.0.1 (default)
zurich-opendata-mcp --http --host 0.0.0.0 --port 8000
OpciónSignificadoPredeterminado
--httpServir Streamable HTTP en lugar de stdio(desactivado → stdio)
--hostDirección de enlace127.0.0.1
--portPuerto de enlace (1–65535)8000
MCP_ALLOWED_HOSTSNombres separados por comas bajo los cuales este servidor es accesible, incluido el puerto (p. ej., zurich.example.ch:8000). Las solicitudes bajo cualquier otro Host reciben 421; el bucle local permanece permitido para que las comprobaciones de salud del contenedor sigan funcionando.(sin establecer)

El valor predeterminado de bucle local es deliberado. Enlazar 0.0.0.0 expone el servidor en cada interfaz, a cualquiera que pueda alcanzar la máquina — no hay autenticación delante de él.

Establezca MCP_ALLOWED_HOSTS siempre que enlace más allá del bucle local. Protege contra el rebinding de DNS: una página en su red resuelve su propio nombre de host a la dirección de este servidor y luego habla con él desde el navegador. Desde el punto de vista del navegador, esa solicitud es de mismo origen, por lo que ninguna regla de origen la detiene — solo la verificación de Host lo hace.

Si se deja sin establecer en un enlace que no sea de bucle local, la verificación permanece desactivada y se registra una advertencia. Ese es el valor predeterminado correcto solo cuando algo delante del servidor valida Host. Deliberadamente no se adivina: en 0.0.0.0 el nombre alcanzable es incognoscible dentro del proceso, y una suposición incorrecta respondería a la misma implementación que se pretende proteger con 421 en cada solicitud.

Seguridad y Límites

  • Solo lectura: Todas las herramientas realizan solo solicitudes HTTP GET — no se escriben, modifican ni eliminan datos.
  • Sin datos personales: Las APIs devuelven conjuntos de datos cívicos abiertos (ocupación de estacionamientos, lecturas meteorológicas, actas parlamentarias). Ninguna información de identificación personal (PII) es procesada o almacenada por este servidor.
  • Límites de velocidad: La búsqueda Solr de CKAN y ParkenDD son APIs públicas sin límites de velocidad documentados; use los parámetros rows y limit de manera conservadora. El servidor aplica un tiempo de espera de 30s por solicitud; los errores transitorios ascendentes (fallos de conexión, HTTP 502/503/504) se reintentan una vez con una breve espera.
  • Actualidad de los datos: Las herramientas en tiempo real (estacionamiento, clima, calidad del aire) reflejan la fuente ascendente en el momento de la consulta. Los datos de medición nunca se almacenan en caché; solo la búsqueda del ID de recurso UGZ actual por año (clima/calidad del aire) se almacena en caché en el proceso durante 24h.
  • Términos de servicio: Los datos están sujetos a los TdS de cada fuente — data.stadt-zuerich.ch, ParkenDD, gemeinderat-zuerich.ch. Todos los datos de la Ciudad de Zúrich se publican bajo CC0 (Abierto por Defecto desde 2021).
  • Sin garantías: Este servidor es un proyecto comunitario, no afiliado con la Ciudad de Zúrich ni con ninguno de los proveedores de APIs. La disponibilidad depende de las APIs ascendentes.

🤝 Contribuciones

Las contribuciones son bienvenidas — consulte CONTRIBUTING.md (Deutsch).

🔒 Seguridad

Solo lectura, sin PII, sin autenticación, un conjunto fijo de endpoints de datos públicos. Consulte SECURITY.md (Deutsch) para conocer la postura de seguridad completa y las decisiones de riesgo aceptado.

📜 Licencia

Licencia MIT — consulte LICENSE. Todos los datos utilizados se publican bajo licencias abiertas (CC0 / Abierto por Defecto desde 2021).

👤 Autor

Hayal Oezkan · malkreide


Impulsado por Protocolo de Contexto de Modelo • 6 APIs • 23 Herramientas • 5 Recursos

Instalación

Ejecute a través de uvx de uv — sin clonar ni instalación manual. Agregue a la configuración de su cliente MCP (mcpServers para Claude Desktop, Cursor y Windsurf; use una clave servers de nivel superior para VS Code en .vscode/mcp.json):

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