MCP en 2026: qué es, por qué importa, cómo integrarlo.
MCP es la primera abstracción del espacio LLM que separa, de verdad, capacidades de clientes. Eso es lo que la hace interesante.
01. Qué problema resuelve
Hasta finales de 2024, cada cliente LLM integraba sus herramientas a mano. La misma capacidad — “consulta esta base”, “busca en este CRM” — terminaba reimplementada tres veces, con tres parsers, tres formas de manejar errores, tres autenticaciones distintas.
Model Context Protocol corta ese ciclo con una idea sencilla: un servidor expone capacidades, varios clientes las consumen. Mismo contrato, distintas interfaces.
Antes era un acuerdo bilateral entre cada par cliente-herramienta. Ahora hay un protocolo, y el protocolo es lo interesante.
02. Las tres primitivas
Todo lo que un MCP server expone cae en una de tres:
- Tools. Funciones que el LLM puede invocar. Tienen nombre, descripción y schema de entrada. Si quieres que el cliente “cree una tarea en Linear”, eso es una tool.
- Resources. Contexto que el LLM puede leer pero no modificar. ADRs, documentación, dashboards. Se identifican por URI.
- Prompts. Plantillas pre-validadas que el cliente invoca con parámetros. Útiles cuando la forma del prompt importa tanto como el contenido.
En servers reales casi todo son tools, algunos resources y casi nadie usa prompts. Si estás empezando, probablemente tú tampoco.
03. Stack mínimo
Lo que aguanta producción sin sorpresas:
- TypeScript + Node 18+.
@modelcontextprotocol/sdkpara implementar el protocolo.- Zod para validar inputs (la SDK soporta Standard Schema, así que también puedes usar Valibot o ArkType, pero Zod es lo más extendido).
- Transports:
stdiopara servers locales que arrancan como subprocess del cliente; Streamable HTTP para servers remotos. Existe un transport HTTP+SSE más viejo, pero está deprecado y solo se mantiene por compatibilidad.
Un server mínimo se ve así:
// src/index.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({ name: 'my-server', version: '0.1.0' });
server.registerTool(
'task_create',
{
description: 'Crea una nueva tarea. Requiere title. Tags opcionales.',
inputSchema: {
title: z.string().min(1),
tags: z.array(z.string()).default([]),
},
},
async ({ title, tags }) => {
const task = await createTaskInDomain({ title, tags });
return { content: [{ type: 'text', text: `Tarea creada: ${task.id}` }] };
}
);
await server.connect(new StdioServerTransport());
Eso basta para arrancar. El cliente (Claude Desktop, Cursor, tu app) descubre task_create vía el handshake del protocolo, ve la descripción y el schema, y puede invocarla.
04. Disciplina del contrato
Montar un MCP que funciona es fácil. Montar uno que sobreviva al sexto cambio de requisitos sin romper clientes es otra cosa, y la diferencia se llama disciplina del contrato.
Tres reglas que vale la pena adoptar desde el día uno:
Los schemas son la única fuente de verdad. Si un parámetro existe en el handler pero no en el schema, no existe. Si existe en el schema pero no en la descripción, no existe. Los tres tienen que coincidir o tienes un bug latente.
Los nombres de tools son API pública. Una vez que un cliente depende de task_create, renombrarlo a create_task rompe clientes silenciosamente. Trátalo como cualquier otro contrato versionado.
Los errores tienen que ser accionables. Un error tipo "Invalid input" no le sirve a nadie. El mismo error como "task_create: campo 'title' vacío — debe tener al menos 1 carácter" permite al cliente corregir sin adivinar. Si el cliente es un LLM, esto es la diferencia entre que reintente bien o entre en bucle.
05. Trampas en producción
Cosas que se descubren cuando el server está vivo y un LLM lo golpea miles de veces al día:
- Auth. stdio hereda la confianza del subprocess; HTTP no. Si vas a remoto, necesitas bearer tokens por cliente o mTLS. No improvises.
- Rate limits por tool. Algunas son baratas (lecturas), otras invocan APIs externas. Un límite global es demasiado grosero — necesitas límites por tool y por cliente.
- Idempotencia. Los clientes reintentan tools en fallos transitorios. Si tu tool no es idempotente, vas a duplicar tareas, mensajes o cobros. Diséñalo desde el principio.
- Observabilidad. Cada invocación debería emitir un trace con cliente, tool, args (o su hash si hay PII), duración y resultado.
06. Cuándo NO es MCP
No toda integración LLM necesita un MCP server. Tres casos donde estarías añadiendo complejidad por hype:
- Un prompt con contexto fijo te resuelve el caso. Si tu sistema responde sobre un documento que nunca cambia, métele el documento al system prompt y sigue. No hay nada que invocar.
- Solo tienes un cliente. Si Claude Desktop es tu único consumidor y no planeas otro, escribe la integración directa con el SDK de Anthropic. El protocolo te cobra complejidad sin beneficio.
- El problema es puramente RAG. Si la tarea es “dado este documento, responde esta pregunta”, el camino es retrieval directo, no una tool que haga RAG.
MCP brilla cuando hay múltiples capacidades + múltiples clientes + requisito de estabilidad. Fuera de ese cuadrante, es plomo en la mochila.
07. Dos preguntas que me hacen seguido
¿MCP vs function calling nativo? Function calling es el mecanismo. MCP es el protocolo encima. Si tu cliente es único y controlado, function calling directo basta. Si necesitas que tres clientes distintos consuman la misma capacidad sin duplicar código, MCP es el puente.
¿Python o TypeScript? Si tu equipo ya es TypeScript-first, TypeScript. Si es Python-first, Python (hay SDK oficial). Lo que no tiene sentido es añadir un runtime nuevo al stack solo para esto.
MCP no es una librería. Es un contrato. Y el contrato es lo que sobrevive al código.