mcpField
C
CalDAV MCP Server

CalDAV MCP Server

本地服务
github.com/lukegskw生产力51 周前更新

关于 CalDAV MCP Server

CalDAV MCP Server 将一个已配置账户连接到 iCloud Calendar,用于管理日历事件。它面向支持 `stdio` 或 Streamable HTTP 的 MCP 客户端,支持每个事件设置多个提醒,并在局部更新时保留 iCalendar 数据。

主要功能

  1. 01发现日历并列出事件
  2. 02创建定时、全天和重复事件
  3. 03设置多个提醒和 Apple 行程时间
  4. 04保留未修改及未知的 iCalendar 数据
  5. 05通过 ETag 控制更新和删除并发

适用场景

  1. 01查看指定时间范围内的事件
  2. 02创建带多个提醒的重复事件
  3. 03更新事件时保留未修改的日历数据

MCP 相关

向 MCP 客户端提供标准化的 iCloud Calendar 读写操作,支持 `stdio` 和 Streamable HTTP 传输方式。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"lukegskw-caldav": {
"command": "npx",
"args": [
"-y",
"@lukegskw/caldav-mcp"
],
"env": {
"CALDAV_USERNAME": "<CALDAV_USERNAME>",
"CALDAV_PASSWORD": "<CALDAV_PASSWORD>"
}
}
}
}
启动命令npx -y @lukegskw/caldav-mcp
需要配置的环境变量
CALDAV_USERNAMEYour CalDAV username
CALDAV_PASSWORD密钥Your CalDAV password or app-specific password

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocighcr.io/lukegskw/caldav-mcp:0.2.0
npm@lukegskw/caldav-mcp0.2.0

工具

6

收录的工具列表 · 更新于 1 周前

此工具无需参数。

详细介绍

CalDAV MCP 服务

TypeScript CI npm npm downloads Container MCP Registry License

CalDAV MCP Server 是一个用于管理 iCloud 日历事件的模型上下文协议服务,原生支持为单个事件设置多个 VALARM 提醒。

首个版本仅正式支持并经人工验证了 iCloud 日历。该服务适用于支持 stdio 或 Streamable HTTP 的任何 MCP 客户端。

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

快速开始

创建一个 Apple app 专用密码,然后选择适合你客户端的选项。

Claude Desktop(一键安装,无需安装 Node.js): 下载 caldav-mcp.mcpb, 用 Claude Desktop 打开,并输入你的 Apple 账户邮箱和 app 专用密码。请参阅 Claude Desktop 扩展。

任何其他 stdio 客户端: 安装 Node.js 22 或更高版本,并将此服务添加到使用 JSON 配置的 MCP 客户端,例如 Gemini CLI 或 Claude Code:

{
  "mcpServers": {
    "icloud-calendar": {
      "command": "npx",
      "args": ["--yes", "@lukegskw/caldav-mcp@latest"],
      "env": {
        "CALDAV_USERNAME": "[email protected]",
        "CALDAV_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
      }
    }
  }
}

重启客户端,并确认它列出了六个日历工具。请参阅下文的客户端专属设置和 Docker 部署。配置文件包含 app 专用密码,请妥善保密。

导航

关于

此服务通过 CalDAV 将一个已配置账户连接到 iCloud。它会发现该账户的日历,并通过 MCP 提供标准化的读写操作。

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

日历资源仅在内存中处理。此服务不收集遥测数据,也不使用应用数据库;只有在明确请求时才会返回原始 iCalendar。

功能

  • 发现已配置 iCloud 账户中可用的日历。
  • 列出半开时间范围内的事件,并展开重复事件。
  • 创建定时、全天和重复事件。
  • 支持每个事件设置零个、一个或多个显示提醒。
  • 读取和写入 Apple Calendar 行程时间(X-APPLE-TRAVEL-DURATION)。
  • 输出 iCloud Calendar 所需的 Apple 提醒扩展。
  • 按不透明资源 ID,或按日历 ID 和 UID 读取事件。
  • 在保留未提供字段和未知 iCalendar 数据的同时应用部分更新。
  • 更新和删除时使用 ETag 实现乐观并发控制。
  • 拒绝单独修改重复事件实例,以免更改整个系列。
  • 从日志和错误中移除凭据、原始日历内容和 CalDAV 路径。
  • 以非 root 容器运行,并配置只读根文件系统。
  • 支持 stdio 和 Streamable HTTP MCP 传输方式。

MCP 工具

list_calendars

列出为已配置账户发现的日历。每个结果都包含不透明的 calendar_id、显示名称、描述、时区,以及尽力获取的写入状态。

list_events

列出半开时间区间内的事件,并展开重复事件。最大范围为 366 天,默认分页大小为 100,最大分页大小为 500。结果按确定性的时间顺序排列。分页游标是不透明的;遍历过程中若事件发生更改,游标不代表快照。

输入示例:

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

按 resource_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": []
}

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

{
  "calendar_id": "opaque-calendar-id",
  "summary": "Weekly planning",
  "start": {
    "date_time": "2026-09-07T09:00:00+02:00",
    "timezone": "Europe/Berlin"
  },
  "end": {
    "date_time": "2026-09-07T09:30:00+02:00",
    "timezone": "Europe/Berlin"
  },
  "rrule": "FREQ=WEEKLY;BYDAY=MO;COUNT=10"
}

包含 30 分钟 Apple Calendar 行程时间的定时事件:

{
  "calendar_id": "opaque-calendar-id",
  "summary": "Dentist",
  "start": {
    "date_time": "2026-10-05T10:00:00+02:00",
    "timezone": "Europe/Amsterdam"
  },
  "end": {
    "date_time": "2026-10-05T10:30:00+02:00",
    "timezone": "Europe/Amsterdam"
  },
  "travel_minutes": 30
}

travel_minutes 用于设置事件开始前的固定行程时长。在此示例中,行程于 09:30 开始,预约时间仍为 10:00–10:30。服务器接受定时事件的整数分钟数,范围为 1 到 1,440;创建不含行程时间的事件时,请省略此字段或使用 null。服务器不会计算路线,也不会更改事件的开始时间、结束时间或提醒。

该时长存储在 Apple 的 X-APPLE-TRAVEL-DURATION 扩展中。其他日历客户端是否显示取决于其对该扩展的支持情况。返回的事件包含四舍五入到整数分钟的 travel_minutes;如果时长缺失、无效或四舍五入后为零,则该值为 null。

update_event

更新事件或重复事件系列的主事件。未提供的字段会保留,null 会移除可空字段,alarms: [] 会移除所有提醒。可选的 expected_etag 可防止覆盖服务器上的较新版本。

对于行程时间,省略 patch.travel_minutes 可保留当前值;设为数字可替换时长;设为 null 可移除时长和相关 Apple 路线元数据。例如,"patch": { "travel_minutes": null } 会清除行程时间。将包含行程时间的事件转换为全天事件时,请同时提供新的开始和结束日期,以及 travel_minutes: null。现有的重复事件例外会保留各自的行程设置。

delete_event

删除事件或完整的重复事件系列,也可选择要求提供已观察到的 ETag。当前版本不支持删除单个展开后的事件实例。

技术栈

安装

前置条件
  • 已启用日历的 iCloud 账户。
  • Apple 账户已启用双重认证。
  • App 专用密码。
  • 使用 Docker 和 Docker Compose 进行容器部署;使用 npx 需安装 Node.js 22+;使用一键扩展需安装 Claude Desktop。
  • 仅从源代码构建时需要 pnpm。Corepack 和 CI 使用 package.json 中固定的版本。
Node.js 要求
用途Node.js
Claude Desktop 扩展(.mcpb)无需安装;Claude Desktop 使用内置的 Node.js
npx 或全局 npm 安装22 LTS 或更高版本;CI 测试 22 和 24
Docker 镜像无需安装;镜像内置 Node.js 24
从源代码构建和贡献22.13 或更高版本,ESLint 10 和 Vitest 5 要求使用;推荐 24

package.json 中的 engines.node 为 >=22。Node.js 20 已于 2026 年 4 月结束生命周期,不受支持;在旧版本上,npm 会打印 EBADENGINE 警告。使用 node --version 检查 MCP 客户端将使用的版本。桌面客户端使用的 node 可能与终端不同,因此,如果客户端无法启动服务,请为其指定 Node.js 22+ 的 npx 绝对路径(macOS/Linux 上使用 command -v npx,Windows 上使用 where npx)。

npm / npx

无需全局安装或克隆仓库。MCP 客户端可以直接启动最新发布的程序包:

CALDAV_USERNAME='[email protected]' \
CALDAV_PASSWORD='xxxx-xxxx-xxxx-xxxx' \
npx --yes @lukegskw/caldav-mcp@latest

该命令会等待通过 stdin 接收 MCP 消息,通常不会向 stdout 输出任何内容。实际使用时,请按照 MCP 客户端配置中的说明将其添加到客户端配置中。若要确保环境可复现,请将 latest 替换为确切的已发布版本,例如 X.Y.Z。

Docker Compose

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

ghcr.io/lukegskw/caldav-mcp:latest

下载 Compose 示例:

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

提供 Apple 账户邮箱和 App 专用密码,然后启动服务:

export CALDAV_USERNAME='[email protected]'
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 标签对应最新的稳定版本。稳定版本也会发布确切标签(例如 0.1.6)和次要系列标签(例如 0.1)。Compose 示例通过摘要固定 latest,以确保部署可复现。若要升级,请下载更新后的 Compose 示例,或将完整镜像引用替换为所需的已发布版本及摘要。

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 安装

从源代码构建需要 Node.js 22.13 或更高版本;建议使用 Node.js 24。 构建和类型检查使用 TypeScript 7。typescript 依赖项将 @typescript/typescript6 作为别名提供给 ESLint,因为 ESLint 仍需要 TypeScript 6 API; @typescript/native 则提供 TypeScript 7 的 tsc 可执行文件。请参阅 TypeScript 迁移指南。

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.comCalDAV 发现 URL。
CALDAV_USERNAME是无Apple Account 电子邮件地址。
CALDAV_PASSWORD是无App 专用密码,而非账户密码。
CALDAV_MCP_TRANSPORT否stdiostdio 或 streamable-http。
CALDAV_MCP_HOST否0.0.0.0HTTP 绑定地址。
CALDAV_MCP_PORT否8100HTTP 监听端口。
CALDAV_MCP_LOG_LEVEL否INFO应用日志级别。
CALDAV_MCP_REQUEST_TIMEOUT_MS否30000CalDAV 请求超时时间。

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

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

MCP 客户端设置

Claude Desktop 扩展(推荐)

适用于 macOS 和 Windows 的 Claude Desktop 可将服务作为一键安装的 MCP Bundle,并使用其内置的 Node.js 运行:

  1. 从最新版本下载 caldav-mcp.mcpb。
  2. 使用 Claude Desktop 打开它(双击,或将其拖到 Settings -> Extensions),然后选择 Install。
  3. 输入 Apple Account 电子邮件地址和 App 专用密码。密码会以敏感设置的形式存储。

若要升级,请安装较新版本中的 .mcpb。请参阅 Claude Desktop 扩展,了解 Bundle 内容以及其构建和发布方式。

Gemini CLI 扩展

直接从 GitHub 安装并启用扩展自动更新:

gemini extensions install https://github.com/lukegskw/caldav-mcp --auto-update

Gemini 会提示输入用户名,并将 App 专用密码作为敏感设置存储。公共扩展库会从此仓库中发现已标记的版本。

手动配置

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

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

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

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

对于启动本地 stdio 服务的客户端,优先使用快速开始中的 npm 命令。如果桌面客户端找不到 npx,请在 macOS/Linux 上使用 command -v npx 返回的绝对路径,或在 Windows 上使用 where npx 返回的路径。

Claude Desktop

扩展是最简单的选择。若要改为手动配置服务,请将快速开始中的 JSON 添加到 claude_desktop_config.json 的 mcpServers 下,然后完全重启 Claude Desktop。请通过 设置 -> 开发者 -> 编辑配置 打开该文件,而不要猜测文件所在位置。

Claude Code

Claude Code 可以在用户级别添加相同的 stdio 服务:

claude mcp add --transport stdio --scope user \
  --env [email protected] \
  --env CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx \
  icloud-calendar -- npx --yes @lukegskw/caldav-mcp@latest

此命令会将这些值写入 Claude 的 MCP 配置。请勿在 shell 历史记录被共享或未安全保留的环境中运行此命令。

Codex

Codex 可以将服务添加到共享的 CLI 和 IDE 配置中:

codex mcp add icloud-calendar \
  --env [email protected] \
  --env CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx \
  -- npx --yes @lukegskw/caldav-mcp@latest

运行 codex mcp list 进行验证。如需更精细的控制,请在 ~/.codex/config.toml 或项目级 .codex/config.toml 中使用官方 Codex MCP 配置。

Gemini CLI

按照 Gemini CLI MCP 配置,在 ~/.gemini/settings.json(用户级别)或项目的 .gemini/settings.json 中将服务添加到 mcpServers 下:

{
  "mcpServers": {
    "icloud-calendar": {
      "command": "npx",
      "args": ["--yes", "@lukegskw/caldav-mcp@latest"],
      "env": {
        "CALDAV_USERNAME": "[email protected]",
        "CALDAV_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
      }
    }
  }
}
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 的参数会显示在主机进程列表中,而环境文件的内容不会。该文件包含配置中所述的变量:

[email protected]
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

如果从 Microsoft Store 安装 Claude Desktop,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
pnpm test:package
pnpm test:distribution
pnpm build:mcpb
pnpm test:mcpb

最后,连接到 MCP 客户端,并确认列出了全部六个工具。

限制

  • 每个服务进程或容器只能配置一个 iCloud 账户。
  • 当前版本的 Streamable HTTP 端点没有身份验证。请将其限制在可信的局域网、VPN 或私有容器网络内;不要直接暴露到互联网。
  • 单个重复事件实例为只读。支持更新或删除整个系列。
  • 仅创建 ACTION:DISPLAY 提醒。
  • 单个 iCalendar 资源大小上限为 5 MiB。
  • 事件列表的日期范围上限为 366 天,每页最多 500 条结果。
  • 每个事件最多可包含 20 个提醒。
  • 当前范围不包括与会者日程安排。
  • 不正式支持 iCloud 以外的提供商。

报告安全问题或附加诊断信息之前,请先阅读 SECURITY.md。

贡献

欢迎贡献。在提交拉取请求之前:

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

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

发布

发布由版本驱动,并从 main 自动执行,这样即使注册表部分不可用,也可以重试,而无需发布第二个 npm 版本。

  1. 使用 pnpm release:prepare X.Y.Z 准备新版本。此命令会同步 npm、MCP Registry、Gemini 和 MCP Bundle(manifest.json)元数据。
  2. 运行验证套件,包括 pnpm test:distribution 和 pnpm test:mcpb。
  3. 将发布更改提交并推送到 main。
  4. 发布工作流会验证提交,并在发布前自动创建对应的 vX.Y.Z 标签。

发布工作流会验证版本,测试打包后的 npm 构件和 Claude Desktop Bundle,并同时发布精确版本、次版本系列和 latest 容器标签,以及 npm 包、MCP Registry 条目和附带 caldav-mcp.mcpb 的 GitHub Release。预发布版本只会获得对应的精确容器标签。Gemini 无需在每次发布时另行编辑,即可发现已标记的扩展。重新运行时会跳过已存在的匹配构件,并继续执行缺失的步骤。有关 .mcpb Bundle 的构建、测试和发布,请参阅 Claude Desktop 扩展。

许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。