CalDAV MCP Server
This CalDAV MCP server lets an MCP client manage iCloud Calendar events over CalDAV.
List available calendars and obtain opaque
calendar_idvalues with best-effort writable status.List events in a semi-open date range up to 366 days, expanding recurring series into occurrences with pagination and chronological ordering.
Read one event by opaque
resource_idor bycalendar_idplus UID, optionally including raw iCalendar for diagnostics.Create timed, all-day, and recurring events with optional location, description, and up to 20
DISPLAYalarms.Update an existing event or complete recurring series with partial patches, preserving omitted/unknown iCalendar data;
nullclears nullable fields andalarms: []removes alarms.Use ETags with
expected_etagfor optimistic concurrency during updates and deletions.Delete an event or entire recurring series, optionally requiring an observed ETag.
Read and write Apple Calendar travel time in the README-described implementation, though this field is not present in the provided schema.
Run via
stdioor Streamable HTTP, with sensitive credentials/raw calendar data redacted from logs and errors.Manage one configured iCloud account per server process; individual recurrence occurrence edits/deletes and attendee scheduling are not supported.
Allows managing iCloud Calendar events, including creating, updating, deleting, and listing events with support for alarms and recurrence.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@CalDAV MCP Serverlist events from my work calendar for next Monday"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
CalDAV MCP Server
CalDAV MCP Server is a Model Context Protocol server for managing iCloud Calendar
events, including native support for multiple VALARM reminders on one event.
iCloud Calendar is the only provider officially supported and manually validated in the
first release. The server works with any MCP client that supports stdio or Streamable
HTTP.
This independent project is not affiliated with, authorized, sponsored, or approved by Apple Inc. Apple and iCloud are trademarks of their respective owner.
Quick start
Create an Apple app-specific password, then pick the option for your client.
Claude Desktop (one click, no Node.js install): download
caldav-mcp.mcpb,
open it with Claude Desktop, and enter your Apple Account email and app-specific
password. See Claude Desktop extension.
Any other stdio client: install Node.js 22 or newer and
add this server to a JSON-configured MCP client such as Gemini CLI or Claude Code:
{
"mcpServers": {
"icloud-calendar": {
"command": "npx",
"args": ["--yes", "@lukegskw/caldav-mcp@latest"],
"env": {
"CALDAV_USERNAME": "user@example.com",
"CALDAV_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
}
}
}
}Restart the client and confirm that it lists six calendar tools. See client-specific setup and Docker deployment below. Keep the configuration file private because it contains the app-specific password.
Related MCP server: DAV MCP Server
Navigation
About
The server connects one configured account to iCloud through CalDAV. It discovers the account's calendars and exposes normalized read and write operations through MCP.
Updates preserve the complete iCalendar resource, including unknown properties, Apple
extensions, VTIMEZONE, recurrence exceptions, and alarms omitted from a patch. Writes
use opaque resource identifiers and ETags instead of assuming that a CalDAV filename
matches an event UID.
Calendar resources are processed in memory. The server has no telemetry and no application database, and raw iCalendar is returned only when explicitly requested.
Features
Discovers calendars available to the configured iCloud account.
Lists events in semi-open time ranges and expands recurring occurrences.
Creates timed, all-day, and recurring events.
Supports zero, one, or multiple display alarms per event.
Reads and writes Apple Calendar travel time (
X-APPLE-TRAVEL-DURATION).Emits the Apple alarm extensions expected by iCloud Calendar.
Reads events by opaque resource ID or by calendar ID and UID.
Applies partial updates while preserving omitted and unknown iCalendar data.
Uses ETags for optimistic concurrency on updates and deletions.
Rejects isolated recurrence mutations instead of changing the complete series.
Redacts credentials, raw calendar content, and CalDAV paths from logs and errors.
Runs as a non-root container with a read-only root filesystem configuration.
Supports
stdioand Streamable HTTP MCP transports.
MCP tools
list_calendars
Lists the calendars discovered for the configured account. Each result includes an
opaque calendar_id, display name, description, timezone, and best-effort write status.
list_events
Lists events in a semi-open interval and expands recurring occurrences. The maximum range is 366 days, the default page size is 100, and the maximum page size is 500. Results use a deterministic chronological order. Pagination cursors are opaque and do not represent a snapshot when events are modified during traversal.
Example input:
{
"calendar_id": "opaque-calendar-id",
"start": "2026-09-01T00:00:00Z",
"end": "2026-10-01T00:00:00Z",
"timezone": "Europe/Berlin",
"limit": 100
}get_event
Reads an event by resource_id, or by a calendar_id and UID pair. Raw iCalendar is
excluded by default and can be requested with include_raw_ical: true for controlled
diagnostics.
create_event
Creates an event and reads back the representation stored by the server.
Timed event with two alarms:
{
"calendar_id": "opaque-calendar-id",
"summary": "Buy Shinkansen tickets",
"start": {
"date_time": "2026-09-06T03:00:00+02:00",
"timezone": "Europe/Berlin"
},
"end": {
"date_time": "2026-09-06T03:30:00+02:00",
"timezone": "Europe/Berlin"
},
"description": "Smart-EX",
"location": null,
"alarms": [
{ "minutes_before": 1440, "action": "DISPLAY" },
{ "minutes_before": 0, "action": "DISPLAY" }
],
"rrule": null
}All-day event with an exclusive end date:
{
"calendar_id": "opaque-calendar-id",
"summary": "Trip",
"start": { "date": "2026-09-06" },
"end": { "date": "2026-09-08" },
"alarms": []
}Recurring events accept an RFC 5545 rule without the RRULE: prefix:
{
"calendar_id": "opaque-calendar-id",
"summary": "Weekly planning",
"start": {
"date_time": "2026-09-07T09:00:00+02:00",
"timezone": "Europe/Berlin"
},
"end": {
"date_time": "2026-09-07T09:30:00+02:00",
"timezone": "Europe/Berlin"
},
"rrule": "FREQ=WEEKLY;BYDAY=MO;COUNT=10"
}Timed event with 30 minutes of Apple Calendar travel time:
{
"calendar_id": "opaque-calendar-id",
"summary": "Dentist",
"start": {
"date_time": "2026-10-05T10:00:00+02:00",
"timezone": "Europe/Amsterdam"
},
"end": {
"date_time": "2026-10-05T10:30:00+02:00",
"timezone": "Europe/Amsterdam"
},
"travel_minutes": 30
}travel_minutes sets a fixed travel duration before the event. In this example,
travel starts at 09:30 and the appointment stays at 10:00–10:30. The server accepts
whole minutes from 1 to 1,440 for timed events; omit the field or use null when
creating an event without travel time. It does not calculate routes or change
the event's start, end, or alarms.
The duration is stored in Apple's X-APPLE-TRAVEL-DURATION extension. Display in
other calendar clients depends on their support for that extension. Returned
events include travel_minutes, rounded to the nearest whole minute, or null
when the duration is missing, invalid, or rounds to zero.
update_event
Patches an event or the master event of a recurring series. Omitted fields are
preserved, null removes a nullable field, and alarms: [] removes all alarms. An
optional expected_etag prevents overwriting a newer server version.
For travel time, omit patch.travel_minutes to keep the current value, set it to a
number to replace the duration, or set it to null to remove the duration and
related Apple routing metadata. For example, "patch": { "travel_minutes": null }
clears travel time. When converting an event with travel time to all-day, include
travel_minutes: null alongside the new start and end dates. Existing recurrence
exceptions retain their own travel settings.
delete_event
Deletes an event or complete recurring series, optionally requiring an observed ETag. Deleting a single expanded occurrence is not supported in the current release.
Tech stack
TypeScript with strict project rules
Installation
Prerequisites
An iCloud account with Calendar enabled.
Two-factor authentication enabled for the Apple Account.
Docker and Docker Compose for container deployment, Node.js 22+ for
npx, or Claude Desktop for the one-click extension.pnpm is required only when building from source. Corepack and CI use the version pinned in
package.json.
Node.js requirements
Use | Node.js |
Claude Desktop extension ( | None to install; Claude Desktop uses its built-in Node.js |
| 22 LTS or newer; CI tests 22 and 24 |
Docker image | None to install; the image ships Node.js 24 |
Building from source and contributing | 22.13 or newer, required by ESLint 10 and Vitest 5; 24 recommended |
engines.node in package.json is >=22. Node.js 20 reached end of life in April 2026
and is not supported; npm prints an EBADENGINE warning on older versions. Check the
version your MCP client will use with node --version. Desktop clients may use a
different node than your terminal, so if a client cannot start the server, point it at
the absolute path of a Node.js 22+ npx (command -v npx on macOS/Linux, where npx
on Windows).
npm / npx
No global install or repository clone is required. MCP clients can launch the latest published package directly:
CALDAV_USERNAME='user@example.com' \
CALDAV_PASSWORD='xxxx-xxxx-xxxx-xxxx' \
npx --yes @lukegskw/caldav-mcp@latestThe command waits for MCP messages on stdin and normally prints nothing to stdout. In
practice, add it to the client configuration as shown in MCP client setup.
For reproducible environments, replace latest with an exact published version such as
X.Y.Z.
Docker Compose
The recommended installation uses the published multi-architecture image:
ghcr.io/lukegskw/caldav-mcp:latestDownload the Compose example:
curl -O https://raw.githubusercontent.com/lukegskw/caldav-mcp/main/compose.example.yamlProvide the Apple Account email and app-specific password, then start the service:
export CALDAV_USERNAME='user@example.com'
export CALDAV_PASSWORD='xxxx-xxxx-xxxx-xxxx'
docker compose -f compose.example.yaml up -dTo publish a different host port, set:
export CALDAV_MCP_PUBLISHED_PORT=18100
docker compose -f compose.example.yaml up -dThe latest tag follows the newest stable release. Stable releases also publish an
exact tag such as 0.1.6 and a minor-series tag such as 0.1. The Compose example
pins latest by digest so deployments are reproducible. To upgrade, download the
updated Compose example or replace the full image reference with the desired
published version and digest.
The Streamable HTTP endpoint will be available at:
http://<host>:8100/mcpThe host port can change without changing port 8100 inside the container. No
persistent volume is required; calendar data remains in iCloud.
Docker run
The same hardened container configuration can be started directly:
docker run -d \
--name caldav-mcp \
--restart unless-stopped \
--read-only \
--user 10001:10001 \
--cap-drop ALL \
--security-opt no-new-privileges:true \
--tmpfs /tmp:size=16m,mode=1777 \
-e CALDAV_PROVIDER=icloud \
-e CALDAV_USERNAME \
-e CALDAV_PASSWORD \
-e CALDAV_MCP_TRANSPORT=streamable-http \
-e CALDAV_MCP_HOST=0.0.0.0 \
-p 8100:8100 \
ghcr.io/lukegskw/caldav-mcp:latestBuild the container from source
Building locally is optional. Prefer the published image unless you need to modify or audit the container build.
git clone https://github.com/lukegskw/caldav-mcp.git
cd caldav-mcp
docker buildx build --load -t caldav-mcp:local .Local Node.js installation
Building from source requires Node.js 22.13 or newer; Node.js 24 is recommended.
Builds and typechecks use TypeScript 7. The typescript dependency aliases
@typescript/typescript6 for ESLint, which still requires the TypeScript 6 API;
@typescript/native supplies TypeScript 7’s tsc executable. See the
TypeScript migration guidance.
git clone https://github.com/lukegskw/caldav-mcp.git
cd caldav-mcp
pnpm install --frozen-lockfile
cp .env.example .env
pnpm build
pnpm start -- --transport stdioIn stdio mode, stdout is reserved exclusively for MCP messages. To run Streamable HTTP
locally:
CALDAV_MCP_TRANSPORT=streamable-http pnpm startConfiguration
All settings use the CALDAV_ or CALDAV_MCP_ prefix.
Variable | Required | Default | Description |
| No |
| Provider policy. iCloud is the supported profile. |
| No |
| CalDAV discovery URL. |
| Yes | None | Apple Account email. |
| Yes | None | App-specific password, not the account password. |
| No |
|
|
| No |
| HTTP bind address. |
| No |
| HTTP listening port. |
| No |
| Application log level. |
| No |
| CalDAV request timeout. |
The core retains an experimental generic provider policy and configurable URL to keep
Apple extensions isolated from the shared iCalendar implementation. No compatibility
with other providers is currently claimed.
Secrets must be supplied through the deployment platform or environment. Never commit
.env, pass credentials as MCP tool arguments, or include them in diagnostic reports.
MCP client setup
Claude Desktop extension (recommended)
Claude Desktop for macOS and Windows installs the server as a one-click MCP Bundle and runs it with its built-in Node.js:
Download
caldav-mcp.mcpbfrom the latest release.Open it with Claude Desktop (double-click it, or drag it onto Settings -> Extensions) and choose Install.
Enter the Apple Account email and app-specific password. The password is stored as a sensitive setting.
To upgrade, install the .mcpb from a newer release. See
Claude Desktop extension for bundle contents and
how it is built and released.
Gemini CLI extension
Install directly from GitHub and enable automatic extension updates:
gemini extensions install https://github.com/lukegskw/caldav-mcp --auto-updateGemini prompts for the username and stores the app-specific password as a sensitive setting. The public extension gallery discovers tagged releases from this repository.
Manual configuration
For any MCP client that accepts Streamable HTTP server definitions, configure the URL:
mcp_servers:
caldav:
url: http://<host>:8100/mcpIf the client shares the Compose network, use the service name and internal port:
mcp_servers:
caldav:
url: http://caldav-mcp:8100/mcpFor clients that launch local stdio servers, prefer the npm command from
Quick start. If a desktop client cannot find npx, use the absolute
path reported by command -v npx on macOS/Linux or where npx on Windows.
Claude Desktop
The extension is the simplest option. To
configure the server manually instead, add the Quick start JSON under
mcpServers in claude_desktop_config.json, then completely restart Claude Desktop.
Open the file through Settings -> Developer -> Edit Config instead of assuming its
location.
Claude Code
Claude Code can add the same stdio server at
user scope:
claude mcp add --transport stdio --scope user \
--env CALDAV_USERNAME=user@example.com \
--env CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx \
icloud-calendar -- npx --yes @lukegskw/caldav-mcp@latestThis command places the values in Claude's MCP configuration. Avoid running it where shell history is shared or retained insecurely.
Codex
Codex can add the server to its shared CLI and IDE configuration:
codex mcp add icloud-calendar \
--env CALDAV_USERNAME=user@example.com \
--env CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-- npx --yes @lukegskw/caldav-mcp@latestRun codex mcp list to verify it. For finer control, use the
official Codex MCP configuration in
~/.codex/config.toml or a project-scoped .codex/config.toml.
Gemini CLI
Following the Gemini CLI MCP configuration,
add the server under mcpServers in ~/.gemini/settings.json (user scope) or the
project's .gemini/settings.json:
{
"mcpServers": {
"icloud-calendar": {
"command": "npx",
"args": ["--yes", "@lukegskw/caldav-mcp@latest"],
"env": {
"CALDAV_USERNAME": "user@example.com",
"CALDAV_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
}
}
}
}Claude Desktop (Docker, stdio alternative)
Claude Desktop launches local stdio servers as subprocesses. Running the published
container this way keeps the app-specific password on the client machine and opens no
network port, which matches the transport guidance in Limitations.
Add the server to claude_desktop_config.json:
{
"mcpServers": {
"icloud-calendar": {
"command": "/absolute/path/to/docker",
"args": [
"run",
"-i",
"--rm",
"--env-file",
"/absolute/path/to/caldav-mcp.env",
"-e",
"CALDAV_PROVIDER=icloud",
"-e",
"CALDAV_MCP_TRANSPORT=stdio",
"ghcr.io/lukegskw/caldav-mcp@sha256:<digest>"
]
}
}
}-i is required. Without an attached stdin the client cannot speak MCP to the
container. --rm removes the container once the client stops it.
Supply credentials through --env-file rather than -e. Arguments passed to
docker run are visible in the host process list; the contents of an env file are not.
The file holds the variables described in Configuration:
CALDAV_USERNAME=user@example.com
CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxxPin the image by digest instead of latest, so that restarting the client cannot
silently start a different version:
docker pull ghcr.io/lukegskw/caldav-mcp:latest
docker images --digests ghcr.io/lukegskw/caldav-mcpRestart Claude Desktop completely after editing the configuration file.
Windows
When Claude Desktop is installed from the Microsoft Store, Windows redirects
%APPDATA%\Claude into the package container and the file lives at:
%LOCALAPPDATA%\Packages\Claude_<package-id>\LocalCache\Roaming\Claude\claude_desktop_config.jsonIn that case dir %APPDATA%\Claude reports nothing. Server logs are written next to the
configuration file, in logs\mcp-server-<server-name>.log.
Use the absolute path to docker.exe, because PATH inside the package container is
not reliable. where docker prints it, typically
C:\Program Files\Docker\Docker\resources\bin\docker.exe. Backslashes must be escaped
in JSON.
Configuration formats differ between MCP clients. Consult the client's documentation for its exact schema and reload or restart it after changing the server definition.
Verification
Check the container state and logs:
docker compose -f compose.example.yaml ps
docker compose -f compose.example.yaml logs caldav-mcpThe container should report healthy. The TCP healthcheck validates the server process,
not iCloud credentials.
Run the repository verification suite:
pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test:unit
pnpm test:integration
pnpm build
pnpm test:package
pnpm test:distribution
pnpm build:mcpb
pnpm test:mcpbFinally, connect with an MCP client and confirm that all six tools are listed.
Limitations
One iCloud account is configured per server process or container.
The Streamable HTTP endpoint has no authentication in the current release. Restrict it to a trusted LAN, VPN, or private container network; do not expose it directly to the internet.
Individual recurrence occurrences are read-only. Updating or deleting the complete series is supported.
Only
ACTION:DISPLAYalarms are created.Individual iCalendar resources are limited to 5 MiB.
Event list ranges are limited to 366 days and pages to 500 results.
Events may contain at most 20 alarms.
Attendee scheduling is outside the current scope.
Providers other than iCloud are not officially supported.
Review SECURITY.md before reporting a security issue or attaching diagnostics.
Contributing
Contributions are welcome. Before opening a pull request:
pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build
docker buildx build --load -t caldav-mcp:test .Changes to CalDAV writes or iCalendar serialization must preserve ETag checks, opaque
resource boundaries, unknown properties, recurrence exceptions, and alarms omitted from
patches. TypeScript changes must continue to satisfy the rules in
.codex/rules/typescript.md.
Releasing
Releases are version-driven and automated from main so that a partial registry outage
can be retried without publishing a second npm version.
Prepare the new version with
pnpm release:prepare X.Y.Z. This synchronizes the npm, MCP Registry, Gemini, and MCP Bundle (manifest.json) metadata.Run the verification suite, including
pnpm test:distributionandpnpm test:mcpb.Commit and push the release changes to
main.The release workflow validates the commit and creates the matching
vX.Y.Ztag automatically before publishing.
The release workflow validates the versions, tests the packed npm artifact and the
Claude Desktop bundle, and publishes the exact, minor-series, and latest container
tags together with the npm package, MCP Registry entry, and GitHub release with
caldav-mcp.mcpb attached. Prereleases receive only their exact
container tag. Gemini can discover the tagged extension without another per-release
edit. A rerun skips matching artifacts that already exist and resumes the missing
steps. See Claude Desktop extension for building,
testing, and shipping the .mcpb bundle.
License
MIT. See LICENSE.
Available Tools
6 toolscreate_eventCreate calendar eventA
Create a new event in a writable iCloud calendar and return the stored representation; existing events are not changed. Use list_calendars first to obtain calendar_id, and use update_event when the event already exists. Timed values require matching offsets and timezones, all-day end dates are exclusive, recurrence rules omit the RRULE: prefix, and travel_minutes sets Apple Calendar travel time for timed events.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | Event end using the same temporal type and timezone as start; an all-day end date is exclusive. | |
| rrule | No | RFC 5545 recurrence rule without the RRULE: prefix; defaults to null. | |
| start | Yes | Event start as a timed date-time or all-day date. | |
| alarms | No | Display reminders; defaults to an empty array. | |
| summary | Yes | Event title, between 1 and 1,024 characters. | |
| location | No | Event location; defaults to null. | |
| calendar_id | Yes | Opaque destination calendar ID returned by list_calendars. | |
| description | No | Event notes; defaults to null. | |
| travel_minutes | No | Apple Calendar travel time in whole minutes before the start; defaults to null. Only valid for timed events. |
Output Schema
| Name | Required | Description |
|---|---|---|
| end | Yes | Normalized event end. |
| uid | Yes | Stored iCalendar UID. |
| etag | Yes | Current ETag for optimistic concurrency, when available. |
| href | Yes | Redacted fingerprint of the CalDAV resource URL. |
| rrule | Yes | Stored RFC 5545 recurrence rule without the RRULE: prefix. |
| start | Yes | Normalized event start. |
| alarms | Yes | Normalized alarms attached to the event. |
| summary | Yes | Stored event title. |
| location | Yes | Stored event location. |
| raw_ical | No | Raw iCalendar resource, included only when explicitly requested. |
| recurring | Yes | Whether this event belongs to a recurring series. |
| calendar_id | Yes | Opaque ID of the containing calendar. |
| description | Yes | Stored event notes. |
| resource_id | Yes | Opaque event ID accepted by get_event, update_event, and delete_event. |
| recurrence_id | Yes | Occurrence identifier for an expanded recurring event. |
| travel_minutes | Yes | Apple Calendar travel time in whole minutes before the start, or null when none is set. |
| recurrence_exception | Yes | Whether this result is an overridden recurrence instance. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a non-read-only, non-idempotent, open-world, non-destructive operation. The description adds useful behavioral context: it writes to a writable iCloud calendar, returns the stored representation, and explicitly states existing events are not changed. It omits permission and rate-limit details, but the annotation coverage lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and usage, then consolidates key temporal and recurrence constraints without wasted text. Every clause carries actionable meaning for invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a nine-parameter create tool with full schema coverage, annotations, and an output schema, the description covers purpose, prerequisites, alternatives, and critical formatting semantics. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents matching timezone offsets, exclusive all-day end dates, the RRULE prefix omission, and travel_minutes being valid only for timed events. The description repeats and emphasizes these constraints but adds little genuinely new parameter-level meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: create a new event in a writable iCloud calendar. It also clarifies that it returns the stored representation and does not modify existing events, which distinguishes it from update_event and other sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly directs the agent to call list_calendars first to obtain calendar_id, and names update_event as the alternative when the event already exists. This gives clear prerequisites and a concrete routing rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_eventDelete calendar eventADestructiveIdempotent
Permanently delete an event or entire recurring series; individual expanded occurrences are not supported. Target it by resource_id or by calendar_id with uid, and supply expected_etag when available to prevent deleting a concurrently changed event.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | No | iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable. | |
| calendar_id | No | Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable. | |
| resource_id | No | Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid. | |
| expected_etag | No | ETag previously returned for the event. When supplied, deletion fails if the event changed since it was read. |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | Yes | Confirms that the resource was deleted. |
| resource_id | Yes | Opaque ID of the deleted event resource. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true and readOnlyHint=false, but the description adds important context beyond them: 'Permanently delete' emphasizes irreversibility, 'entire recurring series' expands the blast radius, and the expected_etag note explains concurrency behavior. No contradiction with annotations; the description makes the destructive semantics vivid and accurate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences carry all essential information with no filler: the action first, then scope, then targeting alternatives, then expected_etag usage. Every clause earns its place, and the most important constraints are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential behavior, the full targeting mechanism, a concurrency safety mechanism, and a key unsupported edge case. An output schema is present, so return-value details need not be described, and the tool is simple enough that nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and each parameter already has a detailed description, including the 'provide it together/alone' relationship between uid, calendar_id, and resource_id. The description essentially paraphrases the same targeting and etag guidance without adding substantial new meaning, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with the specific verb 'delete' and resource 'event or entire recurring series', clearly distinguishing this destructive operation from create/update siblings. It explicitly calls out a key behavioral nuance (expanded occurrences not supported) that makes the tool's scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete targeting instructions: use resource_id, or calendar_id with uid, and optionally expected_etag to guard against concurrent changes. It also states the exclusion for individual expanded occurrences, but it doesn't explicitly compare against alternatives like update_event when modification is desired. This is clear context with minor missing explicit 'when-not-to-use' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventGet calendar eventARead-onlyIdempotent
Read one event by resource_id, preferably from a previous result, or by the calendar_id and uid pair. Use list_events for range searches. Request raw iCalendar only for controlled diagnostics because it may contain sensitive calendar data.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | No | iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable. | |
| calendar_id | No | Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable. | |
| resource_id | No | Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid. | |
| include_raw_ical | No | Include the raw iCalendar resource for controlled diagnostics; it may contain sensitive calendar data. Defaults to false. |
Output Schema
| Name | Required | Description |
|---|---|---|
| end | Yes | Normalized event end. |
| uid | Yes | Stored iCalendar UID. |
| etag | Yes | Current ETag for optimistic concurrency, when available. |
| href | Yes | Redacted fingerprint of the CalDAV resource URL. |
| rrule | Yes | Stored RFC 5545 recurrence rule without the RRULE: prefix. |
| start | Yes | Normalized event start. |
| alarms | Yes | Normalized alarms attached to the event. |
| summary | Yes | Stored event title. |
| location | Yes | Stored event location. |
| raw_ical | No | Raw iCalendar resource, included only when explicitly requested. |
| recurring | Yes | Whether this event belongs to a recurring series. |
| calendar_id | Yes | Opaque ID of the containing calendar. |
| description | Yes | Stored event notes. |
| resource_id | Yes | Opaque event ID accepted by get_event, update_event, and delete_event. |
| recurrence_id | Yes | Occurrence identifier for an expanded recurring event. |
| travel_minutes | Yes | Apple Calendar travel time in whole minutes before the start, or null when none is set. |
| recurrence_exception | Yes | Whether this result is an overridden recurrence instance. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so safety is covered; the description contributes the extra warning that raw iCalendar output may contain sensitive calendar data and should be reserved for diagnostics. It doesn't cover lookup failure behavior (e.g., what happens if the resource_id is stale), which is the only material gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the primary lookup path before the alternative and the parameter caveat. No sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Required-params is zero and the real constraint (resource_id alone OR calendar_id + uid) is not encoded as a schema requirement, so the description carrying that selection logic is exactly what's needed. With annotations and an output schema present, nothing else is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both the either/or key selection and the include_raw_ical sensitivity caveat are already documented in the property descriptions. The description restates rather than adds to them, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one event') and immediately names the two valid lookup keys (resource_id, or calendar_id + uid pair). It also distinguishes itself from list_events, so an agent can tell it apart from a sibling without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes range searching to the alternative ('Use list_events for range searches') and gives a preference rule ('preferably from a previous result') for choosing resource_id over the composite key. It also scopes the raw iCalendar option to controlled diagnostics, which is a when-to-use constraint on a parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_calendarsList calendarsARead-onlyIdempotent
List calendars available in the configured iCloud account. Use this first to obtain the opaque calendar_id required by list_events and create_event; writable is a best-effort capability indicator.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| calendars | Yes | Calendars available to the configured account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already establish read-only, idempotent, and non-destructive behavior, and the description adds meaningful context: the writable field is only a best-effort capability indicator, and calendar IDs are opaque. This helps the agent avoid over-trusting the writable flag and treating IDs as human-readable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences with no filler. It leads with the core function and then adds the most important usage detail, making it easy to scan and act on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that the tool takes no parameters, has a rich set of annotations, and has an output schema, the description covers all necessary context: what is being listed, the account scope, the purpose of the returned IDs, and the reliability of the writable indicator.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, so the baseline for this dimension is 4. The description does not need to explain any parameter semantics because there are none.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool lists calendars in the configured iCloud account, using a specific verb and resource. It also distinguishes itself from the sibling event tools by explaining that it provides the calendar_id needed by list_events and create_event.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs the agent to use this tool first in order to obtain the opaque calendar_id required by event operations. This gives clear sequencing guidance and explains the purpose of the tool relative to its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList calendar eventsARead-onlyIdempotent
List events that overlap the start-inclusive, end-exclusive interval and expand recurring series into occurrences, across at most 366 days. Use list_calendars first to obtain calendar_id and use get_event instead for one known event. Continue with next_cursor and unchanged query filters when more results are available.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | Exclusive end of the event search interval; must be after start and no more than 366 days later. | |
| limit | No | Maximum events to return in this page, from 1 to 500; defaults to 100. | |
| start | Yes | Inclusive start of the event search interval as an ISO 8601 instant. | |
| cursor | No | Opaque next_cursor from the preceding page. Reuse it with the same calendar, interval, and timezone. | |
| timezone | No | Fallback IANA timezone used when an event lacks timezone metadata during recurrence expansion. | |
| calendar_id | Yes | Opaque calendar ID returned by list_calendars. |
Output Schema
| Name | Required | Description |
|---|---|---|
| events | Yes | Events in deterministic chronological order for this page. |
| next_cursor | Yes | Opaque cursor for the next page, or null when this is the last page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/non-destructive, yet the description still adds real behavior: recurring series are expanded into occurrences, the interval is start-inclusive/end-exclusive, the window is capped at 366 days, and cursors must be replayed with identical filters. It stops short of stating result ordering or how cancelled/declined events are treated, which matters for a paginated list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences with zero filler: capability and boundary semantics first, then routing to siblings/prerequisites, then pagination. Each sentence earns its place and the most decision-relevant information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and annotations carry the safety profile. Combined with a fully documented six-parameter schema, the description supplies exactly the missing pieces: recurrence expansion, interval boundary rules, the 366-day cap, and cursor reuse constraints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with start/end/cursor/limit/timezone all documented in the schema itself; the description mostly restates the interval semantics rather than adding new parameter meaning. Baseline 3 applies when the schema already carries the parameter burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list events) plus precise scope: half-open interval overlap and recurrence expansion into occurrences. It explicitly distinguishes itself from get_event (single known event) and list_calendars (ID lookup), so an agent can route without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit prerequisites ('Use list_calendars first to obtain calendar_id'), an explicit alternative ('use get_event instead for one known event'), and pagination continuation rules ('Continue with next_cursor and unchanged query filters'). When-to-use, when-not-to-use, and follow-up behavior are all covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_eventUpdate calendar eventADestructive
Modify an existing event or entire recurring series; individual expanded occurrences are not supported. Target it by resource_id or by calendar_id with uid. Omitted patch fields are preserved, null clears nullable fields, an empty alarms array removes alarms, and expected_etag can prevent a stale write.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | No | iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable. | |
| patch | Yes | Fields to replace. Omitted fields are preserved; null clears nullable values and an empty alarms array removes all alarms. | |
| calendar_id | No | Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable. | |
| resource_id | No | Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid. | |
| expected_etag | No | ETag previously returned for the event. When supplied, the update fails if the event changed since it was read. |
Output Schema
| Name | Required | Description |
|---|---|---|
| end | Yes | Normalized event end. |
| uid | Yes | Stored iCalendar UID. |
| etag | Yes | Current ETag for optimistic concurrency, when available. |
| href | Yes | Redacted fingerprint of the CalDAV resource URL. |
| rrule | Yes | Stored RFC 5545 recurrence rule without the RRULE: prefix. |
| start | Yes | Normalized event start. |
| alarms | Yes | Normalized alarms attached to the event. |
| summary | Yes | Stored event title. |
| location | Yes | Stored event location. |
| raw_ical | No | Raw iCalendar resource, included only when explicitly requested. |
| recurring | Yes | Whether this event belongs to a recurring series. |
| calendar_id | Yes | Opaque ID of the containing calendar. |
| description | Yes | Stored event notes. |
| resource_id | Yes | Opaque event ID accepted by get_event, update_event, and delete_event. |
| recurrence_id | Yes | Occurrence identifier for an expanded recurring event. |
| travel_minutes | Yes | Apple Calendar travel time in whole minutes before the start, or null when none is set. |
| recurrence_exception | Yes | Whether this result is an overridden recurrence instance. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the mutation risk profile is covered. The description usefully adds patch semantics (omitted fields preserved, null clears, empty alarms removes) and the etag-based concurrency guard, which are genuine behavioral facts beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with purpose and scope, then the targeting and patch rules. No filler and nothing repeated for its own sake.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter nested mutation tool, the description covers targeting, patch replace-vs-clear semantics, recurrence limits, and concurrency control, while annotations carry the safety profile and an output schema exists. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning: resource_id stands alone while calendar_id must be paired with uid, and it restates the preserve/clear contract for the patch object. That is modest but real value beyond the per-field schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Modify an existing event or entire recurring series') and immediately bounds scope with a negative ('individual expanded occurrences are not supported'). That scope statement cleanly separates it from create_event, delete_event, and get_event without needing to name them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete invocation guidance: target by resource_id or by calendar_id with uid, and use expected_etag for stale-write protection. It also states an explicit exclusion (no per-occurrence edits), but never names a sibling alternative for cases like deleting or creating, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.2.0- Changed
create_event3 fields changed- added
Input schema / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 1440, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Apple Calendar travel time in whole minutes before the start; defaults to null. Only valid for timed events." +} - added
Output schema / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set." +} - changed
Output schema / requiredPrevious value: -[ - "calendar_id", - "resource_id", - "uid", - "href", - "etag", - "summary", - "start", - "end", - "description", - "location", - "rrule", - "alarms", - "recurring", - "recurrence_exception", - "recurrence_id" -]New value: +[ + "calendar_id", + "resource_id", + "uid", + "href", + "etag", + "summary", + "start", + "end", + "description", + "location", + "rrule", + "alarms", + "travel_minutes", + "recurring", + "recurrence_exception", + "recurrence_id" +]
- Changed
get_event2 fields changed- added
Output schema / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set." +} - changed
Output schema / requiredPrevious value: -[ - "calendar_id", - "resource_id", - "uid", - "href", - "etag", - "summary", - "start", - "end", - "description", - "location", - "rrule", - "alarms", - "recurring", - "recurrence_exception", - "recurrence_id" -]New value: +[ + "calendar_id", + "resource_id", + "uid", + "href", + "etag", + "summary", + "start", + "end", + "description", + "location", + "rrule", + "alarms", + "travel_minutes", + "recurring", + "recurrence_exception", + "recurrence_id" +]
- Changed
list_events2 fields changed- added
Output schema / properties / events / items / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set." +} - changed
Output schema / properties / events / items / requiredPrevious value: -[ - "calendar_id", - "resource_id", - "uid", - "href", - "etag", - "summary", - "start", - "end", - "description", - "location", - "rrule", - "alarms", - "recurring", - "recurrence_exception", - "recurrence_id" -]New value: +[ + "calendar_id", + "resource_id", + "uid", + "href", + "etag", + "summary", + "start", + "end", + "description", + "location", + "rrule", + "alarms", + "travel_minutes", + "recurring", + "recurrence_exception", + "recurrence_id" +]
- Changed
update_event3 fields changed- added
Input schema / properties / patch / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 1440, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Replacement Apple Calendar travel time in whole minutes; omit to preserve it or use null to remove travel time and related routing metadata. A number requires a timed event; converting to all-day requires clearing existing travel time with null." +} - added
Output schema / properties / travel_minutesAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set." +} - changed
Output schema / requiredPrevious value: -[ - "calendar_id", - "resource_id", - "uid", - "href", - "etag", - "summary", - "start", - "end", - "description", - "location", - "rrule", - "alarms", - "recurring", - "recurrence_exception", - "recurrence_id" -]New value: +[ + "calendar_id", + "resource_id", + "uid", + "href", + "etag", + "summary", + "start", + "end", + "description", + "location", + "rrule", + "alarms", + "travel_minutes", + "recurring", + "recurrence_exception", + "recurrence_id" +]
5 tool updates
v0.1.7- Changed
create_event14 fields changed- removed
Output schema / properties / alarms / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / alarms / items / properties / uid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / uid / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / etag / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / etag / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / location / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / location / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / recurrence_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / recurrence_id / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / rrule / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / rrule / typeAdded value: +[ + "string", + "null" +]
- Changed
get_event14 fields changed- removed
Output schema / properties / alarms / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / alarms / items / properties / uid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / uid / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / etag / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / etag / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / location / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / location / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / recurrence_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / recurrence_id / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / rrule / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / rrule / typeAdded value: +[ + "string", + "null" +]
- Changed
list_calendars6 fields changed- removed
Output schema / properties / calendars / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / calendars / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / calendars / items / properties / timezone / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / calendars / items / properties / timezone / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / calendars / items / properties / writable / anyOfRemoved value: -[ - { - "type": "boolean" - }, - { - "type": "null" - } -] - added
Output schema / properties / calendars / items / properties / writable / typeAdded value: +[ + "boolean", + "null" +]
- Changed
list_events18 fields changed- changed
Input schema / properties / end / patternPrevious value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" - changed
Input schema / properties / start / patternPrevious value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" - removed
Output schema / properties / events / items / properties / alarms / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / alarms / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / alarms / items / properties / uid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / alarms / items / properties / uid / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / etag / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / etag / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / location / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / location / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / recurrence_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / recurrence_id / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / events / items / properties / rrule / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / events / items / properties / rrule / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / next_cursor / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / next_cursor / typeAdded value: +[ + "string", + "null" +]
- Changed
update_event14 fields changed- removed
Output schema / properties / alarms / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / alarms / items / properties / uid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / alarms / items / properties / uid / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / etag / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / etag / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / location / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / location / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / recurrence_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / recurrence_id / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / rrule / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / rrule / typeAdded value: +[ + "string", + "null" +]
6 tool updates
v0.1.1- Changed
create_event37 fields changed- added
Input schema / properties / alarms / descriptionAdded value: +"Display reminders; defaults to an empty array." - added
Input schema / properties / alarms / items / descriptionAdded value: +"A display reminder attached to an event." - added
Input schema / properties / alarms / items / properties / action / descriptionAdded value: +"Alarm action; only DISPLAY is supported." - added
Input schema / properties / alarms / items / properties / description / descriptionAdded value: +"Optional notification text for this alarm." - added
Input schema / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before the event start; use 0 for an alarm at start time." - added
Input schema / properties / calendar_id / descriptionAdded value: +"Opaque destination calendar ID returned by list_calendars." - added
Input schema / properties / description / descriptionAdded value: +"Event notes; defaults to null." - changed
Input schema / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A timed calendar value with an explicit offset and IANA timezone.", + "properties": { + "date_time": { + "description": "ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone for the local event time; its offset must match date_time.", + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Input schema / properties / end / descriptionAdded value: +"Event end using the same temporal type and timezone as start; an all-day end date is exclusive." - added
Input schema / properties / location / descriptionAdded value: +"Event location; defaults to null." - added
Input schema / properties / rrule / descriptionAdded value: +"RFC 5545 recurrence rule without the RRULE: prefix; defaults to null." - changed
Input schema / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A timed calendar value with an explicit offset and IANA timezone.", + "properties": { + "date_time": { + "description": "ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone for the local event time; its offset must match date_time.", + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Input schema / properties / start / descriptionAdded value: +"Event start as a timed date-time or all-day date." - added
Input schema / properties / summary / descriptionAdded value: +"Event title, between 1 and 1,024 characters." - added
Output schema / properties / alarms / descriptionAdded value: +"Normalized alarms attached to the event." - added
Output schema / properties / alarms / items / descriptionAdded value: +"A normalized alarm returned by iCloud Calendar." - added
Output schema / properties / alarms / items / properties / action / descriptionAdded value: +"Stored iCalendar alarm action." - added
Output schema / properties / alarms / items / properties / description / descriptionAdded value: +"Stored alarm notification text, when available." - added
Output schema / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before event start, when representable." - added
Output schema / properties / alarms / items / properties / uid / descriptionAdded value: +"Stored alarm UID, when available." - added
Output schema / properties / calendar_id / descriptionAdded value: +"Opaque ID of the containing calendar." - added
Output schema / properties / description / descriptionAdded value: +"Stored event notes." - changed
Output schema / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / end / descriptionAdded value: +"Normalized event end." - added
Output schema / properties / etag / descriptionAdded value: +"Current ETag for optimistic concurrency, when available." - added
Output schema / properties / href / descriptionAdded value: +"Redacted fingerprint of the CalDAV resource URL." - added
Output schema / properties / location / descriptionAdded value: +"Stored event location." - added
Output schema / properties / raw_ical / descriptionAdded value: +"Raw iCalendar resource, included only when explicitly requested." - added
Output schema / properties / recurrence_exception / descriptionAdded value: +"Whether this result is an overridden recurrence instance." - added
Output schema / properties / recurrence_id / descriptionAdded value: +"Occurrence identifier for an expanded recurring event." - added
Output schema / properties / recurring / descriptionAdded value: +"Whether this event belongs to a recurring series." - added
Output schema / properties / resource_id / descriptionAdded value: +"Opaque event ID accepted by get_event, update_event, and delete_event." - added
Output schema / properties / rrule / descriptionAdded value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix." - changed
Output schema / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / start / descriptionAdded value: +"Normalized event start." - added
Output schema / properties / summary / descriptionAdded value: +"Stored event title." - added
Output schema / properties / uid / descriptionAdded value: +"Stored iCalendar UID."
- Changed
delete_event6 fields changed- added
Input schema / properties / calendar_id / descriptionAdded value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable." - added
Input schema / properties / expected_etag / descriptionAdded value: +"ETag previously returned for the event. When supplied, deletion fails if the event changed since it was read." - added
Input schema / properties / resource_id / descriptionAdded value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid." - added
Input schema / properties / uid / descriptionAdded value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable." - added
Output schema / properties / deleted / descriptionAdded value: +"Confirms that the resource was deleted." - added
Output schema / properties / resource_id / descriptionAdded value: +"Opaque ID of the deleted event resource."
- Changed
get_event27 fields changed- added
Input schema / properties / calendar_id / descriptionAdded value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable." - added
Input schema / properties / include_raw_ical / descriptionAdded value: +"Include the raw iCalendar resource for controlled diagnostics; it may contain sensitive calendar data. Defaults to false." - added
Input schema / properties / resource_id / descriptionAdded value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid." - added
Input schema / properties / uid / descriptionAdded value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable." - added
Output schema / properties / alarms / descriptionAdded value: +"Normalized alarms attached to the event." - added
Output schema / properties / alarms / items / descriptionAdded value: +"A normalized alarm returned by iCloud Calendar." - added
Output schema / properties / alarms / items / properties / action / descriptionAdded value: +"Stored iCalendar alarm action." - added
Output schema / properties / alarms / items / properties / description / descriptionAdded value: +"Stored alarm notification text, when available." - added
Output schema / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before event start, when representable." - added
Output schema / properties / alarms / items / properties / uid / descriptionAdded value: +"Stored alarm UID, when available." - added
Output schema / properties / calendar_id / descriptionAdded value: +"Opaque ID of the containing calendar." - added
Output schema / properties / description / descriptionAdded value: +"Stored event notes." - changed
Output schema / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / end / descriptionAdded value: +"Normalized event end." - added
Output schema / properties / etag / descriptionAdded value: +"Current ETag for optimistic concurrency, when available." - added
Output schema / properties / href / descriptionAdded value: +"Redacted fingerprint of the CalDAV resource URL." - added
Output schema / properties / location / descriptionAdded value: +"Stored event location." - added
Output schema / properties / raw_ical / descriptionAdded value: +"Raw iCalendar resource, included only when explicitly requested." - added
Output schema / properties / recurrence_exception / descriptionAdded value: +"Whether this result is an overridden recurrence instance." - added
Output schema / properties / recurrence_id / descriptionAdded value: +"Occurrence identifier for an expanded recurring event." - added
Output schema / properties / recurring / descriptionAdded value: +"Whether this event belongs to a recurring series." - added
Output schema / properties / resource_id / descriptionAdded value: +"Opaque event ID accepted by get_event, update_event, and delete_event." - added
Output schema / properties / rrule / descriptionAdded value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix." - changed
Output schema / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / start / descriptionAdded value: +"Normalized event start." - added
Output schema / properties / summary / descriptionAdded value: +"Stored event title." - added
Output schema / properties / uid / descriptionAdded value: +"Stored iCalendar UID."
- Changed
list_calendars6 fields changed- added
Output schema / properties / calendars / descriptionAdded value: +"Calendars available to the configured account." - added
Output schema / properties / calendars / items / properties / calendar_id / descriptionAdded value: +"Opaque calendar ID used by event tools." - added
Output schema / properties / calendars / items / properties / description / descriptionAdded value: +"Calendar description." - added
Output schema / properties / calendars / items / properties / display_name / descriptionAdded value: +"Calendar display name." - added
Output schema / properties / calendars / items / properties / timezone / descriptionAdded value: +"Calendar timezone, when advertised by the server." - added
Output schema / properties / calendars / items / properties / writable / descriptionAdded value: +"Best-effort writable status; null means unknown."
- Changed
list_events31 fields changed- added
Input schema / properties / calendar_id / descriptionAdded value: +"Opaque calendar ID returned by list_calendars." - added
Input schema / properties / cursor / descriptionAdded value: +"Opaque next_cursor from the preceding page. Reuse it with the same calendar, interval, and timezone." - added
Input schema / properties / end / descriptionAdded value: +"Exclusive end of the event search interval; must be after start and no more than 366 days later." - added
Input schema / properties / limit / descriptionAdded value: +"Maximum events to return in this page, from 1 to 500; defaults to 100." - added
Input schema / properties / start / descriptionAdded value: +"Inclusive start of the event search interval as an ISO 8601 instant." - added
Input schema / properties / timezone / descriptionAdded value: +"Fallback IANA timezone used when an event lacks timezone metadata during recurrence expansion." - added
Output schema / properties / events / descriptionAdded value: +"Events in deterministic chronological order for this page." - added
Output schema / properties / events / items / properties / alarms / descriptionAdded value: +"Normalized alarms attached to the event." - added
Output schema / properties / events / items / properties / alarms / items / descriptionAdded value: +"A normalized alarm returned by iCloud Calendar." - added
Output schema / properties / events / items / properties / alarms / items / properties / action / descriptionAdded value: +"Stored iCalendar alarm action." - added
Output schema / properties / events / items / properties / alarms / items / properties / description / descriptionAdded value: +"Stored alarm notification text, when available." - added
Output schema / properties / events / items / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before event start, when representable." - added
Output schema / properties / events / items / properties / alarms / items / properties / uid / descriptionAdded value: +"Stored alarm UID, when available." - added
Output schema / properties / events / items / properties / calendar_id / descriptionAdded value: +"Opaque ID of the containing calendar." - added
Output schema / properties / events / items / properties / description / descriptionAdded value: +"Stored event notes." - changed
Output schema / properties / events / items / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / events / items / properties / end / descriptionAdded value: +"Normalized event end." - added
Output schema / properties / events / items / properties / etag / descriptionAdded value: +"Current ETag for optimistic concurrency, when available." - added
Output schema / properties / events / items / properties / href / descriptionAdded value: +"Redacted fingerprint of the CalDAV resource URL." - added
Output schema / properties / events / items / properties / location / descriptionAdded value: +"Stored event location." - added
Output schema / properties / events / items / properties / raw_ical / descriptionAdded value: +"Raw iCalendar resource, included only when explicitly requested." - added
Output schema / properties / events / items / properties / recurrence_exception / descriptionAdded value: +"Whether this result is an overridden recurrence instance." - added
Output schema / properties / events / items / properties / recurrence_id / descriptionAdded value: +"Occurrence identifier for an expanded recurring event." - added
Output schema / properties / events / items / properties / recurring / descriptionAdded value: +"Whether this event belongs to a recurring series." - added
Output schema / properties / events / items / properties / resource_id / descriptionAdded value: +"Opaque event ID accepted by get_event, update_event, and delete_event." - added
Output schema / properties / events / items / properties / rrule / descriptionAdded value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix." - changed
Output schema / properties / events / items / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / events / items / properties / start / descriptionAdded value: +"Normalized event start." - added
Output schema / properties / events / items / properties / summary / descriptionAdded value: +"Stored event title." - added
Output schema / properties / events / items / properties / uid / descriptionAdded value: +"Stored iCalendar UID." - added
Output schema / properties / next_cursor / descriptionAdded value: +"Opaque cursor for the next page, or null when this is the last page."
- Changed
update_event41 fields changed- added
Input schema / properties / calendar_id / descriptionAdded value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable." - added
Input schema / properties / expected_etag / descriptionAdded value: +"ETag previously returned for the event. When supplied, the update fails if the event changed since it was read." - added
Input schema / properties / patch / descriptionAdded value: +"Fields to replace. Omitted fields are preserved; null clears nullable values and an empty alarms array removes all alarms." - added
Input schema / properties / patch / properties / alarms / descriptionAdded value: +"Replacement alarm set; use an empty array to remove all alarms." - added
Input schema / properties / patch / properties / alarms / items / descriptionAdded value: +"A display reminder attached to an event." - added
Input schema / properties / patch / properties / alarms / items / properties / action / descriptionAdded value: +"Alarm action; only DISPLAY is supported." - added
Input schema / properties / patch / properties / alarms / items / properties / description / descriptionAdded value: +"Optional notification text for this alarm." - added
Input schema / properties / patch / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before the event start; use 0 for an alarm at start time." - added
Input schema / properties / patch / properties / description / descriptionAdded value: +"Replacement notes; use null to clear the description." - changed
Input schema / properties / patch / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A timed calendar value with an explicit offset and IANA timezone.", + "properties": { + "date_time": { + "description": "ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone for the local event time; its offset must match date_time.", + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Input schema / properties / patch / properties / end / descriptionAdded value: +"Replacement end; provide together with start. An all-day end date is exclusive." - added
Input schema / properties / patch / properties / location / descriptionAdded value: +"Replacement location; use null to clear it." - added
Input schema / properties / patch / properties / rrule / descriptionAdded value: +"Replacement RFC 5545 recurrence rule without RRULE:, or null to make the event non-recurring." - changed
Input schema / properties / patch / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A timed calendar value with an explicit offset and IANA timezone.", + "properties": { + "date_time": { + "description": "ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone for the local event time; its offset must match date_time.", + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Input schema / properties / patch / properties / start / descriptionAdded value: +"Replacement start; provide together with end." - added
Input schema / properties / patch / properties / summary / descriptionAdded value: +"Replacement event title." - added
Input schema / properties / resource_id / descriptionAdded value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid." - added
Input schema / properties / uid / descriptionAdded value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable." - added
Output schema / properties / alarms / descriptionAdded value: +"Normalized alarms attached to the event." - added
Output schema / properties / alarms / items / descriptionAdded value: +"A normalized alarm returned by iCloud Calendar." - added
Output schema / properties / alarms / items / properties / action / descriptionAdded value: +"Stored iCalendar alarm action." - added
Output schema / properties / alarms / items / properties / description / descriptionAdded value: +"Stored alarm notification text, when available." - added
Output schema / properties / alarms / items / properties / minutes_before / descriptionAdded value: +"Whole minutes before event start, when representable." - added
Output schema / properties / alarms / items / properties / uid / descriptionAdded value: +"Stored alarm UID, when available." - added
Output schema / properties / calendar_id / descriptionAdded value: +"Opaque ID of the containing calendar." - added
Output schema / properties / description / descriptionAdded value: +"Stored event notes." - changed
Output schema / properties / end / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / end / descriptionAdded value: +"Normalized event end." - added
Output schema / properties / etag / descriptionAdded value: +"Current ETag for optimistic concurrency, when available." - added
Output schema / properties / href / descriptionAdded value: +"Redacted fingerprint of the CalDAV resource URL." - added
Output schema / properties / location / descriptionAdded value: +"Stored event location." - added
Output schema / properties / raw_ical / descriptionAdded value: +"Raw iCalendar resource, included only when explicitly requested." - added
Output schema / properties / recurrence_exception / descriptionAdded value: +"Whether this result is an overridden recurrence instance." - added
Output schema / properties / recurrence_id / descriptionAdded value: +"Occurrence identifier for an expanded recurring event." - added
Output schema / properties / recurring / descriptionAdded value: +"Whether this event belongs to a recurring series." - added
Output schema / properties / resource_id / descriptionAdded value: +"Opaque event ID accepted by get_event, update_event, and delete_event." - added
Output schema / properties / rrule / descriptionAdded value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix." - changed
Output schema / properties / start / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "date_time": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", - "type": "string" - }, - "timezone": { - "maxLength": 4096, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "date_time", - "timezone" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "date": { - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "type": "string" - } - }, - "required": [ - "date" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "A stored timed calendar value.", + "properties": { + "date_time": { + "description": "Stored ISO 8601 date-time with seconds and an explicit UTC offset or Z.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})$", + "type": "string" + }, + "timezone": { + "description": "IANA timezone associated with the stored date-time.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "date_time", + "timezone" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "An all-day calendar value.", + "properties": { + "date": { + "description": "Calendar date in YYYY-MM-DD format.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + } +] - added
Output schema / properties / start / descriptionAdded value: +"Normalized event start." - added
Output schema / properties / summary / descriptionAdded value: +"Stored event title." - added
Output schema / properties / uid / descriptionAdded value: +"Stored iCalendar UID."
6 tool updates
v0.1.0- First observed
create_event - First observed
delete_event - First observed
get_event - First observed
list_calendars - First observed
list_events - First observed
update_event
TDQS
Scored across 6 tools
Each tool maps to a distinct action on a distinct resource: create/list/get/update/delete events plus list calendars. The descriptions explicitly clarify boundaries, such as list_events vs get_event and update vs create.
All tool names follow a consistent verb_noun snake_case pattern: create_event, list_events, get_event, update_event, delete_event, list_calendars.
Six tools are well-scoped for a CalDAV server: one discovery tool and a complete event CRUD set. No tool appears redundant or trivial.
The surface covers full event lifecycle plus calendar discovery, which is the core domain. Minor gaps exist around calendar-level operations and individual recurring-occurrence edits, though these are documented limitations rather than dead ends.
Maintenance
Related MCP Connectors
Model Context Protocol server for todo.vu task management and time tracking.
MCP server for Cronofy — read calendars, events and free/busy, and create, update or delete events.
Streamable HTTP MCP server for Google Calendar and Sheets with OAuth login.
Model Context Protocol server for Studex tools, notifications, and profile integrations
Related MCP Servers
- AlicenseCqualityDmaintenanceA Model Context Protocol server for AI models to access and manipulate Apple Calendar data on macOS through a standardized interface.730 npm14MIT
- AlicenseDqualityDmaintenanceA Model Context Protocol server that allows users to interact with their CalDAV, CardDAV, and WebDAV services (calendars, contacts, and files) from Fastmail and Apple iCloud accounts.689 npm3MIT
- AlicenseNot gradedqualityCmaintenanceAn HTTP Model Context Protocol (MCP) server exposing iCloud Calendar (CalDAV) tools so MCP-aware clients can list calendars, read events, and create/update/delete events using an iCloud app-specific password.3MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for Apple Calendar via native EventKit API with proper recurring event support.28 npm10MIT