A Model Context Protocol (MCP) server that provides seamless integration with CalDAV calendars, enabling AI assistants to manage events and todos across your calendar systems.
- Complete Calendar Management: Create, read, update, and delete calendar events
- Todo Management: Full CRUD operations for todo items with status tracking
- Batch Operations: Create multiple events or todos efficiently
- Search Capabilities: Find events and todos across all calendars
- Multi-Calendar Support: Work with multiple calendars simultaneously
- Timezone Handling: Built-in Mountain Time to UTC conversion
- Flexible Event Types: Support for both timed and all-day events/todos
This server works with any CalDAV-compliant service, including:
- Nextcloud (recommended)
- Apple iCloud
- Google Calendar (via CalDAV)
- Yahoo Calendar
- Outlook.com
- FastMail
- SOGo
- Radicale
- Baikal
- Python 3.11 or higher
- uv package manager
- CalDAV server credentials
git clone <repository-url>
cd caldav-mcpUsing uv (recommended):
uv syncCreate a .env file in the project root:
CALDAV_URL=https://your-caldav-server.com/remote.php/dav
CALDAV_USERNAME=your-username
CALDAV_PASSWORD=your-password- Nextcloud:
https://your-domain.com/remote.php/dav - iCloud:
https://caldav.icloud.com - Google:
https://apidata.googleusercontent.com/caldav/v2/your-email@gmail.com/events - Yahoo:
https://caldav.calendar.yahoo.com - Outlook:
https://outlook.live.com/owa/calendar/00000000-0000-0000-0000-000000000000/
uv run main.pyThe server should start and display available tools for calendar management.
Run the MCP server locally and connect Claude Desktop directly.
uv run main.pyAdd to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"caldav": {
"command": "uv",
"args": ["run", "main.py"],
"cwd": "/path/to/caldav-mcp"
}
}
}For remote access, deploy the server on a VPS or home server and connect via HTTP. This method requires a secure network connection.
Choose one of these VPN solutions for secure remote access:
Tailscale provides zero-config VPN with excellent security:
-
Install Tailscale on both server and client machines:
# Ubuntu/Debian curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.list | sudo tee /etc/apt/sources.list.d/tailscale.list sudo apt update && sudo apt install tailscale # macOS brew install tailscale
-
Authenticate both machines:
sudo tailscale up
-
Get the Tailscale IP of your server:
tailscale ip -4
Self-hosted VPN solution:
-
Install WireGuard on server:
sudo apt install wireguard
-
Generate keys and configure (see WireGuard documentation)
Cloud-managed VPN:
- Create account at zerotier.com
- Install ZeroTier on both machines
- Join the same network
# On your remote server
git clone <repository-url>
cd caldav-mcp
uv sync
# Create .env file with your CalDAV credentials
nano .env
# Run with custom host and port
uv run python main.py --host 0.0.0.0 --port 7030# Build the image
docker build -t caldav-mcp .
# Run the container
docker run -d \
--name caldav-mcp \
-p 7030:8000 \
-e CALDAV_URL=your-caldav-url \
-e CALDAV_USERNAME=your-username \
-e CALDAV_PASSWORD=your-password \
caldav-mcp{
"mcpServers": {
"caldav": {
"command": "npx",
"args": ["mcp-remote", "http://TAILSCALE-IP:7030/sse", "--allow-http"]
}
}
}Replace TAILSCALE-IP with your server's Tailscale/VPN IP address.
Once connected, you can interact with your calendars using natural language:
- "Create a meeting tomorrow at 2 PM"
- "Show me my events for next week"
- "Update my dentist appointment to 3 PM"
- "Delete the cancelled project meeting"
- "Add a todo to review the quarterly report"
- "Mark the budget planning task as completed"
- "Show me all pending todos"
- "Create a shopping list todo for this weekend"
- "Create calendar events for my entire conference schedule"
- "Add multiple todos for my project milestones"
The MCP server runs remotely, so it cannot auto-detect the user's timezone. Instead, every datetime tool accepts a timezone parameter (IANA name like America/Denver or UTC) that the client passes in on each call. If omitted, the server falls back to the CALDAV_TIMEZONE env var, then to UTC.
- Always pass the user's IANA timezone (e.g.
"America/Denver") to each calendar/todo tool call. - Datetime inputs are interpreted as the user's local wall-clock time:
YYYY-MM-DD HH:MMfor timed items,YYYY-MM-DDfor all-day items. - Times are stored in UTC internally (with a
Zsuffix) so they are unambiguous on any provider. - All times returned by the server are converted to the timezone you supplied and labelled with the zone (e.g.
2026-08-11 06:45 MDT), so results are consistent and match your source documents regardless of how the provider stored them. - Events are returned date-filtered (when
start_date/end_dateare provided) and sorted chronologically.
No manual timezone conversion is required — just pass times as they appear in source documents (e.g. 06:45 Mountain Time on Aug 11 → 2026-08-11 06:45 with timezone: "America/Denver"). Military time is converted to 24-hour format first (e.g., 0645 becomes 06:45).
-
Authentication Errors
- Verify CalDAV URL format
- Check username/password credentials
- Some providers require app-specific passwords
-
Connection Timeouts
- Ensure firewall allows outbound HTTPS (port 443)
- Check if your CalDAV server is accessible
-
Remote Connection Issues
- Verify VPN connectivity between machines
- Check that the server is listening on the correct IP/port
- Ensure firewall allows the chosen port
Run with debug logging:
uv run python main.py --log-level debugimport caldav
client = caldav.DAVClient(
url="YOUR_CALDAV_URL",
username="YOUR_USERNAME",
password="YOUR_PASSWORD"
)
try:
principal = client.principal()
calendars = principal.calendars()
print(f"Found {len(calendars)} calendars")
for cal in calendars:
print(f"- {cal.name}")
except Exception as e:
print(f"Connection failed: {e}")- Use HTTPS: Always use HTTPS CalDAV URLs in production
- VPN Required: Never expose the MCP server directly to the internet
- App Passwords: Use app-specific passwords when available
- Environment Variables: Keep credentials in
.envfiles, never commit them - Firewall: Restrict access to necessary ports only
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request