Tasks

社区译文;来源: MCP 80041ab0

ext-tasks 仓库 包含 MCP Tasks 的完整规范和文档。

modelcontextprotocol/ext-tasks

MCP Tasks 的完整规范和文档。

并非每次工具调用都能立即返回。有些操作,例如 CI 流水线、批处理和人工审批,需要数秒、数分钟甚至更长时间。MCP Tasks 允许服务器返回持久句柄,而不是一直阻塞;客户端可以轮询进度、在需要时提供输入,并在重新连接后获取最终结果。

为什么不直接阻塞?

你可以一直保持连接,直到工作结束。但 Tasks 能解决阻塞方式无法解决的问题:

  • 无需长连接。 阻塞会在整个操作期间占用连接。许多客户端和传输中间件都会设置超时,因此超过几秒后,这种方式往往不可行。
  • 故障恢复能力。 任务 ID 是持久句柄。如果客户端断开连接或重新启动,可以使用同一个 ID 恢复轮询。
  • 进度可见性。 Tasks 携带状态元数据(working、input_required、completed、failed、cancelled)和可选状态消息,让客户端能够了解进度。
  • 执行中交互。 当任务需要输入(例如通过 elicitation 请求用户确认)时,会进入 input_required 状态并公开该请求。客户端通过 tasks/update 响应,无需建立第二条连接,也不需要服务器主动向客户端发送未经请求的消息。
  • 由服务器决定。 服务器按请求决定是否创建任务。客户端只需通过扩展能力选择启用一次,然后处理实际返回的任一种结果形态,无需按工具预热,也无需为每个请求设置标志。

Tasks 如何工作

Tasks 扩展了标准请求流程。当服务器认定某个请求会长时间运行时,会返回任务句柄,而不是最终结果。客户端随后轮询任务是否完成。

  1. 能力协商。 客户端在每个请求的能力中包含 io.modelcontextprotocol/tasks。服务器在自己的 server/discover 能力中公布同一个扩展。

  2. 创建任务。 服务器响应受支持的请求时,返回 CreateTaskResult(通过 resultType: "task" 标识),其中包含 taskId、初始状态、TTL 和建议轮询间隔。发送响应之前,任务必须已经持久化创建。

  3. 轮询。 客户端使用 taskId 调用 tasks/get。响应包含当前状态;如果任务已到达终态,还会包含最终结果或错误。

  4. 执行中输入。 如果任务进入 input_required 状态,tasks/get 响应会包含一个 inputRequests 映射,其中是 elicitation 或其他服务器请求。客户端通过 tasks/update 满足这些请求。

  5. 完成。 状态变为 completed 后,result 字段包含原请求同步执行时应返回的内容。如果状态是 failed,error 字段包含 JSON-RPC 错误。

  6. 取消。 客户端可以随时发送 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 状态,客户端向用户呈现请求。

外部作业系统。 如果服务器封装的 API 已经使用作业 ID,例如云部署、异步 API 或排队作业,则可以在创建作业时返回任务,并在作业完成时解析任务结果。

不可靠的连接。 移动客户端、间歇性网络或连接容易中断的环境。任务 ID 在断开连接后仍然有效。

批处理。 处理大量项目的操作,例如批量导入或大规模更新,其中部分进度也有意义。状态消息可以报告进度。

任务生命周期

状态含义
working操作正在进行。
input_required服务器需要客户端输入才能继续。请参阅 inputRequests。
completed操作已完成。result 字段包含最终输出。
failed执行期间发生 JSON-RPC 错误。error 字段包含详细信息。
cancelled操作已取消,但取消请求不一定总会得到执行。

completed、failed 和 cancelled 都是终态;任务一旦进入终态,其状态就不会再改变。

通知

服务器可以通过 notifications/tasks 推送状态更新。客户端通过 subscriptions/listen 机制选择接收。每条通知都携带完整任务状态,因此无需额外执行一次 tasks/get 往返。

默认方式是轮询。如果服务器支持通知,客户端可以依赖通知而不再轮询。

实现指南

MCP 客户端

要使用带任务信息的响应,客户端必须执行以下步骤:

声明支持

在每个请求的能力中包含该扩展:

{
  "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 能力中包含该扩展:

{
  "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 以外的终态。

客户端支持

MCP Tasks 是核心 MCP 规范 的扩展。不同客户端的宿主支持情况并不相同。

请查看客户端矩阵 ,了解各客户端对扩展的支持情况。客户端和服务器都必须明确选择启用,才能使用 Tasks 支持。

规范

Tasks 扩展在 ext-tasks 仓库 中定义。它使用标准 MCP 扩展协商 机制:客户端在每个请求 _meta 内的 io.modelcontextprotocol/clientCapabilities 的 extensions 字段中声明支持,服务器则在 server/discover 返回的能力中通过 extensions 字段公布支持。