TiendaTech Support MCP Server
README.md
# Agente de soporte con servidor MCP propio
Proyecto 1 de una serie de 7 proyectos chicos, cada uno enfocado en una habilidad puntual que aparece hoy en avisos de trabajo para desarrolladores de agentes de IA. Este cubre: **construir y consumir un servidor MCP (Model Context Protocol) desde cero.**
## El problema que resuelve
Una tienda de electrónica ("TiendaTech") necesita un agente de soporte que pueda:
- Responder preguntas de clientes sobre políticas (devoluciones, garantía, envíos) sin inventar información.
- Consultar y crear tickets de soporte reales, no simulados.
En vez de meter toda esa lógica adentro del prompt o hardcodeada en el cliente del LLM, ese acceso a datos vive en un **servidor MCP separado**: un proceso independiente que expone qué información y qué acciones están disponibles, con un contrato bien definido. El agente (el cliente que habla con Claude) no sabe nada de archivos ni de JSON — solo sabe que existe un servidor con ciertos recursos y herramientas.
Esto es exactamente el problema que MCP fue diseñado para resolver: separar "qué puede hacer un agente" de "qué modelo lo está operando", para no tener que reescribir la integración de datos cada vez que cambiás de LLM o de cliente.
## Arquitectura
```mermaid
flowchart LR
subgraph Cliente["src/agent.ts (proceso 1)"]
CLI[REPL en terminal]
MCPClient[Cliente MCP]
Claude[Anthropic SDK]
end
subgraph Servidor["src/server.ts (proceso 2, hijo)"]
MCPServer[Servidor MCP]
Tools[Tools: search_tickets / get_ticket / create_ticket]
Resources[Resources: artículos de la KB]
end
DB[(data/tickets.json)]
KB[(data/kb/*.md)]
CLI --> MCPClient
MCPClient <-->|stdio JSON-RPC| MCPServer
MCPServer --> Tools
MCPServer --> Resources
Tools <--> DB
Resources <--> KB
MCPClient --> Claude
Claude -->|decide qué tool llamar| MCPClient
```
Son **dos procesos Node separados** que se comunican por stdio con el protocolo MCP (JSON-RPC 2.0):
1. **`src/server.ts`** — el servidor MCP. No sabe nada de Claude ni de IA. Solo expone:
- **Resources** (`kb://politica-devoluciones.md`, etc.): los 3 artículos de la base de conocimiento, como contenido de solo lectura pensado para dar contexto.
- **Tools** (`search_tickets`, `get_ticket`, `create_ticket`): acciones que leen y escriben sobre `data/tickets.json`, una base de tickets de soporte.
2. **`src/agent.ts`** — el agente. Levanta el servidor como proceso hijo, se conecta como cliente MCP, y hace de puente entre MCP y la API de Claude:
- Al arrancar, lee todos los *resources* y los inyecta en el system prompt como contexto fijo.
- Traduce la lista de *tools* del servidor al formato de tool-use de la API de Claude.
- Corre un loop de conversación: si Claude decide llamar una tool, el agente ejecuta esa llamada contra el servidor MCP real y le devuelve el resultado, hasta que Claude da una respuesta final en texto.
## Decisiones técnicas y por qué
- **Resources vs. Tools, a propósito.** MCP distingue explícitamente entre datos de contexto (*resources*, decisión de cuándo leerlos la toma el host/agente) y acciones invocables por el modelo (*tools*, decisión de cuándo usarlas la toma el LLM). Usar ambos primitivos — y no meter todo como tools — muestra que la separación es intencional, no que "tools es lo único que existe en MCP".
- **Transporte stdio, no HTTP/SSE.** Para un servidor MCP local de un solo cliente, stdio es más simple: no hay puertos, no hay CORS, no hay que levantar un server HTTP aparte. El SDK oficial de Anthropic soporta stdio, SSE y Streamable HTTP — stdio es el punto de entrada correcto para entender el protocolo antes de pasar a un despliegue remoto.
- **JSON planos en vez de SQLite/Postgres.** El foco del proyecto es demostrar el protocolo MCP (cómo se define un tool, cómo se valida su input, cómo un cliente lo descubre y lo invoca), no la capa de persistencia. Cambiar `data/tickets.json` por una base real implica tocar únicamente `readTickets`/`writeTickets` en `server.ts` — el contrato MCP hacia el agente no cambia.
- **TypeScript + SDK oficiales.** `@modelcontextprotocol/sdk` (servidor y cliente) y `@anthropic-ai/sdk` son los paquetes oficiales de Anthropic. Se usa la API de alto nivel `McpServer` (`registerTool`/`registerResource`) en vez de la API de bajo nivel con `setRequestHandler`, porque valida automáticamente el input contra el schema de Zod y da mensajes de error más claros — importante cuando el que "llena" los argumentos es un LLM y no un humano.
- **Sin frameworks de agentes (LangChain, etc.).** El loop de tool-use (llamar al modelo → detectar `tool_use` → ejecutar → devolver `tool_result` → repetir) se escribe a mano en ~40 líneas. Para un solo agente con 3 tools, un framework agrega abstracción sin resolver un problema real; y entender ese loop sin magia es la habilidad que se quiere mostrar acá.
## Stack
- Node.js 22 + TypeScript
- [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) — servidor y cliente MCP
- [`@anthropic-ai/sdk`](https://www.npmjs.com/package/@anthropic-ai/sdk) — Claude (modelo `claude-sonnet-4-5`)
- `zod` — validación de inputs de las tools
- Sin base de datos externa: `data/tickets.json` + `data/kb/*.md`
## Cómo correrlo
```bash
npm install
cp .env.example .env # completar ANTHROPIC_API_KEY
npm start # compila y levanta el agente (que a su vez levanta el servidor MCP)
```
Ejemplo de conversación:
```
Vos: hola, tengo un teclado que no me terminó gustando, ¿lo puedo devolver?
Agente: Sí, podés devolverlo dentro de los 30 días de la compra siempre que esté sin uso...
Vos: se me rompió el auricular izquierdo de mis auriculares, ¿tienen algún ticket mío?
→ llamando herramienta MCP: search_tickets({"query":"auricular"})
Agente: Sí, encontré el ticket #1 a nombre de Marcos Videla, sigue abierto...
```
Si querés inspeccionar el servidor MCP de forma aislada (sin Claude), se puede correr con el [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) oficial:
```bash
npm run build
npx @modelcontextprotocol/inspector node dist/server.js
```
## Estructura
```
src/
server.ts # servidor MCP: resources + tools
agent.ts # cliente MCP + integración con Claude + REPL
data/
kb/*.md # base de conocimiento (resources)
tickets.json # base de tickets (tools)
```
## Qué demuestra este proyecto
- Entender MCP como protocolo (no solo como "una librería más"): distinción resources/tools, transporte, ciclo de vida de conexión.
- Diseñar el input schema de una tool con Zod pensando en que quien la va a llamar es un LLM, no un formulario.
- Integrar el tool-use de la API de Claude con una fuente de tools que no está hardcodeada, sino descubierta dinámicamente en runtime contra un servidor externo.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues