caldav-todo-mcp
Integrates with iCloud Reminders over CalDAV using an app-specific password, enabling management of reminders/TODO items through the server's task tools.
Integrates with Nextcloud Tasks over CalDAV, allowing AI assistants to list, create, update, complete, move, delete, sync, import, and export TODO items stored in Nextcloud task collections.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
caldav-todo-mcp
An MCP server that lets an AI assistant read and write TODO items over CalDAV. Your tasks live on your own server (Nextcloud Tasks, Radicale, iCloud Reminders, Fastmail, Baïkal, …) and every other CalDAV client you use sees the same data.
Lists are CalDAV collections; items are RFC 5545 VTODO components. The server
exposes tools to list, create, update, complete, move and delete items, plus a
sync_todos tool that pushes a whole batch to the remote server in one call.
It speaks both MCP transports: stdio for local clients that spawn it, and streamable HTTP for running it as a service, e.g. in Docker.
Requirements
Python 3.11+
A CalDAV account (URL, username, password or app-specific password)
Related MCP server: Task / To-Do Manager — MCP Server
Install
# with uv (recommended)
uv tool install caldav-todo-mcp # once published; or from a checkout:
uv tool install /path/to/caldav-todo-mcp
# or with pip
pip install /path/to/caldav-todo-mcpFor development:
uv venv && uv pip install -e ".[dev]"
uv run pytestConfiguration
The server reads its settings from environment variables (see .env.example):
Variable | Required | Meaning |
| yes | Base URL of the CalDAV server, e.g. |
| usually | Login name |
| usually | Password or app-specific password |
| no | List id or name used when a tool call omits |
| no |
|
| no |
|
| no | HTTP timeout in seconds (default |
Typical URLs:
Provider |
|
Nextcloud |
|
Radicale |
|
iCloud |
|
Fastmail |
|
Baïkal |
|
Running in Docker (HTTP transport)
The image serves MCP over streamable HTTP on port 8000 at /mcp, and a liveness
probe at /health. CalDAV credentials are passed as environment variables; nothing is
baked into the image.
cp .env.example .env # fill in CALDAV_URL / CALDAV_USERNAME / CALDAV_PASSWORD
docker compose up -d --build
curl http://127.0.0.1:8000/healthOr without compose:
docker build -t caldav-todo-mcp .
docker run -d --name caldav-todo-mcp -p 127.0.0.1:8000:8000 \
-e CALDAV_URL=https://cloud.example.com/remote.php/dav/ \
-e CALDAV_USERNAME=alice \
-e CALDAV_PASSWORD=app-password \
-e CALDAV_DEFAULT_LIST=Tasks \
-e MCP_AUTH_TOKEN=change-me \
caldav-todo-mcpThen point your client at http://127.0.0.1:8000/mcp:
claude mcp add --transport http caldav-todo http://127.0.0.1:8000/mcp \
--header "Authorization: Bearer change-me"Server-side settings (all optional):
Variable | Default | Meaning |
|
|
|
|
| Bind address for HTTP |
|
| HTTP port |
|
| HTTP endpoint path |
| unset | When set, |
| unset | Comma-separated |
|
| Stateless streamable HTTP mode (no server-side sessions) |
|
| Plain JSON responses instead of SSE |
|
| Log level |
The same options are available as CLI flags (caldav-todo-mcp --transport http --port 8000),
which take precedence over the environment. The compose file binds the port to
127.0.0.1 only; if you expose it more widely, set MCP_AUTH_TOKEN, because whoever
can reach the endpoint can read and write your tasks.
Using it with a local (stdio) MCP client
Claude Code
claude mcp add caldav-todo \
-e CALDAV_URL=https://cloud.example.com/remote.php/dav/ \
-e CALDAV_USERNAME=alice \
-e CALDAV_PASSWORD=app-password \
-e CALDAV_DEFAULT_LIST=Tasks \
-- caldav-todo-mcpClaude Desktop / other stdio clients
{
"mcpServers": {
"caldav-todo": {
"command": "caldav-todo-mcp",
"env": {
"CALDAV_URL": "https://cloud.example.com/remote.php/dav/",
"CALDAV_USERNAME": "alice",
"CALDAV_PASSWORD": "app-password",
"CALDAV_DEFAULT_LIST": "Tasks"
}
}
}
}You can also run it directly with python -m caldav_todo_mcp, or serve HTTP outside
Docker with caldav-todo-mcp --transport http.
Tools
Tool | What it does |
| List the TODO-capable collections on the server |
| Create a new list |
| Delete a list and everything in it |
| List items (open first, by due date then priority); filters: |
| Fetch one item by UID |
| Create an item: |
| Change any of those fields; |
| Toggle completion (sets |
| Delete an item |
| Move an item to another list |
| Upsert a batch of items by UID; |
| Export a list as an |
| Import VTODOs from |
Every tool takes an optional list_id, which may be the collection id, its display
name (case-insensitive) or its URL. When omitted, CALDAV_DEFAULT_LIST is used; if
that is unset and the server holds exactly one TODO list, that list is used.
Dates are ISO 8601 strings: 2026-11-10 for an all-day due date,
2026-11-10T17:00:00+01:00 for a specific time. Priority follows RFC 5545
(1 highest … 9 lowest).
Syncing a local list to the server
sync_todos is designed for "push my list to the server" workflows. Give each local
item a stable uid and send the whole list:
{
"list_id": "Tasks",
"delete_missing": true,
"items": [
{"uid": "local-1", "summary": "Renew passport", "due": "2026-12-01", "priority": 2},
{"uid": "local-2", "summary": "Call the bank", "status": "COMPLETED"}
]
}The response reports which UIDs were created, updated, unchanged and
deleted. Without delete_missing the call never removes anything. To pull the
server state instead, use list_todos (structured) or export_todos (iCalendar).
Library use
The CalDAV layer is usable without MCP:
from caldav_todo_mcp import Settings, TodoStore
from caldav_todo_mcp.models import TodoInput
store = TodoStore(
Settings(
url="https://cloud.example.com/remote.php/dav/", username="alice", password="app-password"
)
)
for lst in store.list_lists():
print(lst.id, lst.name)
store.create_todo(TodoInput(summary="Water the plants", due="2026-11-10"), "Tasks")Tests
The test suite starts a throwaway Radicale server and runs the full create/update/complete/sync/import flow against it: in-process, over a real stdio MCP connection, and over streamable HTTP (including the bearer-token check):
uv run pytestLicense
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Simple, fast todo app: manage tasks, projects and tags from Claude and other MCP clients.
AI-powered to-do list: add, list, complete and organise tasks across lists from any assistant.
Local-first task manager: create, edit, and complete tasks, projects, and checklists via MCP.
Manage tasks, Focus Zone, notes, projects, and task history from compatible AI assistants.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA persistent todo list server that enables AI assistants to manage tasks across different platforms using the Model Context Protocol. It provides tools for creating, listing, updating, and deleting todos with support for priorities, tags, and due dates.MIT
- FlicenseNot gradedqualityCmaintenanceProvides AI assistants with tools and a resource to manage a personal to-do list, enabling adding, listing, retrieving, completing, and deleting tasks over stdio.-
- AlicenseNot gradedqualityAmaintenanceConnects AI assistants to CalDAV servers so they can list calendars and browse, create, update, or delete events and to-do tasks within a chosen timeframe. Supports scheduling of recurring and all-day events, task filtering and pagination, and completion tracking through natural language.1,412 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to connect to CalDAV servers and manage calendars, events, and tasks through tools for listing, creating, updating, completing, and deleting items.1,412 npmMIT