punctual:

MCP server

A Model Context Protocol server exposing five scheduling tools to AI agents, scoped to the calling API key.

A Model Context Protocol server at /mcp — JSON-RPC 2.0 over a single HTTP POST, no SSE stream, no session id. It speaks protocol versions 2025-11-25, 2025-06-18 and 2025-03-26.

Authority

An agent's authority is exactly its API key's — the same authentication and the same read/write scopes as the REST API. An agent can do nothing to a calendar that the key's owner couldn't do themselves, and tools/list only returns the tools the presented key's scopes actually allow.

Connect

curl https://book.cccrafts.ai/mcp \
  -X POST \
  -H "Authorization: Bearer pk_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25"}}'

The five tools

ToolScopeDoesParameters
list_event_typesreadList the bookable event types owned by the API key holder — id, title, duration, and public booking URL.includeInactive (boolean, optional; default false)
get_available_slotsreadList bookable start times for an event type in a window. Each slot is a UTC instant plus a rendering in the requested timezone.eventTypeId (required); from, to, timezone, limit (1–200, default 50)
create_bookingwriteBook a slot for a guest. start must be exactly a slot start returned by get_available_slots.eventTypeId, start, guestName, guestEmail (required); guestTimezone, answers, idempotencyKey
reschedule_bookingwriteMove a confirmed booking to a new time. Returns a new booking id — the old one is marked rescheduled.bookingId, newStart (required); reason
cancel_bookingwriteCancel a confirmed booking, free its time, and notify the guest. Cannot be undone.bookingId (required); reason

Example: calling a tool

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_available_slots",
    "arguments": { "eventTypeId": "evt_abc123", "timezone": "Europe/Berlin" }
  }
}

A tool that ran and refused — a taken slot, an unknown booking id — comes back as a normal JSON-RPC result with isError: true and a readable message, so the model can decide what to do next rather than treat it as a transport failure.

All times are UTC instants; a timezone parameter only changes how a slot is rendered, never which slots exist. create_booking's start must be copied exactly from a slot returned by get_available_slots — an arbitrary time is refused even if it looks free.

Full tool and schema definitions: src/http/mcp/server.ts.