Novacal MCP
Gestiona tu calendario de Novacal desde tu cliente de IA: explora los tipos de eventos, consulta la disponibilidad y reserva, reprograma o cancela eventos.
Documentación
Un servidor MCP remoto para Novacal. Le brinda a tu cliente de IA ocho herramientas para leer tus tipos de eventos, consultar disponibilidad y reservar, reprogramar o cancelar reuniones.
Se ejecuta como un único Cloudflare Worker y habla Streamable HTTP. Te conectas una vez con OAuth, pegas tu clave de API de Novacal y tu cliente sigue funcionando desde ahí.
Conectar
El servidor alojado está en https://mcp.novacal.io/mcp.
Claude Code
claude mcp add --transport http novacal https://mcp.novacal.io/mcp
Cursor, Windsurf o cualquier cliente con un archivo de configuración MCP
{
"mcpServers": {
"novacal": {
"type": "http",
"url": "https://mcp.novacal.io/mcp"
}
}
}
Claude Desktop y claude.ai
Agrega un conector personalizado y pega la misma URL.
En la primera conexión, tu cliente abre la página de inicio de sesión. Pega tu clave de API de Novacal y presiona Conectar. Eso es toda la configuración.
Herramientas
| Herramienta | Qué hace | Argumentos |
|---|---|---|
novacal_get_event_types | Lista los tipos de eventos de la cuenta | scope (personal o team, opcional) |
novacal_get_event_type | Obtiene un tipo de evento | id |
novacal_create_event_type | Crea un tipo de evento | name, slug, type, duration, hidden_from_profile, color + 10 campos opcionales |
novacal_get_availability | Espacios libres para un tipo de evento en un rango de fechas | event_type_id, start, end, timezone (opcional) |
novacal_get_events | Lista los eventos de la cuenta | ninguno |
novacal_create_event | Reserva un evento | event_type_id, start, end, timezone, time_format, location y form_field_answers (opcional) |
novacal_cancel_event | Cancela un evento futuro | id, cancellation_reason (opcional) |
novacal_reschedule_event | Mueve un evento futuro | id, start, end, timezone, time_format, user_role y form_field_answers (opcional) |
Las herramientas de lectura están marcadas como de solo lectura e idempotentes. novacal_cancel_event está marcada como destructiva, por lo que los clientes que preguntan antes de llamadas destructivas preguntarán.
Alcance de tipos de eventos
novacal_get_event_types acepta un scope opcional:
{ "scope": "personal" }
Usa personal para tus propios tipos de eventos y team para tipos de eventos de equipo. Omítelo para obtener ambos. El servidor le indica al modelo que prefiera personal a menos que pidas un tipo de evento de equipo.
Rangos de fechas de disponibilidad
start y end son fechas YYYY-MM-DD simples. El rango es inclusivo al inicio y exclusivo al final:
[start 00:00, end 00:00)
Para un solo día, pasa el día siguiente como end:
{
"event_type_id": 123,
"start": "2026-05-29",
"end": "2026-05-30",
"timezone": "Europe/Amsterdam"
}
Eso devuelve disponibilidad para el 29 de mayo de 2026. Pasar la misma fecha para start y end es un rango vacío y no devuelve nada.
Zonas horarias
timezone acepta un nombre IANA como Europe/Amsterdam, America/New_York o Asia/Tokyo. Se establece por defecto en UTC cuando se omite.
Al conectar, el servidor lee la zona horaria de tu perfil de Novacal y la coloca en las instrucciones del servidor. Así, el modelo lee fechas relativas en tu zona horaria y muestra horas en tu zona horaria, a menos que pidas otra.
Cómo funciona la autenticación
- Tu cliente inicia un flujo OAuth contra el Worker.
- El Worker sirve
/authorizey solicita tu clave de API de Novacal. - Verifica la clave con
GET /v1/users/me. - Cifra la clave en las propiedades de la sesión OAuth y completa el flujo.
La clave solo se puede recuperar con tu token de acceso. Nunca se escribe en almacenamiento en forma legible, nunca se devuelve a la página y se mantiene fuera de los metadatos de concesión, que se almacenan sin cifrar.
Eliminar la conexión en tu cliente no revoca la clave. Para cortar el acceso, rota la clave en Novacal.
Desarrollo local
Necesitas Node 20+ y una cuenta de Cloudflare para los despliegues.
npm install
npm run dev
| Endpoint | URL |
|---|---|
| MCP | http://127.0.0.1:8787/mcp |
| Página de inicio de sesión | http://127.0.0.1:8787/authorize |
| Verificación de salud | http://127.0.0.1:8787/health |
npm run dev usa el entorno de Wrangler dev. Simula KV y D1 localmente y apunta a una API de Novacal en http://localhost:8010, por lo que nunca toca recursos de producción.
Para probar las herramientas manualmente:
npx @modelcontextprotocol/inspector
Verificaciones
npm run check # tsc --noEmit
npm run lint # biome check
npm run format # biome check --write
npm test # vitest run
CI ejecuta check, lint y test en Node 20 para cada push y pull request.
Despliegue
Crea los recursos de Cloudflare una vez:
npx wrangler kv namespace create OAUTH_KV
npx wrangler d1 create novacal-mcp-server-db
Copia los IDs devueltos en wrangler.toml bajo OAUTH_KV y DB, luego aplica el esquema:
npx wrangler d1 execute novacal-mcp-server-db --remote --file=./migrations/0001_user_credentials.sql
Despliega el entorno production:
npm run deploy
Nota: la tabla
user_credentialses heredada. Las credenciales ahora viven en la sesión OAuth cifrada y nada lee ni escribe en esta tabla. Ella y el enlaceDBpermanecen solo para que los despliegues existentes sigan validando.
Configuración
| Nombre | Tipo | Valor |
|---|---|---|
NOVACAL_API_BASE_URL | var | https://api.novacal.io en producción, http://localhost:8010 en desarrollo |
OAUTH_KV | espacio de nombres KV | almacenamiento de cliente OAuth, concesión y token |
DB | base de datos D1 | heredada, sin uso |
Cómo está estructurado
src/
├── index.ts OAuthProvider wiring, /authorize, metadata routes
├── auth.ts API key verification and the sign-in page
├── mcp.ts tool registration and server instructions
├── api.ts Novacal HTTP client, UpstreamApiError, 30s timeout
├── responses.ts okResult / failedResult envelopes
├── types.ts Env, session props, Novacal types
└── handlers/
├── event-types.ts list, get, create
├── events.ts list, create, cancel, reschedule
└── availability.ts availability lookup
Los manejadores son funciones asíncronas simples sin importaciones de MCP, por lo que son fáciles de probar por sí solos. Cada herramienta envuelve su manejador en un try/catch y devuelve un resultado isError en lugar de lanzar una excepción. Los fallos llegan al modelo como una pista breve, no como un volcado JSON crudo:
401 — Novacal API key is invalid or revoked. Re-authorize at /authorize.
429 — Rate limited by the Novacal API. Wait a moment before retrying.
Las llamadas a la API de Novacal expiran después de 30 segundos.
Rutas públicas
| Ruta | Propósito |
|---|---|
GET / | nombre del servidor y estado |
GET /health | verificación de salud |
GET /.well-known/oauth-protected-resource | metadatos RFC 9728, con variante de sufijo /mcp |
GET POST /authorize | página de inicio de sesión y envío de formulario |
POST /token, POST /register | manejados por OAuthProvider |
POST /mcp | el endpoint MCP, requiere un token de portador |
Enlaces
- Novacal
- Model Context Protocol
- Entrada del registro MCP —
io.github.ste7/novacal-mcp-server