República de ColombiaDatos abiertos del Estado
Datos Vivos
── panorama de datos abiertos
Para desarrolladores y agentes de IA

El MCP de DatosVivos

El mismo motor que responde en el buscador está expuesto como servidor MCP (Model Context Protocol): cualquier agente de IA — Claude, o cualquier cliente compatible — puede buscar, consultar y cruzar los datos abiertos de Colombia como herramientas nativas.

Cómo conectarse

El servidor es de código abierto y corre junto al resto del stack. Clona el repositorio y levanta el servicio:

git clone https://github.com/jsricop/DatosVivos.git
cd DatosVivos
docker compose up -d mcp-server
# SSE endpoint: http://localhost:3000/sse

MCP es un protocolo abierto: el servidor funciona con cualquier cliente que lo soporte. Configuración por cliente:

Claude (Code / Desktop)

# Claude Code — un comando:
claude mcp add --transport sse datosvivos http://localhost:3000/sse

# Claude Desktop — claude_desktop_config.json:
{ "mcpServers": { "datosvivos": { "url": "http://localhost:3000/sse" } } }

OpenAI (Agents SDK / Responses API)

# Agents SDK (pip install openai-agents):
from agents import Agent, Runner
from agents.mcp import MCPServerSse

async with MCPServerSse(params={"url": "http://localhost:3000/sse"}) as mcp:
    agent = Agent(name="datos-colombia", mcp_servers=[mcp])
    out = await Runner.run(agent, "¿Cuántos colegios oficiales hay en Boyacá?")

# Responses API (exige URL pública — expón el servidor o usa un túnel):
client.responses.create(
    model="gpt-4.1",
    tools=[{"type": "mcp", "server_label": "datosvivos",
            "server_url": "https://<tu-host>/sse"}],
    input="¿Cuántos colegios oficiales hay en Boyacá?")

Cursor · VS Code (GitHub Copilot) · Gemini CLI

# Cursor — ~/.cursor/mcp.json:
{ "mcpServers": { "datosvivos": { "url": "http://localhost:3000/sse" } } }

# VS Code (Copilot agent mode) — .vscode/mcp.json:
{ "servers": { "datosvivos": { "type": "sse", "url": "http://localhost:3000/sse" } } }

# Gemini CLI — ~/.gemini/settings.json:
{ "mcpServers": { "datosvivos": { "url": "http://localhost:3000/sse" } } }

Grok, DeepSeek, Llama u otro modelo

Esos modelos no traen cliente MCP propio: se conectan a través de un cliente que sí lo soporte eligiendo el modelo ahí (Cursor, Cline, Continue aceptan Grok/DeepSeek como backend), o programáticamente con el SDK oficial de MCP — útil para cualquier stack:

# pip install mcp — cliente universal en Python:
from mcp import ClientSession
from mcp.client.sse import sse_client

async with sse_client("http://localhost:3000/sse") as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        r = await session.call_tool("query_data", {
            "dataset_id": "emd6-ef7x",
            "soql_query": "SELECT count(*) AS n WHERE sector='OFICIAL'"})
        # → [{ "n": "1721" }] — desde aquí, cualquier LLM consume el resultado

Las herramientas consultan la API pública de datos.gov.co — no necesitan credenciales; un App Token de Socrata (opcional, variable SOCRATA_APP_TOKEN) sube los límites de tasa.

Qué puede hacer un agente conectado

Importante: estas herramientas no se llaman a mano. Al conectarse, el cliente las descubre automáticamente y desde ahí el propio modelo decide cuál usar, con qué argumentos y en qué orden, según lo que le pidas en lenguaje natural. Una sola pregunta puede disparar la cadena completa:

Tú:        "¿Cuántos colegios oficiales hay en Boyacá?"

El agente decide y encadena, solo:
  1. search_datasets("establecimientos educativos Boyacá")  → encuentra emd6-ef7x
  2. get_metadata("emd6-ef7x")                              → descubre la columna sector
  3. query_data("emd6-ef7x", "SELECT count(*) WHERE sector='OFICIAL'")  → 1721

Agente:    "Hay 1.721 establecimientos oficiales en Boyacá,
            según la Gobernación de Boyacá (dataset emd6-ef7x)."

Las 4 herramientas que el agente tiene disponibles — cada tarjeta muestra un ejemplo real de petición, llamada y respuesta:

  • search_datasets

    Busca datasets en el catálogo por palabras clave. Devuelve id, nombre, entidad, filas y enlace de los mejores matches.

    Pides «Busca datasets de establecimientos educativos en Boyacá»

    El agente llama
    search_datasets(query="establecimientos educativos Boyacá", limit=5)
    La herramienta devuelve
    [{ "id": "emd6-ef7x", "name": "Establecimientos Educativos del sector oficial y no oficial…",
       "entity": "Gobernación de Boyacá", "rows_count": 2184, … }]
  • get_metadata

    El esquema completo de un dataset: columnas tipadas con descripción, filas, entidad y fechas de actualización.

    Pides «¿Qué columnas tiene ese dataset?»

    El agente llama
    get_metadata(dataset_id="emd6-ef7x")
    La herramienta devuelve
    { "columns": [{ "field_name": "sector", "type": "text", … },
                  { "field_name": "municipio", "type": "text", … }, … ],
      "rows_count": 2184, … }
  • query_data

    Ejecuta una consulta SoQL sobre el dataset y devuelve las filas. El agente arma la consulta; los datos salen del portal oficial.

    Pides «¿Cuántos son del sector oficial?»

    El agente llama
    query_data(dataset_id="emd6-ef7x", soql_query="SELECT count(*) AS n WHERE sector='OFICIAL'")
    La herramienta devuelve
    [{ "n": "1721" }]
  • cross_datasets

    Cruza de 2 a 5 datasets por una clave compartida (DIVIPOLA, código DANE, NIT) — verifica que la clave exista en cada uno antes del join.

    Pides «Cruza los establecimientos con la matrícula por municipio»

    El agente llama
    cross_datasets(dataset_ids=["emd6-ef7x", "qpq9-e4ne"], join_keys="municipio",
                   select_columns=["municipio", "sector", "total_ie"])
    La herramienta devuelve
    [{ "municipio": "TUNJA", "sector": "OFICIAL", "total_ie": … }, …]

Las herramientas devuelven filas y metadatos reales del portal oficial: el agente razona, los datos salen de la fuente. Código en mcp_server/, licencia abierta.