MCP 与异步 Job 怎样接入 Harness
一句话收获:MCP 解决连接和发现,长任务可靠性仍依赖本地权限、状态和验收。
这个场景在解决什么问题
Agent 需要调用外部能力,可能通过 MCP(Model Context Protocol,模型上下文协议,一种让模型发现和连接外部工具的标准协议)去发现工具;但很多业务是"异步长任务"——提交一个任务,要跑很久才有结果。这两件事要分开看:连接发现是一回事,长任务可靠性是另一回事。
这个场景的目标(goal)是:实现受控发现、长任务状态、回调和结果未知。观察点(observation)是:通过 MCP 发现能力,再启动一条异步任务——先用 MCP 找到能用的工具,再提交一个要跑很久的 Job。
它值得单独学,因为它戳破一个常见误解:别以为连上 MCP 就万事大吉。MCP 解决的是"怎么连接、怎么发现工具",而长任务跑得可不可靠,靠的是本地权限、状态管理和独立验收,这跟 MCP 本身没关系。
先理清这条判断链(文字版)
从"发现能力"到"任务收尾"是一条链,中间要过"异步"这个坎:
- 先看受控发现——客户端只连接固定来源、固定版本的 MCP 服务,只装载当前任务需要的工具最小集,接入前先验证契约与权限。
- 再看提交异步 Job——工具返回任务引用和查询入口,模型会话不用一直等着,队列和任务系统负责推进。
- 然后看回调与结果未知——回调超时后任务进入"未知状态",先查询权威 Job 状态再决定恢复,不能直接重提。
- 最后看最终收束——Job 完成后,Loop 重新读结果、查证据、通知用户,外部状态和证据共同结束任务。
逐层详解
第 1 步:受控发现
原文:客户端连接固定来源和版本的 MCP 服务,只装载当前任务所需工具。
白话:Agent 连 MCP 服务时,不能随便连、随便加载一堆工具,而是只连"固定来源、固定版本"的服务,并且只加载当前任务真正需要的工具(最小集),不用的不装。
类比:像给员工配系统权限,不是把公司所有系统全开给他,而是只开他当前项目要用到的那几个系统、并锁定版本,防止他碰不该碰的、或用错版本。
举例:Agent 这次任务是"查订单",就只连接订单中心的 MCP 服务(固定来源、锁定 v2 版本),只加载"查询订单"这一个工具,不加载"删除订单""改价格"等其他工具——最小集、最小权限。
为什么重要:工具发现也要服从身份和任务范围。别以为"发现工具"是个中性的技术动作,工具发现同样要受"你是谁、这次任务要干嘛"的约束,不能什么工具都给你发现出来。
怎么验证(证据点):
- 服务来源:连接的是哪个固定的 MCP 服务来源。
- 版本固定:连接的版本是锁定的,不是漂移的。
- 工具最小集:只装载了当前任务需要的工具,没有多余。
别踩的坑(边界):MCP 连接成功不证明工具业务正确。连上了、握手成功了,只说明"通道通了",不代表这个工具在业务上是对的、能正确完成你的事。
落地检查:接入前验证契约与权限。落地时在真正接入、真正使用前,要先验证这个 MCP 服务的契约(输入输出对不对)和权限(我能调什么),验证过了才用。
第 2 步:提交异步 Job
原文:工具返回任务引用和查询入口,模型会话无需持续等待。
白话:提交一个长任务(异步 Job)时,工具不要同步地干等着,而是立刻返回一个"任务引用"(比如 Job ID)和"查询入口"(去哪查状态),模型会话不用一直开着等结果。
类比:像去餐厅点了份要炖一小时的菜,服务员不会让你站在后厨门口等,而是给你一个取餐号、告诉你去哪查进度,你可以先干别的。
举例:Agent 提交一个"生成月度报表"的 Job,工具立刻返回 job_id=abc 和查询入口 GET /job/abc/status,然后模型会话就可以结束了,不用挂着连接等一小时。
为什么重要:长任务生命周期位于模型外。长任务的推进(排队、执行、失败重试)由任务系统/队列负责,跟模型会话无关——模型的会话可以关掉,任务照样在跑。
怎么验证(证据点):
- Job 已提交:确认任务真的进了队列,不是提交失败。
- 状态可查询:有明确的查询入口能查到当前状态。
- 支持取消:任务能不能被取消,是有明确说法的。
别踩的坑(边界):模型保持会话不等于任务可靠运行。模型那边一直开着会话、一直轮询,不代表任务本身跑得可靠——任务可靠性靠任务系统,不靠模型盯着。
落地检查:队列和任务系统负责推进。落地时要明确:推进任务的是队列/任务系统,模型只是提交者和查询者,职责要分清楚。
第 3 步:回调与结果未知
原文:回调超时后任务进入未知状态,系统查询权威 Job 状态。
白话:任务完成后,系统可能通过"回调"通知你;但如果回调超时了、没收到,任务就进入"未知状态"——这时候不能瞎猜,要去查询"权威的 Job 状态"(任务系统里的真实状态)。
类比:像等快递,短信通知(回调)没收到,你不能凭空判断"丢了"或"到了",要上快递官网查那个权威的物流状态,以它为准。
举例:报表 Job 完成后回调 Agent 超时了,Agent 现在不知道它到底成没成,于是主动去查权威 Job 状态接口,确认它实际是"已完成"还是"失败"还是"还在跑"。
为什么重要:事件和传输失败不能决定业务结果。回调没收到,可能只是"通知传输"出了问题,不代表"业务结果"有问题——业务结果以权威 Job 状态为准,不能被通知事件绑架。
怎么验证(证据点):
- 回调来源:回调从哪来、是不是可信来源。
- Job 当前状态:查询到的权威 Job 状态是什么。
- 查询回执:查询这个动作有回执、有记录。
别踩的坑(边界):直接重提会生成重复任务。状态未知时,最危险的动作就是"直接重新提交一次",因为如果原任务其实已经成功,重提就会生成一个重复任务,造成重复执行。
落地检查:先查询再决定恢复。落地时的铁律:遇到未知状态,先查询权威状态,再决定是恢复、是重试、还是取消,绝不能先重提。
第 4 步:最终收束
原文:Job 完成后,Loop 重新读取结果、检查证据并通知用户。
白话:任务最终完成后,不是收到"完成事件"就结束,而是 Agent 的 Loop(执行循环)要重新去读取结果、检查证据是否齐全,然后才通知用户。
类比:像项目经理收到"项目完成"的消息,不会直接转发给老板,而是先去核对交付物、检查验收证据,确认没问题了才正式汇报。
举例:报表 Job 显示"已完成",Agent 的 Loop 去读取报表结果对象、核对数据对不对、证据全不全,确认无误后,再通知 summer"报表好了,在这里"。
为什么重要:异步完成事件只是验收入口。收到"任务完成"的事件,只是提醒你"该去验收了",它本身不等于验收通过,验收要重新查结果、查证据。
怎么验证(证据点):
- 结果对象:最终结果对象是可读、可核对的。
- 最终状态:确认了任务的最终状态(成功/失败)。
- 通知依据:通知用户时,有明确的依据(结果+证据)。
别踩的坑(边界):发送通知不等于业务验收本身。给用户发了一条"完成"通知,不代表业务验收通过了——通知只是告知,验收是另一件事。
落地检查:外部状态和证据共同结束任务。落地时任务"结束"要同时满足两个条件:外部权威状态确认完成 + 证据齐全,缺一不可。
落地可行性小结
本场景涉及的核心技术栈:MCP(Model Context Protocol,模型上下文协议)、异步 Job / 队列、回调(callback)、状态查询接口、Loop(执行循环)、Harness(运行框架/骨架)、权威状态源。
真实落地要检查的事:
- MCP 服务要固定来源 + 固定版本 + 工具最小集,接入前验证契约和权限。
- 异步任务提交后返回"任务引用 + 查询入口",模型会话不等待,由队列/任务系统推进。
- 回调超时进入未知状态时,铁律是"先查询权威 Job 状态,再决定恢复",禁止直接重提。
- 任务结束要"外部状态 + 证据"共同判定,不能收到完成事件就宣布成功。
常见坑:
- 把 MCP 连接成功当成"工具业务正确",没验证契约和权限就开用。
- 模型会话一直挂着轮询,误以为"盯着就是可靠"。
- 回调超时后直接重提,结果原任务其实已成功,生成重复任务。
- 收到"完成"事件就发通知,没重新读结果、查证据。
回顾
- MCP 解决连接和发现,长任务可靠性靠本地权限、状态和验收,二者不能混为一谈。
- 工具发现也要受控:固定来源、固定版本、只装当前任务需要的工具最小集。
- 长任务生命周期在模型之外,由队列/任务系统推进,模型只是提交者和查询者。
- 未知状态先查询、后恢复,直接重提会生成重复任务。
- 异步完成事件只是验收入口,最终要"外部状态 + 证据"共同结束任务。