找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1029

积分

0

好友

140

主题
发表于 5 天前 | 查看: 9| 回复: 0

MCP(Model Context Protocol)已成为连接AI助手与外部工具和数据的核心协议之一。其架构的每一次演进都旨在提升效率与兼容性。自2025年3月发布的协议版本起,MCP用全新的Streamable HTTP传输机制取代了原先的HTTP+SSE组合,这标志着协议底层通信方式的一次重大升级。

MCP协议传输技术变更示意图

为什么MCP需要专门的传输协议?

MCP协议基于JSON-RPC 2.0格式在客户端(如AI助手)与服务器(如工具、数据库)间进行通信。传统的HTTP请求-响应模型对于需要连续、低延迟数据交换的AI场景来说效率低下,因为频繁建立连接会引入过高开销。

因此,MCP从一开始就采用了更适合实时数据推送的传输机制。最初,它依赖HTTP+SSE来实现服务器到客户端的流式传输。然而,这种组合在实践中暴露出一些局限性:

  • 不支持连接中断后的流恢复。
  • 要求服务器为每个客户端维护一个长期存活的连接,消耗资源。
  • 通信方向受限:数据仅能通过SSE从服务器流向客户端,客户端需使用额外的HTTP POST通道发送请求。

HTTP+SSE工作流程示意图

Streamable HTTP 的引入正是为了解决上述问题。它支持无状态通信,并可按需升级到SSE以进行流式推送,从而提高了与现代云原生基础设施的兼容性,确保了更稳定、高效的通信体验。目前,主流MCP库在支持新协议的同时,仍保持对旧版HTTP+SSE的向后兼容。

深入剖析被替代的HTTP+SSE

服务器发送事件(SSE)是一种允许Web客户端通过一个持久HTTP连接接收服务器自动更新的技术。与双向的WebSocket不同,SSE是单向的,专用于服务器到客户端的消息推送。

在MCP的旧版实现中,一个典型的HTTP+SSE服务架构要求服务器提供两个端点:

  1. 一个 SSE (GET) 端点:用于客户端建立连接并接收服务器消息流。
  2. 一个 RPC (POST) 端点:用于客户端向服务器发送JSON-RPC请求。

当客户端连接到SSE端点时,服务器会立即通过该连接发送一个特殊的endpoint事件,告知客户端其专属的RPC端点URI。此后,所有客户端的请求都通过向该URI发送POST请求来完成,而服务器的响应则通过原先的SSE连接流式传回。

以下是一个简化的Node.js与浏览器代码示例,展示了HTTP+SSE模式下的基本交互:

服务器端 (Node.js with Express)

const express = require("express");
const app = express();
const PORT = 3000;

let clients = new Map(); // 存储客户端连接

// SSE连接端点
app.get("/sse", (req, res) => {
  const clientId = Date.now().toString();
  res.writeHead(200, {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache",
    Connection: "keep-alive",
  });
  // 为客户端分配唯一的RPC端点
  const rpcEndpoint = `/rpc/${clientId}`;
  res.write(`event: endpoint\ndata: {"uri": "${rpcEndpoint}"}\n\n`);
  clients.set(clientId, { res });
  req.on("close", () => clients.delete(clientId));
});

// 动态RPC端点
app.post("/rpc/:clientId", (req, res) => {
  const { clientId } = req.params;
  const client = clients.get(clientId);
  if (!client) return res.status(404).json({ error: "Client not found" });
  // 处理请求并通过SSE连接返回响应
  const response = { jsonrpc: "2.0", id: req.body.id, result: "pong" };
  client.res.write(`data: ${JSON.stringify(response)}\n\n`);
  res.json({ status: "received" });
});

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

客户端 (Browser JavaScript)

let eventSource;
let rpcEndpoint = null;

function connectSSE() {
  eventSource = new EventSource("/sse");
  eventSource.addEventListener("endpoint", (event) => {
    rpcEndpoint = JSON.parse(event.data).uri;
  });
  eventSource.onmessage = (event) => {
    console.log("Server response:", JSON.parse(event.data));
  };
}

function sendPing() {
  if (!rpcEndpoint) return;
  fetch(rpcEndpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", method: "ping", id: 1 })
  });
}
window.addEventListener("load", connectSSE);

HTTP+SSE的优缺点总结:

  • 优点:支持流式传输大结果;允许服务器主动推送事件;基于标准HTTP协议,实现相对简单。
  • 缺点:本质是单向通信,需要双通道;长连接对服务器资源消耗大;不支持断线重连后的流恢复。

新一代方案:Streamable HTTP 是什么?

Streamable HTTP是一种更灵活的数据流传输方法,它基于纯HTTP协议,无需强制建立长连接即可实现实时通信。虽然它仍可可选地使用SSE来支持流式推送,但这不再是必选项。这使得MCP服务器可以设计为无状态的,彻底摆脱维护大量持久连接的开销。

MCP选择Streamable HTTP而非WebSocket,主要基于以下考虑:

  1. 协议开销:对于无状态RPC调用,WebSocket显得过于重量级。
  2. 协议友好性:SSE和标准HTTP工具(如curl)更易调试和集成,而WebSocket则不然。
  3. 灵活性:WebSocket的升级机制仅适用于GET请求,使得基于POST的流程复杂化。

在Streamable HTTP模式下,服务器只需暴露一个统一的HTTP端点(支持POST和GET)。通信流程变得更加简洁和高效:

  • 客户端请求:通过HTTP POST发送JSON-RPC请求。
  • 服务器响应:可以直接在POST响应体中返回结果(简单RPC),也可以通过返回一个“流ID”并建议客户端使用SSE GET来订阅流式结果(复杂或持续响应)。

Streamable HTTP工作流程示意图

为了支持流恢复,服务器会为每个流分配唯一ID,客户端可以凭此ID重新连接并获取中断后的消息。

Streamable HTTP的核心优势:

  • 无状态友好:服务器无需维护会话状态,易于水平扩展。
  • 基础设施兼容:完美兼容HTTP负载均衡器、代理和所有主流托管平台。
  • 纯HTTP:减少对特定协议(SSE)的依赖,使用标准HTTP工具即可进行测试和调试
  • 向后兼容:易于从HTTP+SSE架构平滑迁移。
  • 灵活流式传输:可按需升级到SSE,实现真正的双向流式通信。

目前,官方MCP SDK(@modelcontextprotocol/sdk)已内置了对Streamable HTTP的完整支持。开发者无需手动处理底层通信细节,可以专注于实现业务逻辑。以下是一个使用官方SDK创建支持流式响应工具的示例:

import { McpServer, createStream } from "@modelcontextprotocol/sdk/server/mcp.js";

const server = new McpServer({ name: "streaming-demo", version: "1.0.0" });

// 注册一个流式工具
server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;
  if (name === "streamEcho") {
    return createStream(async (stream) => {
      const message = args?.message || "Hello";
      for (let i = 0; i < message.length; i++) {
        // 发送部分结果,形成流式响应
        await stream.partial({
          content: [{ type: "text", text: message[i] }],
        });
        await new Promise((r) => setTimeout(r, 200)); // 模拟延迟
      }
      // 发送最终结果
      await stream.final({
        content: [{ type: "text", text: `Echo: ${message}` }],
      });
    });
  }
  throw new Error(`Unknown tool: ${name}`);
});

// 启动服务器,SDK会自动处理Streamable HTTP传输
server.listen();

总结:从HTTP+SSE到Streamable HTTP的演进,反映了MCP协议为适应大规模、云原生AI应用场景所做的努力。新的传输机制通过拥抱无状态设计和纯标准HTTP协议,提供了更好的兼容性、可扩展性和开发者体验,为AI智能体与广阔数字世界的连接奠定了更稳固的基础。


参考资料

  • Antonello Zanini. 《SSE vs Streamable HTTP: The Transport Technologies Behind MCP》
  • MDN Web Docs. 《Using server-sent events》



上一篇:阿里云Tair KVCache与SGLang联合构建HiCache:面向智能体推理的缓存新范式
下一篇:ARP协议深度解析:为什么IP到MAC地址转换是网络通信的基石?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 17:48 , Processed in 0.150997 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表