Novacal MCP
Gerencie seu calendário Novacal pelo seu cliente de IA — navegue pelos tipos de evento, verifique a disponibilidade e agende, reagende ou cancele eventos.
Documentação
Um servidor MCP remoto para Novacal. Ele dá ao seu cliente de IA oito ferramentas para ler seus tipos de evento, verificar disponibilidade e agendar, reagendar ou cancelar reuniões.
Ele roda como um único Cloudflare Worker e fala Streamable HTTP. Você conecta uma vez com OAuth, cola sua chave de API da Novacal, e seu cliente continua funcionando a partir daí.
Conectar
O servidor hospedado está em https://mcp.novacal.io/mcp.
Claude Code
claude mcp add --transport http novacal https://mcp.novacal.io/mcp
Cursor, Windsurf, ou qualquer cliente com um arquivo de configuração MCP
{
"mcpServers": {
"novacal": {
"type": "http",
"url": "https://mcp.novacal.io/mcp"
}
}
}
Claude Desktop e claude.ai
Adicione um conector personalizado e cole a mesma URL.
Na primeira conexão, seu cliente abre a página de login. Cole sua chave de API da Novacal e pressione Conectar. Essa é toda a configuração.
Ferramentas
| Ferramenta | O que faz | Argumentos |
|---|---|---|
novacal_get_event_types | Lista tipos de evento na conta | scope (personal ou team, opcional) |
novacal_get_event_type | Busca um tipo de evento | id |
novacal_create_event_type | Cria um tipo de evento | name, slug, type, duration, hidden_from_profile, color + 10 campos opcionais |
novacal_get_availability | Slots livres para um tipo de evento em um intervalo de datas | event_type_id, start, end, timezone (opcional) |
novacal_get_events | Lista eventos na conta | nenhum |
novacal_create_event | Agenda um evento | event_type_id, start, end, timezone, time_format, location e form_field_answers (opcional) |
novacal_cancel_event | Cancela um evento futuro | id, cancellation_reason (opcional) |
novacal_reschedule_event | Move um evento futuro | id, start, end, timezone, time_format, user_role e form_field_answers (opcional) |
Ferramentas de leitura são marcadas como somente leitura e idempotentes. novacal_cancel_event é marcada como destrutiva, então clientes que pedem confirmação antes de chamadas destrutivas vão pedir.
Escopo do tipo de evento
novacal_get_event_types aceita um scope opcional:
{ "scope": "personal" }
Use personal para seus próprios tipos de evento e team para tipos de evento de equipe. Deixe em branco para obter ambos. O servidor instrui o modelo a preferir personal a menos que você peça um tipo de evento de equipe.
Intervalos de datas de disponibilidade
start e end são datas YYYY-MM-DD simples. O intervalo é inclusivo no início e exclusivo no fim:
[start 00:00, end 00:00)
Para um único dia, passe o dia seguinte como end:
{
"event_type_id": 123,
"start": "2026-05-29",
"end": "2026-05-30",
"timezone": "Europe/Amsterdam"
}
Isso retorna disponibilidade para 29 de maio de 2026. Passar a mesma data para start e end é um intervalo vazio e retorna nada.
Fusos horários
timezone aceita um nome IANA como Europe/Amsterdam, America/New_York ou Asia/Tokyo. O padrão é UTC quando omitido.
Na conexão, o servidor lê o fuso horário do seu perfil Novacal e o coloca nas instruções do servidor. Assim, o modelo lê datas relativas no seu fuso horário e mostra horários no seu fuso horário, a menos que você peça outro.
Como funciona a autenticação
- Seu cliente inicia um fluxo OAuth contra o Worker.
- O Worker serve
/authorizee pede sua chave de API da Novacal. - Ele verifica a chave com
GET /v1/users/me. - Ele criptografa a chave nas propriedades da sessão OAuth e completa o fluxo.
A chave só pode ser recuperada com seu token de acesso. Ela nunca é gravada em armazenamento de forma legível, nunca é ecoada de volta na página e é mantida fora dos metadados da concessão, que são armazenados sem criptografia.
Remover a conexão no seu cliente não revoga a chave. Para cortar o acesso, rotacione a chave na Novacal.
Desenvolvimento local
Você precisa de Node 20+ e uma conta Cloudflare para deploys.
npm install
npm run dev
| Endpoint | URL |
|---|---|
| MCP | http://127.0.0.1:8787/mcp |
| Página de login | http://127.0.0.1:8787/authorize |
| Verificação de saúde | http://127.0.0.1:8787/health |
npm run dev usa o ambiente Wrangler dev. Ele simula KV e D1 localmente e aponta para uma API Novacal em http://localhost:8010, então nunca toca em recursos de produção.
Para testar as ferramentas manualmente:
npx @modelcontextprotocol/inspector
Verificações
npm run check # tsc --noEmit
npm run lint # biome check
npm run format # biome check --write
npm test # vitest run
O CI executa check, lint e test no Node 20 para cada push e pull request.
Deploy
Crie os recursos Cloudflare uma vez:
npx wrangler kv namespace create OAUTH_KV
npx wrangler d1 create novacal-mcp-server-db
Copie os IDs retornados para wrangler.toml em OAUTH_KV e DB, depois aplique o schema:
npx wrangler d1 execute novacal-mcp-server-db --remote --file=./migrations/0001_user_credentials.sql
Faça o deploy do ambiente production:
npm run deploy
Nota: a tabela
user_credentialsé legada. As credenciais agora vivem na sessão OAuth criptografada e nada lê ou escreve nesta tabela. Ela e o bindingDBpermanecem apenas para que implantações existentes continuem validando.
Configuração
| Nome | Tipo | Valor |
|---|---|---|
NOVACAL_API_BASE_URL | var | https://api.novacal.io em produção, http://localhost:8010 em dev |
OAUTH_KV | namespace KV | armazenamento de cliente OAuth, concessão e token |
DB | banco D1 | legado, não utilizado |
Como está estruturado
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
Handlers são funções assíncronas simples, sem imports de MCP, então são fáceis de testar isoladamente. Cada ferramenta envolve seu handler em um try/catch e retorna um resultado isError em vez de lançar erro. Falhas chegam ao modelo como uma dica curta, não como um despejo JSON bruto:
401 — Novacal API key is invalid or revoked. Re-authorize at /authorize.
429 — Rate limited by the Novacal API. Wait a moment before retrying.
Chamadas à API Novacal expiram após 30 segundos.
Rotas públicas
| Rota | Finalidade |
|---|---|
GET / | nome e status do servidor |
GET /health | verificação de saúde |
GET /.well-known/oauth-protected-resource | metadados RFC 9728, com variante de sufixo /mcp |
GET POST /authorize | página de login e envio de formulário |
POST /token, POST /register | tratadas pelo OAuthProvider |
POST /mcp | o endpoint MCP, requer token bearer |
Links
- Novacal
- Model Context Protocol
- Entrada no registro MCP —
io.github.ste7/novacal-mcp-server