小智ESP32代码(6):MCP
MCP(Model Context Protocol)协议是一个基于JSON-RPC 2.0的标准化协议,用于AI模型与外部工具之间的通信。它是一个开放标准,旨在为AI模型提供访问外部工具和数据的标准化方式。在物联网场景中,它允许后台服务(如AI助手)发现设备能力并调用相应功能,而无需了解具体的硬件实现细节。
本文将深入分析小智这个项目中的MCP协议实现,探讨其架构设计和技术特点。
系统架构设计
整体架构图
graph TB
subgraph "后台服务 (MCP Client)"
AI[AI助手/后台API]
MCPClient[MCP客户端]
end
subgraph "通信层"
WS[WebSocket/MQTT]
end
subgraph "ESP32设备 (MCP Server)"
MCPServer[MCP服务器]
ToolRegistry[工具注册表]
ThreadPool[线程池]
end
subgraph "硬件抽象层"
Audio[音频控制]
Display[显示控制]
Camera[摄像头]
LED[LED控制]
end
AI --> MCPClient
MCPClient --> WS
WS --> MCPServer
MCPServer --> ToolRegistry
MCPServer --> ThreadPool
ToolRegistry --> Audio
ToolRegistry --> Display
ToolRegistry --> Camera
ToolRegistry --> LED
ThreadPool --> Audio
ThreadPool --> Display
ThreadPool --> Camera
ThreadPool --> LED
核心组件关系
classDiagram
class McpServer {
-tools_: vector~McpTool*~
-tool_call_thread_: thread
+AddTool(name, desc, props, callback)
+ParseMessage(json)
+DoToolCall(id, name, args, stack_size)
+GetToolsList(id, cursor)
}
class McpTool {
-name_: string
-description_: string
-properties_: PropertyList
-callback_: function
+Call(properties): string
+to_json(): string
}
class PropertyList {
+GetRequired(): vector~string~
+to_json(): string
}
class Property {
-name_: string
-type_: PropertyType
-value_: variant
+set_value~T~(value)
+value~T~(): T
}
McpServer --> McpTool : contains
McpTool --> PropertyList : has
PropertyList --> Property : contains
McpTool --> PropertyList : validates
核心实现分析
1. 工具注册机制
MCP服务器通过AddTool方法注册各种功能工具,每个工具包含名称、描述、参数定义和执行回调:
void McpServer::AddCommonTools() {
auto& board = Board::GetInstance();
// 注册设备状态查询工具
AddTool("self.get_device_status",
"提供设备的实时信息,包括音频、屏幕、电池、网络等状态",
PropertyList(),
[&board](const PropertyList& properties) -> ReturnValue {
return board.GetDeviceStatusJson();
});
// 注册音量控制工具
AddTool("self.audio_speaker.set_volume",
"设置音频扬声器音量",
PropertyList({
Property("volume", kPropertyTypeInteger, 0, 100)
}),
[&board](const PropertyList& properties) -> ReturnValue {
auto codec = board.GetAudioCodec();
codec->SetOutputVolume(properties["volume"].value<int>());
return true;
});
}
2. 消息解析与路由
系统支持三种主要的MCP方法:
flowchart TD
A[接收MCP消息] --> B{解析JSON-RPC}
B --> C{检查方法类型}
C -->|initialize| D[初始化会话]
C -->|tools/list| E[获取工具列表]
C -->|tools/call| F[调用工具]
D --> G[返回协议版本和服务器信息]
E --> H[分页返回工具列表]
F --> I[验证工具和参数]
I --> J{参数验证}
J -->|成功| K[创建执行线程]
J -->|失败| L[返回错误信息]
K --> M[执行工具回调]
M --> N[返回执行结果]
3. 工具调用执行流程
sequenceDiagram
participant Client as MCP客户端
participant Server as MCP服务器
participant Tool as 具体工具
participant Thread as 执行线程
Client->>Server: tools/call请求
Note over Client,Server: {name: "self.audio_speaker.set_volume", arguments: {volume: 50}}
Server->>Server: 查找工具
Server->>Server: 验证参数类型和必需性
alt 参数验证失败
Server->>Client: 返回错误信息
else 参数验证成功
Server->>Thread: 创建执行线程
Thread->>Tool: 调用工具回调函数
Tool->>Thread: 返回执行结果
Thread->>Server: 返回结果
Server->>Client: 返回成功响应
end
4. 异步执行与线程管理
为了避免阻塞主线程,工具调用在独立线程中执行:
void McpServer::DoToolCall(int id, const std::string& tool_name,
const cJSON* tool_arguments, int stack_size) {
// 配置线程参数
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
cfg.thread_name = "tool_call";
cfg.stack_size = stack_size;
cfg.prio = 1;
esp_pthread_set_cfg(&cfg);
// 在新线程中执行工具调用
tool_call_thread_ = std::thread([this, id, tool_iter, arguments]() {
try {
ReplyResult(id, (*tool_iter)->Call(arguments));
} catch (const std::exception& e) {
ESP_LOGE(TAG, "tools/call: %s", e.what());
ReplyError(id, e.what());
}
});
tool_call_thread_.detach();
}
技术特点与优势
1. 解耦设计
- 工具定义与具体实现分离
- 通过回调函数实现功能绑定
- 支持动态添加新工具
2. 类型安全
- 强类型参数验证
- 运行时类型检查
- 支持默认值设置
3. 异步执行
- 非阻塞工具调用
- 可配置线程栈大小
- 异常安全处理
4. 标准化协议
- 基于JSON-RPC 2.0
- 支持分页查询
- 完整的错误处理
实际应用场景
1. 智能家居控制
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.screen.set_brightness",
"arguments": {"brightness": 80}
},
"id": 1
}
2. 设备状态监控
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.get_device_status",
"arguments": {}
},
"id": 2
}
3. 多媒体控制
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "self.camera.take_photo",
"arguments": {"question": "这是什么物体?"}
},
"id": 3
}
扩展性设计
1. 新工具添加
只需实现回调函数并注册到MCP服务器:
// 添加新的LED控制工具
mcp_server.AddTool("self.led.set_color",
"设置LED颜色",
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>();
SetLedColor(r, g, b);
return true;
});
2. 参数类型扩展
系统支持三种基本类型,可根据需要扩展:
enum PropertyType {
kPropertyTypeBoolean,
kPropertyTypeInteger,
kPropertyTypeString
// 可扩展:kPropertyTypeFloat, kPropertyTypeArray等
};
MCP协议为物联网设备提供了一个优雅的解决方案,让设备能够以标准化的方式与AI系统交互,这为构建更智能、更灵活的物联网生态系统奠定了基础。
本文基于ESP32项目中的实际MCP协议实现进行分析,代码示例来自开源项目,遵循相应的开源协议。

浙公网安备 33010602011771号