Radicale
Self-hosted CalDAV (calendar) and CardDAV (contacts) server.
Details
| Directory | ~/agap_git/radicale/ |
| Image | tomsquest/docker-radicale |
| Port | 5232 |
| URL | https://dav.alogins.net |
| Data | /mnt/ssd/dbs/radicale/data/ |
| Config | /mnt/ssd/dbs/radicale/config/config |
Authentication
htpasswd with bcrypt encryption. Users file: /mnt/ssd/dbs/radicale/config/users.
Credentials stored in Vaultwarden as RADICALE_PASSWORD.
Add a user
docker exec radicale-radicale-1 htpasswd -nBb USERNAME PASSWORD \
>> /mnt/ssd/dbs/radicale/config/users
Client Setup
Use any CalDAV/CardDAV client (Thunderbird, DAVx⁵ on Android, Apple Calendar/Contacts).
Server URL: https://dav.alogins.net/USERNAME/
Config
[server]
hosts = 0.0.0.0:5232
[auth]
type = htpasswd
htpasswd_filename = /config/users
htpasswd_encryption = bcrypt
[storage]
filesystem_folder = /data/collections
Storage Layout
Each user gets /data/collections/collection-root/<user>/. Inside, every calendar/addressbook is a directory named by a UUID with a .Radicale.props file (displayname, tag = VCALENDAR / VADDRESSBOOK, supported components, color). Events and tasks are individual .ics files; contacts are .vcf.
MCP Integration
The agap-mcp server exposes Radicale over CalDAV using RADICALE_PASSWORD from Vaultwarden. Source: ~/agap_git/agap-mcp/src/radicale.js. Tools (prefix mcp__agap__):
| Tool | Purpose |
|---|---|
radicale_list_calendars |
List calendars/addressbooks for a user (defaults to alvis) |
radicale_list_events |
List events in a calendar (filename, uid, summary, dtstart, dtend) |
radicale_get_event |
Get raw iCalendar text for one event |
radicale_create_calendar |
MKCALENDAR with displayname, color, components |
radicale_delete_calendar |
DELETE a calendar collection |
radicale_put_event |
PUT an .ics (create or replace) |
radicale_delete_event |
DELETE an event |
radicale_move_event |
Copy event to another calendar, then delete from source |
Env vars on the agap-mcp container:
RADICALE_URL=http://localhost:5232
RADICALE_USER=alvis
Raw CalDAV (without MCP)
# List collections under alvis
curl -u alvis:$RADICALE_PASSWORD -X PROPFIND \
-H 'Depth: 1' -H 'Content-Type: application/xml' \
http://localhost:5232/alvis/ --data '<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"><d:prop><d:displayname/><d:resourcetype/></d:prop></d:propfind>'
# Create a calendar
curl -u alvis:$RADICALE_PASSWORD -X MKCALENDAR \
-H 'Content-Type: application/xml' \
http://localhost:5232/alvis/<uuid>/ --data '<?xml version="1.0"?>
<c:mkcalendar xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:set><d:prop>
<d:displayname>Social</d:displayname>
<c:supported-calendar-component-set><c:comp name="VEVENT"/></c:supported-calendar-component-set>
</d:prop></d:set>
</c:mkcalendar>'