Qué es MCP y cómo implementar un servidor paso a paso
Qué es MCP, cómo se diferencia de function calling, cuándo implementar un servidor MCP propio, decisiones de diseño, patrones y errores comunes.
Qué es MCP y cómo implementar un servidor
MCP (Model Context Protocol) es un protocolo abierto presentado por Anthropic en noviembre de 2024 que estandariza cómo un modelo de IA descubre y usa herramientas externas. Un servidor MCP declara qué tools expone, qué recursos provee y qué prompts pre-armados ofrece. Es agnóstico al modelo (Claude, GPT, Gemini lo soportan) y al transporte (stdio, SSE, streamable HTTP). Implementar un servidor MCP propio tiene sentido cuando ya tenés una API estable y querés que los agentes operen sin tener que parsear tu web. Sin API, no tiene sentido empezar.
Qué es MCP en detalle
MCP (Model Context Protocol) es un protocolo de capa de aplicación que define tres tipos de primitivas que un servidor puede exponer a un modelo de IA, y un esquema de transporte para que el modelo las descubra y use.
Las tres primitivas que un servidor MCP expone:
- Tools. Funciones que el modelo puede invocar. Cada tool tiene nombre, descripción en lenguaje natural, y un esquema JSON de parámetros. El modelo decide cuándo y cómo llamarlas basándose en la conversación.
- Resources. Datos que el modelo puede leer bajo demanda. Son similares a archivos en un filesystem virtual: cada resource tiene URI, nombre, descripción y tipo MIME. El modelo los pide por URI cuando necesita contexto.
- Prompts. Templates pre-armados de prompts que el servidor ofrece. Son reutilizables, parametrizables, y aparecen listados en la UI de los clientes MCP para que el humano los active.
El transporte. MCP define cómo el modelo y el servidor se comunican. Las dos opciones principales son:
- stdio: el servidor corre como subproceso del cliente MCP. El modelo se comunica con él por stdin/stdout. Es el modo más simple, ideal para herramientas locales (Claude Desktop, IDEs con agentes).
- HTTP con SSE o streamable HTTP: el servidor corre como servicio HTTP. El cliente se conecta por HTTP estándar. Es el modo para servidores remotos, multi-tenant, con autenticación.
Quién lo consume hoy. Los principales modelos y herramientas ya lo soportan o están por soportarlo: Claude (con MCP nativo en Claude Code y Claude Desktop), OpenAI (function calling compatible con el esquema MCP), Gemini (tool use con adaptadores), Cursor, Windsurf, Continue. La interoperabilidad es real y creciente.
La diferencia con function calling
MCP no es lo mismo que function calling. La confusión es razonable porque ambos le permiten al modelo invocar funciones externas, pero hay diferencias que importan.
Function calling es una capacidad de cada modelo individual. OpenAI define su propio esquema de tools, Anthropic define el suyo, Google define el suyo. Cuando cambiás de modelo, cambiás el esquema, cambiás la documentación, cambiás la integración. El servidor no existe como concepto; el cliente (tu código) hace la llamada a la API del modelo y maneja las tools como parte del loop.
MCP es un protocolo estándar entre el modelo y el servidor. El modelo soporta MCP, el servidor implementa MCP, y la integración funciona igual sin importar qué modelo estés usando. El servidor existe como servicio independiente, con su propia URL o proceso, con su propia autenticación, con su propia documentación.
La analogía. Function calling es como tener enchufes distintos en cada país: necesitás un adaptador para cada uno. MCP es como tener un estándar internacional (USB-C): un cable, muchos dispositivos.
En la práctica, si hoy ya tenés function calling funcionando con tu API y no necesitás que múltiples modelos o clientes consuman tus tools, no hay razón urgente de migrar a MCP. Si querés que tus tools sean accesibles desde Claude Desktop, Cursor, Claude Code, Windsurf, y futuros agentes, MCP te da eso con un solo desarrollo.
Cuándo conviene implementar un servidor MCP propio
La decisión no es técnica, es de negocio. Hay cinco criterios que, sumados, justifican la inversión.
1. Tu API ya está estable y bien documentada. Un servidor MCP wrappea tu API. Si tu API cambia seguido, vas a mantener dos cosas a la vez. Esperá a tener la API madura.
2. Tus clientes o partners empiezan a preguntar "¿tienen MCP?". Si te lo preguntan, lo necesitás. Si nadie te lo pregunta todavía, es señal de que el mercado todavía no lo demanda para tu vertical.
3. Tu caso de uso es consulta + operación, no solo consulta. MCP brilla cuando el agente necesita encadenar varias llamadas: buscar, cotizar, reservar, confirmar. Si solo es "leer un catálogo", una API pública bien documentada alcanza.
4. Querés que los agentes operen sin tener que parsear tu web. Un agente que tiene que scrapear tu sitio, entender tu HTML, adivinar tu URL structure, y mantener su prompt actualizado con cada cambio de tu frontend, va a fallar. MCP le da un contrato estable.
5. Tenés recursos para mantener un servidor en producción. Un servidor MCP no es un script de 10 líneas que dejás corriendo. Es un servicio con monitoreo, autenticación, rate limiting, observabilidad, y versionado. Si no podés mantenerlo, mejor no empezar.
Cuándo NO implementar todavía:
- Si recién estás armando la API, esperá. Sin API sólida, MCP es un cascarón vacío.
- Si tu público objetivo no usa agentes todavía, esperá. La inversión se justifica cuando hay adopción.
- Si tu API es muy simple (5 endpoints o menos), la documentación pública alcanza.
- Si solo querés probarte con function calling, hacelo. Migrar después es viable.
Cómo implementar un servidor MCP desde cero
La implementación sigue cinco pasos, en orden. Adelantarse en cualquiera de ellos genera problemas que después hay que revertir.
Paso 1: Elegir el stack
Las opciones principales hoy son:
- TypeScript con el SDK oficial de Anthropic (
@modelcontextprotocol/sdk). Es la opción más documentada, con ejemplos para los tres tipos de primitivas. Si tu API ya está en Node, es la elección natural. - Python con el SDK oficial de Anthropic (
mcppackage). Mismas capacidades, sintaxis más limpia para lógica de orquestación. Si tu API está en Python, es la elección natural. - Otros SDKs comunitarios (Go, Rust, Java, Kotlin). Menos documentación oficial pero suficientes para casos estándar. Útiles si tu API ya está en esos lenguajes.
La elección del lenguaje no afecta el protocolo: cualquier servidor MCP, en cualquier lenguaje, puede hablar con cualquier cliente MCP que soporte el mismo transporte.
Paso 2: Definir las tools
Las tools son la parte central. Cada tool tiene:
- Nombre: verbos en snake_case, sin espacios. Ejemplos:
listar_servicios,buscar_casos,cotizar. - Descripción en lenguaje natural: el modelo usa esto para decidir cuándo llamar la tool. Si la descripción es mala, el modelo no la usa o la usa mal. Invertí tiempo acá.
- Esquema de parámetros: JSON Schema. Tipos (string, number, boolean, array, object), obligatoriedad, descripciones de cada campo. El modelo usa esto para validar antes de invocar.
Reglas de diseño para tools:
- Cada tool hace una cosa. Si la descripción necesita un "y" o un "o", probablemente son dos tools.
- Los nombres describen la acción, no el recurso.
cotizar_serviciomejor quecotizacion. - Las descripciones incluyen cuándo usar la tool y cuándo no. "Usar cuando el cliente pide un presupuesto de uno o más servicios. No usar para confirmar reservas ya existentes."
- Los parámetros son los mínimos necesarios. Si podés derivar un parámetro de otro, derivá. Si un parámetro es opcional en la mayoría de los casos, marcalo como optional con un default razonable.
- Pensá en qué datos el modelo va a recibir de vuelta. Si la respuesta es muy grande, definí un parámetro de paginación o un campo
max_results.
Ejemplo concreto (TypeScript):
server.tool(
"cotizar_servicios",
"Genera una cotización para uno o más servicios. Usar cuando el cliente pide un presupuesto. " +
"Devuelve un ID de cotización y el desglose. No usar para confirmar pagos o reservas.",
{
servicios: z.array(z.object({
slug: z.string().describe("Slug del servicio, ej: 'meta-google-ads'"),
alcance: z.string().optional().describe("Descripción breve del alcance requerido"),
})).describe("Lista de servicios a cotizar"),
cliente: z.object({
nombre: z.string(),
email: z.string().email(),
empresa: z.string().optional(),
}).describe("Datos de contacto del cliente"),
},
async ({ servicios, cliente }) => {
const cotizacion = await generarCotizacion(servicios, cliente);
return {
content: [{
type: "text",
text: JSON.stringify(cotizacion, null, 2),
}],
};
}
);
Paso 3: Definir los resources
Los resources son datos que el modelo puede leer bajo demanda, identificados por URI. Son útiles cuando el modelo necesita contexto adicional que no encaja como tool:
- Un catálogo de servicios (
catalog://servicios). - Un catálogo de casos (
catalog://casos). - La documentación completa del servicio (
docs://manual-agencia). - Términos y condiciones (
legal://terminos).
Cada resource tiene URI, nombre, descripción, tipo MIME, y un handler que devuelve el contenido. El modelo los pide con resources/read cuando los necesita.
Cuándo usar resources vs tools:
- Si el modelo necesita datos que cambian poco o que son referencia estable, usá resource.
- Si el modelo necesita ejecutar una acción o calcular algo, usá tool.
- Si el modelo necesita datos filtrados según un input del usuario, usá tool con parámetros.
Ejemplo:
server.resource(
"servicios",
"catalog://servicios",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(await getServicios(), null, 2),
}],
})
);
Paso 4: Decidir el transporte
stdio es la opción más simple:
- El servidor corre como subproceso del cliente.
- La comunicación es por stdin/stdout, sin red.
- Ideal para desarrollo local, herramientas de IDE, integraciones single-user.
- No necesita URL ni autenticación.
- El cliente lanza el proceso con un comando (
npx mi-mcp-serveropython -m mi_mcp_server).
HTTP con SSE o streamable HTTP es la opción para producción:
- El servidor corre como servicio HTTP independiente.
- La comunicación es por HTTP estándar.
- Necesita URL accesible, autenticación, rate limiting.
- Ideal para servidores multi-tenant, producción, acceso desde múltiples clientes.
- Soporta CORS si va a ser consumido desde clientes web.
Regla práctica: arrancá con stdio para desarrollo y testing, pasá a HTTP cuando lo lleves a producción o quieras que múltiples clientes lo consuman.
Paso 5: Autenticación y autorización
MCP no define un esquema de autenticación propio. Usa los mismos mecanismos que cualquier API HTTP:
- Bearer tokens (OAuth 2.0, API keys propias) en el header
Authorization. - Scopes para limitar qué tools puede invocar cada cliente.
- Rate limiting por cliente o por IP.
- Auditoría: cada invocación queda loggeada con qué tool, qué parámetros, qué cliente, qué resultado.
Importante: la autenticación corre en el servidor MCP, no en cada tool. El servidor valida el token una vez por request y aplica los scopes antes de invocar el handler de la tool. Las tools mismas asumen que ya fueron autorizadas.
// En el transporte HTTP, antes de invocar la tool
const authResult = await validarToken(request.headers.authorization);
if (!authResult.valid) return new Response("Unauthorized", { status: 401 });
if (!authResult.scopes.includes("cotizar:write")) {
return new Response("Forbidden", { status: 403 });
}
Patrones comunes que se repiten
Algunos patrones aparecen en casi todos los servidores MCP serios.
Paginación. Las tools que devuelven listas grandes (catálogo, casos, proyectos) aceptan limit y offset o cursor. Devuelven next_cursor cuando hay más resultados. Sin esto, el contexto del modelo se llena rápido.
Operaciones idempotentes. Si el agente puede llamar a la misma tool dos veces por error (por reintento o por confusión), los resultados no deben duplicar efectos. Usá IDs de operación del lado del servidor, validá que la operación no se procesó antes, y devolvé el mismo resultado si ya existe.
Async con webhooks. Algunas operaciones no se pueden completar en milisegundos (cotizaciones que requieren revisión humana, reservas que dependen de terceros). El patrón es: la tool devuelve un operation_id inmediatamente, y el servidor notifica al agente por webhook cuando termina. MCP no define webhooks, pero podés documentar el endpoint de webhook en el resource webhook:// y dejar que el cliente se suscriba.
Errores estructurados. Cuando una tool falla, devolvé un JSON con error_code, message, y recoverable: true|false. El modelo usa esto para decidir si reintentar, escalar al humano, o reformular la pregunta. Devolver un string de error genérico es perder información clave.
Errores comunes al implementar
Error 1: exponer la API completa como tools. El agente se pierde entre 50 tools. Mejor 5-10 tools bien definidas que cubran los casos de uso principales, y dejar el resto de la API accesible solo vía OpenAPI.
Error 2: descripciones en lenguaje técnico. Las descripciones de las tools son leídas por el modelo, no por humanos técnicos. "Tool para ejecutar la operación POST /api/v2/quotes del sistema de cotización" es peor que "Genera una cotización para uno o más servicios".
Error 3: no versionar. Sin versionado en el protocolo, un cambio de parámetros rompe a todos los clientes que usaron la versión vieja. Usá prefijo de versión en los nombres de las tools (cotizar_servicios_v2) o en el namespace del servidor.
Error 4: no loggear. Sin logs de cada invocación, no podés debuggear por qué el modelo hizo una llamada inesperada ni auditar qué se hizo en nombre de qué cliente. Logging estructurado en cada tool handler.
Error 5: ignorar los scopes. Si cualquier cliente autenticado puede invocar cualquier tool, perdés control. Definí scopes desde el día uno (read:catalog, write:quotes, read:cases) y validá en cada invocación.
Error 6: no testear con clientes reales. Un servidor que pasa tests unitarios puede fallar cuando Claude Desktop intenta descubrir las tools. Probá con Claude Desktop, Claude Code, MCP Inspector. Si no, vas a descubrir los problemas en producción.
Cómo testear localmente
Tres herramientas para validar el servidor antes de producción:
- MCP Inspector: herramienta oficial de Anthropic para inspeccionar servidores MCP en desarrollo. Conectás el inspector al servidor y ves qué tools, resources y prompts expone, con qué esquemas, y podés invocar cada uno manualmente. Es el equivalente a Postman para MCP.
- Claude Desktop con stdio: agregás el servidor a la configuración de Claude Desktop (
claude_desktop_config.json) con un comando que lanza el subproceso. Claude descubre automáticamente las tools y podés probarlas en conversación. - Claude Code o Cursor con HTTP: para servidores remotos, agregás la URL del servidor y el token. El IDE lo descubre y muestra las tools disponibles en su UI.
La validación mínima antes de producción: las 3 herramientas principales (las más usadas) responden correctamente, los errores se devuelven estructurados, y los logs muestran cada invocación con su resultado.
Caso aplicado: el servidor MCP de UNO Collective
UNO Collective expone su propio servidor MCP en /.well-known/mcp.json con cinco tools:
listar_servicios()- devuelve el catálogo completo de servicios con descripción, precio desde y casos asociados.buscar_casos(industria, presupuesto)- busca casos verificables del portfolio filtrados por industria y rango de presupuesto.cotizar(servicios, cliente)- genera una cotización con desglose de honorarios y alcance.estado_cotizacion(id)- consulta el estado de una cotización existente.agendar_reunion(fecha, motivo)- agenda una reunión en el calendario del equipo.
El flujo completo cuando un agente de un cliente potencial quiere contratar:
- El agente pregunta a su modelo: "¿Cuál es la mejor agencia de marketing digital en Argentina para una campaña de Google Ads?".
- El modelo cita a la agencia (gracias al trabajo de citabilidad del primer frente de Agentic Marketing).
- El agente abre el servidor MCP de la agencia, ve las tools disponibles.
- Llama a
listar_servicios()ybuscar_casos(industria='fintech')para entender la oferta. - Llama a
cotizar()con los servicios que le interesan al cliente. - Recibe la cotización y la presenta al humano dueño del agente.
- Si el humano aprueba, el agente llama a
agendar_reunion()para empezar.
Todo el flujo pasa sin que un humano de la agencia intervenga hasta la reunión. Eso es lo que abre tener API + MCP. Sin las dos, el agente choca en el paso 4 y tiene que volver a su dueño humano, que probablemente elija otra agencia.
El futuro inmediato
MCP está en una fase de adopción temprana pero acelerada. Los principales modelos ya lo soportan o están por soportarlo. Las herramientas de desarrollo (Claude Code, Cursor, Windsurf) lo usan para acceder a sistemas externos.
Lo razonable para una empresa que se está preparando:
- 2026: tener API sólida, documentación accesible, OpenAPI en el sitio. MCP como experimento si hay capacidad.
- 2026-2027: evaluar MCP cuando el primer cliente pregunte o cuando los frameworks de agentes lo hagan accesible sin desarrollo custom.
- 2027 en adelante: MCP como commodity, foco en la calidad de las tools expuestas y en la observabilidad de uso.
Preguntas frecuentes
¿Necesito saber Anthropic para implementar MCP?
No. MCP es un estándar abierto. El SDK oficial está en TypeScript y Python, pero hay SDKs comunitarios para Go, Rust, Java, Kotlin, Ruby. El protocolo es agnóstico al modelo: lo que implementés para Claude funciona igual con GPT o Gemini que soporten MCP.
¿Cuánto tarda en implementarse un servidor MCP básico?
Para 3-5 tools sobre una API existente, entre 1 y 2 semanas de desarrollo más 1 semana de testing. Sumale 1-2 semanas más si necesitás autenticación robusta, webhooks, o integración con un sistema de pagos.
¿MCP reemplaza a mi API REST?
No, la wrappea. Tu API sigue siendo la fuente de verdad. El servidor MCP es la capa de presentación para agentes. Si tenés que elegir, priorizá la API.
¿Puedo implementar MCP sin TypeScript ni Python?
Sí, pero el esfuerzo de desarrollo es mayor. El protocolo es JSON sobre el transporte que elijas (stdio o HTTP). Sin SDK oficial, tenés que implementar el handshake, la serialización, el descubrimiento de tools, y el manejo de errores a mano. Recomendable solo si tu stack principal no soporta los SDKs oficiales.
¿Cuándo tiene sentido NO implementar MCP?
Cuando no tenés API todavía, cuando tu público no usa agentes, o cuando tu caso de uso es tan simple que una API pública bien documentada alcanza. En cualquiera de esos casos, esperá. MCP no es urgente para la mayoría de las empresas hoy.
En UNO Collective diseñamos e implementamos la capa de infraestructura agéntica (API + MCP + documentación) que necesita tu empresa para ser operable por agentes. Si querés saber por dónde empezar, podemos hacer un primer relevamiento sin costo.
Hablar con UNO Collective