Skip to main content
Glama

CalDAV MCP Server

TypeScript CI Container License

CalDAV MCP Server 是一个用于管理 iCloud Calendar 事件的 Model Context Protocol 服务器,原生支持单个事件上的多个 VALARM 提醒。

iCloud Calendar 是首个版本中唯一官方支持并经过手动验证的提供商。该服务器适用于任何支持 stdio 或 Streamable HTTP 的 MCP 客户端。

这个独立项目与 Apple Inc. 无关联,也未获得其授权、赞助或批准。Apple 和 iCloud 是其各自所有者的商标。

导航

Related MCP server: DAV MCP Server

关于

服务器通过 CalDAV 将一个已配置的账户连接到 iCloud。它发现账户的日历,并通过 MCP 暴露规范化的读写操作。

更新会保留完整的 iCalendar 资源,包括未知属性、Apple 扩展、VTIMEZONE、重复例外以及补丁中省略的提醒。写入使用不透明的资源标识符和 ETag,而不是假设 CalDAV 文件名与事件 UID 匹配。

日历资源在内存中处理。服务器没有遥测功能,也没有应用程序数据库,只有在明确请求时才返回原始 iCalendar。

功能特性

  • 发现已配置的 iCloud 账户可用的日历。

  • 在半开时间范围内列出事件,并展开重复发生的事件。

  • 创建定时、全天和重复事件。

  • 支持每个事件零个、一个或多个显示提醒。

  • 发出 iCloud Calendar 期望的 Apple 提醒扩展。

  • 通过不透明资源 ID 或日历 ID 和 UID 读取事件。

  • 应用部分更新,同时保留省略和未知的 iCalendar 数据。

  • 在更新和删除时使用 ETag 进行乐观并发控制。

  • 拒绝孤立的重复变更,而不是更改整个系列。

  • 从日志和错误中编辑掉凭据、原始日历内容和 CalDAV 路径。

  • 以非 root 容器运行,并配置了只读根文件系统。

  • 支持 stdio 和 Streamable HTTP MCP 传输。

MCP 工具

list_calendars

列出为已配置账户发现的日历。每个结果包括一个不透明的 calendar_id、显示名称、描述、时区和尽力而为的写入状态。

list_events

在半开区间内列出事件,并展开重复发生的事件。最大范围为 366 天,默认页面大小为 100,最大页面大小为 500。结果使用确定性的时间顺序。分页游标是不透明的,在遍历期间修改事件时不代表快照。

示例输入:

{
  "calendar_id": "opaque-calendar-id",
  "start": "2026-09-01T00:00:00Z",
  "end": "2026-10-01T00:00:00Z",
  "timezone": "Europe/Berlin",
  "limit": 100
}

get_event

通过 resource_idcalendar_id 和 UID 对读取事件。默认排除原始 iCalendar,可以通过 include_raw_ical: true 请求以进行受控诊断。

create_event

创建事件并读回服务器存储的表示。

带两个提醒的定时事件:

{
  "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
}

带独占结束日期的全天事件:

{
  "calendar_id": "opaque-calendar-id",
  "summary": "Trip",
  "start": { "date": "2026-09-06" },
  "end": { "date": "2026-09-08" },
  "alarms": []
}

重复事件接受不带 RRULE: 前缀的 RFC 5545 规则:

{
  "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"
}

update_event

修补事件或完整的重复系列。省略的字段会被保留,null 会移除可空字段,alarms: [] 会移除所有提醒。可选的 expected_etag 可防止覆盖较新的服务器版本。

delete_event

删除事件或完整的重复系列,可选地要求观察到的 ETag。当前版本不支持删除单个展开的事件。

技术栈

安装

先决条件

  • 一个启用了日历的 iCloud 账户。

  • 为 Apple 账户启用了双重认证。

  • 一个应用专用密码

  • 用于容器部署的 Docker 和 Docker Compose,或用于本地安装的 Node.js 24+ 和 pnpm。

Docker Compose

推荐的安装使用已发布的多架构镜像:

ghcr.io/lukegskw/caldav-mcp:latest

下载 Compose 示例:

curl -O https://raw.githubusercontent.com/lukegskw/caldav-mcp/main/compose.example.yaml

提供 Apple 账户电子邮件和应用专用密码,然后启动服务:

export CALDAV_USERNAME='user@example.com'
export CALDAV_PASSWORD='xxxx-xxxx-xxxx-xxxx'
docker compose -f compose.example.yaml up -d

要发布不同的主机端口,请设置:

export CALDAV_MCP_PUBLISHED_PORT=18100
docker compose -f compose.example.yaml up -d

latest 标签跟随默认分支上最新的成功构建。对于受控部署或回滚,请将其替换为 Compose 文件中的已发布版本或不可变的 sha-* 标签。

Streamable HTTP 端点将位于:

http://<host>:8100/mcp

主机端口可以更改,而不会更改容器内的端口 8100。不需要持久卷;日历数据保留在 iCloud 中。

Docker run

相同的加固容器配置可以直接启动:

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:latest

从源代码构建容器

本地构建是可选的。除非您需要修改或审计容器构建,否则请优先使用已发布的镜像。

git clone https://github.com/lukegskw/caldav-mcp.git
cd caldav-mcp
docker buildx build --load -t caldav-mcp:local .

本地 Node.js 安装

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 stdio

stdio 模式下,stdout 仅保留用于 MCP 消息。要在本地运行 Streamable HTTP:

CALDAV_MCP_TRANSPORT=streamable-http pnpm start

配置

所有设置都使用 CALDAV_CALDAV_MCP_ 前缀。

变量

必需

默认值

描述

CALDAV_PROVIDER

icloud

提供商策略。iCloud 是受支持的配置文件。

CALDAV_URL

https://caldav.icloud.com

CalDAV 发现 URL。

CALDAV_USERNAME

Apple 账户电子邮件。

CALDAV_PASSWORD

应用专用密码,而不是账户密码。

CALDAV_MCP_TRANSPORT

stdio

stdiostreamable-http

CALDAV_MCP_HOST

0.0.0.0

HTTP 绑定地址。

CALDAV_MCP_PORT

8100

HTTP 监听端口。

CALDAV_MCP_LOG_LEVEL

INFO

应用程序日志级别。

CALDAV_MCP_REQUEST_TIMEOUT_MS

30000

CalDAV 请求超时。

核心保留了一个实验性的 generic 提供商策略和可配置的 URL,以将 Apple 扩展与共享的 iCalendar 实现隔离开来。目前不声称与其他提供商兼容。

必须通过部署平台或环境提供机密信息。切勿提交 .env,将凭据作为 MCP 工具参数传递,或将其包含在诊断报告中。

MCP 客户端设置

对于任何接受 Streamable HTTP 服务器定义的 MCP 客户端,请配置 URL:

mcp_servers:
  caldav:
    url: http://<host>:8100/mcp

如果客户端共享 Compose 网络,请使用服务名称和内部端口:

mcp_servers:
  caldav:
    url: http://caldav-mcp:8100/mcp

对于启动本地 stdio 服务器的客户端,请配置命令以运行 node /absolute/path/to/caldav-mcp/dist/main.js 并设置所需的环境变量。

Claude Desktop(Docker,stdio)

Claude Desktop 将本地 stdio 服务器作为子进程启动。以这种方式运行已发布的容器会将应用专用密码保留在客户端机器上,并且不打开网络端口,这符合限制中的传输指南。

将服务器添加到 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 是必需的。如果没有附加的 stdin,客户端无法与容器进行 MCP 通信。--rm 会在客户端停止容器后将其移除。

通过 --env-file 而不是 -e 提供凭据。传递给 docker run 的参数在主机进程列表中可见;env 文件的内容则不可见。该文件包含配置中描述的变量:

CALDAV_USERNAME=user@example.com
CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx

按摘要固定镜像而不是 latest,这样重启客户端就不会静默启动不同版本:

docker pull ghcr.io/lukegskw/caldav-mcp:latest
docker images --digests ghcr.io/lukegskw/caldav-mcp

编辑配置文件后,完全重启 Claude Desktop。

Windows

通过 设置 -> 开发者 -> 编辑配置 创建和定位配置文件。不要假设路径。当 Claude Desktop 从 Microsoft Store 安装时,Windows 会将 %APPDATA%\Claude 重定向到包容器中,文件位于:

%LOCALAPPDATA%\Packages\Claude_<package-id>\LocalCache\Roaming\Claude\claude_desktop_config.json

在这种情况下,dir %APPDATA%\Claude 不会报告任何内容。服务器日志写在配置文件旁边,位于 logs\mcp-server-<server-name>.log

使用 docker.exe 的绝对路径,因为包容器内的 PATH 不可靠。where docker 会打印它,通常是 C:\Program Files\Docker\Docker\resources\bin\docker.exe。反斜杠必须在 JSON 中转义。

MCP 客户端之间的配置格式不同。请查阅客户端的文档以了解其确切模式,并在更改服务器定义后重新加载或重启它。

验证

检查容器状态和日志:

docker compose -f compose.example.yaml ps
docker compose -f compose.example.yaml logs caldav-mcp

容器应报告 healthy。TCP 健康检查验证服务器进程,而不是 iCloud 凭据。

运行仓库验证套件:

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test:unit
pnpm test:integration
pnpm build

最后,连接 MCP 客户端并确认所有六个工具都已列出。在发布之前,请针对测试日历运行专门的 iCloud 手动验证

限制

  • 每个服务器进程或容器配置一个 iCloud 账户。

  • 当前版本中 Streamable HTTP 端点没有身份验证。将其限制在受信任的 LAN、VPN 或私有容器网络中;不要直接暴露到互联网。

  • 单个重复事件是只读的。支持更新或删除整个系列。

  • 仅创建 ACTION:DISPLAY 提醒。

  • 单个 iCalendar 资源限制为 5 MiB。

  • 事件列表范围限制为 366 天,页面限制为 500 个结果。

  • 事件最多包含 20 个提醒。

  • 与会者调度不在当前范围内。

  • 不正式支持 iCloud 以外的提供商。

有关发现、身份验证、ETag 和 Apple 扩展的指导,请参阅故障排除。在报告安全问题或附加诊断信息之前,请查看 SECURITY.md

贡献

欢迎贡献。在打开拉取请求之前:

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build
docker buildx build --load -t caldav-mcp:test .

对 CalDAV 写入或 iCalendar 序列化的更改必须保留 ETag 检查、不透明资源边界、未知属性、重复例外以及补丁中省略的提醒。TypeScript 更改必须继续满足 .codex/rules/typescript.md 中的规则。

许可证

MIT。请参阅 LICENSE

Available Tools

6 tools
create_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, and recurrence rules omit the RRULE: prefix.

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesEvent end using the same temporal type and timezone as start; an all-day end date is exclusive.
rruleNoRFC 5545 recurrence rule without the RRULE: prefix; defaults to null.
startYesEvent start as a timed date-time or all-day date.
alarmsNoDisplay reminders; defaults to an empty array.
summaryYesEvent title, between 1 and 1,024 characters.
locationNoEvent location; defaults to null.
calendar_idYesOpaque destination calendar ID returned by list_calendars.
descriptionNoEvent notes; defaults to null.

Output Schema

ParametersJSON Schema
NameRequiredDescription
endYesNormalized event end.
uidYesStored iCalendar UID.
etagYesCurrent ETag for optimistic concurrency, when available.
hrefYesRedacted fingerprint of the CalDAV resource URL.
rruleYesStored RFC 5545 recurrence rule without the RRULE: prefix.
startYesNormalized event start.
alarmsYesNormalized alarms attached to the event.
summaryYesStored event title.
locationYesStored event location.
raw_icalNoRaw iCalendar resource, included only when explicitly requested.
recurringYesWhether this event belongs to a recurring series.
calendar_idYesOpaque ID of the containing calendar.
descriptionYesStored event notes.
resource_idYesOpaque event ID accepted by get_event, update_event, and delete_event.
recurrence_idYesOccurrence identifier for an expanded recurring event.
recurrence_exceptionYesWhether this result is an overridden recurrence instance.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description adds meaningful behavioral context: it requires a writable calendar, returns the stored representation, guarantees existing events are unchanged, and warns about timezone offset matching, exclusive all-day end dates, and RRULE prefix omission. These constraints are not deducible from the annotations (readOnlyHint=false, destructiveHint=false).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler. The core purpose is front-loaded, and each subsequent sentence adds distinct, high-value guidance: prerequisites, alternative tool, and tricky format constraints. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex create tool with 8 parameters, the description covers prerequisites, alternatives, return behavior, and the most error-prone input constraints. Since an output schema exists, it appropriately does not need to describe return structure further.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters in detail. The description reinforces key constraints like timezone matching, exclusive all-day ends, and RRULE prefix omission, but these largely restate what the schema properties already say, adding limited new meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource—'Create a new event in a writable iCloud calendar'—and explicitly contrasts with update_event by noting 'existing events are not changed.' This clearly differentiates the tool from its siblings like list_events and get_event.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: 'Use list_calendars first to obtain calendar_id, and use update_event when the event already exists.' This directly routes an agent to prerequisites and alternatives, leaving no ambiguity about the tool's appropriate context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_eventDelete calendar eventA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uidNoiCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable.
calendar_idNoOpaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable.
resource_idNoOpaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid.
expected_etagNoETag previously returned for the event. When supplied, deletion fails if the event changed since it was read.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedYesConfirms that the resource was deleted.
resource_idYesOpaque ID of the deleted event resource.

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 eventA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uidNoiCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable.
calendar_idNoOpaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable.
resource_idNoOpaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid.
include_raw_icalNoInclude the raw iCalendar resource for controlled diagnostics; it may contain sensitive calendar data. Defaults to false.

Output Schema

ParametersJSON Schema
NameRequiredDescription
endYesNormalized event end.
uidYesStored iCalendar UID.
etagYesCurrent ETag for optimistic concurrency, when available.
hrefYesRedacted fingerprint of the CalDAV resource URL.
rruleYesStored RFC 5545 recurrence rule without the RRULE: prefix.
startYesNormalized event start.
alarmsYesNormalized alarms attached to the event.
summaryYesStored event title.
locationYesStored event location.
raw_icalNoRaw iCalendar resource, included only when explicitly requested.
recurringYesWhether this event belongs to a recurring series.
calendar_idYesOpaque ID of the containing calendar.
descriptionYesStored event notes.
resource_idYesOpaque event ID accepted by get_event, update_event, and delete_event.
recurrence_idYesOccurrence identifier for an expanded recurring event.
recurrence_exceptionYesWhether this result is an overridden recurrence instance.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, so the safety profile is clear. The description adds valuable behavioral context beyond annotations by warning that raw iCalendar may contain sensitive data and should only be requested for controlled diagnostics, and by noting that resource_id should preferably come from a previous result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three concise, front-loaded sentences with no fluff. Each sentence earns its place: the primary lookup method, the alternative, and the sensitive-data caveat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the annotations, rich schema, and output schema, the description covers the main operational concerns: how to identify the event, when to use list_events, and the sensitive nature of raw iCalendar. It could be slightly more explicit about the fact that at least one identifier must be provided since the schema lists no required parameters, but the 'by... or by...' phrasing implies this.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and each parameter already has a detailed explanation in the schema. The description restates the resource_id-vs-calendar_id+uid relationship and the raw iCalendar caution, but does not add substantial new parameter-level meaning beyond what the schema already provides, so a baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with the specific verb 'Read one event' and identifies the resource as a calendar event, clearly distinguishing this from sibling tools. It also names the alternative lookup paths (resource_id vs calendar_id+uid pair), making the tool's purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to use list_events for range searches, which is a direct routing instruction to an alternative sibling. It also advises using resource_id from a previous result preferentially and restricts raw iCalendar requests to controlled diagnostics, giving clear when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_calendarsList calendarsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
calendarsYesCalendars available to the configured account.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 eventsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesExclusive end of the event search interval; must be after start and no more than 366 days later.
limitNoMaximum events to return in this page, from 1 to 500; defaults to 100.
startYesInclusive start of the event search interval as an ISO 8601 instant.
cursorNoOpaque next_cursor from the preceding page. Reuse it with the same calendar, interval, and timezone.
timezoneNoFallback IANA timezone used when an event lacks timezone metadata during recurrence expansion.
calendar_idYesOpaque calendar ID returned by list_calendars.

Output Schema

ParametersJSON Schema
NameRequiredDescription
eventsYesEvents in deterministic chronological order for this page.
next_cursorYesOpaque cursor for the next page, or null when this is the last page.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, idempotent, non-destructive behavior, and the description adds substantial behavioral context: interval inclusivity, recurring series expansion, the 366-day maximum, and pagination continuation. This goes well beyond the structured annotation data and discloses important operation semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences cover core behavior, prerequisites, alternative selection, and pagination without repetition or filler. The most critical semantic details are front-loaded, and every clause carries operational value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paginated list operation with six parameters and an output schema, the description covers the required workflow (list_calendars, get_event), recurrence behavior, interval constraints, and pagination instructions. The output schema handles return-value details, and annotations cover the safety profile, so nothing essential is missing from the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value on top by explaining that calendar_id comes from list_calendars, that cursor must be reused with unchanged query filters, and that interval boundaries are inclusive/exclusive. This helps agents understand how the parameters relate to workflow even though the schema already documents each field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource ('List events') and defines precise interval semantics ('start-inclusive, end-exclusive') plus recurrence expansion. It also differentiates from related tools by saying to use 'get_event instead for one known event' and to use 'list_calendars first'. An agent can clearly understand what this tool does and how it differs from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit workflow guidance: call list_calendars first for calendar_id, use get_event for a single known event, and paginate with next_cursor using unchanged filters. This directly tells the agent when to use this tool versus alternatives and how to handle multi-page results.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_eventUpdate calendar eventA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uidNoiCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable.
patchYesFields to replace. Omitted fields are preserved; null clears nullable values and an empty alarms array removes all alarms.
calendar_idNoOpaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable.
resource_idNoOpaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid.
expected_etagNoETag previously returned for the event. When supplied, the update fails if the event changed since it was read.

Output Schema

ParametersJSON Schema
NameRequiredDescription
endYesNormalized event end.
uidYesStored iCalendar UID.
etagYesCurrent ETag for optimistic concurrency, when available.
hrefYesRedacted fingerprint of the CalDAV resource URL.
rruleYesStored RFC 5545 recurrence rule without the RRULE: prefix.
startYesNormalized event start.
alarmsYesNormalized alarms attached to the event.
summaryYesStored event title.
locationYesStored event location.
raw_icalNoRaw iCalendar resource, included only when explicitly requested.
recurringYesWhether this event belongs to a recurring series.
calendar_idYesOpaque ID of the containing calendar.
descriptionYesStored event notes.
resource_idYesOpaque event ID accepted by get_event, update_event, and delete_event.
recurrence_idYesOccurrence identifier for an expanded recurring event.
recurrence_exceptionYesWhether this result is an overridden recurrence instance.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description adds valuable behavioral context: patch semantics ('Omitted patch fields are preserved'), null clearing, empty alarms array behavior, and expected_etag preventing stale writes. This goes beyond what annotations provide and helps an agent predict side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. It front-loads the core action and limitations, then packs targeting and patch semantics into a dense but readable second sentence. Every clause adds useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich input schema, output schema, and annotations, this description covers the essential operational details: what can be modified, how to identify the target, how patches behave, and how to prevent stale writes. No critical calling context appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description earns a 4 by adding cross-parameter semantics not obvious from individual field descriptions: preservation of omitted fields, null clearing, empty alarms removal, and the optimistic concurrency role of expected_etag.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb and resource: 'Modify an existing event or entire recurring series.' It also adds a critical scope limitation ('individual expanded occurrences are not supported') and distinguishes the tool from create/delete/list siblings by focusing on modification of existing entities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete targeting guidance ('by resource_id or by calendar_id with uid') and a clear exclusion ('individual expanded occurrences are not supported'). It does not explicitly name alternatives like create_event or delete_event, but the context is clear enough for an agent to know when this tool applies.

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. Dates show when Glama detected each change.

  1. 5 tool updatesv0.1.7
    • Changedcreate_event14 fields changed
      • removedOutput schema / properties / alarms / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / alarms / items / properties / uid / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / uid / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / etag / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / etag / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / location / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / location / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / recurrence_id / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / recurrence_id / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / rrule / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / rrule / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedget_event14 fields changed
      • removedOutput schema / properties / alarms / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / alarms / items / properties / uid / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / uid / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / etag / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / etag / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / location / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / location / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / recurrence_id / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / recurrence_id / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / rrule / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / rrule / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedlist_calendars6 fields changed
      • removedOutput schema / properties / calendars / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / calendars / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / calendars / items / properties / timezone / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / calendars / items / properties / timezone / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / calendars / items / properties / writable / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / calendars / items / properties / writable / type
        Added value: +[
        +  "boolean",
        +  "null"
        +]
    • Changedlist_events18 fields changed
      • changedInput schema / properties / end / pattern
        Previous 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)))$"
      • changedInput schema / properties / start / pattern
        Previous 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)))$"
      • removedOutput schema / properties / events / items / properties / alarms / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / alarms / items / properties / uid / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / uid / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / etag / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / etag / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / location / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / location / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / recurrence_id / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / recurrence_id / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / events / items / properties / rrule / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / events / items / properties / rrule / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / next_cursor / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / next_cursor / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedupdate_event14 fields changed
      • removedOutput schema / properties / alarms / items / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / alarms / items / properties / uid / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / alarms / items / properties / uid / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / description / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / description / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / etag / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / etag / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / location / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / location / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / recurrence_id / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / recurrence_id / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / rrule / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / rrule / type
        Added value: +[
        +  "string",
        +  "null"
        +]
  2. 6 tool updatesv0.1.1
    • Changedcreate_event37 fields changed
      • addedInput schema / properties / alarms / description
        Added value: +"Display reminders; defaults to an empty array."
      • addedInput schema / properties / alarms / items / description
        Added value: +"A display reminder attached to an event."
      • addedInput schema / properties / alarms / items / properties / action / description
        Added value: +"Alarm action; only DISPLAY is supported."
      • addedInput schema / properties / alarms / items / properties / description / description
        Added value: +"Optional notification text for this alarm."
      • addedInput schema / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before the event start; use 0 for an alarm at start time."
      • addedInput schema / properties / calendar_id / description
        Added value: +"Opaque destination calendar ID returned by list_calendars."
      • addedInput schema / properties / description / description
        Added value: +"Event notes; defaults to null."
      • changedInput schema / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedInput schema / properties / end / description
        Added value: +"Event end using the same temporal type and timezone as start; an all-day end date is exclusive."
      • addedInput schema / properties / location / description
        Added value: +"Event location; defaults to null."
      • addedInput schema / properties / rrule / description
        Added value: +"RFC 5545 recurrence rule without the RRULE: prefix; defaults to null."
      • changedInput schema / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedInput schema / properties / start / description
        Added value: +"Event start as a timed date-time or all-day date."
      • addedInput schema / properties / summary / description
        Added value: +"Event title, between 1 and 1,024 characters."
      • addedOutput schema / properties / alarms / description
        Added value: +"Normalized alarms attached to the event."
      • addedOutput schema / properties / alarms / items / description
        Added value: +"A normalized alarm returned by iCloud Calendar."
      • addedOutput schema / properties / alarms / items / properties / action / description
        Added value: +"Stored iCalendar alarm action."
      • addedOutput schema / properties / alarms / items / properties / description / description
        Added value: +"Stored alarm notification text, when available."
      • addedOutput schema / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before event start, when representable."
      • addedOutput schema / properties / alarms / items / properties / uid / description
        Added value: +"Stored alarm UID, when available."
      • addedOutput schema / properties / calendar_id / description
        Added value: +"Opaque ID of the containing calendar."
      • addedOutput schema / properties / description / description
        Added value: +"Stored event notes."
      • changedOutput schema / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / end / description
        Added value: +"Normalized event end."
      • addedOutput schema / properties / etag / description
        Added value: +"Current ETag for optimistic concurrency, when available."
      • addedOutput schema / properties / href / description
        Added value: +"Redacted fingerprint of the CalDAV resource URL."
      • addedOutput schema / properties / location / description
        Added value: +"Stored event location."
      • addedOutput schema / properties / raw_ical / description
        Added value: +"Raw iCalendar resource, included only when explicitly requested."
      • addedOutput schema / properties / recurrence_exception / description
        Added value: +"Whether this result is an overridden recurrence instance."
      • addedOutput schema / properties / recurrence_id / description
        Added value: +"Occurrence identifier for an expanded recurring event."
      • addedOutput schema / properties / recurring / description
        Added value: +"Whether this event belongs to a recurring series."
      • addedOutput schema / properties / resource_id / description
        Added value: +"Opaque event ID accepted by get_event, update_event, and delete_event."
      • addedOutput schema / properties / rrule / description
        Added value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix."
      • changedOutput schema / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / start / description
        Added value: +"Normalized event start."
      • addedOutput schema / properties / summary / description
        Added value: +"Stored event title."
      • addedOutput schema / properties / uid / description
        Added value: +"Stored iCalendar UID."
    • Changeddelete_event6 fields changed
      • addedInput schema / properties / calendar_id / description
        Added value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable."
      • addedInput schema / properties / expected_etag / description
        Added value: +"ETag previously returned for the event. When supplied, deletion fails if the event changed since it was read."
      • addedInput schema / properties / resource_id / description
        Added value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid."
      • addedInput schema / properties / uid / description
        Added value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable."
      • addedOutput schema / properties / deleted / description
        Added value: +"Confirms that the resource was deleted."
      • addedOutput schema / properties / resource_id / description
        Added value: +"Opaque ID of the deleted event resource."
    • Changedget_event27 fields changed
      • addedInput schema / properties / calendar_id / description
        Added value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable."
      • addedInput schema / properties / include_raw_ical / description
        Added value: +"Include the raw iCalendar resource for controlled diagnostics; it may contain sensitive calendar data. Defaults to false."
      • addedInput schema / properties / resource_id / description
        Added value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid."
      • addedInput schema / properties / uid / description
        Added value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable."
      • addedOutput schema / properties / alarms / description
        Added value: +"Normalized alarms attached to the event."
      • addedOutput schema / properties / alarms / items / description
        Added value: +"A normalized alarm returned by iCloud Calendar."
      • addedOutput schema / properties / alarms / items / properties / action / description
        Added value: +"Stored iCalendar alarm action."
      • addedOutput schema / properties / alarms / items / properties / description / description
        Added value: +"Stored alarm notification text, when available."
      • addedOutput schema / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before event start, when representable."
      • addedOutput schema / properties / alarms / items / properties / uid / description
        Added value: +"Stored alarm UID, when available."
      • addedOutput schema / properties / calendar_id / description
        Added value: +"Opaque ID of the containing calendar."
      • addedOutput schema / properties / description / description
        Added value: +"Stored event notes."
      • changedOutput schema / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / end / description
        Added value: +"Normalized event end."
      • addedOutput schema / properties / etag / description
        Added value: +"Current ETag for optimistic concurrency, when available."
      • addedOutput schema / properties / href / description
        Added value: +"Redacted fingerprint of the CalDAV resource URL."
      • addedOutput schema / properties / location / description
        Added value: +"Stored event location."
      • addedOutput schema / properties / raw_ical / description
        Added value: +"Raw iCalendar resource, included only when explicitly requested."
      • addedOutput schema / properties / recurrence_exception / description
        Added value: +"Whether this result is an overridden recurrence instance."
      • addedOutput schema / properties / recurrence_id / description
        Added value: +"Occurrence identifier for an expanded recurring event."
      • addedOutput schema / properties / recurring / description
        Added value: +"Whether this event belongs to a recurring series."
      • addedOutput schema / properties / resource_id / description
        Added value: +"Opaque event ID accepted by get_event, update_event, and delete_event."
      • addedOutput schema / properties / rrule / description
        Added value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix."
      • changedOutput schema / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / start / description
        Added value: +"Normalized event start."
      • addedOutput schema / properties / summary / description
        Added value: +"Stored event title."
      • addedOutput schema / properties / uid / description
        Added value: +"Stored iCalendar UID."
    • Changedlist_calendars6 fields changed
      • addedOutput schema / properties / calendars / description
        Added value: +"Calendars available to the configured account."
      • addedOutput schema / properties / calendars / items / properties / calendar_id / description
        Added value: +"Opaque calendar ID used by event tools."
      • addedOutput schema / properties / calendars / items / properties / description / description
        Added value: +"Calendar description."
      • addedOutput schema / properties / calendars / items / properties / display_name / description
        Added value: +"Calendar display name."
      • addedOutput schema / properties / calendars / items / properties / timezone / description
        Added value: +"Calendar timezone, when advertised by the server."
      • addedOutput schema / properties / calendars / items / properties / writable / description
        Added value: +"Best-effort writable status; null means unknown."
    • Changedlist_events31 fields changed
      • addedInput schema / properties / calendar_id / description
        Added value: +"Opaque calendar ID returned by list_calendars."
      • addedInput schema / properties / cursor / description
        Added value: +"Opaque next_cursor from the preceding page. Reuse it with the same calendar, interval, and timezone."
      • addedInput schema / properties / end / description
        Added value: +"Exclusive end of the event search interval; must be after start and no more than 366 days later."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum events to return in this page, from 1 to 500; defaults to 100."
      • addedInput schema / properties / start / description
        Added value: +"Inclusive start of the event search interval as an ISO 8601 instant."
      • addedInput schema / properties / timezone / description
        Added value: +"Fallback IANA timezone used when an event lacks timezone metadata during recurrence expansion."
      • addedOutput schema / properties / events / description
        Added value: +"Events in deterministic chronological order for this page."
      • addedOutput schema / properties / events / items / properties / alarms / description
        Added value: +"Normalized alarms attached to the event."
      • addedOutput schema / properties / events / items / properties / alarms / items / description
        Added value: +"A normalized alarm returned by iCloud Calendar."
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / action / description
        Added value: +"Stored iCalendar alarm action."
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / description / description
        Added value: +"Stored alarm notification text, when available."
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before event start, when representable."
      • addedOutput schema / properties / events / items / properties / alarms / items / properties / uid / description
        Added value: +"Stored alarm UID, when available."
      • addedOutput schema / properties / events / items / properties / calendar_id / description
        Added value: +"Opaque ID of the containing calendar."
      • addedOutput schema / properties / events / items / properties / description / description
        Added value: +"Stored event notes."
      • changedOutput schema / properties / events / items / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / events / items / properties / end / description
        Added value: +"Normalized event end."
      • addedOutput schema / properties / events / items / properties / etag / description
        Added value: +"Current ETag for optimistic concurrency, when available."
      • addedOutput schema / properties / events / items / properties / href / description
        Added value: +"Redacted fingerprint of the CalDAV resource URL."
      • addedOutput schema / properties / events / items / properties / location / description
        Added value: +"Stored event location."
      • addedOutput schema / properties / events / items / properties / raw_ical / description
        Added value: +"Raw iCalendar resource, included only when explicitly requested."
      • addedOutput schema / properties / events / items / properties / recurrence_exception / description
        Added value: +"Whether this result is an overridden recurrence instance."
      • addedOutput schema / properties / events / items / properties / recurrence_id / description
        Added value: +"Occurrence identifier for an expanded recurring event."
      • addedOutput schema / properties / events / items / properties / recurring / description
        Added value: +"Whether this event belongs to a recurring series."
      • addedOutput schema / properties / events / items / properties / resource_id / description
        Added value: +"Opaque event ID accepted by get_event, update_event, and delete_event."
      • addedOutput schema / properties / events / items / properties / rrule / description
        Added value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix."
      • changedOutput schema / properties / events / items / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / events / items / properties / start / description
        Added value: +"Normalized event start."
      • addedOutput schema / properties / events / items / properties / summary / description
        Added value: +"Stored event title."
      • addedOutput schema / properties / events / items / properties / uid / description
        Added value: +"Stored iCalendar UID."
      • addedOutput schema / properties / next_cursor / description
        Added value: +"Opaque cursor for the next page, or null when this is the last page."
    • Changedupdate_event41 fields changed
      • addedInput schema / properties / calendar_id / description
        Added value: +"Opaque calendar ID returned by list_calendars. Provide it together with uid when resource_id is unavailable."
      • addedInput schema / properties / expected_etag / description
        Added value: +"ETag previously returned for the event. When supplied, the update fails if the event changed since it was read."
      • addedInput schema / properties / patch / description
        Added value: +"Fields to replace. Omitted fields are preserved; null clears nullable values and an empty alarms array removes all alarms."
      • addedInput schema / properties / patch / properties / alarms / description
        Added value: +"Replacement alarm set; use an empty array to remove all alarms."
      • addedInput schema / properties / patch / properties / alarms / items / description
        Added value: +"A display reminder attached to an event."
      • addedInput schema / properties / patch / properties / alarms / items / properties / action / description
        Added value: +"Alarm action; only DISPLAY is supported."
      • addedInput schema / properties / patch / properties / alarms / items / properties / description / description
        Added value: +"Optional notification text for this alarm."
      • addedInput schema / properties / patch / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before the event start; use 0 for an alarm at start time."
      • addedInput schema / properties / patch / properties / description / description
        Added value: +"Replacement notes; use null to clear the description."
      • changedInput schema / properties / patch / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedInput schema / properties / patch / properties / end / description
        Added value: +"Replacement end; provide together with start. An all-day end date is exclusive."
      • addedInput schema / properties / patch / properties / location / description
        Added value: +"Replacement location; use null to clear it."
      • addedInput schema / properties / patch / properties / rrule / description
        Added value: +"Replacement RFC 5545 recurrence rule without RRULE:, or null to make the event non-recurring."
      • changedInput schema / properties / patch / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedInput schema / properties / patch / properties / start / description
        Added value: +"Replacement start; provide together with end."
      • addedInput schema / properties / patch / properties / summary / description
        Added value: +"Replacement event title."
      • addedInput schema / properties / resource_id / description
        Added value: +"Opaque event resource ID returned by list_events or get_event. Provide it alone instead of calendar_id and uid."
      • addedInput schema / properties / uid / description
        Added value: +"iCalendar UID of the event. Provide it together with calendar_id when resource_id is unavailable."
      • addedOutput schema / properties / alarms / description
        Added value: +"Normalized alarms attached to the event."
      • addedOutput schema / properties / alarms / items / description
        Added value: +"A normalized alarm returned by iCloud Calendar."
      • addedOutput schema / properties / alarms / items / properties / action / description
        Added value: +"Stored iCalendar alarm action."
      • addedOutput schema / properties / alarms / items / properties / description / description
        Added value: +"Stored alarm notification text, when available."
      • addedOutput schema / properties / alarms / items / properties / minutes_before / description
        Added value: +"Whole minutes before event start, when representable."
      • addedOutput schema / properties / alarms / items / properties / uid / description
        Added value: +"Stored alarm UID, when available."
      • addedOutput schema / properties / calendar_id / description
        Added value: +"Opaque ID of the containing calendar."
      • addedOutput schema / properties / description / description
        Added value: +"Stored event notes."
      • changedOutput schema / properties / end / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / end / description
        Added value: +"Normalized event end."
      • addedOutput schema / properties / etag / description
        Added value: +"Current ETag for optimistic concurrency, when available."
      • addedOutput schema / properties / href / description
        Added value: +"Redacted fingerprint of the CalDAV resource URL."
      • addedOutput schema / properties / location / description
        Added value: +"Stored event location."
      • addedOutput schema / properties / raw_ical / description
        Added value: +"Raw iCalendar resource, included only when explicitly requested."
      • addedOutput schema / properties / recurrence_exception / description
        Added value: +"Whether this result is an overridden recurrence instance."
      • addedOutput schema / properties / recurrence_id / description
        Added value: +"Occurrence identifier for an expanded recurring event."
      • addedOutput schema / properties / recurring / description
        Added value: +"Whether this event belongs to a recurring series."
      • addedOutput schema / properties / resource_id / description
        Added value: +"Opaque event ID accepted by get_event, update_event, and delete_event."
      • addedOutput schema / properties / rrule / description
        Added value: +"Stored RFC 5545 recurrence rule without the RRULE: prefix."
      • changedOutput schema / properties / start / anyOf
        Previous 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"
        +  }
        +]
      • addedOutput schema / properties / start / description
        Added value: +"Normalized event start."
      • addedOutput schema / properties / summary / description
        Added value: +"Stored event title."
      • addedOutput schema / properties / uid / description
        Added value: +"Stored iCalendar UID."
  3. 6 tool updatesv0.1.0
    • First observedcreate_event
    • First observeddelete_event
    • First observedget_event
    • First observedlist_calendars
    • First observedlist_events
    • First observedupdate_event

TDQS

A4.7/5.0
Disambiguation5/5

Each tool has a clear, distinct purpose: calendar discovery, range listing, single-event retrieval, create, update, and delete. get_event and list_events are explicitly differentiated as single-item lookup versus range search.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern, with appropriate pluralization for list operations. This makes the tool set predictable and easy to navigate.

Tool Count5/5

Six tools is well-scoped for a CalDAV server: calendar discovery plus full event CRUD. There is no bloat and no unnecessary overlap.

Completeness5/5

The tool set covers the full event lifecycle: list, get, create, update, and delete, with calendar discovery and handling for recurring series and ETags. No obvious gaps exist for typical calendar event workflows.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lukegskw/caldav-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server