Skip to main content
Glama

CalDAV MCP Server

TypeScript CI Container License

CalDAV MCP Server — это сервер Model Context Protocol для управления событиями iCloud Calendar, включая встроенную поддержку нескольких напоминаний VALARM для одного события.

iCloud Calendar — единственный провайдер, официально поддерживаемый и вручную проверенный в первом выпуске. Сервер работает с любым MCP-клиентом, поддерживающим stdio или Streamable HTTP.

Этот независимый проект не связан с Apple Inc., не авторизован, не спонсируется и не одобрен ею. Apple и iCloud являются товарными знаками соответствующих владельцев.

Навигация

Related MCP server: DAV MCP Server

О проекте

Сервер подключает одну настроенную учётную запись к iCloud через CalDAV. Он обнаруживает календари учётной записи и предоставляет нормализованные операции чтения и записи через MCP.

Обновления сохраняют полный ресурс iCalendar, включая неизвестные свойства, расширения Apple, VTIMEZONE, исключения повторений и напоминания, опущенные в патче. Записи используют непрозрачные идентификаторы ресурсов и ETag вместо предположения, что имя файла CalDAV совпадает с UID события.

Ресурсы календаря обрабатываются в памяти. Сервер не имеет телеметрии и не использует базу данных приложения, а необработанный iCalendar возвращается только по явному запросу.

Возможности

  • Обнаруживает календари, доступные настроенной учётной записи iCloud.

  • Перечисляет события в полуоткрытых временных диапазонах и разворачивает повторяющиеся вхождения.

  • Создаёт события с указанием времени, на весь день и повторяющиеся.

  • Поддерживает ноль, одно или несколько отображаемых напоминаний на событие.

  • Генерирует расширения Apple для напоминаний, ожидаемые iCloud Calendar.

  • Читает события по непрозрачному идентификатору ресурса или по паре идентификатор календаря и UID.

  • Применяет частичные обновления, сохраняя опущенные и неизвестные данные iCalendar.

  • Использует ETag для оптимистичной блокировки при обновлениях и удалениях.

  • Отклоняет изолированные изменения повторений вместо изменения всей серии.

  • Скрывает учётные данные, необработанное содержимое календаря и пути CalDAV из журналов и ошибок.

  • Запускается как контейнер без прав root с конфигурацией корневой файловой системы только для чтения.

  • Поддерживает транспорты MCP stdio и Streamable HTTP.

Инструменты 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_id или по паре calendar_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": []
}

Повторяющиеся события принимают правило RFC 5545 без префикса RRULE::

{
  "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 удаляет поле, допускающее значение null, а alarms: [] удаляет все напоминания. Необязательный expected_etag предотвращает перезапись более новой версии сервера.

delete_event

Удаляет событие или полную повторяющуюся серию, при необходимости требуя наблюдаемый ETag. Удаление отдельного развёрнутого вхождения не поддерживается в текущем выпуске.

Технологический стек

Установка

Предварительные требования

  • Учётная запись iCloud с включённым Calendar.

  • Двухфакторная аутентификация, включённая для Apple Account.

  • Специальный пароль приложения.

  • 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 Account и специальный пароль приложения, затем запустите сервис:

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

URL обнаружения CalDAV.

CALDAV_USERNAME

Да

Нет

Адрес электронной почты Apple Account.

CALDAV_PASSWORD

Да

Нет

Специальный пароль приложения, не пароль учётной записи.

CALDAV_MCP_TRANSPORT

Нет

stdio

stdio или streamable-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-клиента

Для любого MCP-клиента, принимающего определения серверов Streamable HTTP, настройте 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, видны в списке процессов хоста; содержимое файла окружения — нет. Файл содержит переменные, описанные в Конфигурации:

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

Создайте и найдите файл конфигурации через Settings -> Developer -> Edit Config. Не предполагайте путь. Когда 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 не имеет аутентификации в текущем выпуске. Ограничьте её доверенной локальной сетью, VPN или частной сетью контейнеров; не открывайте её напрямую в интернет.

  • Отдельные вхождения повторений доступны только для чтения. Поддерживается обновление или удаление всей серии.

  • Создаются только напоминания ACTION:DISPLAY.

  • Отдельные ресурсы iCalendar ограничены 5 МиБ.

  • Диапазоны списков событий ограничены 366 днями, а страницы — 500 результатами.

  • События могут содержать не более 20 напоминаний.

  • Планирование участников выходит за рамки текущего объёма.

  • Провайдеры, отличные от iCloud, официально не поддерживаются.

См. устранение неполадок для получения рекомендаций по обнаружению, аутентификации, ETag и расширениям Apple. Ознакомьтесь с SECURITY.md перед сообщением о проблеме безопасности или прикреплением диагностики.

Участие в разработке

Вклад приветствуется. Перед открытием pull request:

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

Изменения в записи 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, recurrence rules omit the RRULE: prefix, and travel_minutes sets Apple Calendar travel time for timed events.

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.
travel_minutesNoApple Calendar travel time in whole minutes before the start; defaults to null. Only valid for timed events.

Output 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.
travel_minutesYesApple Calendar travel time in whole minutes before the start, or null when none is set.
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 establish that this is a non-read-only, non-idempotent, open-world, non-destructive operation. The description adds useful behavioral context: it writes to a writable iCloud calendar, returns the stored representation, and explicitly states existing events are not changed. It omits permission and rate-limit details, but the annotation coverage lowers the burden.

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

Conciseness5/5

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

The description is front-loaded with purpose and usage, then consolidates key temporal and recurrence constraints without wasted text. Every clause carries actionable meaning for invocation.

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

Completeness5/5

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

Given a nine-parameter create tool with full schema coverage, annotations, and an output schema, the description covers purpose, prerequisites, alternatives, and critical formatting semantics. Nothing essential for correct invocation is missing.

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

Parameters3/5

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

Schema description coverage is 100%, and the schema already documents matching timezone offsets, exclusive all-day end dates, the RRULE prefix omission, and travel_minutes being valid only for timed events. The description repeats and emphasizes these constraints but adds little genuinely new parameter-level meaning beyond the schema.

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

Purpose5/5

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

States a specific verb and resource: create a new event in a writable iCloud calendar. It also clarifies that it returns the stored representation and does not modify existing events, which distinguishes it from update_event and other sibling tools.

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

Usage Guidelines5/5

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

Explicitly directs the agent to call list_calendars first to obtain calendar_id, and names update_event as the alternative when the event already exists. This gives clear prerequisites and a concrete routing rule.

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

delete_eventDelete calendar 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.

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

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.

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

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.
travel_minutesYesApple Calendar travel time in whole minutes before the start, or null when none is set.
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 readOnly, idempotent, openWorld and non-destructive, so safety is covered; the description contributes the extra warning that raw iCalendar output may contain sensitive calendar data and should be reserved for diagnostics. It doesn't cover lookup failure behavior (e.g., what happens if the resource_id is stale), which is the only material gap.

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

Conciseness5/5

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

Three short sentences, front-loaded with the primary lookup path before the alternative and the parameter caveat. No sentence is filler.

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

Completeness5/5

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

Required-params is zero and the real constraint (resource_id alone OR calendar_id + uid) is not encoded as a schema requirement, so the description carrying that selection logic is exactly what's needed. With annotations and an output schema present, nothing else is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so both the either/or key selection and the include_raw_ical sensitivity caveat are already documented in the property descriptions. The description restates rather than adds to them, so the baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource ('Read one event') and immediately names the two valid lookup keys (resource_id, or calendar_id + uid pair). It also distinguishes itself from list_events, so an agent can tell it apart from a sibling without opening any schema.

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

Usage Guidelines5/5

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

Explicitly routes range searching to the alternative ('Use list_events for range searches') and gives a preference rule ('preferably from a previous result') for choosing resource_id over the composite key. It also scopes the raw iCalendar option to controlled diagnostics, which is a when-to-use constraint on a parameter.

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

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

NameRequiredDescriptionDefault

No parameters

Output 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.

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

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.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/non-destructive, yet the description still adds real behavior: recurring series are expanded into occurrences, the interval is start-inclusive/end-exclusive, the window is capped at 366 days, and cursors must be replayed with identical filters. It stops short of stating result ordering or how cancelled/declined events are treated, which matters for a paginated list.

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

Conciseness5/5

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

Three dense sentences with zero filler: capability and boundary semantics first, then routing to siblings/prerequisites, then pagination. Each sentence earns its place and the most decision-relevant information is front-loaded.

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

Completeness5/5

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

An output schema exists, so return values need no explanation, and annotations carry the safety profile. Combined with a fully documented six-parameter schema, the description supplies exactly the missing pieces: recurrence expansion, interval boundary rules, the 366-day cap, and cursor reuse constraints.

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

Parameters3/5

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

Schema description coverage is 100%, with start/end/cursor/limit/timezone all documented in the schema itself; the description mostly restates the interval semantics rather than adding new parameter meaning. Baseline 3 applies when the schema already carries the parameter burden.

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

Purpose5/5

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

States a specific verb and resource (list events) plus precise scope: half-open interval overlap and recurrence expansion into occurrences. It explicitly distinguishes itself from get_event (single known event) and list_calendars (ID lookup), so an agent can route without opening the schema.

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

Usage Guidelines5/5

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

Gives explicit prerequisites ('Use list_calendars first to obtain calendar_id'), an explicit alternative ('use get_event instead for one known event'), and pagination continuation rules ('Continue with next_cursor and unchanged query filters'). When-to-use, when-not-to-use, and follow-up behavior are all covered.

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

update_eventUpdate calendar 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.

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

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.
travel_minutesYesApple Calendar travel time in whole minutes before the start, or null when none is set.
recurrence_exceptionYesWhether this result is an overridden recurrence instance.

TDQS

A4.3/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and idempotentHint=false, so the mutation risk profile is covered. The description usefully adds patch semantics (omitted fields preserved, null clears, empty alarms removes) and the etag-based concurrency guard, which are genuine behavioral facts beyond the annotations.

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

Conciseness5/5

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

Two dense sentences, front-loaded with purpose and scope, then the targeting and patch rules. No filler and nothing repeated for its own sake.

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

Completeness5/5

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

For a 5-parameter nested mutation tool, the description covers targeting, patch replace-vs-clear semantics, recurrence limits, and concurrency control, while annotations carry the safety profile and an output schema exists. Nothing an agent needs to call it correctly is missing.

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

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, but the description adds cross-parameter meaning: resource_id stands alone while calendar_id must be paired with uid, and it restates the preserve/clear contract for the patch object. That is modest but real value beyond the per-field schema text.

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

Purpose5/5

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

States a specific verb and resource ('Modify an existing event or entire recurring series') and immediately bounds scope with a negative ('individual expanded occurrences are not supported'). That scope statement cleanly separates it from create_event, delete_event, and get_event without needing to name them.

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

Usage Guidelines4/5

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

Gives concrete invocation guidance: target by resource_id or by calendar_id with uid, and use expected_etag for stale-write protection. It also states an explicit exclusion (no per-occurrence edits), but never names a sibling alternative for cases like deleting or creating, so it stops short of full routing guidance.

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

Tool Schema Changelog

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

  1. 4 tool updatesv0.2.0
    • Changedcreate_event3 fields changed
      • addedInput schema / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 1440,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Apple Calendar travel time in whole minutes before the start; defaults to null. Only valid for timed events."
        +}
      • addedOutput schema / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set."
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "calendar_id",
        -  "resource_id",
        -  "uid",
        -  "href",
        -  "etag",
        -  "summary",
        -  "start",
        -  "end",
        -  "description",
        -  "location",
        -  "rrule",
        -  "alarms",
        -  "recurring",
        -  "recurrence_exception",
        -  "recurrence_id"
        -]New value: +[
        +  "calendar_id",
        +  "resource_id",
        +  "uid",
        +  "href",
        +  "etag",
        +  "summary",
        +  "start",
        +  "end",
        +  "description",
        +  "location",
        +  "rrule",
        +  "alarms",
        +  "travel_minutes",
        +  "recurring",
        +  "recurrence_exception",
        +  "recurrence_id"
        +]
    • Changedget_event2 fields changed
      • addedOutput schema / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set."
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "calendar_id",
        -  "resource_id",
        -  "uid",
        -  "href",
        -  "etag",
        -  "summary",
        -  "start",
        -  "end",
        -  "description",
        -  "location",
        -  "rrule",
        -  "alarms",
        -  "recurring",
        -  "recurrence_exception",
        -  "recurrence_id"
        -]New value: +[
        +  "calendar_id",
        +  "resource_id",
        +  "uid",
        +  "href",
        +  "etag",
        +  "summary",
        +  "start",
        +  "end",
        +  "description",
        +  "location",
        +  "rrule",
        +  "alarms",
        +  "travel_minutes",
        +  "recurring",
        +  "recurrence_exception",
        +  "recurrence_id"
        +]
    • Changedlist_events2 fields changed
      • addedOutput schema / properties / events / items / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set."
        +}
      • changedOutput schema / properties / events / items / required
        Previous value: -[
        -  "calendar_id",
        -  "resource_id",
        -  "uid",
        -  "href",
        -  "etag",
        -  "summary",
        -  "start",
        -  "end",
        -  "description",
        -  "location",
        -  "rrule",
        -  "alarms",
        -  "recurring",
        -  "recurrence_exception",
        -  "recurrence_id"
        -]New value: +[
        +  "calendar_id",
        +  "resource_id",
        +  "uid",
        +  "href",
        +  "etag",
        +  "summary",
        +  "start",
        +  "end",
        +  "description",
        +  "location",
        +  "rrule",
        +  "alarms",
        +  "travel_minutes",
        +  "recurring",
        +  "recurrence_exception",
        +  "recurrence_id"
        +]
    • Changedupdate_event3 fields changed
      • addedInput schema / properties / patch / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 1440,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Replacement Apple Calendar travel time in whole minutes; omit to preserve it or use null to remove travel time and related routing metadata. A number requires a timed event; converting to all-day requires clearing existing travel time with null."
        +}
      • addedOutput schema / properties / travel_minutes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Apple Calendar travel time in whole minutes before the start, or null when none is set."
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "calendar_id",
        -  "resource_id",
        -  "uid",
        -  "href",
        -  "etag",
        -  "summary",
        -  "start",
        -  "end",
        -  "description",
        -  "location",
        -  "rrule",
        -  "alarms",
        -  "recurring",
        -  "recurrence_exception",
        -  "recurrence_id"
        -]New value: +[
        +  "calendar_id",
        +  "resource_id",
        +  "uid",
        +  "href",
        +  "etag",
        +  "summary",
        +  "start",
        +  "end",
        +  "description",
        +  "location",
        +  "rrule",
        +  "alarms",
        +  "travel_minutes",
        +  "recurring",
        +  "recurrence_exception",
        +  "recurrence_id"
        +]
  2. 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"
        +]
  3. 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."
  4. 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.5/5.0

Scored across 6 tools

Disambiguation5/5

Each tool maps to a distinct action on a distinct resource: create/list/get/update/delete events plus list calendars. The descriptions explicitly clarify boundaries, such as list_events vs get_event and update vs create.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: create_event, list_events, get_event, update_event, delete_event, list_calendars.

Tool Count5/5

Six tools are well-scoped for a CalDAV server: one discovery tool and a complete event CRUD set. No tool appears redundant or trivial.

Completeness4/5

The surface covers full event lifecycle plus calendar discovery, which is the core domain. Minor gaps exist around calendar-level operations and individual recurring-occurrence edits, though these are documented limitations rather than dead ends.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers