MCP stateless vs stateful 差在哪?一張對照表 + 決策樹,決定你的 server 怎麼部署

2026-07-28 之後,MCP 協定層的 stateful 已經被拿掉了。這篇用一張四維對照表和一棵決策樹,帶你決定自己的 MCP server 該怎麼部署、狀態該搬到哪裡去。

MCP stateless vs stateful 差在哪?一張對照表 + 決策樹,決定你的 server 怎麼部署

先把答案給你,你趕時間的話看完這段就可以走。

Stateful(有狀態)是 MCP(Model Context Protocol,模型上下文協定)2026-07-28 規格之前的預設玩法:client 一連上來要先跑 initialize 握手,server 記住這個 session,之後每次呼叫都靠這份記憶接上。Stateless(無狀態)是 2026-07-28 規格之後的預設:協定層的 session 沒了,Mcp-Session-Id 這個 header 也被拿掉,每一個 request 自己帶齊該帶的東西,任何一台健康的機器都能接任何一個請求。

重點是什麼?

「選哪個」這題已經沒得選了。你真正要決定的,是狀態該搬到哪裡去。

協定層的 stateful 被官方直接收掉了。你以為自己在做架構選型,其實你在做遷移規劃。這篇就是把兩邊攤開比一次,然後給你一棵決策樹。

一張四維對照表

維度 Stateful(2026-07-28 之前) Stateless(2026-07-28 之後的預設)
狀態管理 initialize / notifications/initialized 握手建立 session,server 端記住 client 的能力與協定版本,整段連線共用 握手取消。每個 request 自己在 _metaio.modelcontextprotocol/protocolVersionclientCapabilities。server MUST 實作 server/discover 讓 client 查能力
部署(serverless / edge) 難。client 的 session 綁死在特定一台 instance 上,L4/L7 輪詢的負載平衡會把請求送到沒有狀態的機器,只能靠 sticky session 硬綁 任一台 instance 都能服務任一個 request。橫向擴展、autoscaling、failover 全部變單純。list 類結果還多了 ttlMscacheScope,中介層可以快取
Session 處理 Mcp-Session-Id header 追蹤;SSE 斷線可以用 Last-Event-ID 續傳補訊息 協定層 session 與 Mcp-Session-Id 移除。SSE 續傳一起被移除,斷線等於這個 request 直接掉,client 要用新的 request ID 重送。要持久化請改用 tasks 擴充
適用場景 舊 connector 在落日窗內續命。server MAY 同時實作新舊兩套撐過渡期 新建的 server 一律 stateless first。查詢型、工具型、要應付流量尖峰的服務

資料來源:SEP-2575: Make MCP StatelessMCP 2026-07-28 規格變更紀錄

Stateful 與 Stateless 的四個維度對照:狀態被關在容器裡或由請求自己帶著走、單一機器扛下全部負載或多台平均分擔、一條被夾住的長連線或四段各自完整的短請求、一個客製化形狀卡死在專屬插槽或四塊可以互換的通用磚

表格看完,我幫你拆三個 So What。

第一,這次改版的主軸是拆東西。 pinglogging/setLevelnotifications/roots/list_changed 直接移除。HTTP GET endpoint 移除,全部走 POST。resources/subscriberesources/unsubscribe 換成 subscriptions/listen,而且要明確 opt-in 你想收哪幾種通知,沒勾的 server MUST NOT 送。

第二,沒有握手,代表每一個 request 都要獨立認證授權。 官方在安全章節寫得很白:實作者必須確保認證不會因為初始化階段消失而被繞過。這句話對你的意義是,如果你的舊 server 是「握手時驗一次、之後就信任這條連線」,那不只是改個 flag 的事。

第三,斷線的語意變了。 以前 SSE 斷掉可以續傳,現在關掉 SSE stream 在 HTTP 上直接被視為取消這個請求。這對長時間跑的工具影響最大。

商業類比:從百貨熟客制,變成超商取貨編號

我在百貨專櫃當過櫃哥,那個年代的服務邏輯是熟客制:客人的尺寸、偏好、上次買什麼,全部在櫃姐腦袋裡。客人回來報個名字就接得上,體驗確實好。但這套有個死穴,就是換班。那位記得你的人今天休假,或者離職了,這段關係等於重來。

Stateful 的 MCP server 就是這套邏輯。狀態在那台機器的記憶體裡,機器掛了、被 autoscaling 收掉了,session 就沒了。

Stateless 是超商店到店取貨的邏輯。店員完全不認識你,也不需要認識你。你報一組取貨編號,全台灣任何一家門市、任何一個班別的店員都處理得了。

狀態不在店員腦袋裡,在你手上那串號碼。

這串號碼在 MCP 新規格裡有正式名字,叫 state handle(狀態控制碼)。MCP 核心維護者在 sessions-vs-sessionless 的決議文件裡講得很直接:需要跨呼叫狀態的 server,改由 server 鑄造一個明確的 handle,當成一般的 tool 參數讓 client 傳回來。文件裡舉的例子就是購物車:create_basket() 回你一個 { "basket_id": "bsk_a1b2c3" },之後每次加商品都把這個 id 帶上。

做電商的看到這個應該會心一笑,這不就是訂單編號嗎。

具體場景:雙十一晚上十點,你的 MCP server 在幹嘛

想像一下,雙十一晚上十點,你們家的訂單查詢 MCP server 被客服 agent 打爆。

以前,你的 server 是 stateful 的,每個 client 連進來先握手、綁一個 session。流量上來你想加機器,但新開的 instance 接不到活,因為既有的 session 全綁在原本那幾台上。負載平衡器只能靠 sticky session 硬撐,結果是舊機器過載、新機器閒置。更糟的是某台掛掉,那台上面所有的 session 一起陪葬,client 得重連、重握手、重新開始。

現在,stateless 之下每個請求自帶身分與能力宣告,你開十台就有十台在做事,掛一台就少一台,不會有人陪葬。查詢類的 list 結果還能靠 ttlMs 讓中介層快取,尖峰時打到你 server 的量直接少一截。

這就是為什麼這次改版會被講成「MCP 終於能上 serverless」。想看完整的規格變動與落日名單,我在 MCP stateless 新規格解讀 那篇寫得比較細,這裡就不重複。

決策樹:什麼時候該選哪個

切入重點,你只要回答三個問題。

問題一:這台 server 是新蓋的嗎?

是 → stateless,沒有第二個選項。 新規格就是這樣,不用糾結。

否 → 往下。

問題二:舊 server 還在跑 initialize 握手,會馬上壞掉嗎?

不會,短期內都還能跑。官方的 feature lifecycle 政策訂了最短 12 個月的 deprecation window,而且明確允許 server MAY 同時實作舊的 initialize 和新的 stateless RPC,兩邊客戶都接得住。所以答案是:能跑,但要排進行事曆,不要排在最後一個月。

問題三:你的 server 真的需要跨呼叫的狀態嗎?

這題才是重點。答案不同,停車位不同:

MCP 新規格允許狀態停放的四個位置:當成參數夾帶在請求上的 state handle、需要輪詢才拿得到結果的 tasks 擴充、持續推送變更的訂閱長連線、以及什麼都不留的直通呼叫;下方第五個入口是已被封閉的協定層 session,路線在半途就中斷

► 不需要(查詢、報表、單次工具呼叫)
純 stateless,直接上 serverless 或 edge。這是最大宗,也最省事。像廣告報表這種一次問一次答的場景,本來就沒在記東西,可以參考我寫過的 Google Ads MCP 實戰

► 需要,而且是業務狀態(購物車、資料庫連線、多步驟流程)
用 state handle。server 發編號,client 當參數傳回來。狀態進你自己的 Redis 或資料庫,不進協定層。

► 需要,而且是「跑很久、斷線後還要回來拿結果」
用 tasks 擴充。tasks 這次被移出核心協定,變成官方擴充 io.modelcontextprotocol/tasks,改用 tasks/get 輪詢。官方講得很明白:需要持久化或可續傳的工作,必須走 tasks,因為 SSE 續傳已經沒了。

► 需要,而且是「server 要主動推變更通知」
subscriptions/listen,開一條長連線,明確勾選你要收 toolsListChangedresourcesListChanged 還是特定資源的更新。

還有一個是「不要往這裡停」:Roots、Sampling、Logging 三個功能這次被標記為 Deprecated,新專案不要再採用。官方建議的替代作法分別是用 tool 參數或 resource URI 傳目錄、直接接 LLM 供應商的 API、以及用 stderr 或 OpenTelemetry 做日誌。同一批進落日名單的還有 HTTP+SSE transport 和 OAuth 2.0 動態註冊(DCR)。

幾個你可能會問的問題

Q:我現有的 stateful server 明天會壞掉嗎?
不會。12 個月是官方政策訂的最短窗口,而且允許新舊並行。但這是 MCP 第一次真的拿掉東西,過去的版本都是往上加,心態要調整。

Q:沒有 session 了,購物車狀態放哪?
放你自己家。server 發一個 basket_id 之類的 handle 回去,client 每次帶著。協定不幫你記,但也因此不再限制你要記在哪台機器上。

Q:stateless 是不是代表不能做有狀態的應用?
不是。官方 FAQ 引 HTTP 當例子:HTTP 是無狀態協定,整個網路都建在上面。差別在於狀態不能存在協定本身,要嘛放進請求裡,要嘛放一個指向狀態的參照。

Q:那 sampling 和 elicitation 怎麼辦?
改走 MRTR(Multi Round-Trip Requests,多輪往返請求)。server 不再主動送請求給 client,而是回一個 resultType: "input_required" 的結果,把需要的東西列在 inputRequests 裡,client 補完再重送原本那個請求。想搞懂 agent 端這層怎麼接,可以看 Agent Harness 是什麼

這週可以做的四件事

盤點你手上所有 MCP server,標記哪些用到了 initialize 握手、Mcp-Session-IdLast-Event-ID 續傳、pingresources/subscribe 這五個是這次動最大的地方,先知道自己欠多少債。

把每一台 server 的狀態需求歸類到四個停車位之一(不需要 / state handle / tasks / subscriptions/listen)。歸不進去的那幾台,就是你真正要花時間重新設計的。

檢查你的認證是不是「握手時驗一次就信任整條連線」。 是的話,這條要優先改,因為它同時是相容性問題和資安問題。

把 12 個月的落日日期寫進行事曆,往前抓三個月當緩衝。 不是我說,遷移這種事永遠比估的久,而且這次是拆東西不是加東西,測試面積比你想的大。

如果你問我,這次改版對台灣電商團隊其實是好消息。以前要自建一台 MCP server 給內部 agent 用,光是 session 管理、記憶體回收、sticky session 的基礎設施成本就先勸退一半的人。現在一個 stateless 的 server 可以直接丟上雲端函式,流量來了自己長,沒流量就縮回去。

門檻降下來了,剩下的問題就變成你想讓 agent 幫你做什麼。

協作聲明與免責

這篇文章由王董與 AI 一起整理製作完成。文中引用的第三方資料、研究或工具都會標註來源名稱;若原始出處有公開連結,會以 [來源名稱](URL) 形式附上,方便你進一步查找。若文中內容與原始出處有任何出入,請以原文為準。

內容僅供參考與學習交流,不構成任何專業、商業或投資建議,請依自身情況判斷並自行承擔行動風險。文中提及的工具功能、數據與平台政策可能隨時間異動,請以各官方最新公告為準。

Read more

我連發了十幾篇 AI 教學,但那些招式單獨拿走一點用都沒有:讀 Dan Koe〈策略思考的藝術〉

我連發了十幾篇 AI 教學,但那些招式單獨拿走一點用都沒有:讀 Dan Koe〈策略思考的藝術〉

我這陣子連發了十幾篇 AI 工具與教學文,然後讀到 Dan Koe 這篇長文,他開場點名的例子就是「Instagram 上爆紅的最新 Claude Code skill」。他的指控是:收集招式是一種更陰險的廉價多巴胺。這篇把話講開,並用一盤棋跟一個百貨櫃位,說明為什麼同一份技巧在不同人手上結果差那麼多。

By Lewis wang
關小的閥門:把紅色折扣標籤擋在上游,讓下游只流出全價商品

Nike 2026 財報解讀:主動砍 20 億美元經典款供給,把全價銷售救回來

Nike 在營收持平的一年,主動把經典款在市場上的供給砍掉超過 20 億美元,而期末存貨 75 億美元仍與去年持平。動的不是倉庫,是「這一季放多少貨進市場」那個閥門。歐洲把出清渠道砍掉一半以上,換回 15 個百分點的全價實現率。這篇拆解口徑、拆解代價,也給台灣電商三道判斷閘門與五個可以這週就做的動作。

By Lewis wang