Skip to main content
Glama
README.md
# MCP Server real (SDK oficial) + OAuth 2.1 propio — Node.js

Servidor MCP funcional usando `@modelcontextprotocol/sdk`, protegido con
OAuth 2.1 + PKCE implementado desde cero (sin Auth0/Okta/terceros).

## Instalar y correr

```bash
npm install
node server.js
```

Corre en `http://localhost:3000` por defecto. El endpoint MCP está en `/mcp`.

## Probar sin conectar a un LLM todavía

```bash
node test-mcp-client.js
```

Esto usa el `Client` oficial del SDK de MCP: hace OAuth completo, se conecta,
lista tools y las ejecuta. Si esto corre OK, tu servidor está listo para
conectarse a un LLM real.

## Conectar esto a Claude (Claude.ai / Claude Desktop)

### Opción A: probar localmente con un túnel (recomendado para pruebas rápidas)

Claude.ai necesita una URL pública con HTTPS para conectores remotos. Para
probar sin desplegar nada, usa un túnel:

```bash
# instala ngrok (https://ngrok.com) o usa cloudflared
ngrok http 3000
```

Esto te da una URL tipo `https://abc123.ngrok-free.app`. IMPORTANTE: actualiza
las variables de entorno antes de arrancar el server para que el OAuth use
esa URL pública en vez de localhost:

```bash
PUBLIC_BASE_URL=https://abc123.ngrok-free.app node server.js
```

(en Windows PowerShell: `$env:PUBLIC_BASE_URL="https://abc123.ngrok-free.app"; node server.js`)

Luego en Claude.ai:
1. Ajustes → Connectors (o "Conectores") → Add custom connector
2. Pega la URL: `https://abc123.ngrok-free.app/mcp`
3. Claude detecta automáticamente que requiere OAuth (vía el 401 +
   WWW-Authenticate que devuelve tu servidor), te redirige a tu pantalla de
   login (`/authorize`), apruebas, y Claude queda conectado.
4. Ahora puedes pedirle a Claude que use las tools `whoami` o `sumar`.

### Opción B: desplegar en un hosting real

Cualquier servicio que soporte Node.js sirve (Render, Railway, Fly.io, un VPS
con nginx + certbot, etc). Solo necesitas:
- HTTPS válido (obligatorio, OAuth 2.1 no permite HTTP excepto en localhost)
- Variable `PUBLIC_BASE_URL` apuntando a tu dominio real
- Variable `JWT_SECRET` definida explícitamente (no uses la generada al azar)

### Conectar a ChatGPT

ChatGPT soporta MCP remoto vía "Connectors" (en configuración de la cuenta,
o dentro de un GPT personalizado, según el plan). El proceso de descubrimiento
OAuth es el mismo: ChatGPT también lee `/.well-known/oauth-protected-resource`
automáticamente al recibir el 401 inicial. Pega la misma URL `https://tu-dominio/mcp`.

## Estructura

- `server.js` — MCP server con el SDK oficial + rutas OAuth montadas
- `test-mcp-client.js` — cliente de prueba con el SDK (sin necesidad de un LLM)
- `oauth/` — Authorization Server + Resource Server (igual que en el ejemplo anterior)

## Notas sobre las tools de ejemplo

- `whoami` — devuelve la identidad inyectada por el OAuth (userId, clientId, scope).
  Útil para confirmar que la autenticación está llegando correctamente a tus tools.
- `sumar` — tool trivial con input, para ver el patrón estándar de definición
  de herramientas con Zod.

Reemplaza estas dos por las tools reales que necesites. El patrón con
`server.registerTool(nombre, { title, description, inputSchema }, handler)`
es el que debes seguir para cualquier tool nueva.

## Antes de producción (recordatorio, igual que el ejemplo anterior)

1. Reemplaza el almacenamiento en memoria (`oauth/store.js`) por una DB real.
2. Define `JWT_SECRET` explícitamente.
3. HTTPS obligatorio.
4. Reemplaza el login demo en `/authorize` por tu sistema real de usuarios.
5. Agrega rate limiting a `/token` y `/authorize`.