Skip to main content
Glama
DRITI2906
by DRITI2906

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

Related MCP server: MCP Personal Calendar

โœจ 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: until parameter (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 cancellations table

  • Safety limits: Max 1000 instances per query to prevent DOS

๐Ÿ”’ Idempotency

Prevents duplicate events from retries:

  • Optional idempotency_key parameter in calendar.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_utc and idempotency_key for 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

  1. No Sync: Events are stored locally only. No Google Calendar / Outlook sync.

  2. No Notifications: Server doesn't send reminders or alerts.

  3. Recurrence Complexity: Only supports simple rules (no "2nd Tuesday of month").

  4. Performance: Recurrence expansion is brute-force iteration (acceptable for <1000 instances).

  5. 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

F
license - not found
-
quality - not tested
D
maintenance

Maintenance

โ€“Maintainers
โ€“Response time
โ€“Release cycle
โ€“Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DRITI2906/Calendar-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server