MCP (Model Context Protocol): El Protocolo que Invierte la Integración con IA — y el 90% lo Trata Como REST
MCP no es REST con esteroides. Descubre por qué los recursos suscribibles y el descubrimiento dinámico de herramientas son la verdadera revolución del protocolo que el 90% malinterpreta.
Cada API de IA que has escrito este año ya es código legacy
MCP acaba de hacer obsoletas las function schemas hardcodeadas.
Y el 90% de los desarrolladores no se ha dado cuenta.
*La mayoría trata MCP como "OpenAI function calling con otro nombre". Y se pierde lo que realmente importa. *
Llevo cuatro años construyendo integraciones con IA. He visto pasar de system prompts con JSON Schema a function calling nativo, y de ahí a tool use con agentes. Cada iteración prometía simplificar lo mismo: que el modelo pudiera llamar a APIs.
MCP no es una iteración más.
*MCP invierte la relación de control entre la IA y las herramientas. *
En el modelo tradicional — el que usas hoy — tú escribes un schema JSON, lo metes en el prompt, y el modelo decide si llamarlo o no. Tú controlas qué existe y cómo se llama. El modelo es un consumidor pasivo de tu decisión.
MCP le da la vuelta. El servidor MCP anuncia sus capacidades. El modelo las descubre. Decide qué usar. Se suscribe a cambios. Recibe notificaciones cuando los datos se actualizan.
*No es una API. Es un protocolo de descubrimiento. *
Y el 90% de los tutoriales que ves por ahí lo están usando como REST con esteroides. Envuelven una API REST en un MCP server, exponen cuatro tools, y lo llaman día.
Se pierden el 80% del valor del protocolo.
Los Tres Primitivos que Cambian Cómo Piensas la Integración
MCP no tiene endpoints. Tiene tres primitivos, y cada uno resuelve un problema diferente.
1. Resources — Datos Vivos, No Respuestas Estáticas
Un Resource en MCP no es un endpoint que devuelve JSON. Es un nodo de datos al que el modelo puede acceder, leer, y — esto es lo importante — *suscribirse*.
```python
MCP Resource — no es una API call, es un dato vivo
@server.resource("database://users/last-orders")
async def get_recent_orders(user_id: str) -> list[dict]:
Esto no es un endpoint. Es un recurso que el modelo "ve" como dato disponible.
orders = await db.query(
"SELECT * FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT 5",
user_id
)
return orders
```
La diferencia es sutil pero profunda. En function calling, tú dices "modelo, aquí tienes una función para obtener pedidos recientes". El modelo la llama, recibe datos, y se acabó.
En MCP, el Resource es un dato que el modelo sabe que existe. Puede leerlo cuando quiera. Y si el servidor implementa `subscribe`, el modelo recibe notificaciones cuando los datos cambian.
*Esto permite persistent dashboards, live monitoring agents, y asistentes que reaccionan a cambios sin polling. *
2. Tools — Acciones, No Consultas
Los Tools son lo más parecido a function calling. El modelo puede ejecutar acciones: enviar un email, crear un ticket, modificar un registro.
```python
MCP Tool — acción con efecto secundario
@server.tool()
async def send_alert(recipient: str, message: str, priority: str = "normal"):
"""
Envía una alerta a un usuario del sistema.
El modelo decide cuándo llamar esto basado en el contexto.
"""
await email_service.send(
to=recipient,
subject=f"Alerta [{priority}]",
body=message
)
return {"status": "sent", "recipient": recipient}
```
La diferencia con function calling estándar: el modelo no necesita el schema en el prompt. Lo descubre en tiempo real mediante `listTools`.
3. Prompts — Plantillas que el Modelo Puede Invocar
Este es el primitivo que casi nadie usa y que más potencial tiene. Un Prompt en MCP es una plantilla reutilizable que el servidor expone.
El modelo puede decir: "necesito el prompt de bienvenida para un nuevo usuario" — y el servidor devuelve una estructura con variables, ejemplos, y contexto predefinido.
*Es como tener system prompts versionados y gobernados desde el servidor, no desde el cliente. *
El Killer Feature que Nadie Está Usando: Suscripciones a Recursos
Vamos al grano.
Function calling — el de OpenAI, Anthropic, Gemini — es stateless. Llama, recibe, olvida. No hay memoria del estado anterior. No hay capacidad de reaccionar a cambios.
MCP Resources con `subscribe/unsubscribe` rompen eso.
```python
MCP Server con recurso suscribible
@server.resource("dashboard://production-metrics")
class ProductionMetrics:
async def read(self):
return await get_metrics()
async def subscribe(self, client):
Cuando los datos cambian, notificamos al cliente
async for update in metrics_stream():
await client.notify_resource_updated("dashboard://production-metrics")
yield update
```
¿Qué significa esto en la práctica?
Que puedes tener un agente de IA monitorizando un dashboard en tiempo real. Cuando una métrica crítica cambia — un pico de errores, una caída de rendimiento — el Resource notifica al modelo. El modelo decide si actuar.
*Sin polling. Sin timers. Sin 'cada cuánto reviso'. El dato empuja, el modelo reacciona. *
Esto es imposible con REST. Imposible con function calling. Solo posible con un modelo de recursos suscribibles.
El Error del 90%: Tratar MCP como REST
He revisado decenas de MCP servers en GitHub. El patrón es siempre el mismo:
1. Cogen una API REST existente
2. Envuelven cada endpoint como un Tool
3. Lo llaman "migración a MCP"
4. Pierden toda la ventaja
❌ MCP como REST:
```python
@server.tool()
async def get_users():
return requests.get("https://api.example.com/users").json()
@server.tool()
async def create_user(name: str, email: str):
return requests.post("https://api.example.com/users", json={"name": name, "email": email})
```
Esto no es MCP. Es REST con un wrapper. El modelo sigue llamando endpoints. No hay descubrimiento. No hay suscripciones. No hay Resources.
✅ MCP como MCP:
```python
@server.resource("users://active")
async def active_users_resource():
"""El modelo descubre que existe un recurso de usuarios activos.
Puede leerlo cuando quiera. Suscribirse si cambia."""
return await db.query("SELECT * FROM users WHERE active = 1")
@server.tool()
async def deactivate_user(user_id: str):
"""Acción específica. No confundir con recurso."""
await db.execute("UPDATE users SET active = 0 WHERE id = ?", user_id)
El recurso 'users://active' se actualizará automáticamente
await notify_resource_update("users://active")
return {"status": "deactivated"}
```
La diferencia: el modelo sabe que existe un recurso `users://active`. Puede leerlo, consultarlo, suscribirse. La tool `deactivate_user` modifica el recurso, y el recurso notifica el cambio.
*El modelo no llama endpoints. Interactúa con datos vivos. *
Cómo Construir un Servidor MCP que Aproveche el Protocolo
Vale, teoría suficiente. Manos a la obra.
Paso 1: Diseña Alrededor de Resources, No de Tools
La mayoría empieza por "qué acciones necesita el modelo". Error.
Empieza por qué datos necesita ver el modelo. Esos son Resources. Las acciones vienen después.
Para un CRM, los Resources serían: contactos activos, deals abiertos, tareas pendientes. Las Tools: crear contacto, cerrar deal, actualizar tarea.
Paso 2: Usa stdio para Local, SSE para Producción
```python
Servidor MCP con transporte stdio — perfecto para desarrollo local
from mcp.server import Server
from mcp.server.stdio import stdio_server
server = Server("mi-servidor")
@server.resource("files://{path}")
async def read_file(path: str):
"""Expone el sistema de ficheros local como recurso MCP."""
with open(path, "r") as f:
return f.read()
async def main():
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
```
El transporte stdio es perfecto para herramientas locales: Claude Desktop, agentes de terminal, asistentes que necesitan acceso a ficheros sin exponer HTTP.
Para producción, usa SSE (Server-Sent Events). El mismo servidor, diferente transporte.
Paso 3: Implementa la Negociación de Capacidades
MCP no asume nada. El cliente pregunta "¿qué sabes hacer?" y el servidor responde.
```python
El servidor anuncia sus capacidades automáticamente
El cliente las descubre en tiempo real
client = MCPClient("mi-servidor")
capabilities = await client.list_capabilities()
→ {"resources": ["users://active", "dashboard://metrics"],
"tools": ["send_alert", "deactivate_user", "create_report"]}
```
Esto no es solo comodidad. *Es un modelo de seguridad. * Porque el cliente sabe exactamente qué puede hacer el servidor, puede aplicar allow/deny lists por sesión, por usuario, por contexto.
Nada de "el modelo tiene todas las funciones en el prompt y decide". Tú controlas granularmente qué tools y recursos están disponibles en cada momento.
Paso 4: Usa el MCP Inspector Antes de Conectar a Cualquier AI Host
Anthropic publicó una herramienta que el 90% ignora: MCP Inspector. Te da una UI visual para lanzar tool calls, leer resources, y ver qué anuncia tu servidor.
```bash
npx @anthropic-ai/mcp-inspector mi-servidor.py
```
Antes de conectar tu servidor a Claude Desktop, Cursor, o cualquier host, pásalo por el Inspector. Verás:
Qué resources expone realmente
Qué tools están disponibles
Si los schemas son parseables por el modelo
Si las suscripciones funcionan
*El Inspector te ahorra horas de debugging ciego. *
El Patrón que Cambia Cómo Piensas las Integraciones con IA
Lo llamo El Patrón de Recursos Vivos:
1. Identifica los datos que el modelo necesita ver — no las acciones que necesita ejecutar
2. Exponlos como Resources con soporte de suscripción si cambian en el tiempo
3. Define Tools solo para efectos secundarios — crear, modificar, eliminar
4. Deja que el modelo descubra — no le digas qué existe, que lo descubra solo
Este patrón transforma un asistente de IA de "llamador de APIs" a "interactor con datos vivos". La diferencia es enorme cuando escalas a 5, 10, 20 integraciones.
El Futuro es de Descubrimiento, No de Hardcodeo
MCP no es perfecto. JSON-RPC 2.0 como transporte tiene limitaciones. La madurez de los SDKs varía. La documentación aún está en pañales.
*Pero la dirección es correcta. *
El modelo tradicional de integración — escribe un schema, mételo en el prompt, cruza los dedos — no escala. Cada nueva tool requiere actualizar el prompt. Cada cambio de schema requiere re-deploy. Cada integración nueva añade complejidad al system prompt.
MCP propone algo más inteligente: que el servidor diga qué sabe hacer, y el modelo decida qué usar.
*No es una evolución de REST. Es el fin de REST como interfaz para IA. *
Si sigues envolviendo APIs REST como MCP tools, estás construyendo legacy sobre el protocolo del futuro. Los Resources, las suscripciones, el descubrimiento dinámico — eso es MCP.
El resto es ruido.
Lee el artículo completo en brianmenagomez.com
Más sobre mis servicios en brianmenagomez.com
Herramientas: Conversor IAE CNAE · Gestorias cerca de ti · Calculadora IRPF

