Cal MCP

Live

OAUTH 2.0

CALENDAR

Calendar

Let your agent check availability, book meetings, and reschedule events as the real person who owns the Cal.com calendar.

  • Acts as the owner. Every booking and reschedule is attributed to the real user, not a shared scheduling bot.
  • Tokens stay vaulted. Cal.com OAuth credentials sit in an AES-256 vault, resolved per request, never in the prompt.
  • Scoped before every call. Calendar and event-type scopes enforced ahead of each API call, with a 90-day audit trail.
Cal MCP
agent · Acme Q3
Run
Find me a 30-minute slot with Priya next week and book it.
S
cal_availability_get
88ms
Cal agent
Priya is free Tuesday 2:00pm and Thursday 10:30am. I booked the Tuesday 2:00pm slot as a 30-minute intro call and sent both of you a confirmation.
Sources: availability, intro-call event type, next 7 days
calmcp
1 booking
18:29
Message Claude...

Tools your scheduling agent reaches for on Cal.com, scoped per user.

CALL ANY TOOL
Check availability, create and reschedule bookings, list event types, and cancel meetings, each call scoped to the authenticated user's own calendar access.
cal_availability_get
Get availability
Return open time slots for a user or event type across a date range, respecting buffers and booking limits.
Parameters
Name
Type
Required
Description
event_type_id
integer
Optional
Event type to check availability for
date_from
string
Required
Start of the date range in ISO 8601
date_to
string
Required
End of the date range in ISO 8601
cal_bookings_list
List bookings
cal_booking_create
Create booking
cal_booking_reschedule
Reschedule booking
cal_booking_cancel
Cancel booking
cal_event_types_list
List event types
Build your Agent
The same per-user auth pattern wires into every agent framework.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
filter: { connectionNames: ["calmcp"], toolNames: ["cal_availability_get", "cal_bookings_list", "cal_booking_create"] },
pageSize: 100,
});

const agent = createReactAgent({ llm: new ChatOpenAI({ model: "gpt-4o" }), tools });
await agent.invoke({ messages: [{ role: "user", content: "Book a 30-minute intro call next week" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const openai = new OpenAI();
const sk = new ScalekitClient(process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
filter: { connectionNames: ["calmcp"], toolNames: ["cal_availability_get", "cal_bookings_list", "cal_booking_create"] },
pageSize: 100,
});

const res = await openai.responses.create({
model: "gpt-4o",
input: "Find an open slot with Priya and book it",
tools,
});
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const anthropic = new Anthropic();
const sk = new ScalekitClient(process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
filter: { connectionNames: ["calmcp"], toolNames: ["cal_availability_get", "cal_bookings_list", "cal_booking_create"] },
pageSize: 100,
});

const msg = await anthropic.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
tools,
messages: [{ role: "user", content: "Reschedule my Thursday call to next Monday" }],
});
import { LlmAgent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
filter: { connectionNames: ["calmcp"], toolNames: ["cal_availability_get", "cal_bookings_list", "cal_booking_create"] },
pageSize: 100,
});

const agent = new LlmAgent({ name: "cal_agent", model: "gemini-2.0-flash", tools });
await agent.run("List my upcoming bookings this week");
Try these prompts
Paste any prompt into your agent to start managing Cal.com bookings.
Book & schedule
Copy the prompt
Copied
Find me a 30-minute slot with Priya next week and book it.
Copy the prompt
Copied
Book a discovery call with acme@example.com on Thursday afternoon.
Copy the prompt
Copied
Check my open slots for the intro-call event type next week.
Manage bookings
Copy the prompt
Copied
Reschedule my Thursday 3pm call to next Monday morning.
Copy the prompt
Copied
Cancel the demo booking with globex@example.com and let them know.
Copy the prompt
Copied
Move all my Friday meetings back by 30 minutes.
Report & recall
Copy the prompt
Copied
List all my upcoming bookings this week.
Copy the prompt
Copied
Which event types do I currently offer?
Copy the prompt
Copied
How many meetings did I have last month?
SEE HOW AUTH WORKS
The user authorises Cal.com once. Every later agent call uses their token with calendar scope enforced.
1
Authorize
Your user connects
Cal MCP
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Cal MCP
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Cal MCP
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Cal MCP
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other calendar connectors.
OPS
Email-to-calendar scheduling agent
Parse scheduling intent from Gmail threads and create Google Calendar events with the right attendees and timezone.
SALES
Sales call prep agent
Pull Granola notes and Attio contact history to draft a pre-call brief before every sales meeting. Zero rep input.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
Other connector libraries treat auth as a demo afterthought. Calendar data needs real per-user attribution.
01.
Shared tokens break per-user analytics
A shared Cal.com token looks fine in a demo. In production every booking and cancel logs as one service account, so you lose track of whose calendar was touched. Scalekit resolves the real user's credential per call.
// shared token
book → scheduling_bot

// scalekit
book → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Cal today. Others tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Cal.com as the user or as a shared key?
As the user. Scalekit resolves the authenticated user's own Cal.com credential at request time, so every booking, reschedule, and cancel is attributed to them in Cal.com rather than a shared scheduling bot.
Where is the Cal.com token stored?
In an AES-256 encrypted vault, namespaced per tenant. Tokens are fetched only at the moment of a tool call, refreshed automatically before expiry, and revocable from a single dashboard, never exposed to the model or the prompt.
Can I limit what the agent is allowed to do in Cal.com?
Yes. Pass a toolNames filter to listScopedTools to expose only the actions you want, for example read-only availability and booking lists without create or cancel. Scalekit also runs a scope check before each API call.
What happens when a user revokes Cal.com access?
The credential is invalidated at the next tool call, which fails closed rather than falling back to a shared token. Other users are unaffected, and the revocation is recorded in the audit trail.
Can the agent book meetings across time zones and event types?
Yes. Availability is resolved against the user's own working hours, buffers, and booking limits, and Cal.com handles timezone detection for each attendee. You choose which event types the agent can book by scoping the toolNames and event type IDs it receives.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""calmcp"": {
""url"": ""https://mcp.scalekit.com/calmcp"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.calmcp]
url = ""https://mcp.scalekit.com/calmcp""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""calmcp"": {
""url"": ""https://mcp.scalekit.com/calmcp"",
""type"": ""http""
}
}
}