Skip to main content
Glama
Manuel-Mediavilla

reserva-mcp

reserva-mcp — Servidor MCP de reservas de restaurante

Qué es

Un servidor MCP (Model Context Protocol, el estándar abierto de Anthropic que en 2026 también adoptan OpenAI, Google y Microsoft) que expone la gestión de reservas de un restaurante como herramientas tipadas que cualquier agente de IA puede usar: Claude Desktop, Claude Code, Cursor, o un agente propio construido sobre la API de Anthropic. No es un chatbot envuelto en un prompt — es la capa de integración estándar que un agente necesita para actuar sobre un negocio real, no solo hablar de él.

Related MCP server: palate-mcp-server

Demo

  • Conexión por stdio (local, Claude Desktop/Code): ver Cómo probarlo

  • Servidor HTTP desplegado: pendiente

  • Video de uso desde Claude Desktop: pendiente

Las 5 herramientas

Herramienta

Qué hace

Tipo

check_availability

Mesas libres para fecha/hora + nº de comensales

solo lectura

create_reservation

Reserva una mesa (elige la de mejor ajuste automáticamente)

acción

cancel_reservation

Cancela una reserva existente

acción

get_reservation

Busca por ID o por teléfono del cliente

solo lectura

list_today_reservations

Todas las reservas confirmadas de un día (uso admin)

solo lectura

Por qué lo construí así

  • El problema de negocio real no es el CRUD, es la concurrencia. Dos clientes pidiendo la misma mesa a la vez es el caso que de verdad importa en un sistema de reservas. Por eso la garantía contra dobles reservas vive en la propia base de datos (EXCLUDE USING gist sobre el rango de tiempo de cada mesa), no en una validación de aplicación que una carrera de peticiones podría saltarse.

  • Cada tool-call se registra (tool_call_logs): nombre, argumentos, éxito/fallo, latencia, cliente. Esto es la base de datos que un panel de observabilidad de agentes necesitaría — la pieza que el mercado de contratación de IA pide explícitamente en 2026 y que casi ningún portfolio junior tiene.

  • Rate limiting por cliente MCP, para que un agente con un bug (o un bucle de reintentos mal hecho) no pueda machacar el servidor.

  • Dos transportes: stdio para uso local (Claude Desktop/Code, lo que se prueba en desarrollo) y Streamable HTTP para despliegue remoto — el mismo servidor, dos formas de conectarse, tal como recomienda el propio estándar MCP para pasar de "experimento local" a "servicio en producción".

Dos fallos reales encontrados construyendo esto (y cómo los arreglé)

Esta sección es, a propósito, la más importante del README — no por transparencia performativa, sino porque es la prueba de que el proyecto se probó de verdad contra el protocolo real, no solo se compiló.

1. Bajo concurrencia real, la mayoría de las reservas fallaban aunque hubiera mesas libres. Al lanzar 8 peticiones de reserva simultáneas para la misma franja, solo 1 de 8 tenía éxito — a pesar de haber 5 mesas con capacidad suficiente. La causa: el código elegía siempre "la mesa más ajustada" (available[0]) y, si esa mesa concreta perdía la carrera contra otro cliente milisegundos antes, fallaba directamente en vez de probar con la siguiente candidata de la lista. Arreglado añadiendo reintento secuencial sobre las mesas candidatas: si una pierde la carrera (error 23P01, exclusion violation de Postgres), se prueba la siguiente antes de rendirse. Tras el fix, la misma prueba de 8 peticiones concurrentes da 5 de 8 éxitos — el máximo matemáticamente posible con 5 mesas — con 0 dobles reservas en ambos casos. La prueba que lo demuestra vive en eval/run-eval.ts (concurrencia_no_permite_doble_reserva) y se puede volver a correr con npm run eval.

2. El log de observabilidad tiene un punto ciego: no ve los rechazos de esquema. Cuando el cliente MCP envía un argumento con formato inválido (ej. una fecha sin zona horaria), el propio SDK de MCP valida contra el esquema Zod y rechaza la llamada antes de que el código de la herramienta —y por tanto el logger— llegue a ejecutarse. El resultado es correcto de cara al cliente (isError: true), pero esas llamadas no quedan registradas en tool_call_logs, así que hoy no hay forma de saber "cuántas veces un agente mandó argumentos mal formados". Lo documento como limitación conocida en vez de esconderlo: arreglarlo requeriría interceptar a nivel del Server subyacente de MCP, no de registerTool, que es el siguiente paso si este proyecto avanza a producción.

Cómo probarlo con Claude Desktop

npm install
cp .env.example .env   # y rellena DATABASE_URL
npm run db:migrate
npm run db:seed

Añade esto a la configuración de Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "reservas-demo": {
      "command": "npx",
      "args": ["tsx", "/ruta/absoluta/a/reserva-mcp/src/server.ts"]
    }
  }
}

Reinicia Claude Desktop y pregúntale algo como "¿tienes mesa para 4 personas mañana a las 21:00?" — Claude debería llamar a check_availability solo, sin que se lo indiques explícitamente.

Cómo correr el harness de evaluación

npm run eval

Levanta el servidor real por stdio, conecta un cliente MCP real (mismo protocolo que usaría Claude Desktop) y ejecuta 5 casos deterministas, incluida la prueba de concurrencia de 8 peticiones simultáneas. Al final imprime latencia media y p95 por herramienta, calculadas directamente desde tool_call_logs.

Nota honesta: este harness no usa un LLM real (no había credenciales de API disponibles en el entorno donde lo construí) — prueba que el protocolo y la lógica de negocio son correctos, no que un modelo elige bien la herramienta a partir de lenguaje natural. Para esa evaluación, el siguiente paso es apuntar este mismo cliente a la API de Anthropic con tool-use habilitado, correr N prompts en lenguaje natural, y medir la tasa de acierto en la selección de herramienta — la métrica que de verdad piden los roles de "AI Tooling Engineer" en 2026.

Stack

  • TypeScript (strict) + @modelcontextprotocol/sdk (SDK oficial de Anthropic)

  • PostgreSQL con EXCLUDE USING gist para concurrencia real, sin ORM

  • Zod para los esquemas de entrada de cada herramienta

  • Express + Streamable HTTP para el transporte remoto

  • Vitest para la lógica pura (rate limiter); el harness de eval/ cubre la integración end-to-end

Qué haría distinto en producción

  • Persistir el rate limiting en Redis, no en memoria del proceso — necesario en cuanto haya más de una réplica del servidor HTTP.

  • Cerrar el punto ciego de logging de rechazos de esquema (ver arriba).

  • Autenticación real por servidor MCP (hoy cualquiera que conozca la URL del transporte HTTP puede conectarse) — OAuth es parte del propio estándar MCP y está pendiente de integrar.

  • Un tercer transporte SSE quedó fuera de alcance deliberadamente: el SDK lo soporta, pero Streamable HTTP ya cubre el caso de uso remoto y añadir un tercer camino de conexión no aportaba señal nueva para este proyecto.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers