Skip to main content
Glama

EIC · API + MCP

La Encuesta Intercensal del INEGI (2015 y 2025) como API pública y como servidor MCP para IAs.

Un ETL descarga los paquetes de datos abiertos directamente de INEGI y los normaliza en una base DuckDB. Sobre esa base corren una API REST de solo lectura y un servidor MCP para que asistentes como Claude, ChatGPT o Cursor consulten los datos.

Python DuckDB FastAPI MCP Docker License: MIT

🌐 Ya está en línea, úsalo sin montar nada

Qué

URL

Documentación interactiva (Swagger)

https://eic.datzin.com.mx/api/docs

Esquema OpenAPI

https://eic.datzin.com.mx/api/openapi.json

API REST

https://eic.datzin.com.mx/api/…

Servidor MCP (streamable HTTP, sin autenticación)

https://eic.datzin.com.mx/mcp

Es gratis y abierto, con límite de peticiones por IP. Si necesitas más volumen o quieres tu propia copia, móntalo tú mismo.

Related MCP server: emovi-mcp

⚡ Pruébalo

# Población 2025 de todas las entidades
curl "https://eic.datzin.com.mx/api/datasets/eic2025_localidades/datos?indicador=POBTOT&nivel=entidad"

# ¿Qué indicadores hay sobre desplazamiento forzado? (la búsqueda ignora acentos)
curl "https://eic.datzin.com.mx/api/datasets/eic2025_localidades/indicadores?q=desplazamiento"

# Busca una localidad y su clave geográfica
curl "https://eic.datzin.com.mx/api/datasets/eic2025_localidades/geografias?nivel=localidad&q=tijuana"

# Los 10 municipios de Jalisco con más población sin afiliación a servicios de salud
curl "https://eic.datzin.com.mx/api/datasets/eic2025_localidades/ranking?indicador=PCN_PSINDER&nivel=municipio&cve_ent=14"

# Ficha de Zapopan frente a Jalisco y el país, enfocada en carencias sociales
curl "https://eic.datzin.com.mx/api/datasets/eic2025_localidades/perfil/141200000?conjunto=vulnerabilidad"

# ¿Qué cambió en Jalisco entre 2015 y 2025?
curl "https://eic.datzin.com.mx/api/evolucion?cve_ent=14"

Cada estimación trae su precisión estadística:

{
  "cvegeo": "010000000",
  "nombre": "Aguascalientes",
  "nivel": "entidad",
  "indicador": "POBTOT",
  "indicador_nombre": "Población en viviendas particulares habitadas",
  "valor": 1534416.0,
  "error_estandar": 58302.68,
  "lim_inf": 1438496.15,
  "lim_sup": 1630335.85,
  "coef_var": 3.8,
  "nota": null
}

Rutas de la API

Todas son GET.

Ruta

Parámetros

/api/datasets

/api/entidades

/api/datasets/{id}/temas

/api/datasets/{id}/indicadores

tema, q

/api/datasets/{id}/geografias

nivel, cve_ent, q, limit, offset

/api/datasets/{id}/datos

indicador (obligatorio; varios separados por coma), cvegeo, nivel, cve_ent, limit (≤ 10 000), offset

/api/ubicar

q (Zapopan, Juárez, Chihuahua, CDMX…), dataset

/api/datasets/{id}/ranking

indicador, nivel, cve_ent, orden (desc/asc), n (≤ 100), excluir_baja_precision

/api/datasets/{id}/perfil/{cvegeo}

indicador, tema, conjunto (destacados/vulnerabilidad): el lugar junto a su entidad y el país

/api/datasets/{id}/comparar

cvegeo (2 a 10, separados por coma), indicador, tema

/api/datasets/{id}/brecha-genero/{cvegeo}

tema: indicadores de mujeres frente a hombres

/api/evolucion

cve_ent (00 = nacional), tema: cambios 2015 → 2025 con indicadores equivalentes; los que cambiaron de definición vienen aparte en no_comparables

/api/equivalencias

Pares curados de indicadores comparables entre 2015 y 2025

nivel acepta nacional, entidad, municipio, localidad, resto_localidades o distrito. tema acepta el id o parte del nombre (vivienda, educacion).

🐼 Desde pandas

import pandas as pd

df = pd.read_csv("https://eic.datzin.com.mx/api/descargas/eic2025.csv")           # una fila por lugar, una columna por indicador
indicadores = pd.read_csv("https://eic.datzin.com.mx/api/descargas/indicadores.csv")  # qué significa cada columna

Archivo

Qué trae

eic2025.csv

2,776 lugares (país, entidades, municipios y localidades de 50 000+ hab.) × 341 indicadores · 5 MB

eic2015.csv

333 lugares (país, entidades y distritos electorales) × 107 indicadores

eic2025_completo.csv.gz

Una fila por lugar e indicador, con error estándar, límites al 90 % y precision (alta, moderada o baja) · 28 MB

eic2015_completo.csv.gz

Lo mismo para 2015

indicadores.csv

Diccionario de ambos años, con su comparabilidad 2015 ↔ 2025

También puedes pedir cualquier consulta de la API como CSV agregando formato=csv, por ejemplo /api/evolucion?cve_ent=31&formato=csv. Ejemplos completos en ejemplos/notebooks/.

🤖 Conecta tu IA (MCP)

Usa la instancia pública https://eic.datzin.com.mx/mcp, o la URL de tu propia instancia si lo montas. Hay archivos listos para copiar en ejemplos/mcp/.

{
  "mcpServers": {
    "eic": {
      "url": "https://eic.datzin.com.mx/mcp"
    }
  }
}
{
  "servers": {
    "eic": {
      "type": "http",
      "url": "https://eic.datzin.com.mx/mcp"
    }
  }
}
{
  "mcpServers": {
    "eic": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://eic.datzin.com.mx/mcp"]
    }
  }
}

También puedes agregarlo sin JSON: en claude.ai o Claude Desktop, Configuración → Conectores → Agregar conector personalizado.

claude mcp add --transport http eic https://eic.datzin.com.mx/mcp
[mcp_servers.eic]
url = "https://eic.datzin.com.mx/mcp"

O desde la terminal: codex mcp add eic --url https://eic.datzin.com.mx/mcp

  1. Activa el modo desarrollador en Configuración → Aplicaciones y conectores → Configuración avanzada.

  2. Crea un conector con la URL https://eic.datzin.com.mx/mcp.

  3. Elige autenticación: "Sin autenticación".

{
  "mcpServers": {
    "eic": {
      "command": "uv",
      "args": ["--directory", "/ruta/a/EIC-API-MCP", "run", "python", "-m", "eic.mcp_server"]
    }
  }
}

Tools

Tool

Qué hace

ubicar_lugar

Convierte un nombre (Zapopan, Juárez, Chihuahua, CDMX) en su clave cvegeo

perfil_lugar

Ficha de un lugar frente a su entidad y el país; indicadores destacados, de un tema o de vulnerabilidad social

comparar_lugares

Tabla indicador × lugar para 2 a 10 lugares

ranking

Los mayores o menores valores de un indicador en un nivel, opcionalmente dentro de una entidad

brecha_genero

Indicadores de mujeres frente a hombres en un lugar

evolucion_2015_2025

Cambios entre encuestas con indicadores equivalentes, indicando si la diferencia es estadísticamente clara

listar_datasets, buscar_indicadores, buscar_geografias, obtener_datos

Exploración y datos crudos

Todas son de solo lectura. Cada cifra trae su precision según el criterio de INEGI, y el servidor le indica al modelo que no presente como sólidas las estimaciones con muestra insuficiente.

Prompts (pre-consultas)

Son análisis guiados que el cliente te ofrece con un formulario y autocompletado de lugares, temas e indicadores. En Claude Code aparecen como comandos /mcp__eic__<prompt>; en Claude Desktop, en el botón + → EIC. ChatGPT y Codex no muestran prompts, pero puedes pedirles lo mismo con tus palabras (ver ejemplos abajo).

Prompt

Argumentos

Qué hace

guia_rapida

Explica qué datos hay y sugiere preguntas

perfil_lugar

lugar

Perfil sociodemográfico frente a la entidad y el país

comparar_lugares

lugares (separados por ;), tema

Comparación lado a lado

ranking

indicador, nivel, entidad, orden

Los lugares con valores más altos o más bajos

explorar_tema

tema, anio

Qué mide un tema, panorama nacional y entidades extremas

brecha_genero

lugar, tema

Diferencias entre mujeres y hombres

vulnerabilidad_social

lugar

Carencias en salud, educación, alimentación, vivienda, empleo y desplazamiento

evolucion_2015_2025

entidad

Qué cambió entre la Intercensal 2015 y la 2025

ficha_distrito

entidad, distrito

Perfil de un distrito electoral federal (2015)

Resources

URI

Contenido

eic://guia

Guía metodológica: precisión, claves geográficas y comparabilidad

eic://datasets/{dataset}/diccionario

Indicadores de cada dataset agrupados por tema

eic://equivalencias

Pares de indicadores comparables entre 2015 y 2025

eic://entidades

Catálogo de entidades federativas

💬 Qué le puedes pedir a tu IA

Con el conector activo, pregunta en lenguaje natural; la IA elige las tools. Funciona igual en ChatGPT, Claude, Codex o Claude Code.

Perfiles y comparaciones

  • Hazme el perfil sociodemográfico de Zapopan y compáralo con Jalisco y con el país.

  • Compara Monterrey, Guadalajara y Puebla en vivienda: drenaje, internet y hacinamiento.

  • ¿Cómo es Tijuana frente al resto de Baja California en educación y empleo?

Rankings

  • ¿Cuáles son los 10 municipios de Oaxaca con mayor porcentaje de población sin afiliación a servicios de salud? Excluye las estimaciones poco precisas.

  • ¿En qué estados es mayor el desplazamiento forzado por inseguridad?

  • ¿Qué localidades de 50 mil habitantes o más tienen menos acceso a internet?

Temas específicos

  • Hazme un diagnóstico de vulnerabilidad social de Ecatepec de Morelos.

  • ¿Cuál es la brecha de género en escolaridad y participación económica en Chiapas?

  • Explícame qué mide la Intercensal 2025 sobre alimentación y dónde hay más hogares sin acceso a alimentos.

2015 contra 2025

  • ¿Qué cambió en Yucatán entre la Intercensal 2015 y la 2025? Solo dame los cambios estadísticamente claros.

  • ¿Cuánto creció el acceso a internet en cada entidad desde 2015?

  • ¿Qué distritos electorales de Chiapas eran indígenas en 2015 y cómo era su escolaridad?

En Claude Code o Codex, combinando datos y código

  • Con el MCP eic, arma un CSV con el porcentaje de viviendas con internet por municipio de Jalisco y grafícalo con matplotlib.

  • Usa el MCP eic para generar un notebook que compare los 32 estados en los indicadores de vulnerabilidad social.

  • Con el prompt /mcp__eic__perfil_lugar, haz la ficha de Mérida y guárdala como merida.md.

TIP

En ChatGPT, activa el conector desde el menú de herramientas de la conversación o menciónalo:"Usa EIC para…". Si la IA mezcla años, pídele explícitamente "con la Intercensal 2025".

📊 Datos

Dataset

Fuente INEGI

Desagregación

Indicadores

eic2025_localidades

EIC 2025, principales resultados por localidad de 50 000 y más habitantes

Nacional, 32 entidades, 2,478 municipios, 233 localidades

341 en 16 temas

eic2015_distritos

EIC 2015, estadísticas a escalas geoelectorales

Nacional, 32 entidades, 300 distritos electorales federales

107 en 9 temas

IMPORTANT

Sonestimaciones por muestreo. Según el criterio de INEGI, un coeficiente de variación (CV) menor a 15 indica precisión alta, de 15 a 30 moderada, y mayor a 30 baja. nota = MI significa que el dato no está disponible por muestra insuficiente; NA, que no aplica. 2015 y 2025 solo son comparables a nivel nacional y por entidad, porque usan geografías distintas y sus códigos de indicador difieren.

Modelo

Usa formato largo: una fila por dataset, geografía e indicador. Así cualquier consulta funciona igual sin importar si el CSV original tenía 349 o 540 columnas.

erDiagram
    dataset   ||--o{ indicador  : tiene
    dataset   ||--o{ geografia  : tiene
    dataset   ||--o{ tema       : tiene
    tema      ||--o{ indicador  : agrupa
    geografia ||--o{ geografia  : "padre_cvegeo"
    geografia ||--o{ estimacion : "de"
    indicador ||--o{ estimacion : mide
    entidad   ||--o{ geografia  : cve_ent
    indicador ||--o{ equivalencia : "2015 ↔ 2025"
    estimacion {
        varchar dataset_id
        varchar cvegeo
        varchar indicador
        double  valor
        double  error_estandar
        double  lim_inf
        double  lim_sup
        double  coef_var
        varchar nota
    }

El esquema completo está en src/eic/schema.sql. Los temas de 2015 se asignan con los mismos nombres que en 2025, y las equivalencias entre años son una tabla curada en src/eic/equivalencias.csv: 33 pares comparables marcados como exacta o aproximada (con una advertencia cuando cambió algo de la definición) y 5 marcados como no_comparable, que la API y el MCP reportan aparte para que nadie los compare. El ETL también publica en data/descargas/ (servido en /api/descargas) los CSV listos para pandas y cada tabla del modelo en Parquet, para quien prefiera polars o DuckDB.

🧱 Arquitectura

flowchart LR
    INEGI[(inegi.org.mx<br/>datos abiertos)] -->|zip CSV| ETL[etl<br/>corre y termina]
    ETL -->|swap atómico| DB[(eic.duckdb<br/>volumen)]
    DB -->|solo lectura| API[api<br/>FastAPI]
    DB -->|solo lectura| MCP[mcp<br/>FastMCP]
    API --> NGINX[nginx<br/>rate limit + caché]
    MCP --> NGINX
    NGINX -->|127.0.0.1:8081| PROXY[tu proxy con TLS<br/>Caddy · nginx · Cloudflare Tunnel]
    PROXY --> U((usuarios e IAs))

🐳 Móntalo tú mismo

Solo necesitas Docker con Compose v2.

git clone https://github.com/zamax14/EIC-API-MCP.git
cd EIC-API-MCP
docker compose up -d --build

Al arrancar, compose levanta todo en este orden:

  1. etl descarga los datos de INEGI, construye la base en un volumen y termina.

  2. api y mcp arrancan solo si el ETL terminó bien, y abren la base en solo lectura.

  3. nginx las expone en http://127.0.0.1:8081: la API en /api y el MCP en /mcp.

curl http://127.0.0.1:8081/api/datasets   # comprobar

Publicarlo con tu dominio

nginx solo escucha en 127.0.0.1. Para exponerlo pon delante un proxy con TLS que reenvíe todo tu dominio, o las rutas /api y /mcp, a http://127.0.0.1:8081. Por ejemplo:

Caddy (obtiene el certificado HTTPS solo):

eic.tudominio.com {
    reverse_proxy 127.0.0.1:8081
}

Cloudflare Tunnel: en el panel del túnel, agrega un public hostname con tipo de servicio HTTP y URL localhost:8081. Usa HTTP, no HTTPS: el TLS lo pone Cloudflare.

nginx toma la IP real del cliente de X-Forwarded-For, que mandan estos proxies, así que el límite se aplica a cada usuario y no al proxy.

Configuración

Las variables se definen en el entorno o en un archivo .env junto a compose.yaml.

Variable

Default

Qué controla

EIC_PORT

8081

Puerto local de nginx (solo en 127.0.0.1)

EIC_DB_MEMORY

256MB

Memoria máxima de DuckDB por proceso

EIC_DB_THREADS

1

Hilos de DuckDB por proceso

Los límites contra abuso están en deploy/nginx.conf y en compose.yaml:

Capa

Protección

nginx

API: 20 req/s por IP con ráfaga de 100 y 50 conexiones simultáneas. MCP: 50 req/s por IP con ráfaga de 200 y 100 conexiones, porque los servicios de IA juntan a muchos usuarios en pocas IPs. Lo que excede recibe 429

nginx

Caché de 10 min para la API (los datos solo cambian con el ETL); solo GET en /api y cuerpo de 64 KB como máximo en /mcp

API / MCP

Caché de 10 min de las respuestas del MCP en memoria; concurrencia acotada por worker, máximo 10 000 filas por página (500 en el MCP), parámetros validados y SQL siempre parametrizado

DuckDB

Base en solo lectura con memoria e hilos limitados por proceso

Contenedores

API y MCP con 2 workers cada uno; topes de CPU y memoria (API 2 CPU / 768 MB, MCP 2 CPU / 1 GB, nginx 0.5 CPU / 128 MB), medidos para ~100 usuarios simultáneos; logs rotados a 3 × 10 MB; usuario sin privilegios

Si cambias deploy/nginx.conf, aplica la configuración con docker compose up -d --force-recreate nginx.

Actualizar los datos

docker compose run --rm etl

El ETL se salta las descargas que no cambiaron. La API y el MCP detectan la base nueva sin reiniciar. Para programarlo cada semana con cron:

0 4 * * 1  cd /ruta/a/EIC-API-MCP && docker compose run --rm etl >> /var/log/eic-etl.log 2>&1

🛠️ Desarrollo local

Requiere uv.

uv sync
uv run python -m eic.etl                    # descarga de INEGI y construye data/eic.duckdb (~5 s)
uv run uvicorn eic.api:app --reload         # API en http://localhost:8000/docs
uv run python -m eic.mcp_server             # MCP por stdio
uv run python tests/test_etl.py && uv run python tests/test_api.py && uv run python tests/test_mcp.py

python -m eic.etl --offline reconstruye la base con los zips que ya están en data/raw, sin descargar. EIC_DB cambia la ruta de la base.

Para agregar otro paquete de datos abiertos de INEGI, añade una entrada a SOURCES en src/eic/etl.py con su URL y su parser.

Pruebas de carga

loadtest/k6.js simula usuarios que alternan una consulta a la API y una tool del MCP, con una rampa hasta 1000 usuarios. Con la pila levantada (docker compose up -d):

docker run --rm -u "$(id -u)" --network eic-api-mcp_default -p 127.0.0.1:5665:5665 \
  -v "$PWD/loadtest:/scripts" -e BASE=nginx \
  -e K6_WEB_DASHBOARD=true -e K6_WEB_DASHBOARD_EXPORT=/scripts/reporte-nginx.html \
  grafana/k6 run --summary-trend-stats="avg,med,p(95),p(99),max" /scripts/k6.js

Las gráficas se ven en vivo en http://localhost:5665 y quedan en loadtest/reporte-nginx.html.

Variable

Valor por defecto

Uso

BASE

directo

nginx pasa por la caché y los límites por IP, como en producción. directo va a api:8000 y mcp:8000

IPS

una IP por usuario

Número de IPs de cliente simuladas. Con pocas, imita a muchos usuarios de un servicio de IA que salen por las mismas IPs

PAUSA

2

Segundos promedio entre iteraciones de cada usuario; 0 para estrés puro

En modo directo, cada usuario mantiene su propia conexión abierta y --limit-concurrency de uvicorn cuenta conexiones, así que con cientos de usuarios responde 503. Para medir la ruta real usa nginx.

📄 Licencia, fuente y créditos

Código bajo licencia MIT.

Datos: INEGI, Encuesta Intercensal 2015 y 2025, usados conforme a los términos de libre uso de la información del INEGI. Este proyecto no está afiliado al INEGI. Si citas los datos, menciona a INEGI como fuente.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Exposes educational indicators with a gender perspective from Mexico's SIESVIM (INEGI), covering data such as terminal efficiency, dropout rates, and literacy. It enables models to perform contextualized social research and analysis using official Mexican statistics.
    -
  • A
    license
    A
    quality
    C
    maintenance
    MCP server for the ESRU-EMOVI 2023 social mobility survey in Mexico. Enables AI assistants to query weighted statistics, transition matrices, and explore variables from the survey using natural language.
    11
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides access to Mexico's INEGI (national statistics office) indicators API, enabling AI agents to query statistical data through natural language or direct tool calls.
    58 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Connects MCP-compatible AI agents to Peru's official statistics platform (INEI Estadist), providing access to Census 2017 data, population indicators, and geographic profiles for all Peruvian departments, provinces, and districts without requiring an API key.
    9
    MIT