MCP プロトコルIoT制御使用説明

MCP プロトコルIoT制御使用説明

この文書はMCPプロトコルに基づくESP32デバイスのIoT制御実装方法を紹介します。詳細なプロトコルフローはMCPプロトコル文書を参照してください。

概要

MCP(Model Context Protocol)は、IoT制御に推奨される新世代プロトコルで、標準JSON-RPC 2.0形式でバックエンドとデバイス間で「ツール」(Tool)を発見・呼び出し、柔軟なデバイス制御を実現します。

典型的な使用フロー

  1. デバイス起動後、基本プロトコル(WebSocket/MQTTなど)でバックエンドとの接続を確立。
  2. バックエンドがMCPプロトコルのinitializeメソッドでセッションを初期化。
  3. バックエンドがtools/listでデバイスがサポートするすべてのツール(機能)とパラメータ説明を取得。
  4. バックエンドが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プロトコル文書を参照してください。

関連文書

よくある質問

Q: ツール呼び出しタイムアウトの処理方法は?

A: ツールコールバックで長時間ブロッキング操作を避け、時間のかかる操作は非同期処理して即座にステータスを返す。

Q: ツールの動的追加・削除は可能ですか?

A: 現在の実装では通常デバイス起動時にツールを登録、動的管理にはツール登録メカニズムの再設計が必要。

Q: ツール呼び出し権限の処理方法は?

A: ツールコールバックに権限チェックロジックを追加、またはバックエンドAPIレベルで権限制御を行う。