Building Your First AI Scheduling Agent with Temporal Cortex
This tutorial walks through building a working AI scheduling agent — from zero to a booked meeting — using Temporal Cortex and any MCP-compatible AI client (Claude Desktop, VS Code with Copilot, Cursor, or the Claude CLI).
What you’ll build
By the end of this guide, your AI agent will be able to:
- Know the current time, timezone, and DST status
- Resolve natural language like “next Tuesday at 2pm” to precise timestamps
- List your calendars across Google, Outlook, and iCloud
- Find free slots in your schedule
- Book a meeting without double-booking
Step 1: Install the MCP server
npx @temporal-cortex/cortex-mcp
This downloads a native binary for your platform (macOS, Linux, or Windows) and runs the setup wizard. The wizard handles timezone detection, week-start preference, and telemetry consent.
No account required. No Docker. No infrastructure.
Step 2: Connect a calendar provider
npx @temporal-cortex/cortex-mcp auth google
This opens OAuth in your browser. Grant calendar access, and the credentials are stored locally at ~/.config/temporal-cortex/. Temporal Cortex supports three providers — run the auth command for each one you want to connect:
npx @temporal-cortex/cortex-mcp auth google # Google Calendar
npx @temporal-cortex/cortex-mcp auth outlook # Microsoft Outlook
npx @temporal-cortex/cortex-mcp auth caldav # iCloud, Fastmail, etc.
You can connect multiple providers simultaneously. The agent will see all of them.
Step 3: Configure your AI client
Add the MCP server to your client’s configuration. Here’s the JSON for Claude Desktop (paste into claude_desktop_config.json):
{
"mcpServers": {
"temporal-cortex": {
"command": "npx",
"args": ["-y", "@temporal-cortex/cortex-mcp"]
}
}
}
For Claude Code (CLI):
claude mcp add temporal-cortex -- npx -y @temporal-cortex/cortex-mcp
For VS Code, Cursor, or Windsurf, add to your workspace settings (.vscode/mcp.json):
{
"servers": {
"temporal-cortex": {
"command": "npx",
"args": ["-y", "@temporal-cortex/cortex-mcp"]
}
}
}
Restart your AI client. You should see 15 new tools available.
Step 4: The 5-step scheduling workflow
Now ask your agent to schedule a meeting. Behind the scenes, it follows this workflow:
Discover: What calendars are connected?
The agent calls list_calendars to see all connected providers:
// Tool call
{ }
// Response
{
"content": [
{ "id": "google/primary", "provider": "google", "name": "My Calendar", "label": "Work" },
{ "id": "outlook/calendar-uuid", "provider": "outlook", "name": "Calendar", "label": "Personal" }
],
"total": 2
}
Each calendar has a provider-prefixed ID (google/primary, outlook/calendar-uuid). This disambiguates when the same account appears in multiple providers.
Orient: What time is it?
The agent calls get_temporal_context to ground itself in the current time:
// Tool call
{ }
// Response
{
"utc": "2026-03-16T18:30:00+00:00",
"local": "2026-03-16T14:30:00-04:00",
"timezone": "America/New_York",
"day_of_week": "Monday",
"dst_active": true,
"next_dst_transition": "2026-11-01T06:00:00+00:00",
"next_dst_direction": "fall-back"
}
This is critical. Without it, the agent might assume UTC or a timezone from its training data. With it, “next Tuesday at 2pm” is unambiguous.
Resolve: Turn natural language into timestamps
The agent calls resolve_datetime with the user’s expression:
// Tool call
{ "expression": "next Tuesday at 2pm" }
// Response
{
"resolved_utc": "2026-03-17T18:00:00+00:00",
"resolved_local": "2026-03-17T14:00:00-04:00",
"timezone": "America/New_York",
"interpretation": "Tuesday, March 17, 2026 at 2:00 PM"
}
“Next Tuesday” is computed from the current date, not guessed. “2pm” is in the user’s configured timezone, not UTC. The interpretation field gives the agent a human-readable confirmation to show the user.
Query: Is that time free?
The agent calls get_availability to check across all calendars:
// Tool call
{
"start": "2026-03-17T18:00:00+00:00",
"end": "2026-03-17T18:30:00+00:00",
"calendar_ids": ["google/primary", "outlook/calendar-uuid"]
}
// Response
{
"busy": [],
"free": [
{ "start": "2026-03-17T18:00:00+00:00", "end": "2026-03-17T18:30:00+00:00", "duration_minutes": 30 }
],
"calendars_merged": 2
}
The slot is free across both calendars. If it were busy on either one, the agent would see it here — even if the busy event is on a different provider than the one being booked.
Act: Book the meeting
The agent calls book_slot with Two-Phase Commit:
// Tool call
{
"calendar_id": "google/primary",
"start": "2026-03-17T18:00:00+00:00",
"end": "2026-03-17T18:30:00+00:00",
"summary": "Meeting with Alice",
"attendees": ["[email protected]"]
}
// Response
{
"success": true,
"event_id": "abc123",
"booking_id": "def456",
"summary": "Meeting with Alice",
"start": "2026-03-17T18:00:00+00:00",
"end": "2026-03-17T18:30:00+00:00"
}
The 2PC flow ran behind the scenes: lock acquired, no conflicts found, event created in Google Calendar, lock released. If another agent had tried to book the same slot simultaneously, one would succeed and the other would get a conflict error with instructions to find alternative times.
For scenarios where you’re scheduling with external participants who don’t have agents, the compose_proposal tool generates a shareable booking link instead of directly writing to a calendar. This provides a backward-compatible path — the recipient clicks a link and picks a time, no agent required.
What if the slot is busy?
If get_availability returns a busy period, the agent can call find_free_slots to suggest alternatives:
// Tool call
{
"calendar_id": "google/primary",
"start": "2026-03-17T12:00:00-04:00",
"end": "2026-03-17T18:00:00-04:00",
"min_duration_minutes": 30
}
// Response
{
"slots": [
{ "start": "2026-03-17T16:30:00+00:00", "end": "2026-03-17T18:00:00+00:00", "duration_minutes": 90 },
{ "start": "2026-03-17T19:00:00+00:00", "end": "2026-03-17T22:00:00+00:00", "duration_minutes": 180 }
],
"count": 2
}
The agent presents these alternatives to the user and books whichever they choose.
Adding the Agent Skill
The MCP server gives your agent the tools. The Agent Skill teaches it the correct workflow. Install both:
npx @temporal-cortex/cortex-mcp # 18 MCP tools
npx skills add temporal-cortex/skills # Procedural knowledge
The Skill teaches the agent to always call get_temporal_context first, to resolve datetimes before querying calendars, and to check availability before booking. Without the Skill, agents may skip steps or call tools in the wrong order.
Next steps
- Connect multiple providers to see unified availability across Google + Outlook + iCloud
- Try RRULE expansion — ask your agent “when does our biweekly standup happen for the rest of the quarter?”
- Explore the full tool reference at /docs for all 18 tools with parameters and examples
- Read about the Truth Engine to understand why RRULE expansion needs deterministic computation, not LLM inference
- Learn why scheduling is infrastructure — not just a feature — in Scheduling Is Infrastructure