跳到主要内容

模型上下文协议规范(2025-03-26)—— 传输

· 阅读需 14 分钟

翻译自:https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/transports/

ℹ️ 协议修订:2025-03-26

MCP 使用 JSON-RPC 来编码消息。JSON-RPC 消息必须使用 UTF-8 编码。

该协议目前定义了两种标准的传输机制用于客户端与服务器之间的通信:

  1. 通过标准输入和标准输出进行通信
  2. 可流式传输的HTTP

客户端在可能的情况下应该支持标准输入输出。

客户端和服务器也可以以可插拔方式实现自定义传输

标准输入输出

stdio 传输中:

  • 客户端作为一个子进程启动MCP服务器。
  • 服务器从其标准输入(stdin)读取JSON-RPC消息,并将消息发送到其标准输出(stdout)。
  • 消息可以是JSON-RPC请求、通知、响应,或者是一个包含一个或多个请求和/或通知的JSON-RPC批处理
  • 消息通过换行符进行界定,并且必须不包含嵌入的换行符。
  • 服务器可以将UTF-8字符串写入其标准错误(stderr)用于记录日志。客户端可以捕获、转发或忽略这些日志记录。
  • 服务器绝对不可以向它的stdout写入任何非有效MCP消息的内容。
  • 客户端绝不能向服务器的stdin写入任何不是有效MCP消息的内容。

stdio传输

可流式传输的HTTP

ℹ️ 这替换了协议版本 2024-11-05 中的HTTP+SSE 传输。请参阅下面的向后兼容性指南。

可流式的HTTP传输中,服务器作为一个独立的进程运行,可以处理多个客户端连接。这种传输使用HTTP POST和GET请求。服务器可以选择使用服务器发送事件(SSE)来流式传输多个服务器消息。这允许基本的MCP服务器,以及支持流式传输和服务器到客户端通知和请求的更丰富功能的服务器。

服务器必须提供一个支持POST和GET方法的单一HTTP端点路径(以下称为MCP端点)。例如,这可以是像https://example.com/mcp这样的URL。

向服务器发送消息

每个从客户端发送的JSON-RPC消息必须是一个对MCP端点的新的HTTP POST请求。

  1. 客户端必须使用HTTP POST方法向MCP端点发送JSON-RPC消息。

  2. 客户端必须包含一个Accept头部,列出application/jsontext/event-stream作为支持的内容类型。

  3. POST请求的主体必须成为以下之一:

    • 一个单独的JSON-RPC 请求通知响应
    • 一个数组 批处理 一个或多个请求和/或通知
    • 一个数组 批处理 一个或多个响应
  4. 如果输入仅仅包含(任意数量的)JSON-RPC 通知响应:

    • 如果服务器接受输入,服务器必须返回HTTP状态码202 Accepted并且不包含任何内容。
    • 如果服务器不能接受输入,它必须返回一个HTTP错误状态码(例如,400错误的请求)。HTTP响应体可以包含一个没有id的JSON-RPC错误响应
  5. 如果输入包含任意数量的JSON-RPC请求,服务器必须返回Content-Type: text/event-stream以初始化一个SSE流,或者返回Content-Type: application/json以返回一个JSON对象。客户端必须支持这两种情况。

  6. 如果服务器启动一个SSE流:

    • SSE流应该最终包括针对POST正文中发送的每个JSON-RPC请求的一个JSON-RPC响应。这些响应可以批处理的

    • 服务器可以在发送JSON-RPC响应之前发送JSON-RPC请求通知。这些消息应该与发起的客户端请求有关。这些请求和*通知可以批处理

    • 服务器在发送每个收到的JSON-RPC请求的响应之前,不应该关闭SSE流,除非会话过期。

    • 在所有JSON-RPC响应发送完毕后,服务器应该关闭SSE流。

    • 断开连接可能随时可能发生(例如,由于网络条件)。因此:

      • 断开连接不应该被解释为客户端取消了它的请求。
      • 为了取消,客户端应该明确发送一个MCP CancelledNotification
      • 为了避免由于连接断开而导致消息丢失,服务器可以使流可以恢复

监听服务器的消息

  1. 客户端可以向MCP端点发出HTTP GET请求。这可以用来打开一个SSE流,允许服务器与客户端通信,而无需客户端首先通过HTTP POST发送数据。
  2. 客户端必须包含一个Accept头部,列出text/event-stream作为支持的内容类型。
  3. 服务器必须对这个HTTP GET请求返回Content-Type: text/event-stream,或者返回HTTP 405 方法不被允许,表明服务器在这个端点不提供SSE流。
  4. 如果服务器启动一个SSE流:
    • 服务器可以在流上发送JSON-RPC的请求通知。这些请求通知 可以批处理的
    • 这些消息应该与客户端同时运行的任何JSON-RPC请求无关。
    • 服务器不得在流上发送JSON-RPC response除非恢复与先前客户端请求关联的流。恢复
    • 服务器可能会在任何时间关闭SSE流。
    • 客户端可以在任何时候关闭SSE流。

多重连接

  1. 客户端可以同时保持与多个SSE流的连接。

  2. 服务器必须将其每一条JSON-RPC消息只发送在一条已连接的流上;也就是说,它不得在多个流中广播相同的消息。

    • 通过使流可恢复可能可以降低消息丢失的风险。

恢复性和重传

为了支持恢复断开的连接,并重新传送可能丢失的信息:

  1. 正如在SSE标准介绍的,服务器可以附加一个id到他们的SSE事件中。

    • 如果存在,该ID 必须 在该会话中的所有流之间全局唯一——或者如果没有使用会话管理,那么在与那个特定客户端的所有流之间全局唯一。
  2. 如果客户希望在连接断开后恢复,它应该向MCP端点发起一个HTTP GET请求,并包含Last-Event-ID标头用于指示它收到的最后一个事件ID。

    • 服务器可以使用此头部来重放在最后一个事件ID之后本应发送的消息,在被断开的流上,并从那个点恢复流。
    • 服务器不得重播本应在不同流上交付的消息。

换言之,这些事件 ID 应该由服务器在每个流的基础上分配,以便在特定流内充当游标。

会话管理

一个MCP“会话”包含客户端与服务端之间逻辑上相关的交互,始于初始化阶段。为了支持想要建立有状态会话的服务器:

  1. 使用可流式传输的HTTP协议的服务器可以在初始化时分配一个会话ID,通过在载有InitializeResult的HTTP响应中增加Mcp-Session-Id头传递给访问方。

    • 会话ID 应该 是全球唯一且加密安全的(例如,一个安全生成的UUID、一个JWT或一个加密散列)。
    • 会话ID 必须 只包含可见的ASCII字符(范围从0x21到0x7E)。
  2. 如果一个Mcp-Session-Id在初始化期间由服务器返回,使用 Streamable HTTP 传输的客户端必须包在所有随后的HTTP请求中包含该头部。

    • 需要会话 ID 的服务器应该对没有 Mcp-Session-Id 头部的请求(初始化除外)以 HTTP 400 错误请求响应。
  3. 服务器可以在任何时候终止会话,在此之后,它必须用HTTP 404未找到对包含该会话ID的请求作出响应。

  4. 当客户端在包含Mcp-Session-Id的请求中收到HTTP 404响应时,它必须通过发送一个没有附加会话ID的新InitializeRequest来开始一个新会话。

  5. 客户端不再需要某个特定会话时(例如,因为用户要离开该客户端应用程序)应该向MCP端点发送一个包含Mcp-Session-Id头部HTTP DELETE请求,用来明确结束会话。

    • 服务器可以使用HTTP 405方法不允许响应此请求,表明服务器不允许客户端终止会话。

时序图

可流式传输的HTTP传输

向后兼容性

客户端和服务器可以通过以下方式与已弃用的HTTP+SSE传输(来自2024-11-05的协议版本)保持向后兼容:

想要支持旧版客户端的服务器应该:

  • 继续同时托管旧传输的SSE(Server-Sent Events)和POST端点,以及为可流式HTTP传输定义的新的“MCP端点”。
    • 也可以将旧的POST端点和新的MCP端点结合起来使用,但这可能会引入不必要的复杂性。

想要支持旧服务器的客户端应该:

  1. 接受用户提供的一个MCP服务器的URL,该URL可能指向使用旧传输协议或新传输协议的服务器。

  2. 尝试向该URL发送一个包含有InitializeRequest和前述Accept头部的POST请求:

    • 如果成功,客户端可以假设这是一个支持新的Streamable HTTP传输的服务器。
    • 如果它失败并返回一个HTTP 4xx状态码(例如,405 方法不允许 或 404 未找到):
      • 向服务器URL发起一个GET请求,期待这将打开一个SSE流,并将endpoint事件作为第一个事件返回。
      • endpoint 事件到达时,客户端可以认为这是一个运行着旧版HTTP+SSE传输协议的服务器,并且应该使用该传输协议进行所有后续的通信。

自定义传输

客户端和服务器可以根据其特定需求实现额外的自定义传输机制。该协议与传输方式无关,可以在支持双向消息交换的任何通信渠道上实现。

选择支持自定义传输的实施者必须确保它们保留由MCP定义的JSON-RPC消息格式和生命周期要求。自定义传输应当记录它们特定的连接建立和消息交换模式以便于对接。