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 協議的主要互動流程。具體的參數細節和工具功能需要參考 main/mcp_server.ccMcpServer::AddCommonTools 以及各個工具的實作。