Radicale MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Radicale MCPWhat events do I have on my work calendar tomorrow?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Radicale MCP
A thin MCP server for an existing Radicale CalDAV/CardDAV installation. It exposes calendars, tasks, and contacts over Streamable HTTP at /mcp. Radicale remains the data store and DAV server; this package reads and writes through DAV, with no separate database or item cache. The supplied image runs Radicale 3.8.0 and the MCP server as two processes in one container.
Configuration
Variable | Purpose | Default |
| Radicale HTTP base URL used by MCP |
|
| Existing Radicale user for DAV Basic auth | Required |
| Password for that user | Required |
| Single Bearer token for | Required |
| IANA zone for new date-times without an offset |
|
| MCP HTTP listen port in the container |
|
GET /health is public and returns 200 only when a DAV PROPFIND succeeds with the configured credentials. It returns 503 without revealing DAV data when Radicale is unavailable. Every other MCP request requires Authorization: Bearer <MCP_TOKEN>. The MCP server listens on 0.0.0.0 inside the container. Compose publishes both ports on host loopback by default; put an HTTPS reverse proxy in front of /mcp for remote clients.
The included Radicale config uses its native bcrypt htpasswd authentication and owner_only rights. MCP does not create users or collections. Create calendars, task lists, and address books in the Radicale web UI or with a DAV client before using the item tools. The username in DAV_USERNAME must be allowed to access those collections. A calendar that supports both VEVENT and VTODO appears in both list_calendars and list_task_lists.
Related MCP server: ical-mcp
Run on a Railway development VM
Build the image, create a bcrypt htpasswd entry, and keep the password and token in an uncommitted .env on the VM. The hash command prompts for the password, so it need not appear in shell history:
docker build -t radicale-mcp:dev .
docker run --rm -it --entrypoint python radicale-mcp:dev -c 'import bcrypt,getpass; print(bcrypt.hashpw(getpass.getpass("Radicale password: ").encode(), bcrypt.gensalt()).decode())'Put username:generated-hash in a private users file. Set RADICALE_USERS_FILE to its absolute path. Add these values to .env (use actual secrets, not the placeholders):
RADICALE_USERS_FILE=/absolute/path/to/private/users
DAV_USERNAME=username
DAV_PASSWORD=<same Radicale password>
MCP_TOKEN=<long random token>Then run docker compose up --build -d in the Railway VM. Check docker compose ps and curl -fsS http://127.0.0.1:8080/health. The bundled image also exposes Radicale on host loopback port 5232 for its UI and DAV clients. MCP_BIND_ADDRESS, MCP_PUBLISHED_PORT, RADICALE_BIND_ADDRESS, and RADICALE_PUBLISHED_PORT can change the host bindings. Do not expose either HTTP port directly to the Internet without a TLS and access-control boundary.
For an already-running Radicale, run only the Python MCP package with DAV_URL, DAV_USERNAME, DAV_PASSWORD, MCP_TOKEN, and optionally PORT; python -m radicale_mcp.server starts the MCP listener. The ASGI entry point is radicale_mcp.server:app.
Tools and IDs
Collections and items use the DAV href relative to DAV_URL as their id, for example alice/work/ and alice/work/4c1f.ics. Use IDs returned by the tools. IDs are checked against the configured origin and base path; redirects and escaped paths are rejected.
Resource | Tools |
Events |
|
Tasks |
|
Contacts |
|
For example, call create_event with:
{"calendar_id":"alice/work/","summary":"Review","start":"2026-10-01T09:00:00","end":"2026-10-01T10:00:00"}The result includes id, uid, and etag. Pass that exact ETag to update_event:
{"event_id":"alice/work/<id-from-create>.ics","expected_etag":"\"etag-from-create\"","changes":{"summary":"Review moved"}}update_event, update_task, update_contact, complete_task, and all deletes require a current single strong ETag. A concurrent DAV change causes HTTP 412 and the tool call fails; get the item again before retrying. changes modifies only named fields. An omitted field stays as it was; null clears an optional field. UID is never changed by updates. Create uses If-None-Match: *, while updates and deletes use If-Match.
get_event and get_task return raw_ical; get_contact returns raw_vcard. Event patches target the master VEVENT and preserve recurrence overrides, alarms, VTIMEZONE, RRULE, EXDATE, and unrecognized properties. Searches and date filters use DAV REPORT. A recurring event or task is returned as a matching series resource, not an expanded list of occurrences; recurrence_overrides reports how many override VEVENTs are present. List tools return up to 100 items by default and accept limit up to 1000. Search tools filter the full REPORT result before applying the limit.
Date-only events keep all-day DATE values and an exclusive end date. A date-time without an offset uses MCP_TIMEZONE. An explicit ISO offset is normalized to UTC to preserve its instant in iCalendar; existing TZID and floating date-times remain intact when patched with offset-free values. Contacts support name, company, title, multiple emails and phones, and multiline notes. Other vCard fields remain when omitted from an update.
Existing data and verification
Before replacing a Radicale deployment, back up its collection storage, config, and htpasswd file. Point the new container at the same verified data volume (RADICALE_VOLUME) or mount the existing collections directory at /var/lib/radicale/collections, and mount the existing Radicale config and users file read-only. Check that UID 10001 can write the storage volume. Keep the original backup until calendars, tasks, contacts, and their UIDs are visible through DAV and MCP after a restart. This package has no schema migration and should not rewrite stored .ics or .vcf files during transfer.
On the Railway VM, the relevant checks are:
.venv/bin/python -m unittest discover -s tests -v
docker build -t radicale-mcp:dev .The integration test starts a temporary container and Radicale volume, checks MCP authentication, CRUD, ETag conflicts, DAV persistence after restart, and then removes its test resources. Run it only where Docker execution is permitted.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for Cronofy — read calendars, events and free/busy, and create, update or delete events.
MCP server for Nylas — read email, calendars, events and contacts, and send email or create events.
An MCP server that provides access to Testiny projects, test cases and test runs
An authenticated remote MCP server for user-owned devices and one-shot capability invocation.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables CRUD operations for calendar events, journal entries, and todos on any CalDAV server (like Radicale) through the Model Communication Protocol.MIT
- AlicenseAqualityBmaintenanceMCP server for Apple Calendar and CalDAV providers. Enables listing, creating, updating, deleting events, and checking free/busy status with per-calendar write protection.6MIT
- AlicenseAqualityCmaintenanceEnables managing events and subcalendars from kalender.digital through MCP tools for listing, creating, updating, and deleting events and subcalendars.8MIT
- FlicenseNot gradedqualityCmaintenanceEnables managing calendars, events, contacts, and todos via a CalDAV server (Radicale) through MCP tools.-