> ## Content Index
> Fetch the complete content index at: https://growthhackers.tw/llms.txt
> Use this file to discover other available public pages before exploring further.

# MCP stateless vs stateful 差在哪？一張對照表 + 決策樹，決定你的 server 怎麼部署
- URL: https://growthhackers.tw/blog/mcp-stateless-vs-stateful/
- Published: 2026-08-08T14:49:10.000Z
- Updated: 2026-08-08T14:49:10.000Z
- Description: 2026-07-28 之後，MCP 協定層的 stateful 已經被拿掉了。這篇用一張四維對照表和一棵決策樹，帶你決定自己的 MCP server 該怎麼部署、狀態該搬到哪裡去。
- Author: Lewis wang
- Tags: MCP, AI agent, 技術決策, Serverless, API 設計

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

**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 自己在 \_meta 帶 io.modelcontextprotocol/protocolVersion 和 clientCapabilities。server **MUST** 實作 server/discover 讓 client 查能力 |
| **部署（serverless / edge）** | 難。client 的 session 綁死在特定一台 instance 上，L4/L7 輪詢的負載平衡會把請求送到沒有狀態的機器，只能靠 sticky session 硬綁 | 任一台 instance 都能服務任一個 request。橫向擴展、autoscaling、failover 全部變單純。list 類結果還多了 ttlMs 和 cacheScope，中介層可以快取                                       |
| **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 Stateless](https://modelcontextprotocol.io/seps/2575-stateless-mcp?ref=growthhackers.tw) 與 [MCP 2026-07-28 規格變更紀錄](https://modelcontextprotocol.io/specification/latest/changelog?ref=growthhackers.tw)。

![Stateful 與 Stateless 的四個維度對照：狀態被關在容器裡或由請求自己帶著走、單一機器扛下全部負載或多台平均分擔、一條被夾住的長連線或四段各自完整的短請求、一個客製化形狀卡死在專屬插槽或四塊可以互換的通用磚](https://growthhackers.tw/content/images/2026/08/inline-four-dimensions-v1.png)

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

**第一，這次改版的主軸是拆東西。** `ping`、`logging/setLevel`、`notifications/roots/list_changed` 直接移除。HTTP GET endpoint 移除，全部走 POST。`resources/subscribe` 和 `resources/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 新規格解讀](https://growthhackers.tw/blog/mcp-stateless-core-spec/) 那篇寫得比較細，這裡就不重複。

## 決策樹：什麼時候該選哪個

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

**問題一：這台 server 是新蓋的嗎？**

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

否 → 往下。

**問題二：舊 server 還在跑 `initialize` 握手，會馬上壞掉嗎？**

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

**問題三：你的 server 真的需要跨呼叫的狀態嗎？**

這題才是重點。答案不同，停車位不同：

![MCP 新規格允許狀態停放的四個位置：當成參數夾帶在請求上的 state handle、需要輪詢才拿得到結果的 tasks 擴充、持續推送變更的訂閱長連線、以及什麼都不留的直通呼叫；下方第五個入口是已被封閉的協定層 session，路線在半途就中斷](https://growthhackers.tw/content/images/2026/08/inline-state-parking-v1.png)

**► 不需要（查詢、報表、單次工具呼叫）**  
純 stateless，直接上 serverless 或 edge。這是最大宗，也最省事。像廣告報表這種一次問一次答的場景，本來就沒在記東西，可以參考我寫過的 [Google Ads MCP 實戰](https://growthhackers.tw/blog/mcp-google-ads-workflow/)。

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

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

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

還有一個是「不要往這裡停」：**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 是什麼](https://growthhackers.tw/blog/what-is-agent-harness/)。

## 這週可以做的四件事

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

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

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

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

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

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

**協作聲明與免責**

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

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