MCP Avanzado: Cómo Construir Servidores que Sobreviven Producción Real

MCP Avanzado: Cómo Construir Servidores que Sobreviven Producción Real

Programación· 4 min de lectura

La Mayoría de MCP Servers Mueren en Staging

Construyes tu primer MCP server. Funciona perfecto en local.

Lo conectas a Claude. Las tools responden. Te emociona.

Luego lo subes a producción y se rompe todo.

Timeouts silenciosos. Tools que no se registran. Contexto que se corrompe entre llamadas.

El problema real del Model Context Protocol no es la especificación. Es que nadie te enseña a construir servidores que sobrevivan tráfico real.

Este artículo lo hace.

---

El Malentendido Fundamental sobre MCP

La mayoría cree que MCP es un sistema para "darle herramientas a Claude".

No lo es.

El real MCP no es un sistema de tools. Es un protocolo de contexto con herramientas como ciudadanos de primera clase.

La diferencia importa en producción.

Un sistema de tools ejecuta funciones. Un protocolo de contexto mantiene estado coherente entre el modelo, tus datos, y el entorno — con tools, resources, y prompts como primitivas coordinadas.

Si solo construyes tools, estás usando el 30% de la especificación.

Los otros dos pilares — Resources y Prompts — son los que hacen que Claude razone bien con tu dominio específico.

---

Arquitectura de un MCP Server Robusto

Antes de escribir código, define tres cosas:

→ ¿Qué tools ejecuta tu servidor? (acciones con side effects)

→ ¿Qué resources expone? (datos que Claude puede leer y razonar)

→ ¿Qué prompts inyecta? (instrucciones de dominio pre-construidas)

La mayoría solo implementa tools. Ahí empieza el problema.

1. Setup Correcto con el SDK Oficial

Usa @modelcontextprotocol/sdk. No construyas el protocolo a mano.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Por qué stdio y no HTTP por defecto: stdio elimina la complejidad de autenticación en el primer deploy. HTTP con SSE viene después, cuando ya tienes el servidor estabilizado.

2. Tools con Error Handling Real

Lo que hace el 90% de developers:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Esto falla silenciosamente. Claude recibe un error de runtime como respuesta vacía y no sabe qué pasó.

La implementación correcta:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

La clave es isError: true. Claude distingue entre "no hay datos" y "algo falló" — y razona diferente en cada caso.

---

Resources: El Pilar que Nadie Implementa

Las tools ejecutan acciones. Los Resources exponen datos de lectura.

Piénsalo así: una tool es POST /api/action. Un resource es GET /api/data.

Pero la diferencia real es semántica: los resources son contexto persistente que Claude puede consultar sin ejecutar side effects.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Cuando Claude tiene acceso al esquema de tu base de datos como resource, genera queries correctas en el primer intento. Sin el resource, adivina. La diferencia en precisión es drástica.

---

Prompts: Instrucciones de Dominio Pre-construidas

Los Prompts en MCP no son system prompts globales. Son plantillas reutilizables que el usuario puede invocar explícitamente.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Esto es lo que diferencia un MCP server genérico de uno especializado en tu dominio. Los prompts encapsulan el conocimiento experto de tu equipo.

---

Los 3 Errores que Matan MCP en Producción

Error #1: Tools sin descriptions

Claude elige qué tool llamar basándose en la descripción. Sin descripción, elige mal.

server.tool("get_data", { id: z.string() }, handler)

server.tool("get_data", { description: "Obtiene datos de cliente por ID. Incluye historial de compras y preferencias.", inputSchema: { id: z.string() } }, handler)

Error #2: Serializar objetos complejos directamente

MCP transporta texto. Si devuelves un objeto con referencias circulares o funciones, el transporte silently falla.

Siempre JSON.stringify() con manejo de errores antes de devolver datos complejos.

Error #3: No validar inputs con Zod

Claude puede llamar tus tools con datos malformados — especialmente cuando está en cadenas largas de razonamiento. Zod intercepta eso antes de que llegue a tu base de datos.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

---

Deploy: De Local a Producción

Para Claude Desktop (desarrollo local):

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Para producción con múltiples clientes, el transporte cambia a HTTP con SSE:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Esta arquitectura aguanta múltiples sesiones concurrentes. Cada cliente tiene su propio transport aislado.

---

Takeaways Clave

MCP no es solo tools. Resources y Prompts son igual de críticos para producción.

`isError: true` es obligatorio en error handling — Claude razona diferente cuando sabe que algo falló.

Descriptions en todas las tools. Sin descripción, Claude elige mal. Siempre.

Zod en todos los inputs. Valida antes de tocar tu base de datos.

stdio para desarrollo, SSE para producción multi-cliente. No mezcles los contextos.

Los Resources exponen tu esquema de datos. Claude genera código correcto cuando conoce tu dominio.

El model context protocol guide que la mayoría lee te enseña a conectar una tool. Este te enseña a construir sistemas que Claude puede usar para razonar de verdad.

La siguiente frontera de MCP no es más tools — es servers que exponen contexto tan rico que Claude deja de adivinar y empieza a saber.

Brian Mena

Brian Mena

Ingeniero informatico construyendo productos digitales rentables: SaaS, directorios y agentes de IA. Todo desde cero, todo en produccion.

LinkedIn