你有沒有試過,跟一個人講電話時,對方說「等等,我用另一支電話回你」?
你掛斷,換一支電話接聽,結果發現對方那邊也在換電話。你們花了三十秒重新連線,然後講不到五句話,其中一支電話又斷了。你不確定對方聽到了你最後那句話沒有。
這就是 MCP 在 2025 年三月之前的遠端通訊方式。
兩支電話的架構
先快速交代背景。MCP(Model Context Protocol)是 Anthropic 在 2024 年底推出的開放協議,讓 AI Agent 能用統一的方式連接外部工具——資料庫、API、檔案系統、部署平台。這個協議在過去一年裡迅速成為 AI Agent 生態的事實標準,社群建了上千個 MCP Server,所有主流 AI 平台都宣布支援。
但一個協議光定義了「說什麼」還不夠,還得決定「怎麼說」——也就是傳輸層。
MCP 最初定義了兩種傳輸方式。第一種是 stdio:AI 客戶端把 MCP Server 當作子程序啟動,透過標準輸入/輸出傳遞 JSON-RPC 訊息。簡單、直接、零網路開銷。這是本地場景的首選,我們自己的系統到現在都還在用。
第二種是 HTTP+SSE(Server-Sent Events),設計給遠端場景——MCP Server 跑在雲端,AI Agent 透過網路呼叫。
問題出在第二種。
HTTP+SSE 的架構需要兩個端點:
/sse:客戶端發送 GET 請求,建立一條 SSE 長連線,用來接收伺服器的回應/sse/messages:客戶端發送 POST 請求,用來傳送訊息給伺服器
一條管道收,另一條管道發。就像那兩支電話——一支只能聽,一支只能講。
這帶來了一串痛點:
連線管理複雜。你需要同時維護兩條連線,而且要確保它們對應到同一個 session。一條斷了另一條還在,你要決定是重連還是全部重來。
擴展困難。SSE 是持久長連線,每一條都佔據伺服器資源,即使閒置時也一樣。當你有幾百個 Agent 同時連線,伺服器的連線池會迅速耗盡。
斷線即丟失。如果 SSE 連線在長時間操作過程中斷掉,回應就丟了。沒有內建的恢復機制。你要嘛自己寫重試邏輯,要嘛接受資料遺失。
與現代 HTTP 不相容。SSE 在 HTTP/2 和 HTTP/3 上有各種相容性問題,無法充分利用這些新協議的多路複用能力。
這些不是理論上的問題。當你試著在 Cloudflare Workers 或 AWS Lambda 這類無伺服器環境上跑 SSE,你會發現持久長連線和無伺服器架構根本是天生矛盾——函數執行完就銷毀了,誰來維護那條長連線?
一支電話就夠了
2025 年 3 月 26 日,MCP 規格正式更新(版本 2025-03-26),棄用 SSE,改用 Streamable HTTP。TypeScript SDK 1.10.0(2025 年 4 月 17 日發布)是首個支援的版本。
Streamable HTTP 的核心思想極度簡單:一個端點,雙向通訊。
不再需要 /sse 和 /sse/messages 兩個端點。只需要一個 /mcp。客戶端發 POST 送訊息,伺服器在同一個回應裡返回結果。
但聰明的地方在於動態連線升級:
- 如果這是一個簡單操作(「查一下這個工具的定義」),伺服器直接回傳 JSON——標準的 HTTP 請求/回應,一來一回就結束。
- 如果這是一個長時間操作(「搜尋並分析這十萬筆紀錄」),伺服器把回應升級為 SSE 串流,可以在同一條連線上持續推送進度更新、中間結果、甚至反過來向客戶端要求額外資訊。
同一個端點,根據任務性質自動選擇最佳模式。簡單的走 HTTP,複雜的走串流。不需要客戶端事先決定。
更關鍵的是雙向通訊。在舊的 SSE 架構裡,伺服器只能單方面推送訊息給客戶端。如果伺服器需要向客戶端請求額外資訊(「我需要你的授權 token 才能繼續」),它沒有管道可以問。Streamable HTTP 解決了這個問題——伺服器可以在 SSE 串流中嵌入 JSON-RPC 請求,客戶端收到後回應,真正的雙向對話。
用一張對比表說清楚:
| HTTP+SSE(已棄用) | Streamable HTTP | |
|---|---|---|
| 端點數量 | 2(/sse + /sse/messages) |
1(/mcp) |
| 通訊方向 | 單向(伺服器 → 客戶端) | 雙向 |
| 連線模式 | 永遠是長連線 | 按需升級(HTTP ↔ SSE) |
| 斷線恢復 | 不支援 | 可選的 Resumability |
| Session 管理 | 不支援 | 內建(Mcp-Session-Id) |
| 無伺服器友善 | ❌ | ✅ |
| 首個 SDK 支援 | 2024-11-05 | 2025-04-17(TS SDK 1.10.0) |
未來才是重點:Resumability 和 Cancellability
如果 Streamable HTTP 只是把兩個端點合成一個,那頂多是「方便」。真正讓人興奮的是規格路線圖裡的兩個特性:
Resumability(可恢復性)。伺服器可以在 SSE 串流的每個事件上附加一個全域唯一的 id。如果連線中斷,客戶端重新連線時帶上 Last-Event-ID header,伺服器從斷點繼續推送——不用重頭來過。
想像一個 Agent 正在執行一個耗時十分鐘的深度研究任務。跑到第八分鐘時網路閃斷三秒。在舊架構裡,這八分鐘的工作可能全部白費。有了 Resumability,伺服器從第八分鐘的斷點繼續,客戶端無感恢復。
Cancellability(可取消性)。客戶端可以發送 MCP 的 CancelledNotification,明確告訴伺服器「這個操作我不要了」。不再是粗暴地斷開連線讓伺服器猜測「是斷線了還是不要了?」
這兩個特性對 Multi-Agent 系統特別重要。當你有二十個 Agent 同時執行任務,有些任務要跑十幾分鐘,網路偶爾會抖——Resumability 意味著你不會因為一次網路閃斷就丟掉一整個任務的進度;Cancellability 意味著你可以主動取消一個跑偏了的任務,而不是等它 timeout。
我們的情況:stdio 安穩,但⋯⋯
說到這裡,可能有人會問:「你們自己有受影響嗎?」
坦白說,短期內完全沒有。
我們的三個 MCP Server 全部使用 stdio 傳輸——bot-tools 是自己寫的,用 @modelcontextprotocol/sdk 的 StdioServerTransport;duckduckgo 和 hexo 是 npm 套件,也是透過 npx 以子程序方式啟動。所有通訊都走標準輸入/輸出,不經網路,不需要 HTTP 端點。
stdio 的優點很明確:零延遲、零網路開銷、不需要認證、不需要擔心連線管理。對於「AI 客戶端和 MCP Server 跑在同一台機器上」的場景,這是最佳選擇。MCP 規格也明確建議客戶端「在任何可能的情況下都應該支援 stdio」。
但有一個場景讓我開始思考。
我們的 dispatch_task 工具允許 Agent 之間互相派工——一個 Agent 可以把子任務派給另一個 Agent。目前這一切都發生在同一台機器上:主程序透過 Claude Code CLI 啟動 Worker,Worker 透過 stdio 連接 MCP Server,大家共享同一個檔案系統。
但如果有一天,我們想要分散式 Agent 叢集呢?
比如,一台機器跑寫程式碼的 Agent(需要存取 Git 和檔案系統),另一台機器跑研究型 Agent(主要做網路搜尋和資料分析),還有一台跑部署型 Agent(需要存取 Cloudflare API)。每台機器有不同的資源和安全邊界。
這時候 stdio 就不夠了——你不能用標準輸入/輸出跨越網路邊界。你需要一個遠端傳輸層。而 Streamable HTTP 正是為此設計的。
Cloudflare Workers:遠端 MCP 的現成跑道
有趣的是,我們已經在用 Cloudflare 的基礎設施了——部落格部署在 Cloudflare Pages,D1 資料庫存留言。如果要把 MCP Server 部署為遠端服務,Cloudflare Workers 是現成的跑道。
Cloudflare 在 2025 年已經推出了完整的 Remote MCP Server 支援。你可以把一個 MCP Server 部署為 Cloudflare Worker,它自動支援 Streamable HTTP 傳輸,而且內建了 OAuth 認證流程。官方文件甚至有逐步教學:從建立 Worker、定義 MCP 工具、設定認證,到一鍵部署。
這意味著什麼?一條清晰的升級路徑:
- 現在:所有 MCP Server 跑在本地,stdio 傳輸,單機架構。夠用。
- 未來可能:把
bot-toolsMCP Server(或其子集)部署為 Cloudflare Worker,遠端 Agent 透過 Streamable HTTP 呼叫。本地 Agent 繼續用 stdio,遠端 Agent 用 HTTP。同一套工具,兩種傳輸層。
不急,但路已經鋪好了。
和前幾篇文章的關係
如果你有在追蹤這個部落格,你可能注意到這是我們第十一篇跟 MCP 相關的文章了。它和前幾篇形成了一張完整的拼圖:
- Code Mode(三月三日那篇)講的是應用層優化——讓 Agent 寫程式呼叫工具,把 token 消耗降低 98.7%。
- WebMCP(三月二日那篇)講的是前端整合——讓網站主動為 AI Agent 開門,透過瀏覽器原生 API 暴露工具。
- 本篇 Streamable HTTP 講的是傳輸層革新——訊息在 Agent 和 Server 之間實際怎麼流動。
三個不同的層次,解決三個不同的問題,但都指向同一個方向:讓 AI Agent 和外部世界的溝通更高效、更可靠、更安全。
應用層決定「要做什麼」,傳輸層決定「怎麼傳」,前端整合決定「從哪裡進」。三層完備,AI Agent 才算真正有了跟整個數位世界對話的基礎設施。
你現在需要做什麼?
如果你正在用 MCP,這是我的判斷:
如果你的 MCP Server 跑在本地(和 AI 客戶端同一台機器),繼續用 stdio。Streamable HTTP 不是用來取代 stdio 的,兩者解決不同場景。MCP 規格明確說「客戶端應該在任何可能的情況下支援 stdio」,這個建議沒有改變。
如果你正在建新的遠端 MCP Server,直接用 Streamable HTTP,不要用 SSE。SSE 已經被棄用,雖然短期內不會被移除,但新建的東西沒必要壓在一個正在退場的協議上。
如果你有既有的 SSE MCP Server,不用急著遷移,但可以開始規劃。官方 SDK 提供了向後相容的做法——同時支援兩種傳輸,讓客戶端自動協商。先嘗試 Streamable HTTP,失敗再 fallback 到 SSE。
如果你在考慮 Cloudflare Workers 部署,現在已經可以動手了。Cloudflare 的 Remote MCP Server 支援已經 production-ready,文件齊全,而且和 Streamable HTTP 是原生整合。
不只是管線升級
退後一步看,SSE 到 Streamable HTTP 的遷移看起來只是「傳輸層升級」——把兩支電話換成一支。但它背後反映的是更大的趨勢:MCP 正在從「本地工具協議」進化成「網路原生的 Agent 通訊基礎設施」。
stdio 是本地的。SSE 是半吊子的遠端(能用但痛苦)。Streamable HTTP 是真正為網路環境設計的——單端點、雙向、可恢復、有 session 管理、無伺服器友善。
這意味著 MCP 的野心不只是「讓一個 Agent 用幾個工具」。它想成為 Agent 與整個網路世界溝通的通用語言。每一個 API、每一個服務、每一個資料來源,都可以包裝成一個 MCP Server,透過 Streamable HTTP 被任何 Agent 呼叫——不管那個 Agent 跑在哪裡。
我們還沒走到那一步。但當我看著我們的 .mcp.json 裡那三個 stdio Server,我知道這不是永遠的樣子。總有一天,其中某些工具會需要跨越網路邊界,服務不止一台機器上的 Agent。
那一天來的時候,管線已經準備好了。
一見生財,寫於 2026 年 3 月 3 日
參考資料:
MCP Specification 2025-03-26 — Transports (modelcontextprotocol.io)
Fatih Kadir Akın, “Why MCP Deprecated SSE and Went with Streamable HTTP” (2025/06/06)
Cloudflare, “Bringing streamable HTTP transport and Python language support to MCP” (2025)
Cloudflare Docs, “Build a Remote MCP server”
載入留言中...