MCP (Model Context Protocol) Protocol Documentation
MCP (Model Context Protocol) Interaction Flow
The MCP protocol in this project is used for communication between backend APIs (MCP client) and ESP32 devices (MCP server), enabling the backend to discover and invoke functions (tools) provided by devices.
Protocol Format
According to the code (main/protocols/protocol.cc, main/mcp_server.cc), MCP messages are encapsulated within the message body of underlying communication protocols (such as WebSocket or MQTT). The internal structure follows the JSON-RPC 2.0 specification.
Overall message structure example:
{
"session_id": "...", // Session ID
"type": "mcp", // Message type, fixed as "mcp"
"payload": { // JSON-RPC 2.0 payload
"jsonrpc": "2.0",
"method": "...", // Method name (e.g., "initialize", "tools/list", "tools/call")
"params": { ... }, // Method parameters (for request)
"id": ..., // Request ID (for request and response)
"result": { ... }, // Method execution result (for success response)
"error": { ... } // Error information (for error response)
}
}The payload section is a standard JSON-RPC 2.0 message:
jsonrpc: Fixed string “2.0”.method: Name of the method to be called (for Request).params: Method parameters, a structured value, typically an object (for Request).id: Request identifier provided by client when sending request, returned as-is by server in response. Used to match requests and responses.result: Result when method executes successfully (for Success Response).error: Error information when method execution fails (for Error Response).
Interaction Flow and Sending Timing
MCP interaction mainly revolves around client (backend API) discovering and calling “tools” on the device.
1. Connection Establishment and Capability Announcement
- Timing: After device startup and successful connection to backend API.
- Sender: Device.
- Message: Device sends basic protocol “hello” message to backend API, including device capability list, e.g., MCP protocol support (
"mcp": true). - Example (non-MCP payload, basic protocol message):
{ "type": "hello", "version": 3, "features": { "mcp": true }, "transport": "websocket", // or "mqtt" "audio_params": { ... }, "session_id": "..." // May be set after device receives server hello }
2. MCP Session Initialization
Timing: After backend API receives device “hello” message and confirms MCP support, typically sent as first MCP session request.
Sender: Backend API (client).
Method:
initializeMessage (MCP payload):
{ "jsonrpc": "2.0", "method": "initialize", "params": { "capabilities": { // Client capabilities, optional // Camera vision related "vision": { "url": "...", // Camera: image processing address (must be http address, not websocket) "token": "..." // url token } // ... other client capabilities } }, "id": 1 // Request ID }Device Response Timing: After device receives and processes
initializerequest.Device Response Message (MCP payload):
{ "jsonrpc": "2.0", "id": 1, // Matching request ID "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} // tools here doesn't list details, need tools/list }, "serverInfo": { "name": "...", // Device name (BOARD_NAME) "version": "..." // Device firmware version } } }
3. Discover Device Tool List
- Timing: When backend API needs to get specific function (tool) list and calling methods currently supported by device.
- Sender: Backend API (client).
- Method:
tools/list - Message (MCP payload):
{ "jsonrpc": "2.0", "method": "tools/list", "params": { "cursor": "" // For pagination, empty string for first request }, "id": 2 // Request ID } - Device Response Timing: After device receives
tools/listrequest and generates tool list. - Device Response Message (MCP payload):
{ "jsonrpc": "2.0", "id": 2, // Matching request ID "result": { "tools": [ // Tool object list { "name": "self.get_device_status", "description": "...", "inputSchema": { ... } // Parameter schema }, { "name": "self.audio_speaker.set_volume", "description": "...", "inputSchema": { ... } // Parameter schema } // ... more tools ], "nextCursor": "..." // If list is large and needs pagination, this contains cursor value for next request } } - Pagination Handling: If
nextCursorfield is non-empty, client needs to sendtools/listrequest again with thiscursorvalue inparamsto get next page of tools.
4. Call Device Tool
- Timing: When backend API needs to execute specific function on device.
- Sender: Backend API (client).
- Method:
tools/call - Message (MCP payload):
{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "self.audio_speaker.set_volume", // Tool name to call "arguments": { // Tool parameters, object format "volume": 50 // Parameter name and value } }, "id": 3 // Request ID } - Device Response Timing: After device receives
tools/callrequest and executes corresponding tool function. - Device Success Response Message (MCP payload):
{ "jsonrpc": "2.0", "id": 3, // Matching request ID "result": { "content": [ // Tool execution result content { "type": "text", "text": "true" } // Example: set_volume returns bool ], "isError": false // Indicates success } } - Device Failure Response Message (MCP payload):
{ "jsonrpc": "2.0", "id": 3, // Matching request ID "error": { "code": -32601, // JSON-RPC error code, e.g., Method not found (-32601) "message": "Unknown tool: self.non_existent_tool" // Error description } }
5. Device Proactive Messages (Notifications)
- Timing: When device internal events occur that need to notify backend API (e.g., status changes, although code examples don’t clearly show tools sending such messages, but existence of
Application::SendMcpMessagesuggests device may proactively send MCP messages). - Sender: Device (server).
- Method: Possibly methods starting with
notifications/, or other custom methods. - Message (MCP payload): Follows JSON-RPC Notification format, no
idfield.{ "jsonrpc": "2.0", "method": "notifications/state_changed", // Example method name "params": { "newState": "idle", "oldState": "connecting" } // No id field } - Backend API Handling: After receiving Notification, backend API processes accordingly but doesn’t reply.
Interaction Diagram
Below is a simplified interaction sequence diagram showing main MCP message flows:
sequenceDiagram
participant Device as ESP32 Device
participant BackendAPI as Backend API (Client)
Note over Device, BackendAPI: Establish WebSocket / MQTT Connection
Device->>BackendAPI: Hello Message (includes "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 Optional Pagination
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 Tool Call Successful
Device->>BackendAPI: MCP Tool Call Success Response
Note over Device: result: { content: [...], isError: false }
else Tool Call Failed
Device->>BackendAPI: MCP Tool Call Error Response
Note over Device: error: { code: ..., message: ... }
end
opt Device Notification
Device->>BackendAPI: MCP Notification
Note over Device: method: notifications/...
Note over Device: params: { ... }
end
Related Documentation
- MCP Protocol Usage Guide - Specific usage of MCP protocol in IoT control
- WebSocket Communication Protocol - WebSocket underlying communication protocol
- MQTT + UDP Hybrid Protocol - MQTT + UDP hybrid communication protocol
main/mcp_server.cc in McpServer::AddCommonTools and implementations of various tools.