关于 Apple Calendar
Apple Calendar 是通过 EventKit 管理 macOS 日历和提醒事项的本地 MCP 服务。它提供增删改查、标签、日程安排和服务管理工具,数据保留在设备上。
主要功能
- 01日历和提醒事项增删改查
- 02基于井号标签的标签系统
- 03日程与安排工具
- 04查找空闲时段
- 05权限检查与服务控制
适用场景
- 01查看活动和待办提醒
- 02创建或重新安排日历活动
- 03用标签整理条目
- 04查找工作时间内的空档
MCP 相关
它通过 stdio 向 MCP 客户端提供日历和提醒事项工具。服务在本地运行,并通过 EventKit 访问数据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
apple-calendar MCP 服务
一个用于 macOS 日历和提醒事项的个人 MCP 服务,通过 PyObjC 基于
EventKit 构建。
通过 stdio 在本地运行,不会发起网络调用,也不使用云服务。专为
Claude Desktop 使用而构建(连接器名称:apple-calendar),但也适用于
任何 MCP stdio 客户端。
工具涵盖完整的日历/提醒事项 CRUD 功能、基于井号标签的标签系统(tags_*)、日程安排便捷工具(agenda_*、quick_event、reschedule_event、find_free_slots)以及热重启管理工具(server_status、server_restart)。
要求
- macOS 14+(使用现代的
requestFullAccessTo...权限 API,在较旧的 macOS 上会回退到旧版 API) - Python 3.10+,通过 uv 管理
安装
cd apple-calendar-mcp
uv sync
授予权限
EventKit 会将日历/提醒事项的授权关联到最先请求权限的进程(“负责进程”)。有两种授予访问权限的方式:
选项 A - 推荐,通过终端运行一次:
uv run python scripts/setup_permissions.py
这应该会触发以终端身份请求日历和提醒事项权限的系统对话框。在两个对话框中都点击“允许”。
选项 B - 手动操作:
打开系统设置 > 隐私与安全性 > 日历(以及提醒事项),为终端、Python 解释器或 Claude Desktop 启用访问权限——服务器至少运行过一次后,最终出现在此处的项目即可。
如果工具调用返回 "error": "permission_denied",请检查 eventkit_check_permissions 获取当前状态和操作说明,或重新运行设置脚本。
注意:当此服务作为 Claude Desktop 的子进程运行时,macOS 可能会将权限提示归属到 Claude Desktop,也可能完全不显示提示(后台子进程通常无法显示界面)。如果将服务添加到 Claude Desktop 后没有出现对话框,请先在终端中运行设置脚本,然后重启 Claude Desktop。
配置 Claude Desktop
添加到 ~/Library/Application Support/Claude/claude_desktop_config.json
(此仓库的设置已在本机完成此操作——见下文)。mcpServers
键会成为 Claude Desktop 中显示的连接器名称:
{
"mcpServers": {
"apple-calendar": {
"command": "uv",
"args": [
"--directory", "/absolute/path/to/apple-calendar-mcp",
"run", "python", "-m", "apple_calendar_mcp.server"
]
}
}
}
编辑后重启 Claude Desktop(或使用 server_restart,见下文)。
工具
权限
| 工具 | 说明 |
|---|---|
eventkit_check_permissions | 日历/提醒事项授权状态及操作说明 |
日历
| 工具 | 说明 |
|---|---|
calendar_list_calendars | 列出所有日历 |
calendar_list_events | 列出指定日期范围内的事件 |
calendar_get_event | 按 ID 获取单个事件 |
calendar_search_events | 按标题/地点/备注进行文本搜索,可选标签筛选 |
calendar_create_event | 创建事件(地点、备注、URL、标签) |
calendar_edit_event | 编辑事件(包括通过 calendar_name 移动分类);重复事件需要 span |
calendar_delete_event | 删除事件;重复事件需要 span |
提醒事项
| 工具 | 说明 |
|---|---|
reminders_list_lists | 列出所有提醒事项列表 |
reminders_list | 列出提醒事项,可按列表/完成状态/到期日期筛选 |
reminders_get | 按 ID 获取单个提醒事项 |
reminders_search | 按标题/备注进行文本搜索,可选标签筛选 |
reminders_create | 创建提醒事项(到期日期、优先级、标签) |
reminders_edit | 编辑提醒事项 |
reminders_complete | 将提醒事项标记为已完成 |
reminders_delete | 删除提醒事项 |
标签
标签以 #hashtag 的形式添加到备注字段中(EventKit 没有原生标签概念)。规范化规则:转为小写,空格和连字符替换为下划线,移除非字母数字字符。由于标签存储在 notes 中,它们会通过 iCloud 同步,并且可以在系统自带的日历和提醒事项应用中查看和搜索。
| 工具 | 说明 |
|---|---|
tags_list | 列出所有正在使用的标签及其项目数量 |
tags_rename(old_tag, new_tag, scope) | 重命名标签;scope:events|reminders|all |
tags_merge(from_tag, into_tag, scope) | 将一个标签合并到另一个标签 |
tags_delete(tag, scope) | 从所有出现标签的位置将其移除 |
这三个工具都要求使用完全匹配的标签名称(不支持模糊匹配或部分匹配),因为这些操作会批量修改且不可撤销。它们只会改写 notes 中的标签行,其余备注正文会原样保留。
扫描窗口注意事项:tags_list/tags_rename/tags_merge/tags_delete 需要查看“所有”事件,但 EventKit 的日期范围谓词实际上每次调用最多只能覆盖约 4 年。这些工具会将扫描拆分为 3 年的窗口,覆盖过去 6 年至未来 6 年(共 12 年,最多 5000 个事件)——更远日期的事件不会被扫描到。提醒事项没有此限制,会在一次调用中获取(最多 20000 个)。如果扫描达到上限,响应中会包含 "warning" 字段。
**重复事件注意事项:**批量标签编辑会复用与 calendar_edit_event 相同的 calendarItemWithIdentifier_ + EKSpanThisEvent 机制。对于重复系列,该机制只会解析出一个代表性实例,而不是每个可见实例——与基础编辑工具存在相同限制。
自定义日程安排工具
| 工具 | 说明 |
|---|---|
agenda_today | 以易读格式显示今天的日程(事件 + 到期提醒事项) |
agenda_range(start_date, end_date) | 显示指定日期范围内的日程 |
quick_event(text) | 根据简短的自然语言内容创建事件 |
reschedule_event(event_id, new_start) | 移动事件并保留其时长 |
find_free_slots(date, working_hours, min_duration_minutes) | 查找工作时间内的空闲时段(忽略全天事件) |
quick_event 使用轻量级启发式解析器(按设计,不依赖外部 NLP;本项目仅依赖 mcp[cli] 和 pyobjc)。它可以识别:
- 相对日期:
today、tomorrow、mon..sun/ 完整星期名称 - 明确日期:
YYYY-MM-DD - 时间:
3pm、3:30pm、15:00(前面可以加at) - 时长:
for 30 minutes、for 2 hours - 末尾的
#hashtags-> 标签
默认设置:时长为 1 小时;如果没有找到时间,则设为 09:00(如果剩余标题中提到 breakfast/lunch/dinner,则分别设为 08:00/12:00/19:00)。未匹配上述模式的内容会保留在标题中。解析结果仅供参考——对于任何对时间敏感的用途,请先检查返回的 event。
服务管理
| 工具 | 说明 |
|---|---|
server_status | 进程 ID、版本、运行时间、工具数量 |
server_restart | 热重启进程,无需退出 Claude Desktop |
server_stop | 停止进程(不重新启动)——用于暂停对日历/提醒事项的访问 |
server_restart 的工作方式及我们的验证结果
server_restart 会启动一个后台线程,短暂休眠(默认
0.75s,可通过 delay_seconds 配置),刷新 stdout/stderr,然后调用
os.execv,用一个全新的 python -m apple_calendar_mcp.server 替换当前进程映像,从而获取磁盘上的任何代码更改。
我们直接使用原始 MCP Python 客户端对此进行了测试(没有通过 Claude Desktop 的 UI,因为我们无法在此环境中操控它),并观察到:
- 标准输入输出管道的文件描述符能够保留——字节仍会在客户端和新进程之间流动。
- 新进程的 pid 不同,且
uptime_seconds重置为约 0, 这证实重启已发生(server_status的用途正是检测这一点)。 - MCP/JSON-RPC 会话无法保留——它是内存中的状态,会在进程映像被替换时重置。在重启后立即通过旧会话发送的工具调用会被拒绝
(
Invalid request parameters/ “request before initialization was complete”)。 - 在重启后通过同一个标准输入输出管道重新发送 MCP
initialize握手, 即可完全恢复会话——新的 pid、重置后的运行时间,所有工具都可以再次调用。无需启动新子进程,也无需重启 Claude Desktop。
我们无法直接验证的是:Claude Desktop 自己的客户端在刚调用的工具返回请求被拒错误后,是否会自动重新发送 initialize(也就是说,它会自行恢复,还是连接器会显得“卡住”,直到你再次与它交互)。如果调用 server_restart 后工具停止响应:
- 尝试再调用任意工具一两次——有些 MCP 客户端会在出错时透明地重试或重新初始化。
- 如果仍无效,请在 Claude Desktop 的设置中关闭再重新开启
apple-calendar连接器。这无需退出应用,并会强制在新的子进程上执行一次新的initialize。 - 退出并重新打开 Claude Desktop 始终是最后的补救办法,但这就失去了此工具的意义。
如果你发现 Claude Desktop 能够顺利处理,无需手动操作;或者它不是报错而是挂起,请更新此部分。
server_stop
server_stop 是不重新启动的 server_restart:同样会短暂延迟,然后刷新,但它调用的是 os._exit(0) 而不是 os.execv,因此进程会直接终止。我们直接使用原始 MCP 客户端进行了验证,确认:
- 进程会完全退出(通过
ps -p <pid>没有返回任何内容来确认)。 - 此后在该会话上进行的任何工具调用都会立即失败,并返回
ClosedResourceError(标准输入输出管道已关闭)——结果毫无疑问。
它不会自动重启。之后若要继续使用日历/提醒事项工具,请在 Claude Desktop 中关闭再重新开启 apple-calendar 连接器(这会启动一个新的子进程),或重启 Claude Desktop。当你想暂停服务对数据的访问(例如暂时离开),又不想编辑配置文件时,可以使用此工具。
备注
- 所有数据都保留在设备上;服务只通过标准输入输出与 MCP 客户端通信,并通过 EventKit 获取数据。
- 此服务创建的项目会在备注开头添加一行
"Created by Claude Desktop", 方便你区分它们和手动创建的项目。 - 输入和输出的日期均采用 ISO 8601 格式(
2026-03-15T14:00:00),并按本地时区解释。 - 每个工具都会捕获自身的异常,并返回
{"success": false, "error": ..., "message": ...}字典,而不是抛出异常——错误的 ID、日期或权限缺失都不会导致服务崩溃。
开发
uv run python -m apple_calendar_mcp.server # run standalone (reads/writes stdio)
uv sync # after editing pyproject.toml
要使用官方 MCP Inspector 交互式检查工具(需要 Node.js;构建此项目时未安装):
npx @modelcontextprotocol/inspector uv run python -m apple_calendar_mcp.server
由于当时无法使用 Node,我们改用 mcp Python SDK 自带的客户端(ClientSession + stdio_client)验证协议层:完整的 initialize 握手、list_tools(28 个工具)以及具有代表性的工具调用(包括错误情况——无效日期、无效范围、未知 ID、无效优先级 / 范围)均返回了格式正确的响应,且服务未崩溃。我们还使用模拟 EventKit 的假内存存储,验证了标签重命名 / 合并 / 删除的正确性(仅更新匹配的项目、保留备注正文、不影响无关标签);因为要进行真实验证,必须先在此机器上授予日历 / 提醒事项权限。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。