Skip to content

roygabriel/mcp-icloud-calendar

Repository files navigation

iCloud Calendar MCP Server

A Model Context Protocol server that gives AI assistants full access to Apple iCloud Calendar through CalDAV. List calendars, search events, create, update, and delete events -- all from Claude or any MCP-compatible client.

Built with Go and the mcp-go SDK. Ships as a single static binary for Linux, macOS, and Windows.


Table of Contents


Features

Calendar Operations

  • List all iCloud calendars with paths, names, descriptions, and colors
  • Search events with date range filters and pagination
  • Create events with title, time, description, location, and attendees
  • Update individual fields on existing events (partial update with pointer fields)
  • Delete events permanently

Recurring Events & Attendees

  • Expand recurring events (RRULE) into individual occurrences within a date range
  • Manage attendees with roles (CHAIR, REQ-PARTICIPANT, OPT-PARTICIPANT) and statuses

Multi-Account Support

  • Manage multiple iCloud accounts from a single server instance
  • Configure via ACCOUNTS_FILE JSON or single-account environment variables
  • Per-account rate limiting and retry logic

Operational

  • Structured JSON logging with UUID request correlation
  • Configurable timeout middleware on every tool call (default 25s)
  • Automatic retry with exponential backoff for transient failures
  • Rate limiting per account to avoid iCloud throttling
  • Health endpoint (/healthz, /readyz) and Prometheus metrics (/metrics)
  • Audit logging for mutating operations (no PII)
  • Input validation for all tool parameters
  • MCP tool annotations (read-only, destructive, idempotent) for client-side safety
  • Graceful shutdown on SIGTERM/SIGINT
  • mTLS and custom CA support for enterprise deployments
  • file:// credential loading for Docker/Kubernetes secrets
  • CI pipeline with tests, linting, and vulnerability scanning

Quick Start

# Install
go install github.com/rgabriel/mcp-icloud-calendar@latest

# Set credentials (app-specific password, not your main iCloud password)
export ICLOUD_EMAIL="you@icloud.com"
export ICLOUD_PASSWORD="xxxx-xxxx-xxxx-xxxx"

# Run
mcp-icloud-calendar

Or download a prebuilt binary from the Releases page.


Prerequisites

  • Go 1.21+ -- install (only needed when building from source)
  • iCloud account with two-factor authentication enabled
  • App-specific password -- required for CalDAV access

Generating an App-Specific Password

  1. Go to appleid.apple.com and sign in
  2. Navigate to Sign-In and Security > App-Specific Passwords
  3. Click Generate an app-specific password
  4. Enter a label (e.g. "MCP Calendar Server") and click Create
  5. Copy the generated password (xxxx-xxxx-xxxx-xxxx) and store it securely

Notes:

  • Your Apple ID must have two-factor authentication enabled
  • You can create up to 25 active app-specific passwords
  • Changing your main Apple ID password revokes all app-specific passwords
  • Never use your main iCloud password for CalDAV access

Installation

From Source

git clone https://github.com/rgabriel/mcp-icloud-calendar.git
cd mcp-icloud-calendar
make build

Using go install

go install github.com/rgabriel/mcp-icloud-calendar@latest

Docker

docker build -t mcp-icloud-calendar .

docker run \
  -e ICLOUD_EMAIL="you@icloud.com" \
  -e ICLOUD_PASSWORD="xxxx-xxxx-xxxx-xxxx" \
  mcp-icloud-calendar

The Docker image uses a multi-stage build with a distroless base image and runs as a non-root user.

Prebuilt Binaries

Download the binary for your platform from the Releases page. Binaries are available for:

Platform Architecture Binary
Linux x86_64 mcp-icloud-calendar-linux-amd64
Linux ARM64 mcp-icloud-calendar-linux-arm64
macOS Intel mcp-icloud-calendar-macos-amd64
macOS Apple Silicon mcp-icloud-calendar-macos-arm64
Windows x86_64 mcp-icloud-calendar-windows-amd64.exe

SHA256 checksums are provided alongside each binary.


Configuration

Single Account

The server requires two environment variables at minimum:

Variable Required Default Description
ICLOUD_EMAIL Yes Your iCloud email address (Apple ID)
ICLOUD_PASSWORD Yes App-specific password from appleid.apple.com
ICLOUD_CALENDAR_ID No Default calendar path (e.g., /1234567/calendars/home/)
LOG_LEVEL No INFO Logging verbosity: DEBUG, INFO, WARN, ERROR
TOOL_TIMEOUT No 25s Timeout per tool call (Go duration, e.g., 30s, 1m)
MAX_RETRIES No 3 Retry attempts for transient CalDAV failures
RETRY_BASE_DELAY No 1s Base delay for exponential backoff
RATE_LIMIT_RPS No 10 CalDAV requests per second per account
RATE_LIMIT_BURST No 20 Burst allowance for rate limiter
MAX_CONNS_PER_HOST No 10 Max HTTP connections to iCloud per account
HEALTH_PORT No Port for health/metrics HTTP server (e.g., 8080)
TLS_CERT_FILE No Client TLS certificate for mTLS
TLS_KEY_FILE No Client TLS key for mTLS
TLS_CA_FILE No Custom CA certificate

You can set these as environment variables or place them in a .env file:

cp .env.example .env
# Edit .env with your credentials

Credentials support file:// prefixes for Docker/Kubernetes secrets (e.g., ICLOUD_PASSWORD=file:///run/secrets/password).

Multi-Account

To manage multiple iCloud accounts, set the ACCOUNTS_FILE environment variable pointing to a JSON file:

{
  "accounts": [
    {
      "name": "personal",
      "email": "personal@icloud.com",
      "password": "xxxx-xxxx-xxxx-xxxx",
      "calendarId": "/1234567/calendars/home/"
    },
    {
      "name": "work",
      "email": "work@icloud.com",
      "password": "yyyy-yyyy-yyyy-yyyy"
    }
  ]
}

Each tool accepts an optional account parameter. Omit it to use the default account.


Usage with Claude Desktop

Add the server to your Claude Desktop configuration file.

macOS -- ~/Library/Application Support/Claude/claude_desktop_config.json

Linux -- ~/.config/claude/claude_desktop_config.json

Windows -- %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "icloud-calendar": {
      "command": "/path/to/mcp-icloud-calendar",
      "env": {
        "ICLOUD_EMAIL": "you@icloud.com",
        "ICLOUD_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
      }
    }
  }
}

Restart Claude Desktop after saving.


Available Tools

The server exposes 5 MCP tools. Each tool includes schema constraints and annotations indicating whether it is read-only, destructive, or idempotent.

list_calendars

List all available iCloud calendars. Returns each calendar's path, display name, description, and color. Call this first to discover valid calendarId values.

Parameter Type Default Description
account string Account name for multi-account setups

search_events

Search for calendar events within a date range. Returns paginated results with event details including recurrence info and attendees.

Parameter Type Default Description
account string Account name for multi-account setups
calendarId string (server default) Calendar path from list_calendars
startTime string Start of date range (RFC 3339, e.g., 2025-03-01T00:00:00Z)
endTime string End of date range (RFC 3339)
limit number 50 Max events to return (1-500)
offset number 0 Events to skip for pagination
expandRecurrence boolean false Expand recurring events into individual occurrences (requires both startTime and endTime)

create_event

Create a new calendar event. Returns the created event's unique ID.

Parameter Type Default Description
account string Account name for multi-account setups
title string (required) Event title or summary
startTime string (required) Start time (RFC 3339)
endTime string (required) End time (RFC 3339)
description string Event description or notes
location string Event location
calendarId string (server default) Calendar path to create the event in
attendees string JSON array of attendee objects (see below)

Attendee format:

[
  {"email": "alice@example.com", "name": "Alice", "role": "REQ-PARTICIPANT"},
  {"email": "bob@example.com", "name": "Bob", "role": "OPT-PARTICIPANT", "status": "TENTATIVE"}
]

Supported roles: CHAIR, REQ-PARTICIPANT, OPT-PARTICIPANT. Supported statuses: NEEDS-ACTION, ACCEPTED, DECLINED, TENTATIVE.

update_event

Update specific fields of an existing event. Only include the fields you want to change -- omitted fields remain unchanged.

Parameter Type Default Description
account string Account name for multi-account setups
eventId string (required) Event ID (UID) from search_events
calendarId string (server default) Calendar path containing the event
title string Updated title
description string Updated description
location string Updated location
startTime string Updated start time (RFC 3339)
endTime string Updated end time (RFC 3339)

delete_event

Permanently delete a calendar event. This action cannot be undone.

Parameter Type Default Description
account string Account name for multi-account setups
eventId string (required) Event ID (UID) from search_events
calendarId string (required) Calendar path containing the event

Development

Building

make build          # Build binary with version embedding
make test           # Run tests with race detector
make lint           # Run golangci-lint
make clean          # Remove build artifacts
make docker         # Build Docker image
make run            # Build and run

Running Locally

export ICLOUD_EMAIL="you@icloud.com"
export ICLOUD_PASSWORD="xxxx-xxxx-xxxx-xxxx"
make run

Testing

The project includes 88 table-driven tests across 14 test files, covering all tool handlers, CalDAV client logic, input validation, retry/rate-limiting wrappers, recurrence expansion, attendee parsing, and error paths. Tests use mock implementations of the CalendarService interface -- no live CalDAV connection required.

make test

Testing with MCP Inspector

Use the MCP Inspector to interactively test the server:

npx @modelcontextprotocol/inspector mcp-icloud-calendar

CI Pipeline

Every push to main or dev and every pull request runs:

  • go vet and go test -race -- correctness and data race detection
  • golangci-lint -- static analysis (errcheck, govet, staticcheck, gosec, gocritic, and more)
  • govulncheck -- known vulnerability scanning

Tagged releases (v*.*.*) trigger automated cross-platform builds with SHA256 checksums.


Architecture

mcp-icloud-calendar/
  main.go                Server setup, multi-account init, tool registration, middleware chain
  config/
    config.go            Environment variable loading, validation, file:// credential support
    accounts.go          Multi-account JSON configuration
  caldav/
    interface.go         CalendarService interface
    client.go            CalDAV client (caldav.icloud.com, TLS/mTLS)
    retry.go             Retry wrapper with exponential backoff
    ratelimit.go         Rate-limiting wrapper (token bucket)
    recurrence.go        RRULE expansion for recurring events
    attendees.go         Attendee parsing and serialization
    validation.go        Input validation for CalDAV parameters
  tools/
    accounts.go          AccountClients multi-account resolver
    list_calendars.go    list_calendars handler
    search_events.go     search_events handler
    create_event.go      create_event handler
    update_event.go      update_event handler
    delete_event.go      delete_event handler
  health/server.go       Health check and readiness endpoints
  metrics/               Prometheus metrics and tool call middleware
  middleware/             Request ID middleware (UUID correlation)
  logging/               Structured JSON logging (slog)

Client chain: Each account gets its own pipeline: realClient -> RateLimitedClient -> RetryClient

Middleware chain: Each tool call passes through RequestID -> Timeout -> Metrics -> handler. The request ID middleware assigns a UUID for log correlation. The timeout middleware enforces a configurable deadline. The metrics middleware records tool call duration and outcome.

Audit logging: Mutating operations (create_event, update_event, delete_event) are logged via a post-call hook with tool name, account, calendar ID, and status -- no PII (titles, descriptions, locations) is included.

Dependencies

Package Purpose
mcp-go MCP SDK -- tool registration, stdio transport
go-webdav CalDAV protocol client
go-ical iCalendar (RFC 5545) parsing
rrule-go Recurrence rule expansion
godotenv .env file loading
uuid Event UID and request ID generation
prometheus/client_golang Prometheus metrics
x/time/rate Token bucket rate limiter

Security

  • App-specific passwords only -- never accepts or stores your main iCloud password
  • TLS everywhere -- all CalDAV communication uses HTTPS with TLS verification
  • mTLS support -- optional client certificate authentication for enterprise environments
  • Input validation -- all tool parameters are validated for type, range, and format
  • Size and format limits -- title length, time range, and parameter constraints enforced via MCP schema
  • Credential file loading -- file:// prefix for secure secret injection (Docker, Kubernetes)
  • Distroless Docker image -- minimal attack surface, runs as non-root
  • No third-party data sharing -- the server runs locally and communicates only with iCloud servers
  • Revocable access -- app-specific passwords can be revoked at any time from appleid.apple.com
  • Audit trail -- mutating operations are logged without PII for compliance

Never commit your .env file to version control. The .gitignore already excludes it.


Troubleshooting

Authentication Failed

  • Verify you are using an app-specific password, not your main iCloud password
  • Check that two-factor authentication is enabled on your Apple ID
  • Regenerate a new app-specific password at appleid.apple.com
  • Confirm your email address matches your Apple ID

Calendar Not Found

  • Run list_calendars to see the exact calendar paths your account has
  • Calendar paths look like /1234567/calendars/home/ -- always start with /
  • Make sure you are using the path value from list_calendars, not the display name

Invalid Date Format

  • Use RFC 3339 / ISO 8601: 2025-01-15T14:30:00Z
  • Include timezone offset if not UTC: 2025-01-15T14:30:00-05:00

Timeouts or Slow Responses

  • Check your internet connection
  • Reduce the limit parameter for large result sets
  • Use narrower date ranges with startTime/endTime
  • Increase TOOL_TIMEOUT if your network is slow (default: 25s)

Recurring Event Not Expanding

  • Set expandRecurrence to true in search_events
  • Both startTime and endTime must be provided for recurrence expansion
  • Expansion only works within the specified date range

Event Not Found

  • Verify the event ID matches a UID from search_events
  • Ensure you are using the correct calendarId
  • The event may have been deleted or moved since the ID was retrieved

Contributing

Contributions are welcome. Please open an issue to discuss larger changes before submitting a pull request.


License

MIT License -- see LICENSE for details.

About

A Go-based MCP server for Apple iCloud Calendar via CalDAV — manage calendars and events through AI assistants with cross-platform support.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages