這個 Pull Request (#206) 提出了一個名為 "可流式 HTTP" (Streamable HTTP)的新傳輸協(xié)議,用于替代 MCP (Model Context Protocol) 當前使用的 HTTP+SSE 傳輸方式。這是一個重要的技術(shù)改進,旨在解決現(xiàn)有傳輸方式的一些關(guān)鍵限制,同時保留其優(yōu)勢。
地址:https://github.com/modelcontextprotocol/specification/pull/206
主要變更點
與當前的 HTTP+SSE 傳輸相比,新提案做出了以下改變:
1. 移除了?/sse
端點
2. 所有客戶端→服務器的消息都通過?/message
(或類似)端點傳輸
3. 所有客戶端→服務器的請求可以被服務器升級為 SSE,用于發(fā)送通知/請求
4. 服務器可以選擇建立會話 ID 來維持狀態(tài)
5. 客戶端可以通過向?/message
發(fā)送空 GET 請求來初始化 SSE 流這種方法可以向后兼容實現(xiàn),并允許服務器在需要時完全無狀態(tài)運行。
解決的問題
當前的 HTTP+SSE 傳輸存在以下限制:
- ? 不支持可恢復性? 要求服務器維護高可用性的長連接? 服務器消息只能通過 SSE 傳遞
新方案的優(yōu)勢
支持無狀態(tài)服務器?- 不再需要高可用性的長連接
純 HTTP 實現(xiàn)?- MCP 可以在普通 HTTP 服務器上實現(xiàn),不一定需要 SSE
基礎設施兼容性?- 因為"只是 HTTP",確保與中間件和基礎設施兼容
向后兼容?- 這是對當前傳輸方式的漸進式演進
靈活的升級路徑?- 服務器可以在需要時選擇使用 SSE 進行流式響應
使用場景示例
無狀態(tài)服務器
提案支持完全無狀態(tài)的服務器實現(xiàn),無需支持長連接:
1. 始終確認初始化(但無需保留任何狀態(tài))
2. 對任何傳入的?ToolListRequest
用單個?JSON-RPC
響應
3. 處理?CallToolRequest
時執(zhí)行工具,等待完成,然后發(fā)送單個?CallToolResponse
作為 HTTP 響應體
帶流式處理的無狀態(tài)服務器
即使是完全無狀態(tài)且不支持長連接的服務器,在這個設計中仍然可以利用流式處理:
1. 當收到?CallToolRequest
時,服務器指示響應將是 SSE
2. 服務器開始執(zhí)行工具
3. 工具執(zhí)行過程中,服務器通過 SSE 發(fā)送任意數(shù)量的?ProgressNotification
4. 工具執(zhí)行完成后,服務器通過 SSE 發(fā)送?
CallToolResponse
5. 服務器關(guān)閉 SSE 流
有狀態(tài)服務器
有狀態(tài)服務器的實現(xiàn)與現(xiàn)在非常相似,主要區(qū)別是服務器需要生成會話 ID,客戶端需要在每個請求中傳回該 ID。服務器可以使用會話 ID 進行粘性路由或在消息總線上路由消息。
為什么不使用 WebSocket
團隊詳細討論了將 WebSocket 作為主要遠程傳輸方式的可能性,但最終決定不采用,原因包括:
-
- 1. 對于"RPC 式"使用場景,WebSocket 會帶來不必要的運營和網(wǎng)絡開銷2. 在瀏覽器中,無法為 WebSocket 附加頭信息(如
Authorization
- ),且第三方庫無法在瀏覽器中從頭實現(xiàn) WebSocket3. 只有 GET 請求可以透明升級為 WebSocket,這意味著在 POST 端點上需要兩步升級過程,增加復雜性和延遲
團隊也避免將 WebSocket 作為規(guī)范中的額外選項,以限制 MCP 官方指定的傳輸方式數(shù)量,避免客戶端和服務器之間的組合兼容性問題。
待辦事項
? 將會話 ID 責任轉(zhuǎn)移到服務器
? 定義可接受的會話 ID 空間
? 確保中間件/WAF 可以內(nèi)省會話 ID
? 使取消操作明確化
? 要求集中式 SSE GET 用于服務器→客戶端請求和通知
? 將可恢復性轉(zhuǎn)換為每個流的概念
? 設計主動"結(jié)束會話"的方式
? "如果客戶端有認證令牌,應在每個 MCP 請求中包含它"
后續(xù)工作
- ? 標準化對 JSON-RPC 批處理的支持? 支持流式請求體? 在規(guī)范中加入關(guān)于超時的建議,可能還會制定約定,如"發(fā)出進度通知應重置默認超時"
這個提案是在廣泛社區(qū)討論和反饋的基礎上形成的,表明 MCP 正在積極發(fā)展以滿足更廣泛的使用場景需求。