MCP 協議物聯網控制用法說明
本文件介紹如何基於 MCP 協議實作 ESP32 裝置的物聯網控制。詳細協議流程請參考 MCP 協議文件。
簡介
MCP(Model Context Protocol)是新一代推薦用於物聯網控制的協議,透過標準 JSON-RPC 2.0 格式在後台與裝置間發現和呼叫「工具」(Tool),實作靈活的裝置控制。
典型使用流程
- 裝置啟動後透過基礎協議(如 WebSocket/MQTT)與後台建立連線。
- 後台透過 MCP 協議的
initialize
方法初始化會話。 - 後台透過
tools/list
取得裝置支援的所有工具(功能)及參數說明。 - 後台透過
tools/call
呼叫具體工具,實作對裝置的控制。
詳細協議格式與互動請見 MCP 協議文件。
裝置端工具註冊方法說明
裝置透過 McpServer::AddTool
方法註冊可被後台呼叫的「工具」。其常用函式簽名如下:
void AddTool(
const std::string& name, // 工具名稱,建議唯一且有層次感,如 self.dog.forward
const std::string& description, // 工具描述,簡明說明功能,便於大模型理解
const PropertyList& properties, // 輸入參數清單(可為空),支援類型:布林、整數、字串
std::function<ReturnValue(const PropertyList&)> callback // 工具被呼叫時的回呼實作
);
參數說明
- name:工具唯一標識,建議用「模組.功能」命名風格。
- description:自然語言描述,便於 AI/使用者理解。
- properties:參數清單,支援類型有布林、整數、字串,可指定範圍和預設值。
- callback:收到呼叫請求時的實際執行邏輯,回傳值可為 bool/int/string。
典型註冊範例(以 ESP-Hi 為例)
void InitializeTools() {
auto& mcp_server = McpServer::GetInstance();
// 例1:無參數,控制機器人前進
mcp_server.AddTool("self.dog.forward", "機器人向前移動", PropertyList(),
[this](const PropertyList&) -> ReturnValue {
servo_dog_ctrl_send(DOG_STATE_FORWARD, NULL);
return true;
});
// 例2:帶參數,設定燈光 RGB 顏色
mcp_server.AddTool("self.light.set_rgb", "設定RGB顏色", PropertyList({
Property("r", kPropertyTypeInteger, 0, 255),
Property("g", kPropertyTypeInteger, 0, 255),
Property("b", kPropertyTypeInteger, 0, 255)
}), [this](const PropertyList& properties) -> ReturnValue {
int r = properties["r"].value<int>();
int g = properties["g"].value<int>();
int b = properties["b"].value<int>();
led_on_ = true;
SetLedColor(r, g, b);
return true;
});
}
常見工具呼叫 JSON-RPC 範例
1. 取得工具清單
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": { "cursor": "" },
"id": 1
}
2. 控制底盤前進
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.chassis.go_forward",
"arguments": {}
},
"id": 2
}
3. 切換燈光模式
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.chassis.switch_light_mode",
"arguments": { "light_mode": 3 }
},
"id": 3
}
4. 攝影機翻轉
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.camera.set_camera_flipped",
"arguments": {}
},
"id": 4
}
工具註冊最佳實務
1. 命名規範
- 使用有層次的命名:
self.模組.功能
- 保持名稱簡潔且具有描述性
- 避免使用特殊字元和空格
// 好的命名範例
"self.light.set_brightness"
"self.motor.rotate_left"
"self.sensor.get_temperature"
"self.display.show_text"
// 不推薦的命名
"light-control" // 缺少層次
"setBrightness" // 缺少模組資訊
"控制燈光" // 非英文命名
"self.light.set brightness" // 包含空格
2. 參數設計
- 使用清晰的參數名稱
- 設定合理的參數範圍和預設值
- 提供詳細的參數描述
// 參數設計範例
PropertyList({
Property("volume", kPropertyTypeInteger, 0, 100, "音量大小,範圍0-100"),
Property("enabled", kPropertyTypeBool, true, "是否啟用功能"),
Property("message", kPropertyTypeString, "", "要顯示的文字內容")
})
3. 錯誤處理
在工具回呼中進行適當的錯誤處理:
mcp_server.AddTool("self.servo.set_angle", "設定舵機角度", PropertyList({
Property("angle", kPropertyTypeInteger, 0, 180)
}), [this](const PropertyList& properties) -> ReturnValue {
try {
int angle = properties["angle"].value<int>();
if (angle < 0 || angle > 180) {
return "角度超出範圍:0-180";
}
SetServoAngle(angle);
return true;
} catch (const std::exception& e) {
return std::string("設定角度失敗:") + e.what();
}
});
除錯技巧
1. 日誌記錄
在工具實作中新增日誌:
mcp_server.AddTool("self.debug.test", "測試工具", PropertyList(),
[this](const PropertyList& properties) -> ReturnValue {
ESP_LOGI("MCP", "測試工具被呼叫");
// 執行測試邏輯
return "測試完成";
});
2. 參數驗證
新增詳細的參數驗證:
int volume = properties["volume"].value<int>();
if (volume < 0 || volume > 100) {
ESP_LOGE("MCP", "音量參數無效:%d", volume);
return "音量必須在0-100之間";
}
注意事項
- 工具名稱、參數及回傳值請以裝置端
AddTool
註冊為準。 - 推薦所有新專案統一採用 MCP 協議進行物聯網控制。
- 詳細協議與進階用法請查閱 MCP 協議文件。
相關文件
- MCP 協議文件 - 詳細的協議互動流程
- WebSocket 通訊協議 - WebSocket 底層通訊協議
- MQTT + UDP 混合協議 - MQTT + UDP 混合通訊協議
常見問題
Q: 如何處理工具呼叫逾時?
A: 在工具回呼中避免長時間阻塞操作,對於耗時操作可以非同步處理並立即回傳狀態。
Q: 可以動態新增或刪除工具嗎?
A: 目前實作通常在裝置啟動時註冊工具,動態管理需要重新設計工具註冊機制。
Q: 如何處理工具呼叫權限?
A: 可以在工具回呼中新增權限檢查邏輯,或在後台API層面進行權限控制。