mcpField
I
iCloud Calendar (CalDAV)

iCloud Calendar (CalDAV)

本地服务
github.com/Glob0x17生产力03 周前更新

关于 iCloud Calendar (CalDAV)

iCloud Calendar (CalDAV) 是供 MCP 客户端管理 iCloud 日历的 MCP 服务,支持 Linux、macOS 和 Windows。它通过 iCloud CalDAV 列出和编辑事件,并可选择只读模式。

主要功能

  1. 01列出日历及日期范围内的事件
  2. 02创建和更新事件
  3. 03在日历间移动事件
  4. 04按标识符删除事件
  5. 05可选只读模式

适用场景

  1. 01查看多个 iCloud 日历中的事件
  2. 02创建或修改日历条目
  3. 03将事件移至其他日历
  4. 04让客户端只读访问日历

MCP 相关

该服务通过 stdio 向 MCP 客户端提供日历和事件工具,以及日历列表资源。只读模式会移除创建、更新和删除事件的工具。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"glob0x17-mcp-icloud-caldav": {
"command": "uvx",
"args": [
"mcp-icloud-caldav"
],
"env": {
"ICLOUD_USERNAME": "<ICLOUD_USERNAME>",
"ICLOUD_PASSWORD": "<ICLOUD_PASSWORD>",
"MCP_ICAL_READ_ONLY": "<MCP_ICAL_READ_ONLY>",
"MCP_ICAL_LOG_LEVEL": "<MCP_ICAL_LOG_LEVEL>"
}
}
}
}
启动命令uvx mcp-icloud-caldav
需要配置的环境变量
ICLOUD_USERNAMEApple ID email address
ICLOUD_PASSWORD密钥App-specific password from appleid.apple.com (not the Apple ID password)
MCP_ICAL_READ_ONLYSet to true to leave out the create, update and delete tools
MCP_ICAL_LOG_LEVELLog level on stderr: TRACE, DEBUG, INFO, WARNING or ERROR

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

安装包
pypimcp-icloud-caldav0.2.1

工具

6

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

此工具无需参数。

详细介绍

iCloud Calendar MCP 服务

PyPI Python 3.12+ License: MIT

一个 Model Context Protocol 服务,让 MCP 客户端能够通过 CalDAV 访问 iCloud Calendar:列出日历、读取、创建、更新、移动和删除事件。它可在 Linux、macOS 和 Windows 上运行,因为它直接与 iCloud 通信,而不是通过 macOS Calendar 应用。

这是 zwrong/iCalendar 的维护分支,而后者源自 macOS 的 mcp-ical 服务。请参阅此分支中的更改。

工具

工具说明
list_calendars可用日历的名称
list_events指定日期范围内的事件,可选指定一个日历,并按开始时间排序
create_event新建事件:标题、时间、全天、地点、备注、URL、提醒、重复规则
update_event更改上述任意字段,或将事件移动到其他日历
delete_event按标识符删除事件
debug_calendar_connection检查连接:列出日历及过去 7 天的事件数量

calendars://list 资源也会列出日历。设置 MCP_ICAL_READ_ONLY=true 后,三个写入工具将不会注册。

要求

  • Python 3.12 或更高版本,以及 uv
  • 已启用 iCloud Calendar 的 Apple ID
  • 该 Apple ID 的专用 App 密码
专用 App 密码
  1. 登录 appleid.apple.com,打开登录与安全,然后选择专用 App 密码。
  2. 生成一个密码,例如命名为 mcp-icloud-caldav。

用户名是你的 Apple ID 地址,不一定是 @icloud.com 地址。 专用 App 密码可用于访问 iCloud CalDAV、CardDAV 和 IMAP:请勿将其纳入版本控制;如果密码泄露,请撤销。

安装

此软件包以 mcp-icloud-caldav 的名称发布在 PyPI 上。使用 uv 时,MCP 客户端可以直接启动它,无需单独安装:

uvx mcp-icloud-caldav

首次使用时,uvx 会将软件包下载到缓存的隔离环境中。如需永久安装: uv tool install mcp-icloud-caldav(或 pipx install mcp-icloud-caldav)。

从源代码安装:

git clone https://github.com/Glob0x17/mcp-icloud-caldav.git mcp-icloud-caldav
cd mcp-icloud-caldav
uv sync --no-dev
uv run mcp-icloud-caldav

配置

凭据按以下顺序读取:

  1. 环境变量(推荐)

    变量必需默认值
    ICLOUD_USERNAME是
    ICLOUD_PASSWORD是
    CALDAV_SERVER_URL否https://caldav.icloud.com/
  2. MCP_ICAL_CONFIG:JSON 文件的路径,其结构如 config.json.example

  3. 仓库根目录下的 config_private.json,然后是 config.json(为保持兼容而保留)

其他设置:

变量默认值作用
MCP_ICAL_READ_ONLYfalse设为 true 时,不包含 create_event、update_event 和 delete_event
MCP_ICAL_LOG_LEVELINFOTRACE、DEBUG、INFO、WARNING 或 ERROR。日志输出到 stderr

该服务通过 stdio 使用 MCP,并由客户端启动。要手动检查:

[email protected] ICLOUD_PASSWORD=xxxx-xxxx-xxxx-xxxx uvx mcp-icloud-caldav

它会等待 stdin 输入,且不会向 stdout 输出任何内容。

客户端设置

如果客户端找不到 uvx,请使用它的绝对路径(which uvx):客户端通常会在不包含你 shell PATH 的环境中启动服务,因此会出现 spawn uvx ENOENT。常见路径:

安装方式路径
uv 安装程序(Linux、macOS)~/.local/bin/uvx
Apple 芯片上的 Homebrew/opt/homebrew/bin/uvx
Intel Mac 上的 Homebrew/usr/local/bin/uvx

命令和参数是分开的字段:命令是 uvx(或它的路径),而 mcp-icloud-caldav 是参数。如果配置中的命令是单个字符串 "uvx mcp-icloud-caldav",就会因 ENOENT 而失败,因为客户端会查找名称完全相同(包括空格)的程序。

避免在客户端配置中明文保存密码

大多数客户端会将 env 值以明文形式存储在配置文件中。使用一个读取环境变量文件的小型包装脚本即可避免这种情况:

mkdir -p ~/.config/mcp-icloud-caldav && chmod 700 ~/.config/mcp-icloud-caldav
cat > ~/.config/mcp-icloud-caldav/env <<'EOF'
[email protected]
ICLOUD_PASSWORD=xxxx-xxxx-xxxx-xxxx
MCP_ICAL_READ_ONLY=true
EOF
chmod 600 ~/.config/mcp-icloud-caldav/env

cat > ~/.local/bin/mcp-icloud-caldav-run <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
set -a; source "$HOME/.config/mcp-icloud-caldav/env"; set +a
exec /absolute/path/to/uvx mcp-icloud-caldav
EOF
chmod +x ~/.local/bin/mcp-icloud-caldav-run

然后让客户端指向 ~/.local/bin/mcp-icloud-caldav-run。先以只读模式启动,确认读取正常后再切换为 false,是个稳妥的第一步。

Claude Desktop

在 claude_desktop_config.json 中配置(Settings、Developer、Edit Config)。在 macOS 上,文件路径为 ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "icloud-calendar": {
      "command": "uvx",
      "args": ["mcp-icloud-caldav"],
      "env": {
        "ICLOUD_USERNAME": "[email protected]",
        "ICLOUD_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
      }
    }
  }
}

或者,使用包装脚本时,设置 "command": "/home/you/.local/bin/mcp-icloud-caldav-run",且不设置 env。编辑后,请完全退出 Claude Desktop 并重新启动。在 macOS 上,服务日志位于 ~/Library/Logs/Claude/mcp-server-icloud-calendar.log。

Claude Code
claude mcp add --scope user icloud-calendar \
  -e [email protected] -e ICLOUD_PASSWORD=xxxx-xxxx-xxxx-xxxx \
  -- uvx mcp-icloud-caldav

或者,使用包装脚本时,运行 claude mcp add --scope user icloud-calendar -- ~/.local/bin/mcp-icloud-caldav-run。

不要给 -- 后面的内容加引号:-- uvx mcp-icloud-caldav 会将 uvx 注册为命令,并将 mcp-icloud-caldav 注册为参数;而 -- "uvx mcp-icloud-caldav" 会将两者注册为一个程序名,并因 ENOENT 而失败。要修复已有条目,请运行 claude mcp remove icloud-calendar --scope user 将其移除,然后重新添加。

在会话中运行 /mcp 可查看服务状态及其工具;运行 claude mcp get icloud-calendar 可查看已注册的命令和参数。

其他客户端

任何能够启动 stdio 服务的 MCP 客户端都可使用:运行 uvx mcp-icloud-caldav,并设置上述环境变量。该服务也已列入 MCP Registry,名称为 io.github.Glob0x17/mcp-icloud-caldav。

需要了解的行为

  • 时间。 事件时间以 UTC 写入。带有时区偏移的时间(2030-01-07T09:30:00+01:00)会进行转换,不带偏移的时间则视为机器的本地时间。显示时间时会使用机器的时区。全天事件以日期形式写入,并按照 iCalendar 标准将结束日期设为不包含在内。
  • 在日历之间移动。 iCloud 不允许同一个事件 UID 出现在两个日历中,因此移动不能采用“先复制再删除”的方式。update_event 使用 calendar_name 时会执行 WebDAV MOVE,这在服务端是原子操作:如果操作失败,事件仍保留在原处。不进行其他更改的移动会保留原始 iCalendar 数据不变。
  • 查找事件。 列表操作会填充一个内存索引(UID 到 URL 的映射),该索引的生命周期与服务进程相同。之后查找会直接访问事件;如果找不到,则会回退到 iCloud 用于大多数事件的 <calendar>/<UID>.ics URL,最后才扫描所有日历。iCloud 不支持 CalDAV UID 搜索。
  • 数量。 iCloud 每次请求返回的事件数量不限。实际限制在于客户端:许多客户端会将工具结果限制在约 25,000 个 token,也就是此服务输出中的约 300 个事件,因此较长的时间范围应分开查询。
  • 范围。 只能查看托管在 iCloud 上的日历。通过设备上的 Calendar 应用添加的 Exchange、Google 或其他账户无法通过 iCloud CalDAV 访问,订阅的只读(ICS)日历也无法访问。

隐私与安全

  • 唯一的网络目标是已配置的 CalDAV 服务;不会收集遥测数据。
  • 密码绝不会出现在任何级别的日志中,也不会出现在配置对象的 repr 中。
  • 日志仅写入 stderr,因为 stdout 用于 MCP 协议。事件内容(标题、备注)仅在 DEBUG 或更低级别记录;在 INFO 级别,仅记录标识符。有些客户端会将服务的 stderr 保存到磁盘,因此排查问题时请使用 DEBUG。
  • 依赖项已锁定在 uv.lock 中,且仅从官方 PyPI 索引解析。

故障排除

症状可能原因
401 Unauthorized使用了普通 Apple ID 密码,而不是专用密码,或者专用密码已被撤销
spawn uvx ENOENT 或 ENOENT客户端的 PATH 中没有 uvx(请使用其绝对路径),或者命令和参数被注册成了一个字符串(参见客户端配置)
未返回事件日期范围错误、事件位于非 iCloud 日历或订阅日历中,或者时区混用
服务没有响应有内容写入 stdout,破坏了 stdio 协议
Calendar 'X' not found日历名称区分大小写:请检查 list_calendars

debug_calendar_connection 和 MCP_ICAL_LOG_LEVEL=DEBUG 有助于缩小问题范围。

开发

uv sync
uv run pytest -m "not integration"   # unit tests, CalDAV client mocked, no network
uv run ruff check .

集成测试会对真实账户执行只读操作,且仅在设置了凭据时运行:

ICLOUD_USERNAME=... ICLOUD_PASSWORD=... uv run pytest -m integration

项目结构:

mcp_icloud_caldav/
├── server.py          # MCP server, tool registration, logging setup
├── caldav_client.py   # CalDAV access: search, create, update, move, delete, event index
├── ical.py            # Thin calendar manager used by the server
├── models.py          # Event and request models, iCalendar parsing
└── config.py          # Configuration loading
tests/                 # Unit tests
tests/integration/     # Read-only tests against a real account

此分支中的更改

0.2.1:仅更新文档(uvx 路径、ENOENT 原因、macOS 上的客户端路径)。

0.2.0,与 zwrong/iCalendar 0.1.0 相比:

  • 依赖项。 从官方 PyPI 索引重新生成锁文件(之前通过纯 HTTP 的第三方镜像解析软件包)。升级到 mcp 2.x(FastMCP 更名为 MCPServer)和 caldav 3.x;原始代码已无法在当前版本上启动。
  • 配置。 支持环境变量、MCP_ICAL_CONFIG、只读模式、可配置的日志级别,并且在高于 DEBUG 的级别下不记录事件内容。
  • 修复。
    • 创建带时区偏移的事件时会失败(Unable to guess TZID);全天事件和重复事件结束日期的写入也不正确。
    • 闹钟从未被读回。
    • 更新不含位置、备注或 URL 的事件时会失败;修改事件时间会生成无效的 iCalendar 数据。
    • 移动事件时,会在保存副本前删除原事件,因此保存失败会导致事件丢失。
    • 新事件的 UID 中包含空格和机器的主机名。
  • 行为。 按开始时间对事件排序;输出精简,不含空字段;使用内存中的事件索引。
  • 测试。 为配置、只读模式、日志记录、iCalendar 输出、移动操作和查找添加单元测试。
  • 打包。 以 mcp-icloud-caldav 的名称发布到 PyPI,并列入 MCP Registry。Python 软件包和命令从 mcp_ical / mcp-ical 更名,以避免与原始 macOS 项目冲突。移除了未使用的 mcp[cli] extra。

致谢与许可证

MIT,详见 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

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

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