Model Context Protocol para los datos abiertos de la Ciudad de México. Dale a Claude acceso directo a crimen, 911, calidad del aire, ECOBICI y DENUE — sin escribir una sola línea de código de ingesta.
cdmx-mcp
Model Context Protocol para los datos abiertos de la Ciudad de México. Dale a Claude acceso directo a crimen, 911, calidad del aire, ECOBICI y DENUE — sin escribir una sola línea de código de ingesta.
"¿Cuáles son las 10 colonias con más delitos en Cuauhtémoc en 2025?"
↓ Claude llama crime_hotspots(year=2025, alcaldia="CUAUHTEMOC", top_n=10)
↓ cdmx-mcp traduce a SQL contra CKAN
↓ Claude te contesta con la tabla + análisis, en segundos
📋 Prerrequisitos
Necesitás Python 3.10+ y uv (gestor de paquetes moderno para Python — reemplaza a pip + venv + pyenv en un solo binario).
Instalar uv
macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
O con Homebrew (macOS):
brew install uv
Windows
En PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
O con winget:
winget install --id=astral-sh.uv -e
O con Scoop:
scoop install uv
Verificá que quedó instalado:
uv --version # → uv 0.5.x o similar
Instalar Python (si no lo tenés)
uv puede descargar e instalar Python por vos — no hace falta que lo instales manualmente:
uv python install 3.12
Igual, si preferís instalarlo a mano:
- macOS:
brew install python@3.12o desde https://www.python.org/downloads/ - Windows:
winget install Python.Python.3.12o desde la Microsoft Store - Linux (Ubuntu/Debian):
sudo apt install python3.12 python3.12-venv - Linux (Arch):
sudo pacman -S python
Verificá:
python3 --version # → Python 3.10.x o superior
💡 Con
uvno necesitás activar venvs ni pelear con versiones —uv syncleepyproject.toml+uv.locky arma todo solo.
⚡ Quickstart — 30 segundos
git clone https://github.com/devcsar/cdmx-mcp.git
cd cdmx-mcp
uv sync # instala Python + dependencias
uv run python tests/smoke_test.py # verifica: debe decir "smoke: OK"
Ya está instalado. Ahora conectalo a tu cliente preferido:
Claude Code
claude mcp add cdmx -- uv --directory "$(pwd)" run cdmx-mcp
claude # dentro de la sesión: /mcp
O simplemente abrí este directorio con claude y detectará el .mcp.json automáticamente.
Claude Desktop
Editá claude_desktop_config.json (Settings → Developer → Edit Config) y pegá:
{
"mcpServers": {
"cdmx": {
"command": "uv",
"args": ["--directory", "/ruta/absoluta/a/cdmx-mcp", "run", "cdmx-mcp"]
}
}
}
Reiniciá Claude Desktop. Detalle completo por SO → QUICKSTART.md.
Cowork
Pegá el mismo JSON en el editor de MCPs de Cowork, o apuntá al .mcp.json del repo.
🎯 Primer prompt de prueba
Copiá y pegá en Claude:
Lista los 10 tipos de delito más frecuentes en la alcaldía Cuauhtémoc durante 2025. Después hacé una tabla markdown con emojis de barra.
Claude elige crime_hotspots automáticamente y te contesta con datos reales. Más prompts en PROMPTS.md.
📊 Qué cubre
| Fuente | Cubierta vía | Frescura |
|---|---|---|
| FGJ — Carpetas de investigación (delitos) | datos.cdmx.gob.mx (CKAN API) | mensual |
| 911 / LOCATEL — llamadas de emergencia | datos.cdmx.gob.mx (CKAN API) | mensual |
| SIMAT — Calidad del aire | datos.cdmx.gob.mx (CKAN API) | horaria |
| ECOBICI — bicis/docks en tiempo real | GBFS (feed estándar) | 🟢 en vivo |
| DENUE (INEGI) — unidades económicas | API pública INEGI | trimestral |
Nota post-migración: en abril 2026 el portal CDMX migró de OpenDataSoft a CKAN 2.10. Las consultas ahora pasan por
/api/3/action/datastore_search_sql(PostgreSQL real). Los slugs de dataset se conservaron.
🛠 Tools expuestas (9 total)
Genéricas — funcionan con cualquier dataset del portal:
| Tool | Qué hace |
|---|---|
| list_datasets(search?, limit) | Buscar en el catálogo completo |
| describe_dataset(dataset_id) | Schema real (columnas, tipos, total de filas) |
| query_records(dataset_id, where?, select?, order_by?, limit, offset) | Consulta SQL vía datastore_search_sql |
| aggregate(dataset_id, group_by, metric?, where?, limit) | GROUP BY server-side |
Recetas — atajos para el top 5:
| Tool | Qué hace |
|---|---|
| crime_hotspots(year, alcaldia?, category?, top_n) | Top colonias/alcaldías por crimen |
| ecobici_status(station_id? · near_lat+near_lng+radius_m) | Bicis/docks libres en tiempo real |
| air_quality_now(zone?, limit) | Índice SIMAT más reciente |
| denue_near(lat, lng, radius_m, keyword) | Negocios cerca de un punto |
Más cache_stats() y 2 recursos (cdmx://guide/fgj, cdmx://guide/top5).
Shortcuts soportados como dataset_id: fgj · 911 · ids · aire.
🧪 Verificar que funciona
# Test offline (no golpea el portal)
uv run python tests/smoke_test.py
# → smoke: OK
# Test live (opcional — consulta real a datos.cdmx.gob.mx)
CDMX_MCP_LIVE=1 uv run python tests/live_test.py
# → live: OK
El CI corre el smoke test en Python 3.10, 3.11 y 3.12 en cada push.
🔐 Token opcional para DENUE
denue_near requiere un token gratuito de INEGI:
- Registrate en https://www.inegi.org.mx/servicios/api_denue.html (toma 2 min)
- Exportalo antes de iniciar Claude Desktop/Code:
export INEGI_TOKEN=tu_token
O agregalo al env de tu config JSON — ver config/claude_desktop_config.example.json.
🏗 Arquitectura
Claude (Desktop / Cowork / Code)
│ stdio · JSON-RPC
▼
cdmx_mcp.server (FastMCP)
│
┌──────┴──────┬───────────┬──────────┐
▼ ▼ ▼ ▼
ckan gbfs denue cache
(datos.cdmx) (ECOBICI) (INEGI) (TTL + LRU)
- CKAN cubre 4 de las 5 fuentes (FGJ, 911, aire, IDS) con la misma API (
/api/3/action/*). describe_datasetusapackage_show+datastore_searchpara exponer el schema real.query_recordsyaggregatedelegan endatastore_search_sql(PostgreSQL real: identificadores con", literales con').- ECOBICI se consume por GBFS (feed estándar; también sobre-escribible vía
ECOBICI_GBFS_URL). - Cache en memoria con TTL por tool: 15 s para tiempo real, 10 min para queries, 1 h para catálogo.
- Sin tokens excepto DENUE (opcional).
📚 Aprende más
PROMPTS.md— biblioteca de prompts listos para copiar/pegar agrupados por dominio (crimen, movilidad, aire, negocios, combos).QUICKSTART.md— instalación paso a paso por sistema operativo + troubleshooting.examples/— demos específicas por canal:demo-cowork.md· prompts para Cowork (stakeholders no técnicos).demo-claude-desktop.md· flujo guiado en chat.demo-claude-code.md· ejercicios avanzados en terminal con pandas/matplotlib.
🤝 Contribuir
El servidor está diseñado para extenderse fácilmente.
Para añadir una nueva fuente:
- Crear
src/cdmx_mcp/adapters/<fuente>.pycon funciones que devuelvan dicts con la forma{"results": [...], "total_count": N}. - Envolverlas con
cache.cached(...)con un TTL apropiado. - Exponerlas en
server.pycon@mcp.tool()y una docstring clara (Claude la lee). - Agregar el nombre al set
expectedentests/smoke_test.py.
Correr CI local:
uv run python tests/smoke_test.py
CDMX_MCP_LIVE=1 uv run python tests/live_test.py # requiere internet
Issues y PRs son bienvenidos. El workflow de .github/workflows/ci.yml valida que todo compile en Python 3.10 / 3.11 / 3.12.
📄 Licencia
MIT · built at Impact Lab CDMX 01 (abril 2026) por rohan.mx · csar.dev.
Extender
Para añadir una fuente nueva:
- Crear
src/cdmx_mcp/adapters/<fuente>.pycon funciones que devuelvan dicts. - Envolver con
cache.cached(...)para TTL. - Exponer en
server.pycon@mcp.tool().
Licencia
MIT.