1. 什么是任务? #
任务是 MCP 的实验性功能,用于处理长时间运行的操作。请求方发送任务增强请求后,接收方立即返回任务 ID,实际结果通过轮询或延迟获取拿到。
协议版本:2025-11-25
| 通俗理解 | 说明 |
|---|---|
| 异步执行 | 像「提交工单」:先拿到工单号,再轮询状态,完成后取结果 |
| 两阶段响应 | 第一阶段返回任务数据;第二阶段通过 tasks/result 获取实际结果 |
| 适用场景 | 耗时计算、批处理、与外部作业 API 集成 |
2. 本章你将学到 #
- 任务的定义与角色
- 能力声明与工具级协商
- 创建、轮询、获取结果、取消的协议消息
- 任务状态与行为要求
- 错误处理与安全要点
3. 快速导航 #
| 操作 | 方法 | 说明 |
|---|---|---|
| 创建任务 | 在请求中加 task 字段 |
如 tools/call 带 task: { ttl: 60000 } |
| 轮询状态 | tasks/get |
按 pollInterval 轮询直至终止 |
| 获取结果 | tasks/result |
阻塞直至任务完成,返回实际结果 |
| 列出任务 | tasks/list |
支持分页 |
| 取消任务 | tasks/cancel |
显式取消,必须用此方法(非 notifications/cancelled) |
4. 定义与角色 #
| 角色 | 说明 |
|---|---|
| 请求方 | 发送任务增强请求、轮询状态、获取结果的一方;可以是客户端或服务器 |
| 接收方 | 接收请求、执行任务、管理生命周期的一方;可以是客户端或服务器 |
请求方驱动:请求方负责轮询;接收方控制哪些请求支持任务、并管理任务生命周期。
5. 能力 #
双方必须在初始化时声明 tasks 能力,才能使用任务增强。
5.1 服务端能力 #
| 能力 | 说明 |
|---|---|
tasks.list |
支持 tasks/list |
tasks.cancel |
支持 tasks/cancel |
tasks.requests.tools.call |
支持任务增强的 tools/call |
5.2 客户端能力 #
| 能力 | 说明 |
|---|---|
tasks.list |
支持 tasks/list |
tasks.cancel |
支持 tasks/cancel |
tasks.requests.sampling.createMessage |
支持任务增强的采样请求 |
tasks.requests.elicitation.create |
支持任务增强的征询请求 |
5.3 工具级协商 #
工具在 tools/list 中通过 execution.taskSupport 声明:
| 值 | 含义 |
|---|---|
"required" |
必须以任务方式调用 |
"optional" |
可以以任务或普通方式调用 |
"forbidden" 或未定义 |
不得以任务方式调用 |
6. 协议消息 #
6.1 创建任务 #
在请求的 params 中加入 task 字段:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "city": "New York" },
"task": { "ttl": 60000 }
}
}| 字段 | 说明 |
|---|---|
task.ttl |
可选,期望任务生存时长(毫秒) |
响应:接收方返回 CreateTaskResult,包含 taskId、status、pollInterval 等,不包含实际结果。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"task": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "working",
"statusMessage": "The operation is now in progress.",
"createdAt": "2025-11-25T10:30:00Z",
"lastUpdatedAt": "2025-11-25T10:40:00Z",
"ttl": 60000,
"pollInterval": 5000
}
}
}6.2 轮询状态(tasks/get) #
{
"jsonrpc": "2.0",
"id": 3,
"method": "tasks/get",
"params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" }
}请求方应当按 pollInterval 轮询,直至任务达到终止状态或 input_required。
6.3 获取结果(tasks/result) #
{
"jsonrpc": "2.0",
"id": 4,
"method": "tasks/result",
"params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" }
}- 任务已终止:立即返回实际结果(或错误)
- 任务未终止:阻塞直至终止后返回
6.4 取消任务(tasks/cancel) #
{
"jsonrpc": "2.0",
"id": 6,
"method": "tasks/cancel",
"params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" }
}必须使用
tasks/cancel取消任务,不得使用notifications/cancelled。
7. 任务状态 #
| 状态 | 说明 |
|---|---|
working |
正在处理 |
input_required |
需要请求方输入,应调用 tasks/result 获取输入请求 |
completed |
成功完成 |
failed |
执行失败 |
cancelled |
已取消 |
状态转换:working ↔ input_required → 终止状态(completed / failed / cancelled)。终止状态不可再转换。
stateDiagram-v2
[*] --> working
working --> input_required
working --> completed
working --> failed
working --> cancelled
input_required --> working
input_required --> completed
input_required --> failed
input_required --> cancelled
completed --> [*]
failed --> [*]
cancelled --> [*]
8. 行为要点 #
| 类别 | 要点 |
|---|---|
| 任务 ID | 由接收方生成,字符串,在接收方控制的所有任务中唯一 |
| 初始状态 | 创建时必须为 working |
| 关联元数据 | 与任务相关的消息必须在 _meta 中包含 io.modelcontextprotocol/related-task,值为 { "taskId": "..." } |
| 进度 | 支持 进度 通知,progressToken 在整个任务生命周期有效 |
| TTL | 接收方可覆盖请求的 ttl;过期后接收方可删除任务 |
9. 流程示意 #
sequenceDiagram
participant C as 请求方
participant S as 接收方
C->>S: tools/call (含 task)
S-->>C: CreateTaskResult (taskId, working)
loop 轮询
C->>S: tasks/get
S-->>C: 状态 (working / completed / ...)
end
C->>S: tasks/result
S-->>C: 实际结果
10. 错误处理 #
10.1 协议错误 #
| 情况 | 错误码 |
|---|---|
无效或不存在 taskId |
-32602 |
| 无效游标(tasks/list) | -32602 |
| 取消已终止的任务 | -32602 |
| 内部错误 | -32603 |
| 要求任务增强但未使用 | -32600(可选) |
10.2 任务执行错误 #
底层请求失败时,任务进入 failed 状态;statusMessage 可包含诊断信息。tasks/result 返回底层请求原本会返回的内容(成功或错误)。
11. 安全要点 #
| 要点 | 说明 |
|---|---|
| 任务隔离 | 有授权时,接收方必须将任务绑定到授权上下文,拒绝跨上下文访问 |
| 任务 ID | 无授权时,应当使用加密安全的 ID、缩短 TTL |
| 资源管理 | 应对并发任务数、最大 TTL 实施限制,及时清理过期任务 |
| 审计 | 应记录任务创建、完成、获取等事件 |