Документация протокола MCP (Model Context Protocol)

Документация протокола MCP (Model Context Protocol)

Поток взаимодействия MCP (Model Context Protocol)

Примечание: Сгенерировано с помощью ИИ, при реализации бэкенд-сервисов обратитесь к коду для подтверждения деталей!

Протокол 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": { ... }, // Параметры метода (для запроса)
    "id": ...,         // ID запроса (для запроса и ответа)
    "result": { ... }, // Результат выполнения метода (для успешного ответа)
    "error": { ... }   // Информация об ошибке (для ошибочного ответа)
  }
}

Где часть 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):

    {
      "jsonrpc": "2.0",
      "method": "initialize",
      "params": {
        "capabilities": {
          // Возможности клиента, опционально
    
          // Связанное с видением камеры
          "vision": {
            "url": "...", //камера: адрес обработки изображений (должен быть http адрес, не websocket адрес)
            "token": "..." // токен url
          }
    
          // ... другие возможности клиента
        }
      },
      "id": 1 // ID запроса
    }
  • Время ответа устройства: После получения и обработки запроса initialize устройством.

  • Сообщение ответа устройства (полезная нагрузка MCP):

    {
      "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):
    {
      "jsonrpc": "2.0",
      "method": "tools/list",
      "params": {
        "cursor": "" // Для пагинации, первый запрос - пустая строка
      },
      "id": 2 // ID запроса
    }
  • Время ответа устройства: После получения запроса tools/list устройством и генерации списка инструментов.
  • Сообщение ответа устройства (полезная нагрузка MCP):
    {
      "jsonrpc": "2.0",
      "id": 2, // Соответствие ID запроса
      "result": {
        "tools": [ // Список объектов инструментов
          {
            "name": "self.get_device_status",
            "description": "...",
            "inputSchema": { ... } // Схема параметров
          },
          {
            "name": "self.audio_speaker.set_volume",
            "description": "...",
            "inputSchema": { ... } // Схема параметров
          }
          // ... больше инструментов
        ],
        "nextCursor": "..." // Если список большой и нужна пагинация, здесь будет содержаться значение cursor для следующего запроса
      }
    }
  • Обработка пагинации: Если поле nextCursor не пустое, клиент должен снова отправить запрос tools/list и включить это значение cursor в params для получения следующей страницы инструментов.

4. Вызов инструментов устройства

  • Время: Когда бэкенд API нужно выполнить конкретную функцию на устройстве.
  • Отправитель: Бэкенд API (клиент).
  • Метод: tools/call
  • Сообщение (полезная нагрузка MCP):
    {
      "jsonrpc": "2.0",
      "method": "tools/call",
      "params": {
        "name": "self.audio_speaker.set_volume", // Имя вызываемого инструмента
        "arguments": {
          // Параметры инструмента, формат объекта
          "volume": 50 // Имя параметра и его значение
        }
      },
      "id": 3 // ID запроса
    }
  • Время ответа устройства: После получения запроса tools/call устройством и выполнения соответствующей функции инструмента.
  • Сообщение успешного ответа устройства (полезная нагрузка MCP):
    {
      "jsonrpc": "2.0",
      "id": 3, // Соответствие ID запроса
      "result": {
        "content": [
          // Содержимое результата выполнения инструмента
          { "type": "text", "text": "true" } // Пример: set_volume возвращает bool
        ],
        "isError": false // Указывает на успех
      }
    }
  • Сообщение неудачного ответа устройства (полезная нагрузка MCP):
    {
      "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): Следует формату 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 в проекте. Конкретные детали параметров и функции инструментов нужно ссылаться на McpServer::AddCommonTools в main/mcp_server.cc и реализацию каждого инструмента.