Skip to main content
Glama

caldav-mcp

Give AI assistants full read/write access to any CalDAV calendar.

A self-hosted MCP bridge between AI assistants and CalDAV servers. Connect Claude, Cursor, VS Code, and others to Nextcloud, Radicale, Baikal, and any RFC 4791 server through a single Docker container.

License: MIT Python 3.11+ Docker MCP Release M8ven Score

What problem does it solve

Bridges any MCP-compatible AI client (Claude, Cursor, VS Code, Codex, …) to any RFC 4791 CalDAV server (Nextcloud, Radicale, Baikal, …) so the assistant can read and write your calendar directly.

Ask your assistant:

Related MCP server: calendar-mcp

What it does NOT do

  • No stdio transport — Streamable HTTP only. To use stdio, modify server.py to call mcp.run() instead of mcp.run_http_async().

  • Not a CalDAV server — you need an existing CalDAV server (Nextcloud, Radicale, Baikal, etc.).

  • No iTIP/imip scheduling — attendees are stored on events, but no email invitations or scheduling messages are sent.

  • Client-side search — caldav_search_events fetches all events and filters locally. Works well for small-to-medium calendars; may be slow on very large ones.

  • Non-atomic move — caldav_move_event copies the event then deletes the original. A failure after copy leaves a duplicate (the safer failure mode).

  • No hot-reload — config changes require a server restart. The store is frozen into an immutable singleton at startup.

  • Self-hosted only — not a SaaS. You run and operate the server yourself.

Quick start

docker-compose

services:
  caldav-mcp:
    image: ghcr.io/gelse/caldav-mcp:latest
    ports:
      - "8600:8080"
    environment:
      CALDAV_URL: https://cloud.example.com/remote.php/dav/calendars/user/
      CALDAV_USERNAME: user
      CALDAV_PASSWORD: app-password
      CALDAV_MCP_API_KEY: your-secret-token
      TZ: Europe/Vienna
docker compose up -d

Note: CALDAV_URL, CALDAV_USERNAME, and CALDAV_PASSWORD are optional. When set, X-Caldav-* request headers are ignored (environment mode). When omitted, send X-Caldav-Url, X-Caldav-Username, and X-Caldav-Password headers per request (header mode).

Verify

curl -s http://localhost:8600/mcp \
  -H "Authorization: Bearer your-secret-token" \
  -H "X-Caldav-Url: https://cloud.example.com/remote.php/dav/calendars/user/" \
  -H "X-Caldav-Username: user" \
  -H "X-Caldav-Password: app-password" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}'

MCP client config

{
  "mcpServers": {
    "caldav": {
      "type": "http",
      "url": "http://localhost:8600/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY",
        "X-Caldav-Url": "https://cloud.example.com/remote.php/dav/calendars/user/",
        "X-Caldav-Username": "user",
        "X-Caldav-Password": "app-password"
      }
    }
  }
}

Client-specific config files (Claude Desktop, Claude Code, Cursor, VS Code, OpenCode, OpenWebUI): see docs/clients.md.

Why this over other MCP calendar servers

  • Self-hosted — no data leaves your network. No third-party SaaS.

  • Stateless single container — no database, no sidecars. Optional SQLite store for pro mode.

  • Any RFC 4791 server — Radicale CI-integration-tested, Nextcloud used in development. Baikal, ownCloud, iCloud, Fastmail are protocol-compatible.

  • Multi-account without restarts — credentials travel per-request in HTTP headers.

  • Pro mode — optional SQLite store with per-user keys, fan-out reads across multiple remotes. See docs/pro-mode.md.

  • Security built in — optional API key auth, per-IP rate limiting, structured audit logging, read-only mode.

Why Docker (not npx)

caldav-mcp is Python-based (not Node), so npx is not an option. Docker means:

  • No local Python, venv, or dependency management — the pre-built image has everything pinned.

  • Pinned dependencies — the image is built once in CI with fully pinned requirements, identical on every host.

  • One container shared by your entire homelab or team, serving multiple AI clients.

The 14 tools

Queries (7) — read-only

Tool

Description

caldav_list_calendars

List all available calendars

caldav_get_events

Get events in a date range

caldav_get_today_events

Get events for today

caldav_get_week_events

Get events for the next 7 days

caldav_get_event_by_uid

Get a specific event by UID

caldav_search_events

Find events by text

caldav_get_freebusy

Get free/busy information

Mutations (4) — write

Tool

Description

caldav_create_event

Create a new event

caldav_update_event

Partially update an existing event

caldav_delete_event

Delete an event

caldav_move_event

Move an event between calendars

Attendees (3)

Tool

Description

caldav_add_attendee

Add an attendee to an event

caldav_remove_attendee

Remove an attendee from an event

caldav_list_attendees

List attendees of an event

Full API docs: docs/api.md.

Authentication & security

  • API key auth — optional CALDAV_MCP_API_KEY with constant-time comparison. Pro mode uses PBKDF2-HMAC-SHA256 DB-stored keys.

  • Rate limiting — per-IP sliding window (default: 10 failures / 60 s), configurable via CALDAV_MCP_RATE_LIMIT_MAX_FAILURES and CALDAV_MCP_RATE_LIMIT_WINDOW_SECONDS.

  • Audit logging — all auth attempts and tool operations logged. Set CALDAV_MCP_LOG_FORMAT=json for structured output.

  • Read-only mode — CALDAV_MCP_READ_ONLY=true hides all write tools, leaving only the 8 read-only tools visible.

Configuration essentials

Most users only need these:

Variable

Description

CALDAV_URL

CalDAV server URL (set = env mode; unset = header mode)

CALDAV_USERNAME

CalDAV username (env mode)

CALDAV_PASSWORD

CalDAV password (env mode)

CALDAV_MCP_API_KEY

API key for endpoint auth (optional)

TZ

IANA timezone for today/week boundaries (default: UTC)

CALDAV_MCP_READ_ONLY

true to hide write tools

Credential modes: environment variables (env mode), per-request X-Caldav-* headers (header mode), or SQLite store (pro mode). No per-field mixing — all three credentials come from the same source. Full reference: docs/configuration.md.

Pro mode (DB_CONFIG_ENABLED=true): loads users and configs from a SQLite store at startup. Supports per-user keys, fan-out reads across multiple remotes, and dotted-path writes. Requires CALDAV_MCP_DB_PATH and CALDAV_MCP_CONFIG_SECRET. Config changes require a restart. Details: docs/pro-mode.md, docs/cli.md.

Documentation

Document

Contents

docs/api.md

API reference — auth headers, addressing, aggregated results

docs/clients.md

MCP client configuration (Claude Desktop, Cursor, VS Code, …)

docs/cli.md

Config store CLI (caldav-mcp-config)

docs/configuration.md

Full env var reference, TLS, reverse proxy, deployment

docs/pro-mode.md

Pro mode — SQLite store, fan-out, per-user auth

docs/architecture.md

Architecture and design decisions

docs/contributing.md

Development setup, code style, architecture rules

Known gaps & planned features

  • Client-side search does not scale to very large calendars.

  • caldav_move_event is non-atomic (copy + delete; duplicate on failure).

  • Config changes require a server restart — no hot-reload yet.

  • No stdio transport — Streamable HTTP only.

  • Version 0.1.0 — pre-1.0, API may change between releases.

  • X-Caldav-Username / X-Caldav-Password passthrough mode reserved for future use.

  • Future: hot-reload, pro-mode enhancements (see ideas/).

FAQ

I get ERROR:[auth] unauthorized — Set CALDAV_MCP_API_KEY and include Authorization: Bearer <token> (or X-Api-Key) in every request. When CALDAV_MCP_API_KEY is unset the endpoint is open, but never expose it to the internet without auth.

Calendar not found — Calendar names are case-sensitive. Run caldav_list_calendars to see the exact names your server reports.

Events show wrong time — Set the TZ environment variable to your IANA timezone (e.g. Europe/Vienna). Without it, today/week boundaries default to UTC.

SSL certificate errors — For self-signed certs, either import the CA into the system trust store or set CALDAV_MCP_CALDAV_VERIFY_SSL=false for testing.

Can I use stdio? — Not out of the box. The server uses Streamable HTTP transport. To add stdio support, modify server.py to call mcp.run() instead of mcp.run_http_async().

Contributing

See docs/contributing.md.

License

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Provider-agnostic CalDAV calendar MCP server that connects any CalDAV calendar to AI assistants, enabling calendar operations like listing, creating, updating, and deleting events.
      35 PyPI
      AGPL 3.0