起因:为什么这么慢?
我用 Claude Code 搭建了一套 GTD 任务管理系统,通过 MCP(Model Context Protocol)连接滴答清单,让 AI 帮我自动处理收集箱里堆积的任务。
系统搭好后能用,但有个大问题:太慢了。
比如我让 AI「完成这个任务」,要等大约 30 秒才有反应。批量处理 100 多个任务时更是煎熬。
我隐约觉得是 API 调用太多导致的,但具体慢在哪里?有没有更好的做法?于是我找了两个同样连接滴答清单的开源 MCP 项目来对比学习。
找到两个参考项目
我在 GitHub 上找到了两个滴答清单的 MCP 实现:
-
evalor/Dida365MCP(TypeScript)
- GitHub:https://github.com/evalor/Dida365MCP
- 15 个 MCP 工具,支持批量操作,设计比较完善
-
Xrondev/mcp-dida365(Python)
- GitHub:https://github.com/Xrondev/mcp-dida365
- 精简实现,有个巧妙的收集箱发现方法
我把两个项目都克隆到本地,逐个文件看了源码。
发现:大家用的 API 完全一样
看完源码后,第一个发现是:三个项目(包括我自己的)用的都是同一套滴答清单官方 API。
没有什么「隐藏的加速接口」。完成一个任务就是调一次 POST /project/{项目ID}/task/{任务ID}/complete,一次 API 调用,不到 1 秒。
那为什么我的要 30 秒?
问题根源:每次操作都在「全城搜索」
打开我自己的代码一看就明白了。
当 AI 说「完成任务 XX」时,我的工具只收到了一个任务标题。但滴答清单的 API 需要项目ID + 任务ID才能操作。
所以我的工具内部做了这么一件事:
遍历全部 91 个项目 → 每个项目调一次 API 获取任务列表 → 在里面找标题匹配的任务 → 找到后再调 API 完成它
相当于为了完成 1 个任务,先调了 92 次 API。就像你想在一栋大楼里找一个人,结果你挨个敲了全部 91 个房间的门。
开源项目的做法:让调用方自己带 ID
再看 evalor 和 Xrondev 的设计,它们的完成任务工具长这样:
complete_task(project_id="xxx", task_id="yyy")
直接要求调用方提供项目 ID 和任务 ID。不搜索,不遍历,一步到位。
这个 ID 从哪来?AI 之前调用「获取任务列表」时,返回结果里就带着每个任务的 ID。AI 记住这些 ID,后续操作直接用就行了。
这就是关键差异:不是 API 慢,是我自己多做了 91 次没必要的搜索。
我做了哪些优化
优化 1:新增「ID 直达」工具
新增了 3 个工具,直接接收 ID,跳过搜索:
complete_task_by_id(project_id, task_id)— 完成任务update_task_by_id(task_id, project_id, ...)— 更新/移动任务delete_task_by_id(project_id, task_id)— 删除任务
每个工具只需 1 次 API 调用。旧的工具保留了(万一 AI 只知道标题的时候还能用),但在说明里标注了「推荐用新版」。
优化 2:批量操作支持跨项目
之前的批量完成工具只能处理同一个项目的任务。参考 evalor 的设计,改成了支持传入不同项目的任务列表:
# 旧格式(只支持同一项目)
batch_complete_tasks(task_ids=["id1", "id2"], project_id="同一个项目ID")
# 新格式(支持跨项目)
batch_complete_tasks(tasks=[
{"project_id": "项目A", "task_id": "id1"},
{"project_id": "项目B", "task_id": "id2"},
])两种格式都能用,旧的不会坏。
优化 3:串行改并发
之前批量操作是一个一个来的,每 80 个还要暂停 65 秒等 API 限流。
参考 evalor 的 batch.ts(它用了一个并发执行框架),我改成了 5 个并发,用 Python 的 ThreadPoolExecutor 实现。简单说就是同时跑 5 个请求,而不是排队等。
优化 4:项目列表加了缓存
「获取全部项目列表」这个操作被很多功能重复调用。加了个 5 分钟的缓存,同一段时间内只请求一次 API,后面直接用缓存结果。
优化效果
| 场景 | 优化前 | 优化后 |
|---|---|---|
| 完成 1 个任务 | ~92 次 API(约 30 秒) | 1 次 API(不到 1 秒) |
| 批量完成 100 个任务 | 串行 + 暂停(数分钟) | 5 并发(约 10 秒) |
| 批量完成跨项目任务 | 不支持 | 支持 |
总结
这次优化的核心教训只有一句话:
如果你已经知道答案(ID),就别再去搜索了。
技术上没有任何复杂的东西。不需要换 API,不需要换语言,不需要换框架。只是改了工具的输入参数设计——从「接收标题去搜索」变成「直接接收 ID 去操作」。
开源项目的价值不一定在于你要直接用它,而是看看别人是怎么设计的,找到自己的差距。
参考项目
- evalor/Dida365MCP(TypeScript):https://github.com/evalor/Dida365MCP
- Xrondev/mcp-dida365(Python):https://github.com/Xrondev/mcp-dida365
- 滴答清单官方 API 文档:https://developer.dida365.com/docs