Skip to content
MCP 文档版本 2026-07-28 更新于 2026-10-14

订阅

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

打开流

客户端发送 subscriptions/listen 请求,并附带一个 notifications 过滤器,指定它希望接收哪些事件类型。服务端 MUST NOT(不得)发送客户端未显式请求的通知类型。

json
{
  "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"]
    }
  }
}

通知过滤器

FieldTypeDescription
toolsListChangedbooleanReceive notifications/tools/list_changed when tools change
promptsListChangedbooleanReceive notifications/prompts/list_changed when prompts change
resourcesListChangedbooleanReceive notifications/resources/list_changed when list changes
resourceSubscriptionsstring[]Receive notifications/resources/updated for these resource URIs

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

确认

服务端 MUST(必须)将 notifications/subscriptions/acknowledged 作为第一条消息发送,并在 _meta 中的 io.modelcontextprotocol/subscriptionId 下携带该订阅的 ID,且 MUST NOT(不得)在此之前在该订阅上发送任何通知。在 stdio 上,所有订阅共享同一个通道,因此该顺序是按订阅 ID 而非按通道定义的:属于其他订阅的消息 MAY(可以)在此之前交错出现。

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

json
{
  "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(必须)使用该字段将通知与其来源订阅关联起来。

json
{
  "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 进行关联,表示订阅已优雅结束——与之相对的是突发的传输中断,后者不携带任何响应。

json
{
  "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 以重新建立其订阅——服务端不会跨重连保留任何订阅状态。

完整规则见取消。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。