載入中

MCP 用戶端與伺服器透過交換 JSON 訊息來進行通訊,但這些訊息實際上是如何傳輸的呢?所使用的通訊通道稱為傳輸(transport),而實作方式有很多種——從 HTTP 請求、WebSocket,甚至到在明信片上寫 JSON(雖然最後這種方式並不建議用於生產環境)。

Stdio 傳輸

當您剛開始開發 MCP 伺服器或用戶端時,最常使用的傳輸方式是 stdio 傳輸。這種方法很直接:用戶端將 MCP 伺服器作為子程序啟動,並透過標準輸入與輸出串流進行通訊。

stdio 傳輸的示意圖:MCP 用戶端透過伺服器的 stdin 向 MCP 伺服器傳送訊息,伺服器則透過 stdout 將訊息傳回;任一方都可以隨時傳送訊息,且僅在雙方於同一台機器上執行時才有效

運作方式如下:

  • 用戶端使用伺服器的 stdin 向伺服器傳送訊息
  • 伺服器透過寫入 stdout 來回應
  • 伺服器或用戶端都可以隨時傳送訊息
  • 僅在用戶端與伺服器於同一台機器上執行時才有效

實際觀察 Stdio 的運作

您實際上可以直接從終端機測試 MCP 伺服器,而不需要撰寫獨立的用戶端。當您使用 uv run server.py 執行伺服器時,它會監聽 stdin 並將回應寫入 stdout。這表示您可以直接將 JSON 訊息貼到終端機中,並立即看到伺服器的回應。

終端機輸出會顯示完整的訊息交換過程,包括初始化與工具呼叫的範例訊息。

MCP 連線順序

每一個 MCP 連線都必須以特定的三則訊息交握流程開始:

MCP 交握流程的順序圖:用戶端向伺服器傳送 Initialize Request,伺服器以 Initialize Result 回應,接著用戶端傳送 Initialized Notification,此訊息不會收到任何回應

  1. Initialize Request(初始化請求) - 用戶端首先傳送此訊息
  2. Initialize Result(初始化結果) - 伺服器以其能力回應
  3. Initialized Notification(已初始化通知) - 用戶端確認(不預期有回應)

只有在完成此交握流程之後,您才能傳送其他請求,例如工具呼叫或提示清單查詢。

訊息類型與流向

MCP 支援多種雙向流動的訊息類型:

用戶端與伺服器之間 MCP 訊息類型的圖表:用戶端發起的請求/結果配對,例如 Call Tool Request → Call Tool Result;伺服器發起的配對,例如 Create Message Request 與 List Roots Request;以及雙方各自發出、不需要回應的單向通知

關鍵在於,有些訊息需要回應(請求 → 結果),而有些則不需要(通知)。用戶端與伺服器都可以隨時發起通訊。

四種通訊情境

無論使用哪種傳輸方式,您都需要處理四種不同的通訊模式:

標題為「我們要如何用 stdio 實作這些情境?」的示意圖,列出四種模式——用戶端向伺服器發出的初始請求、伺服器向用戶端的回應、伺服器向用戶端發出的初始請求,以及用戶端向伺服器的回應——旁邊是連接到 MCP 伺服器 stdin 與 stdout 的 MCP 用戶端

  • 用戶端 → 伺服器請求:用戶端寫入 stdin
  • 伺服器 → 用戶端回應:伺服器寫入 stdout
  • 伺服器 → 用戶端請求:伺服器寫入 stdout
  • 用戶端 → 伺服器回應:用戶端寫入 stdin

stdio 傳輸的美妙之處在於其簡潔性——任一方都可以隨時使用這兩個通道發起通訊。

為何這很重要

理解 stdio 傳輸至關重要,因為它代表了雙向通訊能夠無縫運作的「理想」情況。當我們轉向其他傳輸方式(例如 HTTP)時,我們會遇到一些限制,使得伺服器無法隨時向用戶端發起請求。在我們處理其他傳輸方式的限制之前,stdio 傳輸可作為我們理解完整 MCP 通訊樣貌的基準。

對於開發與測試而言,stdio 傳輸非常完美。而對於需要讓用戶端與伺服器在不同機器上執行的生產環境部署,您則需要考慮其他具有各自取捨的傳輸選項。