CalDAV calendar operations (list, create, update, delete events) as MCP tools.
SaferSkills independently audited caldav-mcp (MCP Server) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<div align="center">
🗓️ A CalDAV Model Context Protocol (MCP) server to expose calendar operations as tools for AI assistants.
</div>
{
"mcpServers": {
...,
"calendar": {
"command": "npx",
"args": [
"caldav-mcp"
],
"env": {
"CALDAV_BASE_URL": "<CalDAV server URL>",
"CALDAV_USERNAME": "<CalDAV username>",
"CALDAV_PASSWORD": "<CalDAV 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:
npx tscnode dist/index.js<!-- TOOLS:START - generated by scripts/gen-tool-docs.ts -->
List all calendars returning both name and absolute URL. Pass a calendar's url unchanged as calendarUrl to the other tools.
Parameters: none
Returns:
List all events between start and end date in the calendar specified by its URL
Parameters:
calendarUrl: stringend: string — End date (ISO 8601)start: string — Start date (ISO 8601)Returns:
uid, summary, start, end, and optionally description and locationCreates an event in the calendar specified by its URL. For all-day events, set wholeDay to true. For a single-day all-day event, use start and end datetimes on the same calendar date; they do not need to be identical timestamps.
Parameters:
calendarUrl: stringdescription: string (optional)end: string — End datetime (ISO 8601)location: string (optional)recurrenceRule: object (optional)byday: array of string (optional)bymonth: array of number (optional)bymonthday: array of number (optional)count: number (optional)freq: enum (DAILY | WEEKLY | MONTHLY | YEARLY) (optional)interval: number (optional)until: string (optional)start: string — Start datetime (ISO 8601)summary: stringwholeDay: boolean (optional) — Create as a whole-day eventReturns:
Updates an existing event in the calendar specified by its URL. Only provided fields are changed. For a one-day full-day event, set wholeDay to true and set start and end to the same calendar day.
Parameters:
calendarUrl: stringdescription: string (optional)end: string (optional)location: string (optional)recurrenceRule: object (optional)byday: array of string (optional)bymonth: array of number (optional)bymonthday: array of number (optional)count: number (optional)freq: enum (DAILY | WEEKLY | MONTHLY | YEARLY) (optional)interval: number (optional)until: string (optional)start: string (optional)summary: string (optional)uid: string — Unique identifier of the event to update (obtained from list-events)wholeDay: boolean (optional) — Update whether this is a whole-day eventReturns:
Deletes an event in the calendar specified by its URL
Parameters:
calendarUrl: stringuid: string — Unique identifier of the event to delete (obtained from list-events)Returns:
List tasks (VTODOs) in the calendar specified by its URL. By default returns only open tasks (NEEDS-ACTION and IN-PROCESS), sorted by manual order then due date. Use status to include completed (COMPLETED) or all (ALL) tasks, and limit/offset to page through long lists.
Parameters:
calendarUrl: stringdue_after: string (optional) — Only tasks with a due date at or after this (ISO 8601). Undated tasks are excluded when a due window is set.due_before: string (optional) — Only tasks with a due date at or before this (ISO 8601). Undated tasks are excluded when a due window is set.limit: number (optional) — Max tasks to return (default 50, max 500)offset: number (optional) — Tasks to skip (default 0)status: enum (OPEN | ALL | NEEDS-ACTION | COMPLETED | IN-PROCESS | CANCELLED) (optional) — Filter by status. OPEN (default) = NEEDS-ACTION + IN-PROCESS; ALL = everything; or an exact status (NEEDS-ACTION, COMPLETED, IN-PROCESS, CANCELLED).Returns:
{ todos, total, limit, offset } where total is the count before pagination. Each todo has uid, summary, status, and optionally due, start, completed, description, location.Creates a task (VTODO) in the calendar specified by its URL. Only summary is required; a task may have no dates. Use due for a deadline and start for when work should begin.
Parameters:
calendarUrl: stringdescription: string (optional)due: string (optional) — Due datetime (ISO 8601)location: string (optional)start: string (optional) — Start datetime (ISO 8601)status: enum (NEEDS-ACTION | COMPLETED | IN-PROCESS | CANCELLED) (optional) — Defaults to NEEDS-ACTION when omittedsummary: stringReturns:
Updates an existing task (VTODO) in the calendar specified by its URL. Only provided fields are changed. To mark a task done, prefer the complete-todo tool.
Parameters:
calendarUrl: stringdescription: string (optional)due: string (optional)location: string (optional)start: string (optional)status: enum (NEEDS-ACTION | COMPLETED | IN-PROCESS | CANCELLED) (optional)summary: string (optional)uid: string — Unique identifier of the todo to update (from list-todos)Returns:
Marks a task (VTODO) as done. Sets its status to COMPLETED and records the completion time.
Parameters:
calendarUrl: stringuid: string — Unique identifier of the todo to complete (from list-todos)Returns:
Deletes a task (VTODO) in the calendar specified by its URL
Parameters:
calendarUrl: stringuid: string — Unique identifier of the todo to delete (from list-todos)Returns:
<!-- TOOLS:END -->
MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.