2
Radicale
agap-mcp edited this page 2026-05-26 08:27:50 +00:00

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>'