Calendar MCP Server
A production-quality MCP server for calendar management with robust timezone handling, recurrence support, and idempotency guarantees.
README
MCP Calendar Server
A production-quality Model Context Protocol (MCP) server for calendar management with robust timezone handling, recurrence support, and idempotency guarantees.
๐ฏ What is MCP?
The Model Context Protocol is a standardized way for AI agents (like Claude, ChatGPT, etc.) to interact with external tools and data sources. This server exposes calendar operations as MCP tools, allowing AI assistants to:
- Create events with timezone-aware scheduling
- List events with automatic recurrence expansion
- Cancel individual instances or entire event series
โจ Features
๐ Timezone Correctness (Top Priority)
Timezone handling is notoriously difficult. Here's how we handle it:
- Storage: All events stored in UTC (source of truth)
- Input: Accept ISO 8601 datetime + IANA timezone (e.g.,
"Asia/Kolkata") - Output: Return events in their original timezone
- DST Handling: Recurrence expansion happens in local time to preserve wall-clock semantics (e.g., "9 AM daily" stays at 9 AM even across DST transitions)
- Library: Uses Luxon for robust timezone math
Why UTC Storage?
- Single source of truth
- No ambiguity during DST transitions
- Easy comparison and sorting
- Portable across systems
Why Original Timezone Matters?
- Preserves user intent ("9 AM in Kolkata" not "3:30 AM UTC")
- Correct recurrence expansion (daily meetings stay at same wall time)
๐ Recurrence Support
Supports repeating events with:
- Frequencies:
daily,weekly,monthly - Intervals: Every N days/weeks/months (e.g., "every 2 weeks")
- End Dates:
untilparameter (ISO 8601)
Implementation Design:
- Recurrence rules stored as JSON in the database
- Virtual instances generated on-demand during
calendar.list - No duplicate rows for recurring events
- Cancel individual instances via
cancellationstable - Safety limits: Max 1000 instances per query to prevent DOS
๐ Idempotency
Prevents duplicate events from retries:
- Optional
idempotency_keyparameter incalendar.create - If key exists, returns existing event (no duplicate created)
- Unique constraint enforced at database level
๐พ Storage
Uses SQLite with better-sqlite3:
- Synchronous API: Simpler, more reliable than async
- WAL Mode: Better concurrency
- Schema:
events: Core event data (title, start_utc, duration, timezone, recurrence)cancellations: Tracks cancelled instances of recurring events- Indexes on
start_utcandidempotency_keyfor performance
๐ฆ Installation
# Clone or navigate to project directory
cd calender-mcp
# Install dependencies
npm install
# Build TypeScript
npm run build
๐ Usage
Running the Server
npm start
The server runs on stdio (standard input/output) as per MCP specification.
Configuring with Claude Desktop
Add to your Claude Desktop config (claude_desktop_config.json):
{
"mcpServers": {
"calendar": {
"command": "node",
"args": ["C:/path/to/calender-mcp/dist/index.js"]
}
}
}
Example Tool Calls
1. Create a Simple Event
{
"tool": "calendar.create",
"arguments": {
"title": "Team Standup",
"start": "2026-01-20T09:00:00",
"end": "2026-01-20T09:30:00",
"tz": "Asia/Kolkata"
}
}
2. Create a Recurring Event
{
"tool": "calendar.create",
"arguments": {
"title": "Weekly Review",
"start": "2026-01-20T15:00:00",
"end": "2026-01-20T16:00:00",
"tz": "America/New_York",
"recurrence": {
"freq": "weekly",
"interval": 1,
"until": "2026-06-30T23:59:59"
},
"idempotency_key": "weekly-review-2026"
}
}
3. List Events
{
"tool": "calendar.list",
"arguments": {
"range_start": "2026-01-20T00:00:00Z",
"range_end": "2026-01-27T00:00:00Z"
}
}
4. Cancel an Entire Event Series
{
"tool": "calendar.cancel",
"arguments": {
"event_id": "abc-123-def-456"
}
}
5. Cancel a Specific Instance
{
"tool": "calendar.cancel",
"arguments": {
"event_id": "abc-123-def-456",
"instance_start_utc": "2026-01-27T10:00:00.000Z"
}
}
๐๏ธ Architecture
src/
โโโ index.ts # MCP server setup & tool registration
โโโ storage/
โ โโโ db.ts # SQLite schema & connection
โโโ time/
โ โโโ timezone.ts # UTC conversion utilities (Luxon)
โโโ recurrence/
โ โโโ expand.ts # Recurrence expansion logic
โโโ tools/
โโโ create.ts # calendar.create handler
โโโ list.ts # calendar.list handler
โโโ cancel.ts # calendar.cancel handler
๐งช Testing
Create a test script (test.mjs):
import { spawn } from 'child_process';
const server = spawn('node', ['dist/index.js']);
// Send MCP request
const request = {
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: {
name: 'calendar.create',
arguments: {
title: 'Test Event',
start: '2026-01-20T10:00:00',
end: '2026-01-20T11:00:00',
tz: 'UTC'
}
}
};
server.stdin.write(JSON.stringify(request) + '\n');
server.stdout.on('data', (data) => {
console.log('Response:', data.toString());
});
Run: node test.mjs
๐ง Known Limitations
- No Sync: Events are stored locally only. No Google Calendar / Outlook sync.
- No Notifications: Server doesn't send reminders or alerts.
- Recurrence Complexity: Only supports simple rules (no "2nd Tuesday of month").
- Performance: Recurrence expansion is brute-force iteration (acceptable for <1000 instances).
- No Conflict Detection: Doesn't prevent overlapping events.
๐ฎ Future Extensions
- Calendar Sync: Integrate with Google Calendar API, Microsoft Graph
- Notifications: Email/SMS reminders via Twilio, SendGrid
- Search: Full-text search on event titles/notes
- Attachments: Store files/links with events
- Attendees: Multi-user support with invitations
- Conflict Detection: Warn about overlapping events
- Advanced Recurrence: RRULE support (RFC 5545)
๐ Design Decisions
Why Luxon over Moment/Date-fns?
- Immutable: Safer API, no accidental mutations
- IANA Timezone Support: Built-in, no extra plugins
- Modern: Active development, ESM-first
Why SQLite over JSON Files?
- ACID Guarantees: Atomic writes, no corruption
- Indexes: Fast lookups on
start_utc,idempotency_key - Constraints: Unique keys enforced at DB level
- Scalability: Handles thousands of events efficiently
Why Virtual Instances for Recurrence?
- Storage Efficiency: One row instead of hundreds
- Flexibility: Change recurrence rule retroactively
- Cancellations: Track exceptions cleanly
๐ License
ISC
Built with โค๏ธ for the MCP ecosystem
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.