mcp-twake-dav
Give your AI assistant secure access to Twake Calendar and your contacts, in the Twake.ai Digital Workplace.

What is it?
mcp-twake-dav is a Model Context Protocol (MCP) server. MCP is the open standard that lets AI assistants (Claude Desktop, Claude Code, Hermes Agent, Cursor, VS Code and many others) use external tools. This server exposes your calendars and address books to the assistant as 20 tools: agenda, availability, events, reminders, invitations and contacts.
It speaks the open standards CalDAV (RFC 4791), CardDAV (RFC 6352) and CalDAV scheduling (RFC 6638). It is built for Twake Calendar and works with other SabreDAV-compatible servers (Nextcloud, SOGo, DAViCal, ownCloud…).
Part of Twake.ai
Twake.ai is the truly open source and sovereign Digital Workplace developed by LINAGORA: Twake Mail, Twake Calendar, Twake Drive, Twake Chat and Twake Visio with a single account, hosted in France or on your own infrastructure.
Three open source MCP servers connect AI assistants to the whole workplace:
| MCP server | Twake.ai service | Protocol |
|---|---|---|
| mcp-twake-mail | Twake Mail | JMAP |
| mcp-twake-dav (this project) | Twake Calendar and contacts | CalDAV / CardDAV |
| mcp-twake-drive | Twake Drive | cozy-stack API |
Used together, they let one assistant prepare a meeting from the invitation, the related email thread and the documents in the drive, without your data leaving your servers.
What it brings
- Your day at a glance: "What's on my agenda today? Where is my 3 pm meeting?"
- Finding a slot: "When am I free for one hour with Marie next week?"
- Scheduling in natural language: "Book a project review on Tuesday at 10 with Pierre and Marie" (dates like "next Monday" or "in two weeks" are understood).
- Reminders and invitations: add or remove reminders, list pending invitations and answer them.
- Contacts: find an email address or a phone number, create and update contact cards.
- Sovereignty: the server runs next to your assistant and talks directly to your calendar server. Pair it with a self-hosted or European AI model to keep the whole chain under your control.
Features
20 MCP tools
| Category | Tools |
|---|---|
| Calendar, read | get_next_event, get_todays_schedule, get_events_in_range, search_events, check_availability, list_calendars |
| Calendar, write | create_event (with attendees and recurrence), update_event, delete_event ⚠️, add_alarm, remove_alarm |
| Invitations | list_invitations, respond_to_invitation ⚠️ |
| Contacts, read | search_contacts, get_contact_details, list_contacts, list_addressbooks |
| Contacts, write | create_contact, update_contact, delete_contact ⚠️ |
⚠️ = deletes data or makes the server notify other people. Every tool carries MCP annotations (readOnlyHint, destructiveHint, openWorldHint) so clients can ask for confirmation.
Highlights
- Attendees and organizer:
create_eventinvites attendees, with the organizer taken fromDAV_ORGANIZER_EMAIL/DAV_ORGANIZER_NAME; the server sends the invitations. - Recurring events: RRULE expansion with safety limits, single-occurrence edits and deletions, and an opt-out (
DAV_RECURRING_WRITES=false) for cautious deployments. - Reliable updates: events are found by UID with a server-side query; updates use parse-modify-serialize, so alarms, attendees and
X-properties are preserved. - Status display: cancelled and tentative events, attendee participation status.
- Five authentication methods: Basic, Bearer, OpenPaaS ESNToken, token command (short-lived tokens refreshed before every call) and an external credentials file.
- Reverse proxy support:
DAV_HREF_PREFIXfor servers published under a path prefix that their responses omit (Twake Calendar / OpenPaaS). - CTag-based caching, retries with backoff, natural-language dates (chrono-node), HTTPS enforced.
Requirements
- Node.js >= 20
- A CalDAV / CardDAV server: Twake Calendar, Nextcloud, SOGo, DAViCal, ownCloud… (HTTPS required, except
localhost) - An MCP client: Claude Desktop, Claude Code, Hermes Agent, Cursor, VS Code, or any MCP-compatible assistant
Installation
Interactive setup (recommended):
npx mcp-twake-dav setup
The wizard asks for your server URL and credentials, tests the connection, lists your calendars and address books, lets you pick the defaults, and can write the Claude Desktop configuration for you.
Global install:
npm install -g mcp-twake-dav
From source:
git clone https://github.com/linagora/mcp-twake-dav.git
cd mcp-twake-dav
npm install
npm run build # then run: node build/index.js
Configuration
The server is configured through environment variables, usually set in your MCP client configuration.
Authentication
| Method | Variables |
|---|---|
| Basic (default) | DAV_URL, DAV_USERNAME, DAV_PASSWORD |
| Bearer | DAV_URL, DAV_AUTH_METHOD=bearer, DAV_TOKEN |
| ESNToken (OpenPaaS) | DAV_URL, DAV_AUTH_METHOD=esntoken, DAV_TOKEN |
| Token command | DAV_URL, DAV_AUTH_METHOD=command, DAV_TOKEN_COMMAND |
- With token command, the server runs
DAV_TOKEN_COMMANDto get an access token, either raw on stdout or as JSON{"access_token": "...", "expires_at": <epoch seconds>}, and refreshes it before every call. A single broker you control can then own the OIDC grant for several tools. DAV_CREDENTIALS_FILEpoints to a file holdingDAV_USERNAME=…,DAV_PASSWORD=…orDAV_TOKEN=…lines, so secrets stay out of the MCP client configuration.
Other options
| Variable | Description | Default |
|---|---|---|
DAV_DEFAULT_CALENDAR |
Calendar used when the assistant does not name one ("all" in a tool call still searches every calendar) |
all calendars |
DAV_DEFAULT_ADDRESSBOOK |
Address book used by default | all address books |
DAV_ORGANIZER_EMAIL / DAV_ORGANIZER_NAME |
Organizer written in events that have attendees | none |
DAV_RECURRING_WRITES |
false = update_event / delete_event refuse recurring series and occurrences |
true |
DAV_HREF_PREFIX |
Path prefix stripped by a reverse proxy, e.g. /dav for Twake Calendar / OpenPaaS |
none |
USER_TIMEZONE |
IANA time zone used to display and interpret dates, e.g. Europe/Paris |
system time zone |
LOG_LEVEL |
fatal, error, warn, info, debug, trace |
info |
Twake Calendar
Twake Calendar publishes its SabreDAV endpoint under /dav/ and accepts OIDC Bearer tokens:
DAV_URL=https://calendar.example.com/dav/
DAV_HREF_PREFIX=/dav
DAV_AUTH_METHOD=command
DAV_TOKEN_COMMAND="/usr/local/bin/my-token-broker token"
[email protected]
DAV_DEFAULT_CALENDAR="Jane Doe"
Without DAV_HREF_PREFIX, discovery fails with cannot find homeUrl or calendars come back empty.
Use it with your assistant
Claude Desktop
Edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Linux: ~/.config/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop:
{
"mcpServers": {
"twake-dav": {
"command": "npx",
"args": ["-y", "mcp-twake-dav"],
"env": {
"DAV_URL": "https://dav.example.com",
"DAV_USERNAME": "[email protected]",
"DAV_PASSWORD": "your-password",
"DAV_DEFAULT_CALENDAR": "My Calendar",
"DAV_DEFAULT_ADDRESSBOOK": "My Contacts",
"USER_TIMEZONE": "Europe/Paris"
}
}
}
}
Claude Code
claude mcp add twake-dav --scope user \
-e DAV_URL=https://dav.example.com \
-e [email protected] \
-e DAV_CREDENTIALS_FILE=~/.config/mcp-twake-dav/credentials \
-- npx -y mcp-twake-dav
Hermes Agent
mcp_servers:
twake_dav:
command: npx
args: ["-y", "mcp-twake-dav"]
env:
DAV_URL: https://calendar.example.com/dav/
DAV_HREF_PREFIX: /dav
DAV_AUTH_METHOD: command
DAV_TOKEN_COMMAND: /usr/local/bin/my-token-broker token
DAV_ORGANIZER_EMAIL: [email protected]
DAV_RECURRING_WRITES: "false"
Other MCP clients
Any client that can launch a stdio MCP server works: command npx, arguments -y mcp-twake-dav, and the environment variables above.
Recommended safe configuration
Creating, moving or deleting an event with attendees makes the server email them in your name, and contact deletion is final (CardDAV has no trash). For an assistant that acts on its own:
- ask it to confirm the recap (title, date, place, attendees) before
create_event,update_eventordelete_event; - set
DAV_RECURRING_WRITES=falseand edit recurring series in Twake Calendar; - filter out
respond_to_invitation(anddelete_contactif not needed) in your MCP client, for example with Hermes Agent:
tools:
exclude: [respond_to_invitation, delete_contact]
Event descriptions and contact notes may be written by third parties (prompt injection). See SECURITY.md.
Usage examples
- "What's my next meeting, and where is it?"
- "Show my schedule for this week."
- "Am I free tomorrow afternoon? Find me a 45-minute slot."
- "Create a meeting with Pierre on Thursday at 2 pm and invite him."
- "Add a 15-minute reminder to my dentist appointment."
- "Do I have pending invitations?"
- "What's Marie's email address? Update her phone number."
Troubleshooting
| Symptom | Fix |
|---|---|
Configuration validation failed |
Set the variables required by your DAV_AUTH_METHOD (see Authentication). |
401 Unauthorized |
Check the credentials; with a token, check that it is valid and not expired. |
URL must use HTTPS |
Use https:// (HTTP is only accepted for localhost / 127.0.0.1). |
cannot find homeUrl / empty calendars |
The server sits behind a path prefix: set DAV_HREF_PREFIX (e.g. /dav). |
Event not found on update or delete |
Pass the calendar name, or calendar: "all". |
| No calendars or address books | Check the account's permissions in the server's web interface. |
| Tools missing in the client | Restart the client after editing its configuration; check that npx is in the PATH. |
Run with LOG_LEVEL=debug for details (logs go to stderr).
Architecture
MCP client ⇄ stdio (JSON-RPC) ⇄ mcp-twake-dav ⇄ HTTPS (CalDAV / CardDAV) ⇄ Twake Calendar / any DAV server
Layers: Zod configuration with HTTPS enforcement, Pino logger on stderr, tsdav clients with pluggable authentication and href-prefix rewriting, retry and CTag cache, calendar and address book services, ical.js transformers (iCalendar, vCard, RRULE, time zones), and the MCP tools.
Development
npm install
npm run build # compile TypeScript
npm test # Vitest suite, no real server needed
npm run dev # watch mode
node scripts/check-command-auth.mjs # token-command refresh against a mock CalDAV server
Contributing
Contributions are welcome: read CONTRIBUTING.md and our Code of Conduct. Please report vulnerabilities privately as described in SECURITY.md. Release notes are in CHANGELOG.md.
License
Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
Copyright © 2026 LINAGORA
About
mcp-twake-dav is developed by LINAGORA, French open source software publisher, as part of Twake.ai. For support, hosting or integration of Twake.ai and its AI connectors, contact LINAGORA at https://linagora.com.