订阅

社区译文;来源: MCP 80041ab0

subscriptions/listen 会打开一条从服务器到客户端的长期通知流。与一次性请求不同,该流保持打开并持续传送通知,直到客户端将其取消。它取代了原先的 resources/subscribe RPC 和 HTTP GET 端点。

打开流

客户端发送 subscriptions/listen 请求,并使用 notifications 过滤器指定希望接收的事件类型。服务器MUST NOT发送客户端未明确请求的通知类型。

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    },
    "notifications": {
      "toolsListChanged": true,
      "resourceSubscriptions": ["file:///project/config.json"]
    }
  }
}

通知过滤器

字段类型说明
toolsListChangedboolean工具变化时接收 notifications/tools/list_changed
promptsListChangedboolean提示变化时接收 notifications/prompts/list_changed
resourcesListChangedboolean资源列表变化时接收 notifications/resources/list_changed
resourceSubscriptionsstring[]针对这些资源 URI 接收 notifications/resources/updated

所有字段均为可选。省略字段等同于不订阅对应通知类型。

确认

服务器MUST将 notifications/subscriptions/acknowledged 作为第一条消息发送,并在 _meta 的 io.modelcontextprotocol/subscriptionId 下携带订阅 ID;在此之前,服务器MUST NOT在该订阅上发送任何通知。在 stdio 中,每个订阅共享同一个通道,因此该顺序按订阅 ID 而不是按通道定义:属于其他订阅的消息MAY穿插在该确认前发送。

确认中的 notifications 字段反映服务器同意支持的子集。服务器不支持的通知类型会被省略。

{
  "jsonrpc": "2.0",
  "method": "notifications/subscriptions/acknowledged",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    },
    "notifications": {
      "toolsListChanged": true,
      "resourceSubscriptions": ["file:///project/config.json"]
    }
  }
}

客户端SHOULD将确认的过滤器与请求的过滤器进行核对,并妥善处理不支持的类型。

接收通知

流上传送的所有通知都在 _meta 中携带 io.modelcontextprotocol/subscriptionId,用于标识打开该流的 subscriptions/listen 请求。该值是 subscriptions/listen 请求的 JSON-RPC ID。在上面的示例中,请求使用了 "id": 1,因此确认和所有后续通知都携带订阅 ID 1。在所有消息共享同一通道的 stdio 中,客户端MUST使用此字段将通知与其来源订阅关联起来。

{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    },
    "uri": "file:///project/config.json"
  }
}

多个并发订阅

客户端MAY同时拥有多个活动订阅,例如一个监听工具列表变化,另一个监听资源更新。每个订阅由其 subscriptions/listen 请求的 JSON-RPC 请求 ID 标识,流上的每条通知都在 io.modelcontextprotocol/subscriptionId 中携带该 ID,以便客户端对通知进行多路分解。

取消

订阅在以下情况下结束:

  • 客户端取消订阅:关闭 SSE 流(HTTP),或发送引用 subscriptions/listen 请求 ID 的 notifications/cancelled(stdio)。
  • 服务器关闭订阅(例如在停机期间):服务器SHOULD发送成功的 subscriptions/listen 响应,表示正常结束(参见正常关闭 ),随后关闭流。
  • 底层传输关闭(HTTP 超时、TCP 断开、stdio 进程退出)。

正常关闭

当服务器主动结束订阅时(例如停机期间),它SHOULD在关闭流前,以完成结果响应原始 subscriptions/listen 请求。除标准结果字段和订阅元数据外,该结果不携带特定于方法的数据。这是对长期请求的 JSON-RPC 响应,通过其 id 进行关联,表明订阅正常结束;突然断开的传输不会携带该响应。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    }
  }
}

与流上的其他消息一样,该响应在 _meta 中携带 io.modelcontextprotocol/subscriptionId,以标识它关闭的订阅。该值与来源 subscriptions/listen 请求的 JSON-RPC id 相同。

客户端收到此响应后即可知道订阅已正常关闭;如果传输关闭时没有该响应,则表示意外断开,客户端MAY将其视为重新连接的触发条件。

在 stdio 中,如果连接终止后重新建立,客户端MUST重新发送 subscriptions/listen 来恢复订阅,因为服务器不会跨连接保存订阅状态。

完整规则参见取消 。