Skip to main content
Glama

dav-mcp

Give your AI agents the power of organization — Transform them into orchestrating assistants managing calendars, contacts, and tasks.

Built on 27 production-ready tools spanning CalDAV, CardDAV, and VTODO protocols.

License: MIT npm version


Quick Start

Claude Code plugin

In Claude Code, run:

/plugin install dav-mcp --marketplace PhilflowIO/dav-mcp

Claude Code then asks for your server URL, username and password. The plugin also brings a skill that teaches Claude to use the tools well. Details are in the plugin README.

One-click install (Claude Desktop)

  1. Download dav-mcp-<version>.mcpb from the latest release. Releases from 4.1.2 on carry this file.

  2. Open it with Claude Desktop (macOS or Windows). Claude shows an install dialog.

  3. Enter your server URL, username and password. The password is stored as a secret. Leave the authentication method at Basic unless your server needs Digest.

The .mcpb file is an MCP Bundle: the server with its dependencies, so neither Node.js nor npx needs to be installed.

Claude Desktop / Cursor (Local)

Add to your MCP config file:

{
  "mcpServers": {
    "dav-mcp": {
      "command": "npx",
      "args": ["-y", "dav-mcp"],
      "env": {
        "CALDAV_SERVER_URL": "https://dav.example.com",
        "CALDAV_USERNAME": "your_username",
        "CALDAV_PASSWORD": "your_password"
      }
    }
  }
}

Config file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Restart Claude Desktop after adding the configuration.


n8n (Remote HTTP)

Start the HTTP server:

CALDAV_SERVER_URL=https://dav.example.com \
CALDAV_USERNAME=your_username \
CALDAV_PASSWORD=your_password \
BEARER_TOKEN=your-secret-token \
npx dav-mcp --http

Then in n8n:

  1. Add AI Agent node

  2. Add MCP Client Tool node and connect to AI Agent

  3. Configure:

    • MCP Endpoint: http://localhost:3000/mcp

    • Authentication: Bearer

    • Token: your-secret-token

Custom port:

npx dav-mcp --http --port=8080

Docker

Pull the published image (distroless, runs as non-root, no shell):

docker run -d --name dav-mcp -p 3000:3000 --env-file .env \
  ghcr.io/philflowio/dav-mcp:latest

Tags: latest, the exact release (5.0.0) and the minor line (5.0). Set PORT to serve on a different port; the healthcheck follows it.

Or build from source:

git clone https://github.com/PhilflowIO/dav-mcp.git
cd dav-mcp
cp .env.example .env
# Edit .env with your credentials
docker-compose up

Related MCP server: caldav-mcp

The Orchestration

When partial tools force your AI to improvise, complete tools let it execute precise operations across all components.

Capability

dav-mcp

Most MCPs

Calendar Management

Full CRUD (12 tools)

Create + list only (2-3 tools)

Contact Management

Complete CardDAV (8 tools)

Often missing entirely

Task Management

Full VTODO support (7 tools)

Rarely included

Field-Based Updates

All RFC properties + custom fields

Rarely available

Free/Busy

Works on every server (client-side)

Native REPORT, unsupported by most

Server-Side Filtering

Efficient queries

Dumps all data

Multi-Provider

Any CalDAV/CardDAV server

Limited provider support

Total Tools

27 tools

2-6 tools


Available Tools (27 Total)

CalDAV Tools (12 tools)

  1. list_calendars - List all available calendars

  2. list_events - List ALL events (use calendar_query for filtered searches)

  3. create_event - Create a new calendar event

  4. update_event - PREFERRED: Update any event field (SUMMARY, LOCATION, STATUS, custom X-* properties); move or convert an event with start_date/end_date/all_day

  5. update_event_raw - Update event with raw iCal data (advanced)

  6. delete_event - Delete an event permanently

  7. calendar_query - PREFERRED: Search and filter events efficiently by text, date range, or location

  8. make_calendar - Create a new calendar collection, optionally with a time zone (an IANA name such as Europe/Berlin, sent as a VTIMEZONE)

  9. update_calendar - Update calendar properties (display name, description, color, time zone)

  10. delete_calendar - Delete a calendar and all its events

  11. calendar_multi_get - Batch fetch multiple specific events by URLs

  12. freebusy_query - Find free and busy time in a range ("when am I free?"), calculated client-side

CardDAV Tools (8 tools)

  1. list_addressbooks - List all available address books

  2. list_contacts - List ALL contacts (use addressbook_query for filtered searches)

  3. create_contact - Create a new contact (vCard)

  4. update_contact - PREFERRED: Update any contact field (FN, EMAIL, TEL, ORG, ADR, custom X-* properties)

  5. update_contact_raw - Update contact with raw vCard data (advanced)

  6. delete_contact - Delete a contact permanently

  7. addressbook_query - PREFERRED: Search and filter contacts efficiently by name, email, or organization

  8. addressbook_multi_get - Batch fetch multiple specific contacts by URLs

VTODO Tools (7 tools)

  1. list_todos - List ALL todos/tasks (use todo_query for filtered searches)

  2. create_todo - Create a new todo/task with optional due date, priority, status

  3. update_todo - PREFERRED: Update any todo field (SUMMARY, STATUS, PRIORITY, DUE, PERCENT-COMPLETE, custom X-* properties)

  4. update_todo_raw - Update todo with raw VTODO iCal data (advanced)

  5. delete_todo - Delete a todo/task permanently

  6. todo_query - PREFERRED: Search and filter todos efficiently by status/due date

  7. todo_multi_get - Batch fetch multiple specific todos by URLs

Time zones

An event or todo written without a time zone (a "floating" time such as DTSTART:20261010T090000, or an all-day date) is read in its calendar's time zone, as CalDAV specifies (RFC 4791 §9.9): the zone set with make_calendar / update_calendar, which list_calendars shows. A calendar without one is read in the zone dav-mcp runs in: the TZ environment variable (for example TZ=Europe/Berlin in Docker or an HTTP deployment), else the system's. A time without a zone given to the create and update tools is read the same way, and an event stored without a zone stays without one when it is moved. freebusy_query prints its slots in the calendar's zone and names it.


Real-World Applications

n8n Automation Workflows

  • Meeting Management: "Show me all Friday meetings" → calendar_query with date filter returns only relevant events

  • Contact Search: "Find everyone at Google" → addressbook_query with org filter finds matches efficiently

  • Task Reporting: "Show overdue high-priority tasks" → todo_query with filters returns specific results

  • Scheduled Cleanup: Daily cron job deletes completed tasks using targeted queries

Claude Desktop Integration

  • Quick Event Creation: "Create team meeting tomorrow 2 PM" → create_event executes immediately

  • Contact Lookup: "What's Sarah's email?" → addressbook_query with name filter finds contact

  • Calendar Overview: "What's on my calendar next week?" → calendar_query with date range shows events

  • Calendar Management: "Create a new calendar called Project Luna" → make_calendar creates collection


Works Across All Major Providers

Works with any CalDAV/CardDAV server that follows RFC 4791 and RFC 6352:

  • Nextcloud - Full support

  • Baikal - Full support

  • Radicale - Full support

  • iCloud - Works with app-specific password

  • Any RFC-compliant server - Standard protocol support


Authentication

AUTH_METHOD selects how dav-mcp logs in (case-insensitive):

AUTH_METHOD

Credentials

Use for

Basic (default)

CALDAV_USERNAME, CALDAV_PASSWORD

Almost every server. If the server only offers Digest (for example Baikal set to Digest), dav-mcp switches to Digest by itself — no setting needed.

Digest

CALDAV_USERNAME, CALDAV_PASSWORD

Servers that only accept Digest (RFC 7616). Unlike the automatic switch under Basic, which first sends the password once Basic-encoded and is then rejected, Digest never sends the password — use it when the connection is not HTTPS.

OAuth (or OAuth2)

GOOGLE_*, see below

Google Calendar

dav-mcp needs Node.js 22 or newer. A wrong configuration — an unknown AUTH_METHOD value, or missing credentials for the chosen method — stops the server at startup instead of falling back to Basic.


Google Calendar (OAuth2)

For Google Calendar, use OAuth2 authentication:

{
  "mcpServers": {
    "dav-mcp": {
      "command": "npx",
      "args": ["-y", "dav-mcp"],
      "env": {
        "AUTH_METHOD": "OAuth",
        "GOOGLE_USER": "your@gmail.com",
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret",
        "GOOGLE_REFRESH_TOKEN": "your-refresh-token"
      }
    }
  }
}

Security

  • Input Validation: All inputs validated with Zod schemas before execution

  • Rate Limiting (HTTP mode): 100 requests per 15 minutes per client address, counted before the bearer token is checked. Clients on loopback or a private network (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) — another container on the same Docker network, for example — get 10,000. Limitation: dav-mcp sees the address of whatever connects to it. Behind a Docker port mapping or a reverse proxy that is the bridge gateway or the proxy, so all outside clients share that one address, its one counter and its raised limit. Rate-limit per client at the proxy if you expose the HTTP transport.

  • Bearer Auth: Token authentication for HTTP transport

  • No Credential Storage: Pass-through only, never logged or cached

  • Structured Logging: Audit trail with request IDs, no PII exposure

  • Tool-Call Log Off by Default: LOG_TOOL_CALLS=true records every tool call with its arguments, for debugging — to ~/.local/state/dav-mcp/tool-calls.jsonl (or $XDG_STATE_HOME, %LOCALAPPDATA% on Windows, or TOOL_CALL_LOG_FILE), readable by you only. TOOL_CALL_LOG_MODE=console sends it to stderr instead.

  • CORS Protection: Whitelist origins, block cross-site attacks


Privacy Policy

dav-mcp runs on your machine (or your own server) and talks only to the DAV server you configure. It has no telemetry and shares nothing with its maintainers or third parties. Tool results go to the AI assistant that called the tool. Credentials and calendar data are not stored by dav-mcp; the optional tool-call log is off by default. Full policy: PRIVACY.md. Contact: hello@philflow.io.


Documentation


Contributing

Pull requests are welcome! Please read CONTRIBUTING.md for guidelines.


License

MIT License - see LICENSE for details


Acknowledgments

Built with:

  • tsdav - Excellent TypeScript CalDAV/CardDAV library

  • tsdav-utils - Field-agnostic utility layer for RFC-compliant field updates

  • MCP SDK - Model Context Protocol by Anthropic

  • ical.js - RFC-compliant iCalendar parser


Questions? Issues? Create a GitHub issue


Built for AI agents managing calendars, contacts, and tasks

Available Tools

27 tools
addressbook_multi_getA

Batch fetch multiple specific contacts by their URLs. Use when you have exact contact URLs and want to retrieve their details

Inputs: contact_urls (required), addressbook_url (required).

addressbook_queryA

⭐ PREFERRED: Search and filter contacts efficiently (name, email, organization). Use for "find contacts with...", "search for email...", "contacts at company..." queries. Use instead of list_contacts when ANY filter is specified. Omit addressbook_url to search across ALL addressbooks automatically.

Inputs: limit, name_filter, email_filter, addressbook_url, +1 more.

calendar_multi_getA

Batch fetch multiple specific calendar events by their URLs. Use when you have exact event URLs and want to retrieve their details

Inputs: event_urls (required), calendar_url (required).

calendar_queryA

⭐ PREFERRED: Search and filter calendar events efficiently. Use instead of list_events to avoid loading thousands of entries. Omit calendar_url to search across ALL calendars automatically.

Inputs: limit, calendar_url, summary_filter, time_range_end, +2 more.

create_contactA

Create a new contact (vCard) with name, email, phone, organization, and other details

Inputs: full_name (required), addressbook_url (required), note, email, +4 more.

create_eventB

Create a new calendar event with title, date, time, optional description and location

Inputs: summary (required), end_date (required), start_date (required), calendar_url (required), +3 more.

create_todoA

Create a new todo/task in a calendar. Use this when user wants to add a task, todo item, or reminder with optional due date, priority, and status.

Inputs: summary (required), calendar_url (required), status, due_date, +3 more.

delete_calendarA

Delete a calendar and all its events. WARNING: on servers without a trash bin this cannot be undone; servers with one (e.g. Nextcloud) keep the calendar in the trash for a while. Use this when user explicitly asks to "delete calendar" or "remove calendar"

Inputs: calendar_url (required).

delete_contactA

Permanently delete a contact (vCard) from the address book. WARNING: This action cannot be undone — the contact is removed from the server immediately. Use only when the user explicitly requests deletion. Obtain the vCard URL and etag from list_contacts or addressbook_query first. The etag ensures no conflicting changes occurred since the contact was last retrieved.

Inputs: vcard_url (required), vcard_etag (required).

delete_eventA

Permanently delete a calendar event. WARNING: This action cannot be undone — the event is removed from the server immediately. Use only when the user explicitly requests deletion. Obtain the event URL and etag from list_events or calendar_query first. The etag ensures no conflicting changes occurred since the event was last retrieved.

Inputs: event_url (required), event_etag (required).

delete_todoA

Permanently delete a todo/task from the calendar. WARNING: This action cannot be undone — the todo is removed from the server immediately. Use only when the user explicitly requests deletion. Obtain the todo URL and etag from list_todos or todo_query first. The etag ensures no conflicting changes occurred since the todo was last retrieved.

Inputs: todo_url (required), todo_etag (required).

freebusy_queryA

Find free and busy time in a date range — use for "when am I free?", "am I available Tuesday afternoon?" or finding a slot for a new meeting. Searches all calendars unless one is given. Events marked TRANSPARENT (does not block time) and cancelled events are ignored; recurring events are expanded.

Inputs: time_range_end (required), time_range_start (required), calendar_url, include_event_details.

list_addressbooksA

List all available address books from the CardDAV server. Use this to get address book URLs needed for other contact operations

Inputs: no named parameters.

list_calendarsA

List all available calendars from the CalDAV server. Use this to get calendar URLs needed for other operations

Inputs: no named parameters.

list_contactsA

List ALL contacts from an address book without filtering. WARNING: Returns all contacts which can be thousands - use addressbook_query instead when searching for specific contacts by name, email, or organization to save tokens

Inputs: addressbook_url (required).

list_eventsA

List ALL events from a single calendar without filtering. WARNING: Returns all events which can be many thousands - use calendar_query instead for searching with filters (supports multi-calendar search).

Inputs: calendar_url (required), time_range_end, time_range_start.

list_todosA

List ALL todos/tasks from a calendar. WARNING: Returns all todos without filtering - use todo_query for searches with filters by status, summary, or due date.

Inputs: calendar_url (required).

make_calendarA

Create a new calendar collection on the CalDAV server with optional color, description, and component types. A timezone is accepted but not applied yet (the result says so). The URL is derived from display_name. If a calendar already exists at that URL, nothing is created and the error names the existing calendar — use it instead of creating another. If the URL is only held by something else (e.g. a deleted calendar in the trash bin), a numeric suffix is added (-2, -3, ...). Always use the URL returned in the response.

Inputs: display_name (required), color, timezone, components, +1 more.

todo_multi_getA

Batch fetch multiple specific todos by their URLs. More efficient than fetching one by one when you have exact todo URLs.

Inputs: todo_urls (required).

todo_queryA

⭐ PREFERRED: Search and filter todos efficiently. Use instead of list_todos to conserve tokens. Omit calendar_url to search across ALL calendars automatically.

Inputs: limit, calendar_url, status_filter, summary_filter, +2 more.

update_calendarB

Update an existing calendar's properties (display name, description, color, timezone). Use this when user asks to "rename calendar", "change calendar color", or "update calendar properties"

Inputs: calendar_url (required), color, timezone, description, +1 more.

update_contactB

PREFERRED: Update contact fields without vCard formatting. Supports: FN (full name), N (structured name), EMAIL, TEL (phone), ORG (organization), TITLE (job title), NOTE, URL, ADR (address), BDAY (birthday), and any RFC 6350 vCard property including custom X-* properties.

Inputs: vcard_url (required), vcard_etag (required), fields.

update_contact_rawA

ADVANCED: Update contact with raw vCard data. Requires manual vCard formatting - use update_contact instead for simple field updates (name, email, phone). Only use this if you have complete pre-formatted vCard data or need to update advanced vCard properties.

Inputs: vcard_url (required), vcard_etag (required), updated_vcard_data (required).

update_eventA

PREFERRED: Update event fields without iCal formatting. Use start_date/end_date/all_day to move an event or convert it between all-day and timed. Use fields for everything else: SUMMARY (title), DESCRIPTION (details), LOCATION (place), STATUS (TENTATIVE/CONFIRMED/CANCELLED), and any other RFC 5545 property including custom X-* properties (e.g., X-ZOOM-LINK, X-MEETING-ROOM).

Inputs: event_url (required), event_etag (required), fields, all_day, +2 more.

update_event_rawA

ADVANCED: Update event with raw iCal data. Requires manual iCal formatting - use update_event instead for simple field updates (summary, description). Only use this if you have complete pre-formatted iCal data or need to update advanced iCal properties.

Inputs: event_url (required), event_etag (required), updated_ical_data (required).

update_todoA

PREFERRED: Update todo fields without iCal formatting. Supports: SUMMARY (title), DESCRIPTION (details), STATUS (NEEDS-ACTION/IN-PROCESS/COMPLETED/CANCELLED), PRIORITY (0-9), DUE (due date), PERCENT-COMPLETE (0-100), and any RFC 5545 VTODO property including custom X-* properties.

Inputs: todo_url (required), todo_etag (required), fields.

update_todo_rawA

ADVANCED: Update todo with raw VTODO iCal data. Requires manual iCal formatting - use update_todo instead for simple field updates (summary, description, status). Only use this if you have complete pre-formatted VTODO data or need to update advanced iCal properties.

Inputs: todo_url (required), todo_etag (required), updated_ical_data (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 27 tools

    Disambiguation4/5

    Tools are cleanly partitioned by resource (calendar/event/contact/todo) and descriptions explicitly disambiguate list vs query vs multi_get and update vs update_raw, with PREFERRED/WARNING markers guiding selection. There is genuine overlap among the three read paths for each resource (e.g. list_events vs calendar_query vs calendar_multi_get), but descriptions make the boundaries clear.

    Naming Consistency4/5

    Most tools follow a verb_noun pattern (list_events, create_contact, update_todo, delete_calendar) consistently. Deviations are systematic rather than chaotic: the noun-first *_query and *_multi_get families, the *_raw suffix variants, and make_calendar instead of create_calendar. Readable overall but not a single uniform convention.

    Tool Count4/5

    27 tools is on the heavy side, but it reflects a broad CalDAV/CardDAV domain spanning calendars, events, todos, contacts, and addressbooks, each with its own CRUD lifecycle. The count is inflated somewhat by per-resource *_raw and list/query/multi_get variants, but each tool serves a defensible purpose.

    Completeness4/5

    Full lifecycle coverage (list/query/create/update/delete) exists for events, todos, and contacts, plus calendar management and freebusy queries. Minor gaps remain: addressbooks can only be listed (no create/update/delete), and there is no dedicated attendee/RSVP handling for events.

    Maintenance

    ActivityMaintained
    ResponsivenessMixed handling

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      A
      maintenance
      Connects 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.
      732 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables AI assistants to connect to CalDAV servers and manage calendars, events, and tasks through tools for listing, creating, updating, completing, and deleting items.
      732 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Connects AI assistants to CalDAV servers so they can list calendars, browse events within a timeframe, and create, update, delete, or complete events and tasks (VTODOs) through natural language. Supports recurring events, all-day entries, and todo filtering by status or due date with pagination.
      732 npm
      MIT