MCP プロトコルIoT制御使用説明
この文書はMCPプロトコルに基づくESP32デバイスのIoT制御実装方法を紹介します。詳細なプロトコルフローはMCPプロトコル文書を参照してください。
概要
MCP(Model Context Protocol)は、IoT制御に推奨される新世代プロトコルで、標準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プロトコルを統一使用してIoT制御を行うことを推奨。
- 詳細なプロトコルと高度な使用法はMCPプロトコル文書を参照してください。
関連文書
- MCPプロトコル文書 - 詳細なプロトコル相互作用フロー
- WebSocket通信プロトコル - WebSocket下層通信プロトコル
- MQTT + UDP混合プロトコル - MQTT + UDP混合通信プロトコル
よくある質問
Q: ツール呼び出しタイムアウトの処理方法は?
A: ツールコールバックで長時間ブロッキング操作を避け、時間のかかる操作は非同期処理して即座にステータスを返す。
Q: ツールの動的追加・削除は可能ですか?
A: 現在の実装では通常デバイス起動時にツールを登録、動的管理にはツール登録メカニズムの再設計が必要。
Q: ツール呼び出し権限の処理方法は?
A: ツールコールバックに権限チェックロジックを追加、またはバックエンドAPIレベルで権限制御を行う。