Model Context Protocol (MCP): Guía Completa para Crear Servidores MCP en 2026
Guía práctica de 2026 para crear servidores MCP en Python y TypeScript, elegir transporte (stdio, SSE, Streamable HTTP), integrar con Claude Desktop y evitar los tres principales vectores de ataque.
Model Context Protocol (MCP) es un estándar abierto publicado por Anthropic en noviembre de 2024 que define un protocolo cliente-servidor uniforme para que aplicaciones de LLM accedan a datos, herramientas y prompts externos sin integraciones ad-hoc. En esta guía práctica de 2026 vas a crear tu primer servidor MCP en Python y TypeScript, entender los tres transportes soportados (stdio, HTTP+SSE y Streamable HTTP), integrarlo con Claude Desktop y aplicar las prácticas de seguridad que exige la especificación revisada en marzo de 2026.
MCP es a los LLMs lo que USB-C es al hardware: un protocolo único que reemplaza N×M integraciones ad-hoc entre modelos y fuentes de datos.
Un servidor MCP expone tres primitivas: tools (funciones ejecutables), resources (datos legibles con URI) y prompts (plantillas reutilizables).
Los SDKs oficiales soportan Python, TypeScript, Java, Kotlin, C#, Swift y Rust. FastMCP 2.10 (Python) y @modelcontextprotocol/sdk 1.15 (Node) son los más maduros a mediados de 2026.
La versión 2025-06-18 del protocolo incorpora Streamable HTTP como transporte remoto por defecto y sustituye al antiguo HTTP+SSE.
Claude Desktop, Cursor, VS Code, Windsurf y Zed ya funcionan como clientes MCP; con un solo servidor cubres todos ellos.
Los principales vectores de ataque son prompt injection vía descripciones de tools, token confusion en OAuth y exfiltración por resources mal segmentados.
¿Qué es Model Context Protocol?
Model Context Protocol es un protocolo abierto basado en JSON-RPC 2.0 que estandariza cómo una aplicación de IA (host) descubre e invoca capacidades expuestas por servicios externos (servidores). Antes de MCP, cada integración entre un LLM y una fuente de datos concreta (Slack, Postgres, un CRM interno) requería un adaptador propio. El resultado era el clásico problema N×M, donde N clientes y M herramientas producían N×M piezas de pegamento incompatibles.
MCP resuelve ese problema definiendo un contrato único. Un servidor MCP anuncia sus tools, resources y prompts mediante mensajes tools/list, resources/list y prompts/list. El cliente los consume igual sin importar si el servidor está escrito en Python, Rust o Kotlin, ni si corre en local por stdio o en un contenedor remoto tras HTTPS. Anthropic mantiene la especificación abierta bajo licencia MIT, y la gobernanza pasó en abril de 2026 a un comité neutral con participación de OpenAI, Google DeepMind y la Linux Foundation.
Honestamente, cuando probé la primera versión del protocolo a finales de 2024 pensé que iba a ser otro estándar más muriendo de éxito. Me equivoqué. Desde el lanzamiento inicial, el catálogo público de servidores ha crecido de 25 a más de 4.200 implementaciones registradas en el repositorio oficial de servidores, con integraciones para GitHub, Notion, Linear, Postgres, Cloudflare, Sentry, Stripe y decenas de bases de datos vectoriales. Eso convierte a MCP en el equivalente del sistema de paquetes npm para la capa de contexto de los agentes.
MCP vs function calling: ¿en qué se diferencian?
La confusión más común es equiparar MCP con function calling. Ambos permiten que un LLM invoque código externo, pero operan en niveles distintos. Function calling es una capacidad del modelo (una forma de emitir JSON estructurado que representa una llamada), mientras que MCP es un protocolo de transporte y descubrimiento entre el host y los servidores que exponen esas funciones. En la práctica, un cliente MCP traduce los tools recibidos del servidor a definiciones de function calling que el modelo entiende.
Dimensión
Function calling
Model Context Protocol
Ámbito
Una API por proveedor (OpenAI, Anthropic, Gemini)
Protocolo estándar cross-vendor
Descubrimiento dinámico
No: las tools se definen en el prompt
Sí: tools/list en tiempo de conexión
Reutilización entre apps
Baja: cada app redefine sus tools
Alta: un servidor sirve a N clientes
Estado y suscripciones
Sin sesión
Sesión persistente con notificaciones
Transporte
Depende de la SDK del proveedor
stdio, SSE o Streamable HTTP
Recursos legibles (no ejecutables)
No definidos
Primitiva resources con URIs
Plantillas de prompt reutilizables
No
Primitiva prompts
La consecuencia práctica: si escribes un servidor MCP para tu CRM interno, funciona a la vez en Claude Desktop, Cursor, VS Code y en tu propio agente construido con LangGraph, sin duplicar la lógica de conexión. Para profundizar en cómo se orquestan estas capacidades entre agentes, revisa nuestra guía sobre patrones de diseño para sistemas multi-agente.
Arquitectura del protocolo: host, cliente y servidor
MCP define tres roles claramente separados:
Host: la aplicación que embebe el LLM (Claude Desktop, Cursor, tu propio agente). Gestiona la interfaz de usuario, la política de aprobación y el ciclo de vida.
Cliente: un componente dentro del host que mantiene una conexión 1:1 con un servidor. Un host suele tener varios clientes activos simultáneamente.
Servidor: proceso independiente que expone capacidades. Puede correr como subproceso local (stdio) o como servicio remoto (HTTPS con Streamable HTTP).
La conversación sigue el patrón request/response de JSON-RPC con notificaciones asíncronas para eventos como notifications/resources/updated. Cada sesión arranca con el handshake initialize, donde cliente y servidor negocian versión del protocolo y capacidades soportadas (sampling, roots, elicitation en la revisión 2025-06-18). Los mensajes se serializan como UTF-8 sin BOM y, en el caso de stdio, se separan por saltos de línea.
Cómo crear un servidor MCP en Python paso a paso
El camino más corto en Python en 2026 pasa por FastMCP, una biblioteca que abstrae el protocolo con decoradores estilo FastAPI. Instálala junto al SDK oficial:
# Requiere Python 3.10 o superior
pip install "fastmcp>=2.10" "mcp>=1.9"
Crea un archivo weather_server.py. Vamos a construir un servidor que expone dos tools (obtener temperatura actual y previsión a 7 días) y un resource con la lista de ciudades soportadas:
from fastmcp import FastMCP
from pydantic import BaseModel, Field
import httpx
mcp = FastMCP(name="weather-es", version="1.0.0")
CITIES = {
"madrid": (40.4168, -3.7038),
"barcelona": (41.3874, 2.1686),
"ciudad-de-mexico": (19.4326, -99.1332),
"buenos-aires": (-34.6037, -58.3816),
}
class Forecast(BaseModel):
city: str = Field(..., description="Slug de la ciudad, ej. 'madrid'")
days: int = Field(7, ge=1, le=14, description="Numero de dias 1-14")
@mcp.tool()
async def current_temperature(city: str) -> dict:
"""Devuelve la temperatura actual en grados Celsius para una ciudad."""
if city not in CITIES:
raise ValueError(f"Ciudad no soportada: {city}")
lat, lon = CITIES[city]
async with httpx.AsyncClient(timeout=10) as client:
r = await client.get(
"https://api.open-meteo.com/v1/forecast",
params={"latitude": lat, "longitude": lon, "current": "temperature_2m"},
)
r.raise_for_status()
data = r.json()
return {"city": city, "celsius": data["current"]["temperature_2m"]}
@mcp.tool()
async def forecast(params: Forecast) -> dict:
"""Devuelve la prevision de temperaturas maximas y minimas por dia."""
lat, lon = CITIES[params.city]
async with httpx.AsyncClient(timeout=10) as client:
r = await client.get(
"https://api.open-meteo.com/v1/forecast",
params={
"latitude": lat,
"longitude": lon,
"daily": "temperature_2m_max,temperature_2m_min",
"forecast_days": params.days,
},
)
r.raise_for_status()
return r.json()["daily"]
@mcp.resource("cities://list")
def list_cities() -> str:
"""Recurso legible con las ciudades soportadas por el servidor."""
return "\n".join(sorted(CITIES.keys()))
if __name__ == "__main__":
mcp.run(transport="stdio")
Prueba el servidor localmente con el inspector oficial, que valida los mensajes JSON-RPC y te deja invocar tools desde el navegador:
El inspector abre http://localhost:6274. Conecta, pulsa List tools y ejecuta current_temperature con city="madrid". Si obtienes la temperatura, el servidor está listo para integrarse con cualquier cliente MCP.
Servidor MCP en TypeScript con el SDK oficial
Para stacks JavaScript/TypeScript, el paquete de referencia es @modelcontextprotocol/sdk. En 2026 la versión estable es 1.15 y requiere Node.js 20 o superior. Inicializa el proyecto:
Crea src/server.ts. Vamos a implementar un servidor que lista issues abiertas de un repositorio GitHub. Fíjate en cómo se declaran las capacidades y se registran los handlers:
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: "github-issues",
version: "1.0.0",
});
server.registerTool(
"list_open_issues",
{
title: "List open issues",
description: "Devuelve las issues abiertas de un repositorio publico de GitHub.",
inputSchema: {
owner: z.string().min(1),
repo: z.string().min(1),
limit: z.number().int().min(1).max(50).default(10),
},
},
async ({ owner, repo, limit }) => {
const url = `https://api.github.com/repos/${owner}/${repo}/issues?state=open&per_page=${limit}`;
const res = await fetch(url, {
headers: {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "mcp-github-issues/1.0",
},
});
if (!res.ok) throw new Error(`GitHub API ${res.status}`);
const issues = (await res.json()) as Array<{ number: number; title: string; html_url: string }>;
const summary = issues
.filter((i: any) => !i.pull_request)
.map((i) => `#${i.number} ${i.title} :: ${i.html_url}`)
.join("\n");
return { content: [{ type: "text", text: summary || "Sin issues abiertas." }] };
},
);
const transport = new StdioServerTransport();
await server.connect(transport);
Ejecuta con npx tsx src/server.ts y conéctalo al inspector igual que en el ejemplo Python. Este mismo servidor puede empaquetarse como binario con @vercel/ncc o distribuirse por npm; los clientes MCP invocarán npx para lanzarlo.
Transportes: stdio, SSE y Streamable HTTP
MCP admite tres transportes en 2026, cada uno con un caso de uso claro.
stdio (local, subproceso)
El cliente lanza el servidor como proceso hijo y se comunica por stdin/stdout. Es el modo por defecto para servidores locales porque no requiere puertos, no expone superficie de red y respeta los permisos del usuario. Todos los ejemplos de esta guía usan stdio.
HTTP+SSE (deprecado)
Definido en la especificación 2024-11-05, usaba un GET con Server-Sent Events para las respuestas y POST para las peticiones. Sigue funcionando por compatibilidad, pero está marcado para retirar en la revisión de octubre de 2026.
Streamable HTTP (recomendado para remoto)
Introducido en la especificación 2025-06-18, unifica peticiones y respuestas en un único endpoint POST con Transfer-Encoding: chunked. Permite servidores stateless, balanceadores estándar y despliegue en plataformas serverless como Cloudflare Workers, Vercel Functions o AWS Lambda. Ejemplo de handler en Node.js:
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID(),
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000);
Streamable HTTP también soporta resumable streams: si la conexión se corta, el cliente puede reanudar desde el último event-id recibido, algo bastante útil en agentes de larga duración.
Cómo instalar servidores MCP en Claude Desktop
Claude Desktop lee su configuración desde un archivo JSON. En macOS está en ~/Library/Application Support/Claude/claude_desktop_config.json; en Windows en %APPDATA%\Claude\claude_desktop_config.json. Añade el servidor Python de la sección anterior así:
Reinicia Claude Desktop. Verás un icono con el número de tools disponibles. Al primer uso de cada tool, Claude solicita confirmación explícita del usuario. Este patrón de human-in-the-loop es una restricción de la especificación, no una opción del host: los servidores no pueden ejecutar tools sin el consentimiento del cliente.
Para clientes que soportan servidores remotos (Cursor 0.45+, VS Code con la extensión oficial MCP, Anthropic API con el MCP connector), la configuración usa type: "http" y la URL del endpoint Streamable HTTP en lugar de command.
Seguridad de servidores MCP en producción
La superficie de riesgo de MCP se documenta en el apartado de seguridad de la especificación. Los tres vectores más frecuentes en 2026 son:
Prompt injection en descripciones de tools. Un servidor malicioso puede incluir instrucciones ocultas en description o en el resultado de un tool para redirigir al modelo. Mitígalo con listas blancas de servidores confiables y sanitiza descripciones antes de pasarlas al LLM.
Token confusion en OAuth. La revisión 2025-06-18 añade RFC 8707 Resource Indicators como requisito para servidores remotos: el token de acceso debe indicar explícitamente el servidor destino, evitando que un servidor MCP replaye credenciales contra otro backend.
Exfiltración por resources excesivos. Un servidor con acceso a file:// puede exponer secretos si el modelo, engañado, pide leer .env. Aplica roots (el mecanismo estándar para acotar el sistema de ficheros accesible) y define allowlists por URI.
Para producción, considera desplegar los servidores tras una capa de gateway (Cloudflare AI Gateway, Kong, o el proyecto open source MCP Gateway de OpenAI publicado en mayo de 2026) que aplique rate limiting, autenticación mTLS y auditoría estructurada. La telemetría de las invocaciones debe integrarse con tu stack de observabilidad; nuestra guía de observabilidad de LLMs con LangFuse, LangSmith y Helicone cubre cómo trazar peticiones que atraviesan varios servidores MCP.
Ecosistema y registro oficial de servidores
El repositorio modelcontextprotocol/servers mantiene una lista curada por categoría: reference servers (filesystem, memory, sequential-thinking), integraciones oficiales de vendors (GitHub, Stripe, Cloudflare, Sentry, Notion) y una sección comunitaria con más de 4.000 entradas. En febrero de 2026 se lanzó mcp.dev, un registro con búsqueda semántica, badges de auditoría de seguridad y métricas de uso agregadas por cliente.
Herramientas emergentes que vale la pena seguir:
mcp-agent: framework para orquestar múltiples servidores MCP con patrones inspirados en el paper Building Effective Agents de Anthropic.
LangChain MCP adapter: convierte tools MCP en tools LangChain, útil para migrar agentes existentes sin reescribirlos.
MCP Prompt Studio: IDE especializado en desarrollar y depurar la primitiva prompts, con reproducción determinista de sesiones.
Si estás construyendo agentes que combinan MCP con recuperación de conocimiento, revisa nuestra guía de RAG agéntico para pipelines de recuperación inteligente. Los patrones son complementarios, y muchos servidores MCP nuevos son en realidad backends de RAG expuestos como tools.
Preguntas frecuentes
¿Qué lenguajes de programación soportan MCP oficialmente?
A julio de 2026, los SDKs oficiales mantenidos por Anthropic y la comunidad cubren Python, TypeScript/JavaScript, Java, Kotlin, C#, Swift y Rust. Existen implementaciones no oficiales en Go, Elixir y Ruby que siguen la misma especificación JSON-RPC.
¿Es seguro usar servidores MCP de terceros?
Depende de la fuente. Los servidores de referencia y las integraciones oficiales del repositorio modelcontextprotocol/servers pasan revisión. Cualquier servidor stdio corre con los permisos de tu usuario, así que aplica el mismo criterio que a extensiones de VS Code y prefiere servidores auditados o con badge en mcp.dev.
¿Puedo usar MCP con modelos que no sean de Anthropic?
Sí. MCP es agnóstico del modelo: define un protocolo entre host y servidor, no entre servidor y LLM. Clientes como Cursor, VS Code o agentes construidos con LangGraph funcionan con GPT-4o, Gemini 2.5, Llama 3.3 o modelos locales servidos por Ollama.
¿Cuál es la diferencia entre un tool y un resource en MCP?
Un tool es una función invocable con efectos: envía correos, ejecuta consultas, modifica estado. Un resource es datos legibles direccionados por URI: el contenido de un archivo, filas de una tabla, o un dump de logs. Los resources se leen sin efectos y suelen aparecer en el contexto del modelo como texto o binarios.
¿MCP reemplaza a los frameworks de agentes como LangGraph o CrewAI?
No. MCP es la capa de conexión con herramientas y datos, no el runtime de razonamiento del agente. LangGraph, CrewAI o Anthropic Agents SDK definen el bucle de decisión, la memoria y los grafos de estado, y consumen servidores MCP como fuente de capacidades. Son complementarios.
Comparativa técnica de LangGraph, CrewAI y AutoGen en 2026: modelo de orquestación, coste por turno, checkpointing y MCP. Con el mismo agente implementado en los tres frameworks y datos reales de latencia.
Guía práctica sobre los 6 patrones fundamentales de orquestación multi-agente: supervisor centralizado, pipeline, fan-out/fan-in, handoff, debate y enjambre. Con ejemplos en Python y frameworks como LangGraph, CrewAI y AutoGen.