π A CardDAV Model Context Protocol (MCP) server to expose contacts and address books as tools for AI assistants.
- Connect to CardDAV servers
- List address books
- List contacts in an address book
- Get the full details of a single contact
- Create contacts (vCard)
- Update contacts β partial updates that preserve vCard properties written by other clients
- Delete contacts by UID
{
"mcpServers": {
...,
"contacts": {
"command": "npx",
"args": [
"carddav-mcp"
],
"env": {
"CARDDAV_BASE_URL": "<CardDAV server URL>",
"CARDDAV_USERNAME": "<CardDAV username>",
"CARDDAV_PASSWORD": "<CardDAV password>"
}
}
}
}
Run the MCP server in development mode with auto-reload:
npm run devThis will run the TypeScript code directly with watch mode and automatically load environment variables from .env.
Alternatively, you can compile TypeScript to JavaScript and run it:
- Compile:
npx tsc- Run:
node dist/index.jsList all address books returning both name and URL
Parameters: none
Returns:
- List of all available address books
List all contacts in the address book specified by its URL. Returns a summary per contact; use get-contact for full details.
Parameters:
addressBookUrl: string
Returns:
- A list of contacts, each containing
uid,fn(formatted name),emails, andphones
Get the full details of a single contact in the address book specified by its URL
Parameters:
uid: string β Unique identifier of the contact to fetch (obtained from list-contacts)addressBookUrl: string
Returns:
- The contact's parsed fields (
uid,fn,name,emails,phones, and optionallyorg,title,note) plus the raw vCard invcard
Creates a contact (vCard) in the address book specified by its URL. If name is omitted, structured name parts are derived from fn.
Parameters:
addressBookUrl: stringfn: string β Formatted display name of the contactname: object (optional) β Structured name parts (family, given, middle, ...)family: string (optional)given: string (optional)middle: string (optional)prefix: string (optional)suffix: string (optional)
emails: array of string (optional)phones: array of string (optional)org: string (optional) β Organization / companytitle: string (optional) β Job title or rolenote: string (optional)
Returns:
- The unique ID of the created contact
Updates an existing contact in the address book specified by its URL. Only provided fields are changed; emails and phones replace the full list (pass an empty array to clear them, or an empty string to clear org, title, or note). Other vCard properties are preserved.
Parameters:
uid: string β Unique identifier of the contact to update (obtained from list-contacts)addressBookUrl: stringfn: string (optional)name: object (optional)family: string (optional)given: string (optional)middle: string (optional)prefix: string (optional)suffix: string (optional)
emails: array of string (optional)phones: array of string (optional)org: string (optional)title: string (optional)note: string (optional)
Returns:
- The unique ID of the updated contact
Deletes a contact in the address book specified by its URL
Parameters:
uid: string β Unique identifier of the contact to delete (obtained from list-contacts)addressBookUrl: string
Returns:
- Confirmation message when the contact is successfully deleted
Two complementary end-to-end checks against a real CardDAV server (both read credentials from .env):
npm run smokeβ deterministic SDK harness (scripts/smoke.ts). Spawns the built server over stdio via the MCP client SDK and asserts the create β list β get β update β delete contact round-trip.npm run smoke:agentβ agent-ergonomics harness (scripts/smoke-agent.sh). Drives the server viaclaude -pwith a JSON output schema, validating that tool names, descriptions, schemas, and error messages are usable by an LLM.