> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended** (the `-y` flags skip prompts, so the command runs without an interactive terminal):
> ```bash
> npx -y @scalekit-inc/cli setup -y
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup -y
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents in `~/.agents/skills`.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Connect AI agents to the Cal MCP server

The Cal MCP connector routes your AI agent's tool calls to Cal's own MCP server through Scalekit. Each user signs in to Cal once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 35 tools.

**Authentication:** OAuth 2.1/DCR
**Categories:** Calendar, Productivity, AI
**Tools:** 35: 18 read, 13 write, 4 destructive
**Users sign in with:** OAuth
**OAuth app:** Your own Cal MCP server app
**Built by:** Vendor MCP
**Try it:** [Playground in the Scalekit dashboard](https://app.scalekit.com/ws/signup?sk_intent=playground&provider=CALMCP)

## What you can do

- **Manage bookings**: create, confirm, reschedule, and cancel bookings, and add attendees or mark no-shows
- **Check availability**: find open time slots for a host and read busy times from connected calendars
- **Manage event types**: create, update, and delete the meeting types people can book
- **Set working hours**: create, update, and delete availability schedules, including the default schedule
- **Manage organizations**: add, update, and remove organization members, and read routing forms and their responses

## Setup

1. ### Install the SDK

   **Node.js**

   ```bash
   npm install @scalekit-sdk/node dotenv
   ```

   **Python**

   ```bash
   pip install scalekit-sdk-python python-dotenv
   ```

2. ### Set your credentials

   Add your Scalekit credentials to your `.env` file. Find values in **[app.scalekit.com](https://app.scalekit.com)** > **Developers** > **API Credentials**.

   ```sh title=".env"
   SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
   SCALEKIT_CLIENT_ID=<your-client-id>
   SCALEKIT_CLIENT_SECRET=<your-client-secret>
   ```

3. ### Create the Cal MCP connection

   In **AgentKit > Connections**, create a Cal MCP connection and copy its redirect URI. The name you give it is the `connection_name` your code passes. See [Configure connections](/agentkit/connections/).

4. ### Register an OAuth app

   Cal MCP server connections use your own OAuth app. Register one with Cal MCP server and add the redirect URI you copied.

   Then enter the app's Client ID and Client Secret on the Cal MCP connection.

5. ### Authorize a user and make your first call

   **Node.js** (`quickstart.mts`)

   ```typescript
   import { ScalekitClient } from '@scalekit-sdk/node'
   import 'dotenv/config'
   import { createInterface } from 'node:readline/promises'

   const scalekit = new ScalekitClient(
     process.env.SCALEKIT_ENVIRONMENT_URL,
     process.env.SCALEKIT_CLIENT_ID,
     process.env.SCALEKIT_CLIENT_SECRET,
   )
   const actions = scalekit.actions

   const connector = 'calmcp'
   const identifier = 'user_123'

   // Generate an authorization link for the user
   const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
   console.log('Authorize Cal MCP:', link)
   const rl = createInterface({ input: process.stdin, output: process.stdout })
   await rl.question('Press Enter after authorizing...')
   rl.close()

   // Make your first call
   const result = await actions.executeTool({
     connector,
     identifier,
     toolName: 'calmcp_get_me',
     toolInput: {},
   })
   console.log(result)
   ```

   ```bash
   npx tsx quickstart.mts
   ```

   **Python** (`quickstart.py`)

   ```python
   import os
   from scalekit import ScalekitClient
   from dotenv import load_dotenv
   load_dotenv()

   scalekit_client = ScalekitClient(
       env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
       client_id=os.getenv("SCALEKIT_CLIENT_ID"),
       client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
   )
   actions = scalekit_client.actions

   connection_name = "calmcp"
   identifier = "user_123"

   # Generate an authorization link for the user
   link_response = actions.get_authorization_link(
       connection_name=connection_name,
       identifier=identifier,
   )
   print("Authorize Cal MCP:", link_response.link)
   input("Press Enter after authorizing...")

   # Make your first call
   result = actions.execute_tool(
       tool_input={},
       tool_name="calmcp_get_me",
       connection_name=connection_name,
       identifier=identifier,
   )
   print(result)
   ```

   ```bash
   python quickstart.py
   ```

   Each user signs in once. See [Authorize a user](/agentkit/tools/authorize/) for the full flow and statuses.

## Tools

Pass the exact name to `execute_tool`, with an input like each tool's example. To ask for a tool that's missing, use the [request form](https://scalekitsupport.portal.usepylon.com/forms/request-a-connector-tool).

**Node.js**

```typescript
const result = await actions.executeTool({
  toolName: 'calmcp_get_availability',
  toolInput: {
    end: '2024-08-14',
    start: '2024-08-13',
  },
  connector: 'calmcp',
  identifier: 'user_123',
})
```

**Python**

```python
result = actions.execute_tool(
    tool_name="calmcp_get_availability",
    tool_input={
        "end": "2024-08-14",
        "start": "2024-08-13",
    },
    connection_name="calmcp",
    identifier="user_123",
)
```

`result.data` is the app's response as JSON, and `result.execution_id` (`executionId` in Node.js) is the ID of the call.

### `calmcp_get_availability`

Get Availability · Read-only

Get available time slots for a host. You MUST provide at least one identifier: (1) eventTypeId, (2) eventTypeSlug + username, (3) eventTypeSlug + teamSlug, or (4) usernames (comma-separated, min 2, for dynamic events). 'username' is the host whose availability you are checking. Start/end must be in UTC ISO 8601.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `end` (`string`, required): Range end in UTC, ISO 8601 (e.g. '2024-08-14' or '2024-08-14T18:00:00Z')
- `start` (`string`, required): Range start in UTC, ISO 8601 (e.g. '2024-08-13' or '2024-08-13T09:00:00Z')
- `bookingUidToReschedule` (`string`, optional): Booking UID being rescheduled — ensures original time appears in available slots
- `duration` (`integer`, optional): Desired slot duration in minutes (for variable-duration or dynamic events, defaults to 30)
- `eventTypeId` (`integer`, optional): Event type ID. Use this OR (eventTypeSlug + username) OR (eventTypeSlug + teamSlug).
- `eventTypeSlug` (`string`, optional): Event type slug. Must be combined with username (individual) or teamSlug (team).
- `format` (`string`, optional): Response format: 'range' (start+end) or 'time' (start only)
- `organizationSlug` (`string`, optional): Organization slug, needed when the user/team is within an organization.
- `teamSlug` (`string`, optional): Team slug. Required with eventTypeSlug for team event types.
- `timeZone` (`string`, optional): IANA time zone for returned slots (e.g. America/New_York). Defaults to UTC.
- `username` (`string`, optional): Username of the host whose availability you are checking. Required with eventTypeSlug for individual event types.
- `usernames` (`string`, optional): Comma-separated or array of usernames for dynamic events (min 2). organizationSlug is needed only if users belong to an org.

Example input: `{"end":"2024-08-14","start":"2024-08-13"}`

### `calmcp_get_booking`

Get Booking · Read-only

Get a specific booking by its UID (use get_bookings to find UIDs). Returns full details including attendees, location, and metadata.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `bookingUid` (`string`, required): Booking UID

Example input: `{"bookingUid":"<bookingUid>"}`

### `calmcp_get_booking_attendee`

Get Booking Attendee · Read-only

Get a specific attendee by their numeric ID within a booking. Use get_booking_attendees to find attendee IDs.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `attendeeId` (`integer`, required): Attendee ID. Use get_booking_attendees to find this.
- `bookingUid` (`string`, required): Booking UID

Example input: `{"attendeeId":1,"bookingUid":"<bookingUid>"}`

### `calmcp_get_booking_attendees`

Get Booking Attendees · Read-only

Get all attendees for a booking by its UID.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `bookingUid` (`string`, required): Booking UID

Example input: `{"bookingUid":"<bookingUid>"}`

### `calmcp_get_bookings`

Get Bookings · Read-only

List bookings with pagination (default 100, max 250 per page — use take/skip for more). Supports filtering by status (upcoming, recurring, past, cancelled, unconfirmed), attendee email/name, event type, team, date ranges (afterStart, beforeEnd), and sorting (sortStart, sortEnd, sortCreated).

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `afterCreatedAt` (`string`, optional): Filter bookings created after this ISO 8601 date
- `afterStart` (`string`, optional): Filter bookings starting after this ISO 8601 date
- `afterUpdatedAt` (`string`, optional): Filter bookings updated after this ISO 8601 date
- `attendeeEmail` (`string`, optional): Filter by attendee email
- `attendeeName` (`string`, optional): Filter by attendee name
- `beforeCreatedAt` (`string`, optional): Filter bookings created before this ISO 8601 date
- `beforeEnd` (`string`, optional): Filter bookings ending before this ISO 8601 date
- `beforeUpdatedAt` (`string`, optional): Filter bookings updated before this ISO 8601 date
- `bookingUid` (`string`, optional): Filter by booking UID
- `eventTypeId` (`integer`, optional): Filter by event type ID
- `eventTypeIds` (`string`, optional): Comma-separated event type IDs (e.g. '100,200')
- `skip` (`integer`, optional): Results to skip (offset)
- `sortCreated` (`string`, optional): Sort by creation time. One of: `asc`, `desc`.
- `sortEnd` (`string`, optional): Sort by end time. One of: `asc`, `desc`.
- `sortStart` (`string`, optional): Sort by start time. One of: `asc`, `desc`.
- `sortUpdatedAt` (`string`, optional): Sort by updated time. One of: `asc`, `desc`.
- `status` (`string`, optional): Comma-separated statuses: upcoming, recurring, past, cancelled, unconfirmed
- `take` (`integer`, optional): Max results to return (default 100, max 250)
- `teamId` (`integer`, optional): Filter by team ID
- `teamsIds` (`string`, optional): Comma-separated team IDs (e.g. '50,60')

Example input: `{}`

### `calmcp_get_busy_times`

Get Busy Times · Read-only

Get busy/blocked time blocks from a connected calendar (e.g. Google Calendar) between two dates. Returns a list of time ranges when the user is unavailable. Required: dateFrom, dateTo (YYYY-MM-DD), credentialId, and externalId. WORKFLOW: (1) Call get_connected_calendars first to get the real credentialId (number) and externalId (e.g. email) for the calendar — NEVER guess or fabricate these. (2) Provide dateFrom and dateTo as YYYY-MM-DD strings. (3) Optionally pass timeZone (IANA, e.g. 'America/New_York') to localise the results.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `credentialId` (`number`, required): The credential ID of the calendar integration. Use get_connected_calendars to obtain this — never guess.
- `dateFrom` (`string`, required): Start date for the query (e.g. '2024-08-13'). Required.
- `dateTo` (`string`, required): End date for the query (e.g. '2024-08-14'). Required.
- `externalId` (`string`, required): The external calendar ID (e.g. the email address for Google Calendar). Use get_connected_calendars to obtain this — never guess.
- `loggedInUsersTz` (`string`, optional): IANA time zone of the logged-in user (e.g. 'America/New_York'). Used to interpret date boundaries.
- `timeZone` (`string`, optional): IANA time zone for the query (e.g. 'America/New_York'). Defaults to UTC.

Example input: `{"credentialId":1,"dateFrom":"2024-08-13","dateTo":"2024-08-14","externalId":"<externalId>"}`

### `calmcp_get_conferencing_apps`

Get Conferencing Apps · Read-only

List all conferencing applications connected to the authenticated user's account (e.g. Zoom, Google Meet, Cal Video).

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `calmcp_get_connected_calendars`

Get Connected Calendars · Read-only

List all calendar integrations connected to the authenticated user's account. Returns each calendar's credentialId and externalId, which are required by get_busy_times. Also shows the user's destination calendar.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `calmcp_get_default_schedule`

Get Default Schedule · Read-only

Get the authenticated user's default schedule.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `calmcp_get_event_type`

Get Event Type · Read-only

Get a specific event type by its numeric ID (use get_event_types to find IDs). Returns full details including locations, booking fields, and schedule.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `eventTypeId` (`integer`, required): Event type ID. Use get_event_types to find this.

Example input: `{"eventTypeId":1}`

### `calmcp_get_event_types`

Get Event Types · Read-only

List event types. Without parameters returns all event types for the authenticated user. Pass 'username' to list another user's event types, or username + eventSlug for a specific one. Use usernames (comma-separated) for dynamic group event types.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `eventSlug` (`string`, optional): Slug of a specific event type to return. Must be used together with username.
- `orgId` (`number`, optional): Organization ID to filter by (alternative to orgSlug).
- `orgSlug` (`string`, optional): Organization slug to filter by.
- `sortCreatedAt` (`string`, optional): Sort event types by creation date. One of: `asc`, `desc`.
- `username` (`string`, optional): Username of the person whose event types you want to list. Omit to list the authenticated user's event types.
- `usernames` (`string`, optional): Comma-separated usernames for fetching a dynamic group event type (e.g. 'alice,bob').

Example input: `{}`

### `calmcp_get_me`

Get Me · Read-only

Get the authenticated user's profile including username, email, time zone, default schedule, and organizationId. Call this first when you need the user's own details (email, username, organizationId) for other tools.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `calmcp_get_org_membership`

Get Org Membership · Read-only

Get a specific organization membership by its numeric ID.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `membershipId` (`integer`, required): Membership ID. Use get_org_memberships to find this.
- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.

Example input: `{"membershipId":1,"orgId":1}`

### `calmcp_get_org_memberships`

Get Org Memberships · Read-only

List all memberships in an organization. Supports pagination with take/skip.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.
- `skip` (`number`, optional): Results to skip (offset)
- `take` (`number`, optional): Max results to return

Example input: `{"orgId":1}`

### `calmcp_get_org_routing_form_responses`

Get Org Routing Form Responses · Read-only

Get responses for a specific routing form. Supports filtering by date ranges, routed booking UID, and sorting.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.
- `routingFormId` (`string`, required): Routing form ID. Use get_org_routing_forms to find this — never guess.
- `afterCreatedAt` (`string`, optional): Created after (ISO 8601)
- `afterUpdatedAt` (`string`, optional): Updated after (ISO 8601)
- `beforeCreatedAt` (`string`, optional): Created before (ISO 8601)
- `beforeUpdatedAt` (`string`, optional): Updated before (ISO 8601)
- `routedToBookingUid` (`string`, optional): Filter by routed booking UID
- `skip` (`number`, optional): Results to skip
- `sortCreatedAt` (`string`, optional): Sort by created. One of: `asc`, `desc`.
- `sortUpdatedAt` (`string`, optional): Sort by updated. One of: `asc`, `desc`.
- `take` (`number`, optional): Max results

Example input: `{"orgId":1,"routingFormId":"<routingFormId>"}`

### `calmcp_get_org_routing_forms`

Get Org Routing Forms · Read-only

List routing forms for an organization. Supports filtering by team IDs, date ranges, routed booking UID, and sorting.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.
- `afterCreatedAt` (`string`, optional): Created after (ISO 8601)
- `afterUpdatedAt` (`string`, optional): Updated after (ISO 8601)
- `beforeCreatedAt` (`string`, optional): Created before (ISO 8601)
- `beforeUpdatedAt` (`string`, optional): Updated before (ISO 8601)
- `routedToBookingUid` (`string`, optional): Filter by routed booking UID
- `skip` (`number`, optional): Results to skip
- `sortCreatedAt` (`string`, optional): Sort by created. One of: `asc`, `desc`.
- `sortUpdatedAt` (`string`, optional): Sort by updated. One of: `asc`, `desc`.
- `take` (`number`, optional): Max results
- `teamIds` (`array`, optional): Filter by team IDs

Example input: `{"orgId":1}`

### `calmcp_get_schedule`

Get Schedule · Read-only

Get a specific schedule by its numeric ID. Returns availability slots and overrides.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `scheduleId` (`integer`, required): Schedule ID

Example input: `{"scheduleId":1}`

### `calmcp_get_schedules`

Get Schedules · Read-only

List all schedules for the authenticated user.

Read only: yes. Destructive: no. Idempotent (safe to retry): no.

Inputs: none.

Example input: `{}`

### `calmcp_add_booking_attendee`

Add Booking Attendee · Write

Add a new attendee to an existing booking. Required: name, email, timeZone. ASK THE USER for all attendee details — never guess or fabricate names, emails, or time zones.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `bookingUid` (`string`, required): Booking UID
- `email` (`string`, required): Attendee email address. Ask the user — never guess or fabricate.
- `name` (`string`, required): Attendee name. Ask the user — never guess.
- `timeZone` (`string`, required): IANA time zone. Ask the user — never guess.
- `language` (`string`, optional): ISO 639-1 language code (e.g. 'en')
- `phoneNumber` (`string`, optional): Phone in international format. Ask the user — never guess.

Example input: `{"bookingUid":"<bookingUid>","email":"<email>","name":"<name>","timeZone":"America/New_York"}`

### `calmcp_calculate_routing_form_slots`

Calculate Routing Form Slots · Write

Submit a routing form response and get available slots. The response object contains the user's answers (keys are routing form field slugs/IDs). Use get_org_routing_forms to find routingFormId. Start/end must be in UTC ISO 8601.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `end` (`string`, required): Range end in UTC, ISO 8601 (e.g. '2024-08-14' or '2024-08-14T18:00:00Z')
- `response` (`object`, required): Routing form response object. Keys are routing form field IDs, values are the user's answers. Use get_org_routing_forms to discover the form's fields and their IDs. Ask the user for the answer values — never fabricate.
- `routingFormId` (`string`, required): Routing form ID. Use get_org_routing_forms to find this — never guess.
- `start` (`string`, required): Range start in UTC, ISO 8601 (e.g. '2024-08-13' or '2024-08-13T09:00:00Z')
- `bookingUidToReschedule` (`string`, optional): Booking UID being rescheduled — ensures original time appears in available slots
- `duration` (`number`, optional): Desired slot duration in minutes (for variable-duration events)
- `format` (`string`, optional): Slot format: 'range' returns start+end, 'time' returns start only. One of: `range`, `time`.
- `timeZone` (`string`, optional): IANA time zone for returned slots (default UTC)

Example input: `{"end":"2024-08-14","response":{},"routingFormId":"<routingFormId>","start":"2024-08-13"}`

### `calmcp_confirm_booking`

Confirm Booking · Write

Confirm a pending booking that requires manual confirmation. Only the host can confirm.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `bookingUid` (`string`, required): Booking UID

Example input: `{"bookingUid":"<bookingUid>"}`

### `calmcp_create_booking`

Create Booking · Write

Create a booking. WORKFLOW: (1) Use get_event_types to find the event type ID/slug. (2) Call get_availability to find open slots — NEVER pick a time without checking availability first. (3) If using bookingFieldsResponses, call get_event_type first to discover required custom fields. (4) For attendee details (name, email, timeZone), use get_me if booking for yourself, otherwise ASK THE USER — never guess or fabricate attendee info. Identify the event type by: eventTypeId, OR eventTypeSlug + username (individual), OR eventTypeSlug + teamSlug (team). The 'start' time MUST be in UTC ISO 8601. 'username' is the HOST whose calendar you are booking. 'attendee' is the GUEST (the caller).

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `attendee` (`object`, required): Attendee details — the person making the booking (the guest/caller), NOT the host. To book another user's calendar, set their username in the 'username' field and put YOUR (the caller's) details here. NEVER guess or fabricate email addresses — ask the user if unknown.
- `start` (`string`, required): Start time in UTC, ISO 8601 (e.g. 2024-08-13T09:00:00Z). Must be UTC.
- `allowBookingOutOfBounds` (`boolean`, optional): If true and the authenticated user is a host, allow booking outside the configured scheduling window (e.g. before minimumBookingNotice or beyond the booking window). Ignored for non-hosts.
- `allowConflicts` (`boolean`, optional): If true and the authenticated user is a host, skip availability conflict checks. Ignored for non-hosts.
- `bookingFieldsResponses` (`object`, optional): Custom booking field responses as {slug: value} pairs
- `eventTypeId` (`integer`, optional): Event type ID. Required unless eventTypeSlug + username (or teamSlug) are provided.
- `eventTypeSlug` (`string`, optional): Event type slug (e.g. '15min'). Must be combined with username (for individual) or teamSlug (for team).
- `guests` (`array`, optional): Additional guest emails to include. Ask the user for guest emails — never guess or fabricate.
- `lengthInMinutes` (`integer`, optional): Desired booking length for variable-duration event types. Uses event type default if omitted.
- `location` (`object`, optional): Meeting location override as an object. Must match one of the event type's configured location types: {type:'integration',integration:'cal-video'|'google-meet'|'zoom'|...}, {type:'attendeePhone',phone:'+...'}, {type:'attendeeAddress',address:'...'}, {type:'attendeeDefined',location:'...'}, {type:'address'}, {type:'link'}, {type:'phone'}, or {type:'organizersDefaultApp'} (team events only).
- `metadata` (`object`, optional): Metadata key-value pairs (max 50 keys, keys ≤40 chars, string values ≤500 chars)
- `organizationSlug` (`string`, optional): Organization slug, needed when the user/team is within an organization.
- `teamSlug` (`string`, optional): Team slug. Required with eventTypeSlug for team event types.
- `username` (`string`, optional): Username of the host whose calendar you are booking on. Required with eventTypeSlug for individual event types.

Example input: `{"attendee":{},"start":"2024-08-13"}`

### `calmcp_create_event_type`

Create Event Type · Write

Create a new event type. Required: title, slug, lengthInMinutes. Supports locations, booking fields, buffers, recurrence, confirmation policy, seats, and more.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `lengthInMinutes` (`integer`, required): Duration in minutes
- `slug` (`string`, required): URL-friendly slug (e.g. '30min')
- `title` (`string`, required): Event type title
- `afterEventBuffer` (`integer`, optional): Minutes blocked on calendar after the meeting ends.
- `beforeEventBuffer` (`integer`, optional): Minutes blocked on calendar before the meeting starts.
- `bookingFields` (`array`, optional): Custom fields added to the booking form. Each object defines a field with properties like name, type, label, required, etc.
- `bookingLimitsCount` (`object`, optional): Limit how many times this event can be booked per period (e.g. {day: 2, week: 5}).
- `bookingWindow` (`object`, optional): Limit how far in the future this event can be booked.
- `confirmationPolicy` (`object`, optional): Manual confirmation policy. Controls whether bookings require host confirmation.
- `customName` (`string`, optional): Custom event name template with variables: {Event type title}, {Organiser}, {Scheduler}, {Location}.
- `description` (`string`, optional): Description shown on the booking page
- `destinationCalendar` (`object`, optional): Which external calendar new bookings are added to.
- `disableGuests` (`boolean`, optional): If true, bookers cannot add guest emails.
- `hidden` (`boolean`, optional): Whether the event type is hidden from the public profile.
- `hideCalendarNotes` (`boolean`, optional): Hide calendar notes from the booking.
- `lengthInMinutesOptions` (`array`, optional): Multiple duration options the attendee can choose from (e.g. [15, 30, 60]). If provided, the booker picks their preferred duration.
- `locations` (`array`, optional): Locations where the event takes place. If not provided, Cal Video is used. Each element is a location object (e.g. {type: 'inPerson', address: '...'}). Note: setting a conferencing app as location requires the app to already be installed.
- `lockTimeZoneToggleOnBookingPage` (`boolean`, optional): Lock the timezone on the booking page.
- `minimumBookingNotice` (`integer`, optional): Minimum minutes before the event that a booking can be made.
- `offsetStart` (`integer`, optional): Offset timeslots shown to bookers by a specified number of minutes.
- `onlyShowFirstAvailableSlot` (`boolean`, optional): Limit availability to one slot per day (the earliest available).
- `recurrence` (`object`, optional): Recurrence settings to create a recurring event type (e.g. {frequency: 'weekly', interval: 1, occurrences: 12}).
- `requiresBookerEmailVerification` (`boolean`, optional): Whether booker must verify their email before the booking is confirmed.
- `scheduleId` (`integer`, optional): Use a specific schedule instead of the user's default. Use get_schedules to find schedule IDs.
- `seats` (`object`, optional): Enable seated events. Object with seatsPerTimeSlot and other seat settings.
- `slotInterval` (`integer`, optional): Length of each slot in minutes. Defaults to the event duration.
- `successRedirectUrl` (`string`, optional): URL to redirect the booker to after a successful booking.

Example input: `{"lengthInMinutes":1,"slug":"30min","title":"<title>"}`

### `calmcp_create_org_membership`

Create Org Membership · Write

Add a user to an organization. Required: userId (must be a real user ID from the system) and role (MEMBER, ADMIN, or OWNER). Platform managed users should only have MEMBER role.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.
- `role` (`string`, required): Role (managed users: MEMBER only). One of: `MEMBER`, `OWNER`, `ADMIN`.
- `userId` (`number`, required): User ID of the person to add. Must be a real user ID — ask the user for this, never guess.
- `accepted` (`boolean`, optional): Whether accepted
- `disableImpersonation` (`boolean`, optional): Disable impersonation

Example input: `{"orgId":1,"role":"MEMBER","userId":1}`

### `calmcp_create_schedule`

Create Schedule · Write

Create a new schedule. Required: name, timeZone, isDefault. Each user should have exactly one default schedule. Supports availability slots and date-specific overrides.

Read only: no. Destructive: no. Idempotent (safe to retry): no.

Inputs:

- `isDefault` (`boolean`, required): Whether this is the user's default schedule. Each user should have exactly one default schedule.
- `name` (`string`, required): Schedule name
- `timeZone` (`string`, required): IANA time zone used to calculate available times (e.g. America/New_York)
- `availability` (`array`, optional): Availability slots. If not provided, defaults to Mon-Fri 09:00-17:00.
- `overrides` (`array`, optional): Date-specific overrides. Use to change availability for a specific date or mark it as unavailable.

Example input: `{"isDefault":true,"name":"<name>","timeZone":"America/New_York"}`

### `calmcp_mark_booking_absent`

Mark Booking Absent · Write

Mark host or attendees as absent for a past booking. Set host=true if the host was absent. Use get_booking_attendees to look up real attendee emails before calling this.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `bookingUid` (`string`, required): Booking UID
- `attendees` (`array`, optional): Attendees with absent status. Use real attendee emails from the booking.
- `host` (`boolean`, optional): Whether the host was absent

Example input: `{"bookingUid":"<bookingUid>"}`

### `calmcp_reschedule_booking`

Reschedule Booking · Write

Reschedule a booking to a new time. WORKFLOW: (1) Call get_availability to find open slots — NEVER pick a new time without checking availability first. (2) The new start time must be in UTC ISO 8601. rescheduledBy is only needed for confirmation-required bookings — use the event owner's email (from get_me) for auto-confirmation. Never fabricate emails.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `bookingUid` (`string`, required): Booking UID
- `start` (`string`, required): New start time in UTC, ISO 8601 (e.g. 2024-08-13T09:00:00Z)
- `rescheduledBy` (`string`, optional): Only needed when rescheduling a booking that requires confirmation. If the event owner's email is provided, the rescheduled booking is auto-confirmed; otherwise the owner must confirm. Use get_me to get the authenticated user's email — never fabricate.
- `reschedulingReason` (`string`, optional): Reason for rescheduling

Example input: `{"bookingUid":"<bookingUid>","start":"2024-08-13"}`

### `calmcp_update_event_type`

Update Event Type · Write

Update an existing event type by ID (use get_event_types to find IDs). Any provided field replaces the current value. Array fields (locations, bookingFields) replace entirely — fetch the current event type first with get_event_type to avoid losing existing values.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `eventTypeId` (`integer`, required): Event type ID to update. Use get_event_types to find this.
- `afterEventBuffer` (`integer`, optional): Minutes blocked on calendar after the meeting.
- `beforeEventBuffer` (`integer`, optional): Minutes blocked on calendar before the meeting.
- `bookingFields` (`array`, optional): Updated booking fields array. Replaces ALL existing booking fields. To modify fields, first fetch the current event type with get_event_type, then include all desired fields here.
- `bookingLimitsCount` (`object`, optional): Limit how many times this event can be booked per period (e.g. {day: 2, week: 5}).
- `bookingWindow` (`object`, optional): Limit how far in the future this event can be booked.
- `confirmationPolicy` (`object`, optional): Manual confirmation policy settings.
- `customName` (`string`, optional): Custom event name template.
- `description` (`string`, optional): New description
- `destinationCalendar` (`object`, optional): Which external calendar new bookings are added to.
- `disableGuests` (`boolean`, optional): If true, bookers cannot add guest emails.
- `hidden` (`boolean`, optional): Whether the event type is hidden.
- `hideCalendarNotes` (`boolean`, optional): Hide calendar notes.
- `lengthInMinutes` (`integer`, optional): New duration in minutes
- `lengthInMinutesOptions` (`array`, optional): Multiple duration options the attendee can choose from (e.g. [15, 30, 60]). If provided, the booker picks their preferred duration.
- `locations` (`array`, optional): Updated locations array. Replaces all existing locations.
- `lockTimeZoneToggleOnBookingPage` (`boolean`, optional): Lock timezone on booking page.
- `minimumBookingNotice` (`integer`, optional): Minimum minutes before event that a booking can be made.
- `offsetStart` (`integer`, optional): Offset timeslots by specified minutes.
- `onlyShowFirstAvailableSlot` (`boolean`, optional): Show only the earliest available slot per day.
- `recurrence` (`object`, optional): Recurrence settings (e.g. {frequency: 'weekly', interval: 1, occurrences: 12}).
- `requiresBookerEmailVerification` (`boolean`, optional): Whether booker must verify their email.
- `scheduleId` (`integer`, optional): Schedule ID to use instead of default. Use get_schedules to find schedule IDs.
- `seats` (`object`, optional): Seated event settings.
- `slotInterval` (`integer`, optional): Length of each slot in minutes.
- `slug` (`string`, optional): New URL-friendly slug
- `successRedirectUrl` (`string`, optional): Redirect URL after successful booking.
- `title` (`string`, optional): New title

Example input: `{"eventTypeId":1}`

### `calmcp_update_me`

Update Me · Write

Update the authenticated user's profile. Supports name, email, bio, time zone, week start, time format, default schedule, locale, avatar URL, and custom metadata.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `avatarUrl` (`string`, optional): URL of the user's avatar image
- `bio` (`string`, optional): Short biography or description
- `defaultScheduleId` (`integer`, optional): ID of the default schedule to use for event types
- `email` (`string`, optional): Email address
- `locale` (`string`, optional): Locale / language code (e.g. 'en', 'fr', 'de')
- `metadata` (`object`, optional): Custom metadata key-value pairs (max 50 keys, keys ≤40 chars, string values ≤500 chars)
- `name` (`string`, optional): Display name
- `timeFormat` (`integer`, optional): Time format: 12 or 24
- `timeZone` (`string`, optional): IANA time zone (e.g. America/New_York)
- `weekStart` (`string`, optional): Week start day (e.g. Monday, Sunday)

Example input: `{}`

### `calmcp_update_org_membership`

Update Org Membership · Write

Update an organization membership. Can change role, accepted status, or impersonation settings.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `membershipId` (`integer`, required): Membership ID. Use get_org_memberships to find this.
- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.
- `accepted` (`boolean`, optional): Whether accepted
- `disableImpersonation` (`boolean`, optional): Disable impersonation
- `role` (`string`, optional): New role. One of: `MEMBER`, `OWNER`, `ADMIN`.

Example input: `{"membershipId":1,"orgId":1}`

### `calmcp_update_schedule`

Update Schedule · Write

Update an existing schedule. Array fields (availability, overrides) replace all existing entries.

Read only: no. Destructive: no. Idempotent (safe to retry): yes.

Inputs:

- `scheduleId` (`integer`, required): Schedule ID
- `availability` (`array`, optional): New availability slots. Replaces all existing slots.
- `isDefault` (`boolean`, optional): Set as the user's default schedule.
- `name` (`string`, optional): New name
- `overrides` (`array`, optional): Date-specific overrides. Replaces all existing overrides.
- `timeZone` (`string`, optional): New IANA time zone

Example input: `{"scheduleId":1}`

### `calmcp_cancel_booking`

Cancel Booking · Destructive

Cancel a booking by UID. For recurring non-seated bookings, set cancelSubsequentBookings=true to cancel future recurrences. For seated bookings, pass seatUid to cancel a specific seat instead of the entire booking. Confirm with the user before cancelling.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `bookingUid` (`string`, required): Booking UID
- `cancellationReason` (`string`, optional): Reason for cancellation
- `cancelSubsequentBookings` (`boolean`, optional): For recurring non-seated bookings only: if true, also cancels all subsequent recurrences after this one.
- `seatUid` (`string`, optional): UID of the specific seat to cancel within a seated booking. Required when cancelling an individual seat instead of the entire booking.

Example input: `{"bookingUid":"<bookingUid>"}`

### `calmcp_delete_event_type`

Delete Event Type · Destructive

Permanently delete an event type by ID. This action is irreversible — confirm with the user before proceeding.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `eventTypeId` (`integer`, required): Event type ID to delete. Use get_event_types to find this.

Example input: `{"eventTypeId":1}`

### `calmcp_delete_org_membership`

Delete Org Membership · Destructive

Remove a membership from an organization. This action is irreversible — confirm with the user before proceeding.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `membershipId` (`integer`, required): Membership ID. Use get_org_memberships to find this.
- `orgId` (`integer`, required): Organization ID. Use get_me to obtain your organizationId — never guess.

Example input: `{"membershipId":1,"orgId":1}`

### `calmcp_delete_schedule`

Delete Schedule · Destructive

Delete a schedule by its numeric ID. This action is irreversible — confirm with the user before proceeding.

Read only: no. Destructive: yes. Idempotent (safe to retry): yes.

Inputs:

- `scheduleId` (`integer`, required): Schedule ID

Example input: `{"scheduleId":1}`

## Related

Other Calendar connectors ([all 13](/agentkit/connectors/?category=calendar)):

- [Google Calendar](/agentkit/connectors/googlecalendar/): Scalekit connector, OAuth, 30 tools
- [Microsoft 365](/agentkit/connectors/microsoft365/): Scalekit connector, OAuth, 317 tools
- [Outlook](/agentkit/connectors/outlook/): Scalekit connector, OAuth, 126 tools


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
