主题
Tasks
面向长时间运行的 MCP 操作的异步任务执行
ext-tasks 仓库包含 MCP Tasks 的完整规范与文档。
modelcontextprotocol/ext-tasks
MCP Tasks 的完整规范与文档。
并非每次工具调用都会立即返回。有些操作——CI 流水线、批处理、人工审批——需要数秒、数分钟甚至更长时间。MCP Tasks 让服务端返回一个持久化句柄,而不是阻塞等待,这样客户端就可以轮询进度、在需要时提供输入,并在重新连接后获取最终结果。
为什么不直接阻塞?
你当然可以一直保持连接打开,直到工作完成。但 Tasks 解决了阻塞无法解决的问题:
- 无需长连接。 阻塞会在操作期间一直占用连接。许多客户端和传输中间层都设有超时,使得阻塞超过几秒就变得不切实际。
- 崩溃恢复能力。 任务 ID 是一个持久化句柄。如果客户端断开连接或重启,它可以用同一个 ID 恢复轮询。
- 进度可见性。 Tasks 携带状态元数据(
working、input_required、completed、failed、cancelled)以及可选的状态消息,让客户端能够看到进度。 - 执行中途交互。 当任务需要输入时(例如通过征询请求用户确认),它会转为
input_required并暴露该请求。客户端通过tasks/update进行响应——无需第二条连接,也无需服务端主动向客户端发送消息。 - 服务端主导。 由服务端逐请求决定是否创建任务。客户端只需通过扩展能力一次性选择加入,然后处理到达的任意结果形态。无需按工具预热,也无需按请求设置标志。
Tasks 如何工作
Tasks 扩展了标准请求流程。当服务端判定某个请求将长时间运行时,它会返回一个任务句柄,而不是最终结果。客户端随后轮询完成情况。
能力协商。 客户端在其逐请求能力中包含
io.modelcontextprotocol/tasks。服务端在其自身的server/discover能力中声明同一扩展。任务创建。 针对受支持的请求,服务端返回一个
CreateTaskResult(由resultType: "task"标识),其中包含taskId、 初始状态、TTL 和建议的轮询间隔。任务在响应发送之前就已持久化创建。轮询。 客户端使用
taskId调用tasks/get。响应携带当前状态,对于终态还会携带最终结果或错误。执行中途输入。 如果任务转为
input_required,tasks/get响应会包含一个inputRequests映射,其中带有征询或其他服务端请求。客户端通过tasks/update完成这些请求。完成。 当状态达到
completed时,result字段 包含原请求在同步情况下本应返回的内容。如果状态为failed,error字段包含 JSON-RPC 错误。取消。 客户端可以随时发送
tasks/cancel。 取消是协作式的——服务端确认该意图,但没有义务停止工作。
sequenceDiagram
participant Client
participant Server
Client->>Server: tools/call (with tasks capability)
Server-->>Client: CreateTaskResult (taskId, status: working)
loop Poll until terminal
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: working)
end
Note over Client,Server: Server needs user input
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: input_required, inputRequests)
Client->>Server: tasks/update (taskId, inputResponses)
Server-->>Client: ack
loop Poll until terminal
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: working)
end
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: completed, result)
何时使用 Tasks
当你的用例涉及以下情况时,Tasks 是一个很好的选择:
长时间运行的操作。 需要数分钟或数小时的 CI 流水线、批数据处理或模型训练作业。
人在回路的工作流。 审批关卡、审核步骤,或任何需要暂停等待用户确认的操作。任务会转为 input_required,客户端则呈现该请求。
外部作业系统。 如果你的服务端封装了一个已经使用作业 ID 的 API(云部署、异步 API、排队工作),那么在你创建作业时返回一个任务,并在作业完成时将其解决。
不可靠的连接。 移动客户端、间歇性网络,或连接会中断的环境。任务 ID 能在断开连接后继续存在。
批处理。 处理大量条目的操作(批量导入、批量更新),其中部分进度是有意义的。状态消息会报告进度。
任务生命周期
| 状态 | 含义 |
|---|---|
working | 操作正在进行中。 |
input_required | 服务端在继续之前需要客户端输入。参见 inputRequests。 |
completed | 操作已完成。result 字段包含最终输出。 |
failed | 执行期间发生了 JSON-RPC 错误。error 字段包含详细信息。 |
cancelled | 操作已被取消(不一定会被真正执行)。 |
completed、failed 和 cancelled 是终态——一旦到达,任务状态不再改变。
通知
服务端可以通过 notifications/tasks 推送状态更新。客户端通过 subscriptions/listen 机制选择接收这些通知。每条通知都携带完整的任务状态,从而无需额外进行一次 tasks/get 往返。
轮询是默认方式。如果服务端支持通知,客户端可以依赖通知而非轮询。
实现指南
面向 MCP 客户端
要消费任务增强型响应,你的客户端必须:
声明支持
在其逐请求能力中包含该扩展:
```jsonc
{
"jsonrpc": "2.0",
"id": 1,
"method": "...",
"params": {
// Other fields...
"_meta": {
// Other fields...
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {},
},
},
},
},
}
```
处理多态结果
在发出受支持的请求(例如 `tools/call`)时,要准备好接收标准结果或带有 `resultType: "task"` 的 `CreateTaskResult`。
轮询完成状态
使用返回的 `taskId` 调用 `tasks/get`,并遵守 `pollIntervalMs` 值。持续轮询,直到任务达到终态(`completed`、`failed` 或 `cancelled`)。
处理输入请求
如果任务状态为 `input_required`,读取 `inputRequests` 映射,将请求呈现给用户或模型,并通过 `tasks/update` 提交响应。
持久化任务 ID
持久存储任务 ID,以便在客户端崩溃或重启后能够恢复轮询。
面向 MCP 服务端
要从你的服务端返回任务:
声明支持
在你的 `server/discover` 能力中包含该扩展:
```jsonc
{
"jsonrpc": "2.0",
"id": 1,
"result": {
// Other fields...
"capabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {},
},
},
},
}
```
检查客户端能力
在返回 `CreateTaskResult` 之前,确认客户端已在其逐请求能力中包含该扩展。绝不要向未声明支持的客户端返回任务。
返回 CreateTaskResult
当请求将长时间运行时,以 `resultType: "task"` 和一个 `Task` 对象作为响应,该对象包含唯一的 `taskId`、初始状态、`ttlMs` 和 `pollIntervalMs`。任务必须在发送响应之前持久创建。
提供 tasks/get
在每次轮询时返回当前任务状态。对于终态,包含 `result`(在 `completed` 时)或 `error`(在 `failed` 时)字段。
处理 tasks/update
接受以未完成的 `inputRequests` 为键的 `inputResponses`。以空结果确认。忽略针对未知或已满足键的响应。
处理 tasks/cancel
以空结果确认取消请求。尽可能遵从,但取消是协作式的——任务仍可能达到非 `cancelled` 的终态。
客户端支持
NOTE
MCP Tasks 是核心 MCP 规范的扩展。宿主支持因客户端而异。
有关各客户端对扩展的支持情况,请参阅客户端矩阵。任务支持需要客户端和服务端双方的显式选择加入。
规范
Tasks 扩展在 ext-tasks 仓库中定义。它使用标准的 MCP 扩展协商机制:客户端在每个请求的 _meta 中发送的 io.modelcontextprotocol/clientCapabilities 的 extensions 字段中声明支持,服务端在 server/discover 返回的能力中声明其支持。