专栏 · Agent 工程手艺 › 第 120 期 · AGENT 工程 · 收录于 2026 年 8 月 16 日
MCP 异步任务:为什么没有 agent 支持它?——Cornelia Davis(Temporal)
CD
Cornelia Davis · AI Engineer
5,797观看
144赞
2.5%点赞率
16评论
62.7万频道订阅
数据截至 8 月 27 日
TL;DR · 三句话
- 一MCP tasks 就是"让一个工具变成长跑作业":你调用它,拿回来的不是结果而是一个 handle(把手,可以理解成取件码),工具在后台慢慢跑、汇报进度、能停在"等人批准"这一步不动,最后你再凭把手取结果——而规范白纸黑字要求:task 一旦启动就必须是 durable(持久)的,client 挂了、server 宕了、人休假去了、连接断了,它都得活着,等基础设施回来还能接着交互。→ 详细
- 二没有 agent 实现它,不是懒,是 V1 规范有两处硬伤:一是
tasks/list 把协议做成了有状态的,而且这个接口没有任何过滤条件——后端攒了一百万个 task,你得全翻一遍才能找到要找的那个;二是"等人输入"这件事是从 tasks/result 的长连接里隧穿出去的,中间那段要开长会话、由 server 反过来向 client 索取响应,实现起来极其别扭。→ 详细 - 三V2 的方向对了:协议走向 stateless,tasks 从核心降级成一个 extension(扩展),
tasks/list 直接砍掉,"等人输入"改成由 client 主动推一条 update 进去(本质就是 Temporal 里的 signal 概念);而任务的生命周期状态机原封不动地留着——因为那部分设计本身就是靠谱的。→ 详细
01
开场就把答案摊开:不是没人做,是聪明人故意先不做
- 标题问的是"到底为什么没有哪个 agent 支持 MCP tasks",她给的第一个答案是 "因为他们聪明"——11 月发布的那版 MCP tasks 规范当时标着 experimental(实验性,言外之意随时可能推翻重来)。她自己也替观众反驳了一句:experimental 的东西那些 client 支持了一大堆,凭什么这个不行?第二个答案才是真原因——"这东西挺麻烦的",里面复杂度相当高。→ 详细
- 讲者 Cornelia Davis,Temporal 的技术专家,做的是分布式系统;微服务那个年代她做过 Cloud Foundry、Kubernetes、GitOps、Weaveworks,还就此写过一本书。这个背景决定了本场的视角:她不是从 AI 圈出发看 MCP,是从"长跑作业怎么才不丢"这个二十年老问题出发看 MCP 的。→ 详细
02
全场不谈抽象,只用一个采购订单例子落地
- 她刻意不空谈概念,整场绑在一个采购订单(purchase order,PO)场景上:进来一张 PO → 先记录收货这件事 → 然后并行做两摊事,一摊是后台杂活(更新库存、发通知),另一摊是支付发票。→ 详细
- 议程也提前剧透了结论:先讲 tasks 概览 → 讲 V1(11 月那版规范)→ 讲 7 月要出的新版(V2,改动"相当激进")→ 两个 live demo → 收获。她开场问了现场一句"有多少人想用 task 做点什么、也就是异步 MCP tool",说明这已经是台下普遍的真实需求。→ 详细
03
为什么发票这一步非得"长跑":工具内部藏着两轮人工
- 支付发票是通过一个 MCP tool 完成的,而这个 tool 本身又是一串步骤:先去 ERP 里做校验 → 走一次 human in the loop 请求审批 → 再跟 ERP 对一次账 → 再来一轮 human in the loop,以此类推。也就是说,从调用方看它只是"一个工具",从内部看它是一条带人工卡点的流水线。→ 详细
- 她的结论很直白:"它是长跑的,它不可能按 request/response 那种方式工作"——request/response 是"我问一句你答一句、答完连接就断",而这条流水线可能卡在"等某个人批准"上好几天。这正是 MCP tasks 要解决的问题。→ 详细
- 她甩了两段代码,说"今天不是讲 Temporal 的,我真正想让你们看的重点是 reject 和 approve 这两个动作"——它说明我们有一套机制,可以往一个已经跑起来的流程里发信号。这才是关键。整场的技术内核就一句话:一切都是围绕异步展开的。→ 详细
- 于是 MCP tasks 的定义就落地了:你调用一个 MCP tool,它在后台长时间运行,最后你再把结果拿回来。→ 详细
04
表面上极简单:换回来的不是结果,是一个 handle
- 时序图跟你脑子里想的一模一样:调用 tool,拿回来的不是结果而是一个 handle(把手/取件码),之后你跟这个 handle 打交道。她自己也说:"这又不是什么高深的火箭科学,看着挺简单。"→ 详细
- 转折立刻来了:"可你真要让它在很长的时间跨度上跑得住,事情就比这复杂多了。"——整场剩下的 18 分钟全是在拆这句话。→ 详细
05
长跑必然撞上的四类故障(她一条条点名)
- 底层规律一句话:一件事跑得越久,中间出现基础设施抖动把它搞崩的概率就越大。她点名的四类:① 网络抖动;② 网络本身的各种状况(断连、重连);③ 等着某个人做 in-the-loop 那一步,结果人家休假去了(她开玩笑说"就像我后天也要去休假一样");④ 进程直接崩了——处理采购单的那个 agent 可能挂掉,你的 MCP server 也可能挂掉。→ 详细
- 注意第三类的分量:"人休假了"被她和"网络断了""进程崩了"并列成同一等级的基础设施故障。这是全场最反直觉、也最有价值的一句框定——在长跑作业里,人类的响应时间不是流程的一个环节,而是一种你控制不了的故障源。→ 详细
06
规范的硬要求:task 不许凭空消失,必须是 durable 的
- 她直接引规范原文的措辞:一旦你启动了一个 task,它就必须是 durable(持久)的。翻译成人话:上一页那些倒霉事——client 挂了、人休假了、server 宕了、连接断了——task 都得活下来;等基础设施恢复之后,你还得能继续跟它交互。→ 详细
- 这件事分两半:server 端怎么做 durable,她 3 月在 MCP Dev Summit 讲过一整场(现场给了二维码指向那个 YouTube 视频,全场她反复提到"我一直提的那场演讲");今天这场是那次的延伸,讲的是 client 端——也就是至今没人做的那一半。→ 详细
07
Demo 1 上半场:她忘了启动 server,反而把最强的点演示出来了
- 她不用聊天界面演示,用的是一个 dashboard,理由很实在:"在这儿点两下按钮给你们看,比我现场敲字要高效得多。"界面上显示已提交的采购订单数量,点一下按钮就发起一张 PO。→ 详细
- 结果按下去没反应——她压根没启动 server。然后她当场把翻车变成论据:"你看,我刚才不是说了嘛,即使 server 没在跑,这套东西也得能工作。"→ 详细
- 她补启动两个窗口:上面是后端(MCP server),下面是 MCP client;从启动画面能看到 client 端用的是 FastMCP。切回去一看——虽然提交的时候 server 还没起来,那次提交依然生效了,系统把它记下来了。→ 详细
- 界面最右边那个 invoice task 完整走了一遍状态:submitted(已提交)→ working(运行中)→ input required(等输入),现在停在等审批。左右两块 dashboard 分别显示后端在跑 invoice、前端在跑 PO,还有一条叫 task tracker 的东西(下一段揭晓)。→ 详细
08
Demo 1 下半场:审批信号打进后端,重试到 ERP 通为止
- 点进 invoice 能看到就是前面画的那条流水线:已经跟 ERP 做完校验,现在停在等人工审批。PO 那一侧则是:已记录收货 → 并行调用发票处理这个 MCP task → 同时后台杂活也在并行跑。→ 详细
- PO 流程里那条 task tracker workflow 就是她自己写的 MCP client 实现——"记得我说过没人在 client 端实现这个吗?所以我就自己写了一个。"整场的立论基础就在这儿:没人做,那我做一个给你看。→ 详细
- 她点开 input required → 批准 → 提交,信号进到后端,后端接着往下走付款流程。日志里能看到她特意编排了几次 retry(重试)——"ERP 那边试了好几次才通"——发票行项目付掉,task completed,顶层 dashboard 上所有流程全绿。→ 详细
- 收尾她加了一句最狠的:"我完全可以中途把 server 杀掉,它照样会跟你们刚才看到的一模一样地继续跑完。"——而且这个她其实已经无意中演示过了(开头那次 server 没起来的提交)。→ 详细
09
V1 的核心资产:一台任务生命周期状态机 + 五个方法
- task 是自带生命周期的,这是她认为规范里"特别有意思"的一点。状态机长这样:working(运行中)→ 可以进入 input required(等输入)→ 从 input required 又能回到 working → 最后要么 complete(完成)、要么被 cancel(取消)、要么 fail(失败);demo 里还看到起手的 submitted(已提交)。→ 详细
- 关键洞察:"task 规范里讲的其实是 task 的生命周期。"——它不是给你加了个"异步开关",它是给"一件事正在被处理的过程"发了一套官方词汇表。此外还有一大堆语义围绕怎么获取输入、怎么交付结果。→ 详细
- 方法清单(V1):
tools/call 完全没变,只是想走异步时多传一些 metadata 进去;然后是 tasks/get(查状态)、tasks/cancel(取消)、tasks/list(列出)、tasks/result(取结果)。→ 详细
- 前四个是 request-response 风格(问一句答一句就断),只有
tasks/result 会保持一条连接开着、让连接一直活着——这个差别是下面两个硬伤的根源。→ 详细
10
V1 硬伤之一:`tasks/list` 让协议变成有状态的,而且没有任何过滤
- 它本来是个救命设计:既然 durability 由 server 负责,那 client 掉线了、用户拖太久没回、网络断了重连之后,就用
tasks/list 回过头问 server "你手上都有哪些 task",然后接着往下走。→ 详细
- 崩在规模上:"如果你只有一个 task、两个 task 没问题,哪怕 10 个可能也还行。但如果外面跑着一大堆 agent、后端攒了一百万个 task 呢?剧透一下:这个 endpoint 上没有任何过滤条件。你得把一百万个 task 全翻一遍,才能找到你想交互的那一个。" 结论:这个设计要被砍掉了。→ 详细
- 她给这一条配了句判词:"能做,不代表就该这么做。"→ 详细
11
V1 硬伤之二:「等人输入」是从取结果的长连接里硬挤出去的
tasks/result 单看时序图很简单——它本来没有交互性。但一旦任务进入 input required,头尾两段都没问题,中间那段却要用一种很别扭的协议:开一条长连接,然后由 server 反过来向 client 发起 elicitation(反向索取信息)。她的原话是"这就变得极其麻烦了"。→ 详细
- 这个 demo 她因为时间不够没跑(说"很乐意单独演示,我明天一整天都在,走廊上找我"),改成展示 server 端要搭出来的架构图:注意她用的是 FastMCP——FastMCP 已经支持 server 端,也有一部分 client 端能力;架构图左下角那个写着 MCP client protocol handler 的小方块,配上刚才那套取结果的流程,"实际长成了这个样子"(她连说两次那张图很丑)。→ 详细
12
"太麻烦"的真身:长连接断在半路,你怎么接着往下走
- 复杂度是方方面面的:"我必须维持一条长连接。那问题来了——万一连接中途断了怎么办?我回来之后怎么从断掉的地方接着往下走?" 她指出:task 规范里有很大一块篇幅讲的就是 durable 这件事——规范作者当然知道这有多难。→ 详细
- 于是回扣标题:"为什么到现在都没有哪个 client 支持这套协议?喏,这就是原因。太麻烦了。" 然后转折:"到了 V2 还是有点麻烦,但确实好多了。"→ 详细
13
V2 的方向:协议走向 stateless,MCP 拆成"内核 + 扩展"
- 消息源:今年 5 月,Angie Jones 发了一篇博客——她在 Agentic AI Foundation(MCP 现在归这个基金会)负责开发者体验。其中一条让 Cornelia "当场想跳起来庆祝":协议要走向 stateless(无状态)了。→ 详细
- 她给出的分量判断带着二十年老兵的情绪:"我在微服务这块摸爬滚打了很多年,在大规模分布式系统里,有状态的协议绝对是最要命的东西。"(有状态=server 必须记着"你是谁、你上次问到哪了",一旦重启或换台机器就全乱。)→ 详细
- 第二条改动同样关键:MCP 被结构化拆成一个 core(内核)加上若干 extension(扩展)——这跟同场前面讲 MCP UI 那场提到的 extension 是同一件事。而 tasks 本身就变成了一个 extension。→ 详细
14
V1 → V2 究竟改了什么:砍一个、加一个、留一个
- 砍掉
tasks/list。 她的评价毫不留情:"挺好——它本来也没多大用,尤其在大规模场景下。"→ 详细
- 加一个 client 主动推送的 update endpoint。 原来"在一条长会话上传 input required"的别扭做法,换成了一个接口,让你从 client 这边直接说一句"这是我给你的更新"。她点破了这东西的血统:"还记得我前面给你们看的那张截图吗,Temporal 里有个概念叫 signal,这东西本质上就是那个——一种往长期运行的 task 里发信号的方式。"(方向反转是重点:从"server 求 client 给"变成"client 主动推"。)→ 详细
tasks/result 保留,但形态变了——它不再依赖那套基于长会话的协议。→ 详细
- 生命周期管理原封不动。 她特意把状态机图重新放上来强调这一点:"这些 task 的生命周期管理是没变的。这个设计本身是靠谱的。"——协议层可以推翻重来,但"一件事有哪几种状态"这个抽象扛住了,这是全场最值得记住的一条判断。→ 详细
- 总体观感:"从 V1(那张丑图)到 V2,client 和 server 之间的协议干净太多了,实现起来也容易得多。" 但她也没吹过头——她给了一页"要实现 tasks 你需要做的所有事"的汇总,评价是 "还是相对麻烦"。→ 详细
15
Server 端实现的大头:把 task 状态机映射到你自己的业务状态机
- 这是她一句带过、但含金量极高的一点:在 server 端(比如发票处理这个场景),她自己维护了一台状态机,发票在里面流转。→ 详细
- "你在 server 端实现这些 task 的时候,很大一部分工作就是把 task 的生命周期状态,映射到后端 MCP server(或者说那个 tool)里真正在跑的业务状态机上。"——换句话说,协议只给你一套通用词汇(working / input required / complete),你的业务有自己的一套词汇(待校验 / 待审批 / 待对账 / 已付款),实现工作的本质是做这两套词汇之间的翻译。→ 详细
16
她对规范的正面批评:这里凭什么是 should 而不是 MUST
tasks/list 砍掉之后带来一个连锁后果:client 端就必须自己持久化 task ID 了(不然 task 还活着,你却再也找不到它)。→ 详细
- 她的批评很具体:"规范目前的措辞是 client『应该(should)』持久化 task ID,但它同时又指出:如果你不持久化 task ID,你就再也拿不回来了。所以我不太理解为什么这里不是一个全大写的 MUST。"(在规范文本里 should 是建议、MUST 是强制,这个词之差决定了实现方会不会认真做。)→ 详细
- 她顺带强调的另一条建议:"你很可能会有很多个 agent 在同时处理采购单……所以能同时跑多个任务,我觉得也是非常关键的。"——并发不是锦上添花,是这个协议的默认工作条件。→ 详细
17
Demo 2:多单并发,以及 V1 参考实现那个 FIFO 缺陷
- 她一口气提交了一批采购单,先给大家看 V1 情况下 client 与 server 之间的协议长什么样——"那是真的挺难看";从上层视角看 V2 跟 V1 的界面表现一模一样(协议的改善是藏在下面的)。→ 详细
- 一个只有实现过的人才知道的坑:"在 V1 协议的参考实现里,如果你有多个任务同时处于 input required 状态,虽然你能看到有很多个在同时跑,但在 client 这边它们是 FIFO(先进先出)的"——你只能先回复排在第一个的那个。 她那版实现有一部分工作就是专门绕开这个缺陷。→ 详细
- 她展开 task tracker(也就是她的 MCP client)给大家看内部:"还记得那张巨长的时序图吗?那里面涉及一大堆步骤。而我这里是把它整个实现成了一个 workflow。" 里面能看到 elicitation 的处理逻辑,是从 server 端往回传给 client 的。→ 详细
- 方法论上这一步值得单独记:她把"一个通信协议"实现成了"一条持久工作流"——协议里的每一步握手都变成 workflow 里一个可重放、断了能续的节点。这就是 client 端 durability 的落地方式。→ 详细
18
校对注:她的预测 vs 2026-07-28 正式落地的规范
- 说中的部分:① tasks 确实从核心移出、成了官方扩展
io.modelcontextprotocol/tasks,跟她讲的"core + extension 拆分、task 变成 extension"完全一致;② tasks/list 确实没了;③ 确实新增了让 client 回传输入的 tasks/update——正是她说的那个"client 直接说一句『这是我给你的更新』"的接口,血统也确实是 signal;④ 生命周期状态机保留。→ 详细
- 有出入的一处:她在台上说"
tasks/result 还在,只是不再依赖长会话";而正式落地版走得更彻底——改用 tasks/get 轮询取代阻塞式的 tasks/result,那个"开着连接等结果"的方法本身被拿掉了。演讲时 V2 尚未定稿,属于方向对、细节更激进。→ 详细
- 值得玩味的呼应:她在结尾自己就担心了轮询的代价(一百万 task 就是一百万个 client 各自 get),而落地版恰恰把主路径押在了
tasks/get 轮询上——所以她点名的 notifications 协议,正是这个坑将来的解药(见下方「收尾」)。→ 详细
19
闪电问答 / 收尾
本场没有闪电问答,收尾是她"正在继续做的两件事":
- ① 即便 V2 也撑不到百万级,解法是 notifications 协议。 她的算术很朴素:"如果我有一百万个 task 在跑,就意味着有一百万个 client 在对着这一百万个 task 一个个做 get。这是扛不住的。" 而 MCP tasks 规范里其实有一部分是 notifications(通知)协议,她说自己"还没研究得特别深,但看着很有希望"——思路是与其让一百万个 client 各自轮询,不如给一个统一的 endpoint,client 只问一句『有东西变了吗』,有的话告诉我是哪几个,我再去拉那几个。她的判断:从可扩展性的角度看,这个方向是对的。→ 详细
- ② 一两个月内出一版更简单的实现,目标是做进 FastMCP。 她的原话是"我的目标是把它做进 FastMCP,这样你就可以沿用你今天做 MCP server 大概率已经在用的那套框架和协议了"——也就是把"实现 tasks"的门槛从"自己写一个 client"降到"升级一下依赖"。→ 详细
- ③ 代码全部开源。 她全场三次承诺会分享代码,最后现场展示了 Git repo 二维码,并说幻灯片也会放进那个 repo。→ 详细
- ④ 超时致谢收场。 "谢谢下一位讲者让我超时了几分钟。我人就在附近,大家有问题的话到走廊上找我。"→ 详细
20
联系方式
- Cornelia Davis — Temporal 技术专家(technologist),《Cloud Native Patterns》作者;分布式系统背景:Cloud Foundry / Kubernetes / GitOps / Weaveworks。
- 配套深讲(server 端 durability):她 2026-03 在 MCP Dev Summit 的演讲,现场以二维码指向 YouTube(本场是它的 client 端续集)。→ 详细
- 代码与幻灯片:现场展示的 Git repo 二维码(口播未念出 URL,需从视频画面截取)。→ 详细
- 本人:"我人就在附近,大家有问题的话到走廊上找我";她也说明天全天在场,愿意单独补演示那个没跑完的 demo。→ 详细