关于 MustDo
MustDo 是用于通过 Claude 等 MCP 客户端管理 MustDo iOS 闹钟待办事项的 MCP 服务。它访问用户 iCloud 私有 CloudKit 数据库,提供托管 OAuth 中继或供开发者使用的本地 stdio 方式。
主要功能
- 01按日期和状态列出待办事项
- 02添加、更新、完成、延后和删除待办事项
- 03支持重复计划和截止时间
- 04将待办记录保存在用户的 iCloud CloudKit 数据库
- 05提供托管中继和本地 stdio 方式
适用场景
- 01查看日期范围内待处理或已完成的待办事项
- 02创建带截止时间的闹钟待办事项
- 03更新重复任务或标记某次任务完成
- 04通过 MCP 客户端延后或删除待办事项
MCP 相关
MustDo 将账户和待办事项操作作为 MCP 工具提供。托管中继通过 OAuth 使用远程 MCP;开发者可在本地通过 stdio 运行服务。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://ltng.jp/api/mustdo/mcpclaude mcp add --transport http jp-ltng-mustdo https://ltng.jp/api/mustdo/mcp{"mcpServers":{"jp-ltng-mustdo":{"type":"http","url":"https://ltng.jp/api/mustdo/mcp"}}}在 Cursor 中打开{"servers":{"jp-ltng-mustdo":{"type":"http","url":"https://ltng.jp/api/mustdo/mcp"}}}在 VS Code 中打开{"mcpServers":{"jp-ltng-mustdo":{"type":"http","url":"https://ltng.jp/api/mustdo/mcp"}}}{"mcpServers":{"jp-ltng-mustdo":{"serverUrl":"https://ltng.jp/api/mustdo/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
mustdo-mcp
MustDo 的 MCP 服务——一款 iOS 待办闹钟,会持续响铃,直到你完成待办。
它让 Claude(Claude Code、Claude Desktop、claude.ai、Claude iPhone app)和任何其他 Model Context Protocol 客户端读取和写入你的 MustDo 待办事项。
- 你的数据保存在自己的 iCloud 中。 MustDo 没有自己的待办事项数据库。它们存储在你 Apple ID 的 CloudKit private 数据库中(容器
iCloud.jp.lightning.mustdo,区域MustDo)。 此服务与 Apple 的 CloudKit Web Services 通信,并读取和写入与 iPhone 应用相同的记录。 - 开发者绝不会存储你的待办事项。 本仓库中的本地服务和托管中继(见下文)都不会在 Lightning LLC 的服务器上保留待办事项内容。
- 写入后,CloudKit 会向你的 iPhone 推送静默通知,因此应用会立即更新。
两种使用方式
| A. 托管中继(推荐) | B. 在本地运行此仓库(开发者) | |
|---|---|---|
| 可使用的平台 | claude.ai、Claude iPhone app,以及支持远程 MCP + OAuth 的任何客户端 | Mac 上的 Claude Code / Claude Desktop(stdio) |
| 设置 | 添加自定义连接器,使用 Apple ID 登录 | Node 24、构建、配置并登录。需要 CloudKit API Token,目前不对外公开提供(见下文) |
| Lightning LLC 存储的内容 | 仅你的 CloudKit 登录令牌,使用 AWS KMS 加密(见下文) | 无 |
A. 托管中继 — https://ltng.jp/api/mustdo/mcp
- claude.ai → 设置 → 连接器 → 添加自定义连接器 → URL
https://ltng.jp/api/mustdo/mcp(命名为“MustDo”)。 - 点击连接。你会看到 ltng.jp 上的同意页面,说明存储的内容,随后会跳转到 Apple 登录页面。 使用你在 MustDo 应用中使用的同一个 Apple ID登录。
- 完成。此连接器也可在 Claude iPhone app 中使用。
中继会保留的内容,如实说明:
- 登录时,Apple 会签发 CloudKit 登录令牌(
ckWebAuthToken)。中继会使用 AWS KMS 加密此令牌(AWS 东京区域),以便在每次请求时代表你调用 CloudKit。 - 它也会存储连接器本身的哈希 OAuth 访问令牌和刷新令牌。
- 它不会存储或记录你的待办事项内容、Apple ID 邮箱、密码或原始 iCloud 用户 ID。
- **断开连接:**在 claude.ai 中移除连接器,并且访问 https://ltng.jp/api/mustdo/disconnect。
使用 Apple ID 确认后,存储的令牌会立即删除。如果 Apple 使登录失效,令牌也会自动删除(此时工具会返回
RECONNECT_REQUIRED;只需重新连接)。
完整说明:https://ltng.jp/mustdo/mcp。
B. 在本地运行(stdio)
要求:
- 安装了 Node.js 24 或更高版本的 macOS
- 已安装 MustDo 应用,且至少同步到 iCloud 一次(应用会创建区域和
Account记录) - MustDo 容器的 CloudKit API Token。目前不对公众提供——见下文“关于 CloudKit API Token”。没有此令牌时,请使用托管中继(A)
git clone https://github.com/lightning-llc-jpn/mustdo-mcp mustdo-mcp
cd mustdo-mcp
npm install
npm run build # -> dist/index.js
npm test # vitest; CloudKit is mocked
在 Claude Code 中注册:
claude mcp add mustdo \
-e MUSTDO_CK_API_TOKEN=<MUSTDO_CK_API_TOKEN> \
-e MUSTDO_CK_ENV=production \
-- node /path/to/mustdo-mcp/dist/index.js
或者将设置放入 ~/.mustdo/config.json,并在不使用 -e 的情况下注册:
{
"apiToken": "<MUSTDO_CK_API_TOKEN>",
"environment": "production"
}
然后让 Claude 运行一次 sign_in 工具。服务会在浏览器中打开 Apple 登录页面,
监听 http://localhost:51234/callback,并将返回的令牌保存到 ~/.mustdo/auth.json(模式 0600)。
关于 CloudKit API Token
CloudKit Web Services 的每个请求都需要两个 Token:
| Token | 含义 | 持有者 |
|---|---|---|
ckAPIToken | 用于标识容器(iCloud.jp.lightning.mustdo)。由容器所有者在 CloudKit Dashboard 中创建。Apple 设计它用于“从网站或嵌入式 Web 视图”访问,也就是说,它是一个客户端 Token,具有固定的 Sign-in Callback URL。 | Lightning LLC(该容器归 MustDo 开发者团队所有)。你无法自行创建——CloudKit Dashboard 只允许团队为自己的容器创建 Token。 |
ckWebAuthToken | 你的个人 CloudKit 会话,由 Apple 在你使用 Apple ID 登录时签发。这是实际授予你访问个人数据库权限的凭证。 | 仅你持有。存储在 ~/.mustdo/auth.json 中。使用生产环境 Token 时,Apple 会在登录期间通过 ltng.jp 上的重定向返回该 Token(见下文;不会在那里存储或记录任何内容)。之后,该 Token 只会发送给 Apple。 |
API Token 适用于整个容器,最终用户无法创建。Lightning LLC 目前不公开分发该 Token,因此不向普通用户提供本地运行此服务的方式——请使用托管中继(A)。 发布代码是为了让你能准确查看 MCP 服务如何处理你的数据。
供参考,生产环境的 Token 将 Sign-in Callback 设置为
https://ltng.jp/api/mustdo/oauth/local-callback,它只会重定向回 http://localhost:51234/callback,
不会存储或记录任何内容。
配置
环境变量的优先级高于 ~/.mustdo/config.json。
| 环境变量 | config.json 键 | 默认值 | 含义 |
|---|---|---|---|
MUSTDO_CK_API_TOKEN | apiToken | (必填) | MustDo 容器的 CloudKit API Token |
MUSTDO_CK_ENV | environment | development | production 用于 App Store 数据。development 仅适用于 MustDo 开发者 |
MUSTDO_CK_CONTAINER | container | iCloud.jp.lightning.mustdo | 保持不变 |
MUSTDO_CK_ZONE | zoneName | MustDo | 保持不变 |
MUSTDO_CALLBACK_PORT | callbackPort | 51234 | 登录回调监听的端口 |
MUSTDO_HOME | — | ~/.mustdo | config.json 和 auth.json 所在位置 |
MUSTDO_LOG_LEVEL | — | INFO | DEBUG / INFO / WARN / ERROR(在 stderr 上输出 JSON 行) |
auth.json 按环境分别保存;切换 MUSTDO_CK_ENV 后需要再次运行 sign_in。
Apple 会在一段时间后使会话过期(CloudKit 会返回 HTTP 421);此时工具会返回 NOT_SIGNED_IN,你需要再次运行 sign_in。
工具
所有工具均返回 JSON。输出中的日期为 ISO 8601 格式(UTC)。输入中的日期可以是:
YYYY-MM-DD— 当天的默认时间(见下文)YYYY-MM-DDTHH:mm— 账户时区的当地时间- 带偏移量的完整 ISO 8601 格式
| 工具 | 参数 | 功能 |
|---|---|---|
sign_in | waitSeconds?(5–300,默认 90) | **仅限本地。**打开 Apple 登录页面并保存 ckWebAuthToken。中继上不提供此工具。 |
get_me | — | 账户信息:timeZone、today、weekday、defaultTime、defaultDueNext、试用/订阅日期、canAddTodo。进行日期计算前请先调用此工具。 |
list_todos | date?、from?、to?(YYYY-MM-DD,含首尾日期)、status?(默认 pending / done / skipped / all)、includeRepeating?(默认 true) | 列出待办事项。已删除的待办事项不会列出。重复待办事项以模板的形式返回在 repeating 下(不会展开),并附带日期范围内每天的 occurrences。 |
add_todo | title(1–200)、due?、repeat?、notes?(≤2000)、sound? | 创建 source = "mcp" 的待办事项。如果省略 due,则设为明天的默认时间。 |
update_todo | id、title?、due?、repeat?(对象或 null)、notes?(字符串或 null)、sound?、status? | 只更改传入的字段。repeat 会替换整个规则;null 或 { "kind": "none" } 会移除重复规则。 |
complete_todo | id、occurrenceDate? | 一次性待办事项:status = done。重复待办事项:将当天的发生项标记为已完成(默认:今天)。 |
snooze_todo | id、until、occurrenceDate? | 延后至 until。重复待办事项:仅延后当天的发生项。 |
delete_todo | id | 软删除(deletedAt)。应用会在 14 天后彻底清除该待办事项。 |
**注意:**AI 客户端会根据你的指示添加、更改和删除待办事项。已删除的待办事项会在 14 天后从 iCloud 中移除,且无法恢复。请自行检查 AI 执行的操作结果。
delete_todo标注为具有破坏性(destructiveHint),而get_me/list_todos标注为只读(readOnlyHint),因此支持这些标注的客户端会在删除前询问。
默认时间和省略 due 的情况
每个账户都有一个默认提醒时间(Account.defaultTime,格式为 HH:mm,在应用设置中设定;若未设置则为 09:00)。
add_todo未提供due→ 设为明天(按账户时区)的默认时间。 月份/年份边界和夏令时转换均按当地时间计算。due: "2026-10-10"→ 设为当天的默认时间。get_me会返回defaultTime和defaultDueNext,客户端可据此告知用户提醒何时响起。
示例:
// "Remind me to buy milk" → tomorrow at the default time
{ "title": "Buy milk" }
// "Call the dentist on the 10th" → that day at the default time
{ "title": "Call the dentist", "due": "2026-10-10" }
// "Today at 3pm"
{ "title": "Submit report", "due": "2026-10-06T15:00" }
重复规则
与 iOS Calendar app 使用相同的词汇。用作 add_todo / update_todo 的输入,并由 list_todos 返回。
{
"kind": "none | daily | weekly | monthly | yearly",
"interval": 1, // 1 = every, 2 = every other … (1–99)
"weekdays": [2, 4], // weekly only. 1 = Sun … 7 = Sat. Empty → weekday of `due`
"monthly": { "mode": "dayOfMonth | weekdayOrdinal", "ordinal": 1, "weekday": 2 },
"end": { "kind": "never | until | count", "until": "2026-12-31", "count": 10 }
}
| 需求 | repeat |
|---|---|
| 每天 | { "kind": "daily" } |
| 每周一和周三 | { "kind": "weekly", "weekdays": [2, 4] } |
| 每隔一周 | { "kind": "weekly", "interval": 2 } |
| 每 3 天 | { "kind": "daily", "interval": 3 } |
| 每月 5 日 | { "kind": "monthly" },并将 due 设为每月 5 日(29–31 日会调整为月末) |
| 每月第一个星期一 | { "kind": "monthly", "monthly": { "mode": "weekdayOrdinal", "ordinal": 1, "weekday": 2 } } |
| 每月最后一个星期五 | { "kind": "monthly", "monthly": { "mode": "weekdayOrdinal", "ordinal": -1, "weekday": 6 } } |
| 每年 | { "kind": "yearly" }(使用 due 的月/日;非闰年时,2 月 29 日 → 2 月 28 日) |
| 执行 10 次后停止 | { "kind": "daily", "end": { "kind": "count", "count": 10 } } |
| 截止至 12 月 31 日 | { "kind": "weekly", "weekdays": [2], "end": { "kind": "until", "until": "2026-12-31" } } |
省略的字段使用默认值(interval 为 1,weekdays 为 [],monthly.mode 为 dayOfMonth,end.kind 为 never)。
取值范围:interval 为 1–99,ordinal 为 1–5 或 -1,weekday 为 1–7,count 为 1–999。其他值均会返回 INVALID_ARGUMENT。
仍接受旧版格式 { "kind", "weekdays", "until" }。
展开在 app 中进行,而非此处。 list_todos 会返回模板以及 occurrences
(按天记录 done / skipped / snooze)。范围筛选仅会排除确定不可能在该范围内触发的模板(首次出现时间晚于范围、until 早于范围、每周规则没有匹配的星期几)。
错误
失败时会返回 isError: true,以及格式为 { "code": "...", "message": "...", "details"?: {...} } 的正文。
code | 含义 |
|---|---|
NOT_SIGNED_IN | 没有有效的 ckWebAuthToken(本地)。运行 sign_in。 |
RECONNECT_REQUIRED | 托管中继上发生相同问题。请在 claude.ai 中重新连接该连接器。 |
NOT_CONFIGURED | API Token 缺失或被 CloudKit 拒绝(HTTP 401/403)。 |
PAYMENT_REQUIRED | 账户试用期已结束,且没有有效订阅。仅影响 add_todo。 |
NOT_FOUND | 找不到此 To-Do,或它已被删除。 |
INVALID_ARGUMENT | 日期无效、重复规则超出范围、标题为空等。 |
CONFLICT | 另一台设备连续两次更改了记录。请重试。 |
CLOUDKIT_ERROR | 其他任何 CloudKit 错误(例如,应用从未同步导致区域缺失)。 |
SIGN_IN_TIMEOUT | 10 分钟的登录侦听器已过期。 |
INTERNAL | 意外错误。 |
安全模型
- 只有通过你自己的 Apple ID 会话(
ckWebAuthToken)才能访问你的 To-Dos,该会话由 Apple 的登录页面签发。 没有它,任何人——包括开发者——都无法读取你的私人数据库。 - API Token 仅用于标识容器,并确定 Apple 登录后可以重定向到的位置。 Apple 将其定位为客户端 Token(通常会嵌入 CloudKit JS 网页中)。它本身不会授予访问任何用户私人数据的权限。
- 本地环境中,会话存储在
~/.mustdo/auth.json(0600)中,日志以 JSON 格式写入 stderr,且绝不包含 Token; 登录侦听器仅绑定到127.0.0.1/::1。 - 在中继上,会话按用户使用 AWS KMS 加密(采用加密上下文的信封加密),OAuth Token 仅以加盐的 SHA-256 哈希形式存储,必须使用 PKCE S256,刷新 Token 会轮换并检测重用,且 To-Do 内容绝不会写入存储或日志。
- 写入时使用 CloudKit
recordChangeTag(乐观锁定),冲突时重试一次;删除采用软删除。 - 发现问题?请参阅 SECURITY.md。
开发
npm install
npm run build # tsc → dist/
npm test # vitest (CloudKit mocked in test/fakeCloudKit.ts)
npm run typecheck # tsc --noEmit
MUSTDO_LOG_LEVEL=DEBUG node dist/index.js # run the stdio server by hand
目录结构:
src/
index.ts entry point (stdio)
server.ts wiring for stdio: sign_in + the 7 To-Do tools
tools.ts tool definitions (zod schemas) shared by stdio and the relay
core.ts public entry for the shared core (no auth/config/stdio)
service.ts tool logic: filtering, upserts, conflict retry
cloudkit.ts thin CloudKit Web Services client (query / lookup / modify, 421 handling)
records.ts CloudKit record <-> model conversion
dates.ts time-zone-aware date math using Intl only
auth.ts auth.json and the sign-in callback listener
config.ts env / ~/.mustdo/config.json
model.ts enums, allowlists, RepeatRule types (mirrors the Swift app)
errors.ts ToolError / NotSignedInError
log.ts JSON logs to stderr (setLogSink to redirect)
test/ vitest
dist/core.js(包 exports)是托管中继使用的共享核心:除 auth.ts、config.ts、index.ts 和 server.ts 外的所有内容。请确保其中不包含任何访问本地文件系统或浏览器的代码。
工作流:从 issue 开始
每项更改都从 GitHub issue 开始。在提交说明中引用该 issue,格式为 Issue #N
(例如 Fix the due-date default for repeating To-Dos (Issue #12);合并提交也一样),并在更改进入 main 后关闭该 issue。单独使用 #12 不予接受。
bash tools/git-hooks/install.sh # once per clone: installs the commit-msg hook that enforces this
推送的提交会由 .github/workflows/issue-number.yml 再次检查。
许可证
MIT — Copyright (c) 2026 Lightning LLC。请参阅 LICENSE。
MustDo 是 Lightning LLC 的产品。Apple、iCloud 和 CloudKit 是 Apple Inc. 的商标。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。