MCP (Model Context Protocol) 協議文件
MCP (Model Context Protocol) 互動流程
注意: AI 輔助產生,在實作後台服務時,請參照程式碼確認細節!
本專案中的 MCP 協議用於後台 API(MCP 客戶端)與 ESP32 裝置(MCP 伺服器)之間的通訊,以便後台能夠發現和呼叫裝置提供的功能(工具)。
協議格式
根據程式碼 (main/protocols/protocol.cc
, main/mcp_server.cc
),MCP 訊息是封裝在基礎通訊協議(如 WebSocket 或 MQTT)的訊息體中的。其內部結構遵循 JSON-RPC 2.0 規範。
整體訊息結構範例:
{
"session_id": "...", // 會話 ID
"type": "mcp", // 訊息類型,固定為 "mcp"
"payload": { // JSON-RPC 2.0 負載
"jsonrpc": "2.0",
"method": "...", // 方法名 (如 "initialize", "tools/list", "tools/call")
"params": { ... }, // 方法參數 (對於 request)
"id": ..., // 請求 ID (對於 request 和 response)
"result": { ... }, // 方法執行結果 (對於 success response)
"error": { ... } // 錯誤資訊 (對於 error response)
}
}
其中,payload
部分是標準的 JSON-RPC 2.0 訊息:
jsonrpc
: 固定的字串 “2.0”。method
: 要呼叫的方法名稱 (對於 Request)。params
: 方法的參數,一個結構化值,通常為物件 (對於 Request)。id
: 請求的標識符,客戶端傳送請求時提供,伺服器回應時原樣回傳。用於匹配請求和回應。result
: 方法成功執行時的結果 (對於 Success Response)。error
: 方法執行失敗時的錯誤資訊 (對於 Error Response)。
互動流程及傳送時機
MCP 的互動主要圍繞客戶端(後台 API)發現和呼叫裝置上的「工具」(Tool)進行。
1. 連線建立與能力通告
- 時機: 裝置啟動並成功連接到後台 API 後。
- 傳送方: 裝置。
- 訊息: 裝置傳送基礎協議的 “hello” 訊息給後台 API,訊息中包含裝置支援的能力清單,例如透過支援 MCP 協議 (
"mcp": true
)。 - 範例 (非 MCP 負載,而是基礎協議訊息):
{ "type": "hello", "version": 3, "features": { "mcp": true }, "transport": "websocket", // 或 "mqtt" "audio_params": { ... }, "session_id": "..." // 裝置收到伺服器hello後可能設定 }
2. 初始化 MCP 會話
時機: 後台 API 收到裝置 “hello” 訊息,確認裝置支援 MCP 後,通常作為 MCP 會話的第一個請求傳送。
傳送方: 後台 API (客戶端)。
方法:
initialize
訊息 (MCP payload):
{ "jsonrpc": "2.0", "method": "initialize", "params": { "capabilities": { // 客戶端能力,可選 // 攝影機視覺相關 "vision": { "url": "...", //攝影機: 圖片處理地址(必須是http地址, 不是websocket地址) "token": "..." // url token } // ... 其他客戶端能力 } }, "id": 1 // 請求 ID }
裝置回應時機: 裝置收到
initialize
請求並處理後。裝置回應訊息 (MCP payload):
{ "jsonrpc": "2.0", "id": 1, // 匹配請求 ID "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} // 這裡的 tools 似乎不列出詳細資訊,需要 tools/list }, "serverInfo": { "name": "...", // 裝置名稱 (BOARD_NAME) "version": "..." // 裝置韌體版本 } } }
3. 發現裝置工具清單
- 時機: 後台 API 需要取得裝置當前支援的具體功能(工具)清單及其呼叫方式時。
- 傳送方: 後台 API (客戶端)。
- 方法:
tools/list
- 訊息 (MCP payload):
{ "jsonrpc": "2.0", "method": "tools/list", "params": { "cursor": "" // 用於分頁,首次請求為空字串 }, "id": 2 // 請求 ID }
- 裝置回應時機: 裝置收到
tools/list
請求並產生工具清單後。 - 裝置回應訊息 (MCP payload):
{ "jsonrpc": "2.0", "id": 2, // 匹配請求 ID "result": { "tools": [ // 工具物件清單 { "name": "self.get_device_status", "description": "...", "inputSchema": { ... } // 參數 schema }, { "name": "self.audio_speaker.set_volume", "description": "...", "inputSchema": { ... } // 參數 schema } // ... 更多工具 ], "nextCursor": "..." // 如果清單很大需要分頁,這裡會包含下一個請求的 cursor 值 } }
- 分頁處理: 如果
nextCursor
欄位非空,客戶端需要再次傳送tools/list
請求,並在params
中帶上這個cursor
值以取得下一頁工具。
4. 呼叫裝置工具
- 時機: 後台 API 需要執行裝置上的某個具體功能時。
- 傳送方: 後台 API (客戶端)。
- 方法:
tools/call
- 訊息 (MCP payload):
{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "self.audio_speaker.set_volume", // 要呼叫的工具名稱 "arguments": { // 工具參數,物件格式 "volume": 50 // 參數名及其值 } }, "id": 3 // 請求 ID }
- 裝置回應時機: 裝置收到
tools/call
請求,執行相應的工具函式後。 - 裝置成功回應訊息 (MCP payload):
{ "jsonrpc": "2.0", "id": 3, // 匹配請求 ID "result": { "content": [ // 工具執行結果內容 { "type": "text", "text": "true" } // 範例:set_volume 回傳 bool ], "isError": false // 表示成功 } }
- 裝置失敗回應訊息 (MCP payload):
{ "jsonrpc": "2.0", "id": 3, // 匹配請求 ID "error": { "code": -32601, // JSON-RPC 錯誤碼,例如 Method not found (-32601) "message": "Unknown tool: self.non_existent_tool" // 錯誤描述 } }
5. 裝置主動傳送訊息 (Notifications)
- 時機: 裝置內部發生需要通知後台 API 的事件時(例如,狀態變化,雖然程式碼範例中沒有明確的工具傳送此類訊息,但
Application::SendMcpMessage
的存在暗示了裝置可能主動傳送 MCP 訊息)。 - 傳送方: 裝置 (伺服器)。
- 方法: 可能是以
notifications/
開頭的方法名,或者其他自訂方法。 - 訊息 (MCP payload): 遵循 JSON-RPC Notification 格式,沒有
id
欄位。{ "jsonrpc": "2.0", "method": "notifications/state_changed", // 範例方法名 "params": { "newState": "idle", "oldState": "connecting" } // 沒有 id 欄位 }
- 後台 API 處理: 接收到 Notification 後,後台 API 進行相應的處理,但不回覆。
互動圖
下面是一個簡化的互動序列圖,展示了主要的 MCP 訊息流程:
sequenceDiagram participant Device as ESP32 Device participant BackendAPI as 後台 API (Client) Note over Device, BackendAPI: 建立 WebSocket / MQTT 連線 Device->>BackendAPI: Hello Message (包含 "mcp": true) BackendAPI->>Device: MCP Initialize Request Note over BackendAPI: method: initialize Note over BackendAPI: params: { capabilities: ... } Device->>BackendAPI: MCP Initialize Response Note over Device: result: { protocolVersion: ..., serverInfo: ... } BackendAPI->>Device: MCP Get Tools List Request Note over BackendAPI: method: tools/list Note over BackendAPI: params: { cursor: "" } Device->>BackendAPI: MCP Get Tools List Response Note over Device: result: { tools: [...], nextCursor: ... } loop 可選分頁 BackendAPI->>Device: MCP Get Tools List Request Note over BackendAPI: method: tools/list Note over BackendAPI: params: { cursor: "..." } Device->>BackendAPI: MCP Get Tools List Response Note over Device: result: { tools: [...], nextCursor: "" } end BackendAPI->>Device: MCP Call Tool Request Note over BackendAPI: method: tools/call Note over BackendAPI: params: { name: "...", arguments: { ... } } alt 工具呼叫成功 Device->>BackendAPI: MCP Tool Call Success Response Note over Device: result: { content: [...], isError: false } else 工具呼叫失敗 Device->>BackendAPI: MCP Tool Call Error Response Note over Device: error: { code: ..., message: ... } end opt 裝置通知 Device->>BackendAPI: MCP Notification Note over Device: method: notifications/... Note over Device: params: { ... } end
相關文件
- MCP 協議使用指南 - MCP 協議在物聯網控制中的具體用法
- WebSocket 通訊協議 - WebSocket 底層通訊協議
- MQTT + UDP 混合協議 - MQTT + UDP 混合通訊協議
這份文件概述了該專案中 MCP 協議的主要互動流程。具體的參數細節和工具功能需要參考
main/mcp_server.cc
中 McpServer::AddCommonTools
以及各個工具的實作。