CalDAV MCP Server — calendar events, scheduling, and availability
Project description
caldav-blade-mcp
A precision CalDAV MCP server that gives AI agents structured access to calendar data. Built for the Model Context Protocol with token efficiency as a first-class design goal.
Why another calendar MCP?
Most calendar integrations dump entire iCalendar blobs into the context window. A single week view can burn 3,000+ tokens before the model even starts reasoning. caldav-blade-mcp takes a different approach:
- Compact output — pipe-delimited, one line per event, null fields omitted. A day's events in ~200 tokens.
- Batch operations —
cal_events_batchfetches N calendars in one tool call. One call instead of eleven for a family digest. - Purpose-built views —
cal_today,cal_week,cal_freebusygive you exactly what you need with zero configuration. - Write-gated — read by default, writes require explicit opt-in.
cal_deletehas an additionalconfirm=truesafety gate.
Quick start
# Install
uv pip install -e .
# Configure (single provider)
export CALDAV_URL="https://caldav.fastmail.com/dav/calendars/user/you@fastmail.com"
export CALDAV_USERNAME="you@fastmail.com"
export CALDAV_PASSWORD="app-specific-password"
# Run
caldav-blade-mcp
13 tools, 3 categories
Read (9 tools)
| Tool | Purpose | Token cost |
|---|---|---|
cal_info |
Health check — providers, connection, write gate | ~50 |
cal_calendars |
List all calendars (name, UID, provider) | ~20/cal |
cal_events |
Events from one calendar in date range | ~30/event |
cal_events_batch |
Events from N calendars in one call | ~30/event |
cal_event |
Full detail by UID (attendees, recurrence) | ~100 |
cal_search |
Search by text, attendee, location | ~30/event |
cal_today |
Today's events across all calendars | ~30/event |
cal_week |
This week's events across all calendars | ~30/event |
cal_freebusy |
Busy periods only — cheapest availability check | ~15/period |
Write (4 tools, gated)
| Tool | Purpose |
|---|---|
cal_create |
Create event with all fields (description, location, recurrence, attendees, alarm) |
cal_update |
Partial update — only changed fields, auto-increments SEQUENCE |
cal_delete |
Delete by UID — requires confirm=true |
cal_move |
Move event between calendars |
Output format
── Work ──
08:30-09:30 | Standup | uid=abc123
14:00-15:00 | Design review @ Level 3 | loc=Level 3 | uid=def456
── Personal ──
All day | School holidays | uid=ghi789
18:30-19:30 | Swim squad | uid=jkl012
Multi-provider support
Run against multiple CalDAV servers simultaneously — useful when calendars span Fastmail, iCloud, Google, or self-hosted (Radicale, Baïkal, Nextcloud).
export CALDAV_PROVIDERS="fastmail,icloud"
export CALDAV_FASTMAIL_URL="https://caldav.fastmail.com/dav/calendars/user/..."
export CALDAV_FASTMAIL_USERNAME="you@fastmail.com"
export CALDAV_FASTMAIL_PASSWORD="fm-app-password"
export CALDAV_ICLOUD_URL="https://caldav.icloud.com/"
export CALDAV_ICLOUD_USERNAME="you@icloud.com"
export CALDAV_ICLOUD_PASSWORD="app-specific-password"
Single-provider mode (the CALDAV_URL / CALDAV_USERNAME / CALDAV_PASSWORD env vars) remains fully supported for simple setups.
Security model
| Layer | Mechanism |
|---|---|
| Write gate | CALDAV_WRITE_ENABLED=true required for any mutation |
| Delete safety | cal_delete additionally requires confirm=true |
| Credential scrubbing | Passwords and server URLs stripped from all error output |
| Bearer auth | Optional CALDAV_MCP_API_TOKEN for HTTP transport |
| No caching | Credentials read from env at startup, never persisted |
Claude Code integration
Add to your MCP config (e.g. claude.nix or settings.json):
{
"mcpServers": {
"calendar-piers": {
"type": "stdio",
"command": "uv",
"args": ["--directory", "~/src/caldav-blade-mcp", "run", "caldav-blade-mcp"],
"env": {
"CALDAV_URL": "...",
"CALDAV_USERNAME": "...",
"CALDAV_PASSWORD": "...",
"CALDAV_WRITE_ENABLED": "false"
}
}
}
}
A bundled SKILL.md teaches Claude the optimal tool-calling patterns — batch over individual, freebusy over full event scans, convenience views for common queries.
Development
make install-dev # Install with dev + test dependencies
make test # Unit tests (mocked caldav, no server needed)
make check # Lint + format + type-check
make run # Start MCP server (stdio)
Architecture
src/caldav_blade_mcp/
├── server.py — FastMCP 2.0 server, 13 @mcp.tool decorators
├── client.py — CalDAVClient with multi-provider, typed exceptions
├── formatters.py — Token-efficient output (pipe-delimited, null omission)
├── models.py — Provider config, write-gate, constants
└── auth.py — Bearer token middleware for HTTP transport
Built with FastMCP 2.0, caldav, and python-dateutil.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file caldav_blade_mcp-0.1.1.tar.gz.
File metadata
- Download URL: caldav_blade_mcp-0.1.1.tar.gz
- Upload date:
- Size: 124.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6db79882e7a92868e400fc184500139f57ee26f20c8808c2d37d16f3d00b4515
|
|
| MD5 |
56328048c1237b0541c0359b9f7b066b
|
|
| BLAKE2b-256 |
6e36ffcd24c0bf9f3c4174e3c9f0769bccee9eb586a94b00e39214252e9e1bdf
|
Provenance
The following attestation bundles were made for caldav_blade_mcp-0.1.1.tar.gz:
Publisher:
publish.yml on Groupthink-dev/caldav-blade-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
caldav_blade_mcp-0.1.1.tar.gz -
Subject digest:
6db79882e7a92868e400fc184500139f57ee26f20c8808c2d37d16f3d00b4515 - Sigstore transparency entry: 1395693236
- Sigstore integration time:
-
Permalink:
Groupthink-dev/caldav-blade-mcp@ffd3a3af43c1873ba520fd593feb9e00cd99e164 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Groupthink-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ffd3a3af43c1873ba520fd593feb9e00cd99e164 -
Trigger Event:
push
-
Statement type:
File details
Details for the file caldav_blade_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: caldav_blade_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08be27185980c5a1db048a0efd0eee723aacb5317f0eccd923f4edbd4f514fe6
|
|
| MD5 |
0f1c5fbb242ad9d2a9095cf26c0e2fea
|
|
| BLAKE2b-256 |
68b1192447338902d53ef5bd696edc158ea012c20fc2b880040b7caf0a2ea6b2
|
Provenance
The following attestation bundles were made for caldav_blade_mcp-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on Groupthink-dev/caldav-blade-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
caldav_blade_mcp-0.1.1-py3-none-any.whl -
Subject digest:
08be27185980c5a1db048a0efd0eee723aacb5317f0eccd923f4edbd4f514fe6 - Sigstore transparency entry: 1395693238
- Sigstore integration time:
-
Permalink:
Groupthink-dev/caldav-blade-mcp@ffd3a3af43c1873ba520fd593feb9e00cd99e164 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Groupthink-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ffd3a3af43c1873ba520fd593feb9e00cd99e164 -
Trigger Event:
push
-
Statement type: