Skip to content
AI•4 min read

Build your MCP server (and its footguns)

Mi servidor MCP funcionaba perfecto en local. Agregué un console.log para depurar una respuesta rara, y el cliente dejó de responder. Sin error, sin mensaje: dejó de funcionar. Pasé una hora revisando el código antes de entender que el bug era el log.

MCP es un protocolo elegante con trampas muy concretas. Esta pieza tiene el servidor mínimo y los tres footguns que te van a morder, con las fuentes de cada uno.

Qué es un servidor MCP

MCP (Model Context Protocol) es el estándar para conectar herramientas y datos a cualquier agente: escribes un servidor una vez y lo consumen Claude, tu IDE, tu app o un framework. El servidor expone tools (acciones), resources (datos) y prompts (plantillas), y el cliente los descubre en tiempo de ejecución. - Source: Model Context Protocol - especificación oficial

Es una de las 9 piezas del harness: la que convierte tu sistema en algo que cualquier agente puede usar.

Cuándo escribirlo (y cuándo no)

Escríbelo si quieres que varios clientes usen la misma capacidad (tu editor, tu app, un agente de terceros), o si vas a publicar una integración.

No lo escribas si la tool solo la usa tu app internamente: una función local es más simple y más rápida. MCP añade valor cuando la interoperabilidad lo justifica.

El servidor mínimo

// Simplificado. Fuente: SDK oficial de MCP
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: "petlog-tickets", version: "1.0.0" });

server.tool(
  "list_tickets",
  "Lista los tickets abiertos, opcionalmente filtrados por estado",
  { status: z.string().optional() },
  async ({ status }) => ({
    content: [{ type: "text", text: JSON.stringify(await db.listTickets(status)) }],
  }),
);

await server.connect(new StdioServerTransport());

Eso ya es un servidor usable: define una tool, su descripción y sus parámetros, y la conecta por stdio. El cliente la descubre y la llama como cualquier otra.

Footgun 1: console.log rompe el protocolo

Con el transporte stdio, el cliente se comunica con tu servidor por stdout. Cuando haces console.log, escribes en el mismo canal: el cliente recibe un mensaje que no es MCP y, según el cliente, se cae; en el mejor caso, tus logs desaparecen dentro del protocolo. - Source: Logging: A Huge MCP Footgun - AI Hero

Opciones: usar un transporte que no use stdout (como SSE), escribir a un archivo de log, o mandar a stderr (que el cliente no lee como protocolo). - Source: Logging: A Huge MCP Footgun - AI Hero

Regla de oro: en un servidor MCP, stdout es del protocolo, no tuyo.

Footgun 2: servidores stateful

Si guardas el transporte en memoria (el patrón clásico con SSE), pasan dos cosas: solo atiende un cliente a la vez (el segundo cliente desconecta al primero) y, al reiniciar el proceso, se pierde todo el estado. Peor: eso te obliga a un servidor de larga vida y no puede desplegarse en serverless (Vercel, Lambda), porque no conservan estado en memoria. - Source: The Problem With MCP: Stateful Servers - AI Hero

La solución documentada es mover el estado a un almacén externo (Redis) y dejar el servidor sin estado; el ejemplo de Vercel en mcp-on-vercel sigue ese enfoque y se puede adaptar a cualquier plataforma serverless. - Source: The Problem With MCP: Stateful Servers - AI Hero

Footgun 3: errores silenciosos

Un servidor MCP que lanza una excepción sin mensaje deja al cliente esperando o falla sin contexto. Dos reglas: devuelve errores estructurados con explicación (qué falló, con qué parámetros) y define timeouts en las tools lentas. Si tu tool llama a una API, el error de esa API debe volver como resultado, no como crash.

Cómo lo conectas

  • Claude Code y otros agentes de terminal: se declaran en la configuración del cliente y quedan disponibles para todas tus sesiones.
  • Vercel AI SDK: consume tools MCP como parte de tu agente en TypeScript. - Source: MCP Tools - Vercel AI SDK
  • Google ADK: soporta MCP tools, y además puedes exponer un agente como servidor MCP. - Source: MCP tools - Google ADK

5 pasos para el tuyo

  1. Elige una tool que uses en 2+ contextos (no inventes una para probar).
  2. Escribe el servidor con stdio y pruébalo con un cliente real.
  3. Silencia los console.log desde el primer commit (logger a archivo).
  4. Hazlo sin estado: nada de variables globales; si necesitas estado, a un store externo.
  5. Documenta cada tool como API pública: descripción clara, parámetros tipados, errores útiles.

Esto es "MCP" dentro de la guía Agentes: de cero a producción, y el marco general está en Qué es un agente, de verdad.

¿Qué capacidad tuya merece un servidor MCP? Cuéntame en los comentarios: casi siempre es esa que repites en todos tus agentes.

Referencias

> More posts