xiaozhi-esp32 MCP 物联网控制完全指南:工具注册、调用与内置工具详解

发布时间:2026/9/10 13:47:20
xiaozhi-esp32 MCP 物联网控制完全指南:工具注册、调用与内置工具详解 xiaozhi-esp32 MCP 物联网控制完全指南工具注册、调用与内置工具详解【免费下载链接】xiaozhi-esp32An MCP-based chatbot | 一个基于MCP的聊天机器人项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32本篇技术指南面向基于 MCPModel Context Protocol实现 ESP32 设备 IoT 控制的开发者。它以 xiaozhi-esp32 仓库中 docs/mcp-usage.md 为核心骨架结合 docs/mcp-protocol.md 的线上协议说明与 main/mcp_server.cc 的源码实现完整讲解设备端如何注册工具Tool、后端如何通过 JSON-RPC 2.0 发现并调用这些工具、以及内置工具的分类与用法。读完本文你将能够为任意开发板编写自定义 MCP 工具并正确实现后端调用链。MCP 与 IoT 控制为什么推荐用 MCP在 xiaozhi-esp32 中MCP 是官方推荐的 IoT 控制协议。设备端ESP32作为MCP Server通过 WebSocket 或 MQTT 与后端 API作为MCP Client保持连接后端借助 MCP 动态发现设备注册的工具并通过 JSON-RPC 2.0 消息调用它们从而以统一、灵活的方式暴露设备功能。相比写死一套私有指令协议MCP 的优势在于可发现性后端通过tools/list随时获取设备当前可调用的工具及输入参数 Schema无需前后端同步维护文档可扩展性新功能只需在设备端AddTool注册一个新工具AI 模型与后端即可立即感知并调用权限分层通过普通工具与 user-only 工具两套注册 API天然区分AI 可自主调用与仅用户授权操作两类能力。更详细的线上消息格式请参考仓库中的 mcp-protocol.md。典型交互流程一次完整的 MCP IoT 控制会话遵循以下四个步骤设备上线设备启动后通过 WebSocket 或 MQTT 连接后端并在传输层 hello 消息中声明能力MCP 支持通过features.mcp true表示初始化会话后端发送initialize调用建立 MCP 会话设备回复协议版本2024-11-05、能力集与serverInfo设备名与固件版本发现工具后端发送tools/list获取可用工具列表及其输入 Schema调用工具后端针对具体动作发送tools/call携带工具名与参数设备执行回调并返回结果。其中步骤 3 支持分页当设备端工具列表超过单包上限源码中GetToolsList的max_payload_size 8000字节时响应会携带nextCursor后端需用该游标继续请求下一页直至nextCursor为空见 main/mcp_server.cc。设备端注册工具的两套 API所有工具都注册在McpServer单例上通过McpServer::GetInstance()获取。仓库提供了两套注册 API对应两类不同权限的工具McpServer::AddTool注册普通工具。出现在默认的tools/list响应中可被 AI 模型自主调用适合语音/文本控制类功能McpServer::AddUserOnlyTool注册 user-only仅用户工具。默认隐藏只有后端以withUserToolstrue请求时才返回适合重启、固件升级、截图上传等特权或用户主动发起的操作防止 AI 自主触发危险动作。两者的函数签名完全一致void AddTool( const std::string name, // 唯一工具名如 self.dog.forward const std::string description, // 给模型的自然语言描述 const PropertyList properties, // 输入参数可为空支持 bool / int / string std::functionReturnValue(const PropertyList) callback // 实现逻辑 ); void AddUserOnlyTool( const std::string name, const std::string description, const PropertyList properties, std::functionReturnValue(const PropertyList) callback );参数语义参数说明name全局唯一标识建议采用module.action风格如self.audio_speaker.set_volume便于分类与检索description自然语言描述AI 模型依赖它决定何时调用该工具描述应包含使用前提与返回值说明properties输入参数集合支持布尔、整数、字符串三种类型整数可带 min/max 范围也可提供默认值callback工具实现返回bool、int或std::string等返回值Property 与 ReturnValue 的底层细节源码佐证从 main/mcp_server.h 可以看到Property类提供了丰富的构造函数支持多种声明方式均定义于该头文件Property(name, type)必填参数Property(name, type, default_value)带默认值的可选参数Property(name, type, min, max)整数范围约束仅限整数构造时校验Property(name, type, default, min, max)同时带默认值与范围约束且校验默认值必须在范围内。set_valueint()还会在运行时再次校验数值是否越界越界会抛出std::invalid_argument最终以tools/call错误响应返回给后端见 main/mcp_server.h。ReturnValue是std::variantbool, int, std::string, cJSON*, ImageContent*其中cJSON*用于返回结构化 JSON如设备状态ImageContent*用于返回 Base64 编码的图片内容见 main/mcp_server.h。McpTool::Call会把返回值序列化为 MCP 标准响应普通值放入content[0].text图片放入type: image的内容块见 main/mcp_server.h。另外PropertyList::GetRequired()会把无默认值的属性标记为 JSON Schema 中的required数组user-only 工具还会在to_json()中附加annotations.audience: [user]标注见 main/mcp_server.h。实战示例以 ESP-Hi 机器狗为例仓库中 main/boards/espressif/esp-hi/esp_hi.cc 的InitializeTools()是教科书级的注册示范。该函数在板子构造函数中被调用通过McpServer::GetInstance()获取单例后注册多个工具。示例 1无参数工具——机器狗基础动作void InitializeTools() { auto mcp_server McpServer::GetInstance(); // 基础动作控制 mcp_server.AddTool(self.dog.basic_control, 机器人的基础动作。机器人可以做以下基础动作\n forward: 向前移动\nbackward: 向后移动\nturn_left: 向左转\nturn_right: 向右转\nstop: 立即停止当前动作, PropertyList({ Property(action, kPropertyTypeString), }), this - ReturnValue { const std::string action properties[action].valuestd::string(); if (action forward) { servo_dog_ctrl_send(DOG_STATE_FORWARD, NULL); } else if (action backward) { servo_dog_ctrl_send(DOG_STATE_BACKWARD, NULL); } else if (action turn_left) { servo_dog_ctrl_send(DOG_STATE_TURN_LEFT, NULL); } else if (action turn_right) { servo_dog_ctrl_send(DOG_STATE_TURN_RIGHT, NULL); } else if (action stop) { servo_dog_ctrl_send(DOG_STATE_IDLE, NULL); } else { return false; // 未知动作返回 false } return true; }); }注意其description直接把可用的动作枚举写进了自然语言描述里这是为了让 AI 模型能准确构造action参数值——name是程序标识description才是模型的使用说明书。示例 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 - ReturnValue { int r properties[r].valueint(); int g properties[g].valueint(); int b properties[b].valueint(); led_on_ true; SetLedColor(r, g, b); return true; });这里r/g/b三个整数参数通过Property(name, kPropertyTypeInteger, 0, 255)声明了 0–255 的合法范围这些范围会被序列化进inputSchema的minimum/maximum字段后端拿到后即可用于参数校验与模型提示。注册 user-only 工具特权操作应使用AddUserOnlyTool例如清除本地图片缓存这类仅用户可主动触发的动作mcp_server.AddUserOnlyTool(self.display.clear_cache, Clear locally cached images. User-only action., PropertyList(), [](const PropertyList) - ReturnValue { ClearLocalCache(); return true; });以这种方式注册的工具不会出现在常规的tools/list响应中后端必须设置params.withUserTools true才能看到。从源码 main/mcp_server.cc 可以看出GetToolsList在list_user_only_tools为 false 时会直接跳过所有user_only()工具。内置工具清单设备启动时main/application.cc 会调用McpServer::AddCommonTools()与McpServer::AddUserOnlyTools()自动注册一批通用工具板级InitializeTools()再在其后追加板卡专属工具。源码注释特别说明为了让常用工具命中后端 prompt cache、降低响应延迟通用工具会被插入到工具列表的最前面见 main/mcp_server.cc。默认AI 可调用工具——来自AddCommonTools工具说明self.get_device_status返回设备实时信息包括音频、屏幕、电池、网络等当前状态也是控制类操作的第一步如调音量前先查询当前音量self.audio_speaker.set_volume设置扬声器音量volume: 0-100实际调用codec-SetOutputVolume()self.screen.set_brightness设置屏幕亮度brightness: 0-100仅在存在背光控制器时注册self.screen.set_theme切换 UI 主题theme:light或dark仅 LVGL 使能时注册self.camera.take_photo调用板载摄像头拍照并回答给定的question仅带摄像头且 LVGL 使能的板卡注册从源码看这些工具大多带条件注册set_brightness仅在board.GetBacklight()非空时注册set_theme、take_photo仅编译进HAVE_LVGL分支且硬件存在时注册见 main/mcp_server.cc。user-only 工具——来自AddUserOnlyTools这类工具默认隐藏后端必须以withUserToolstrue请求tools/list才能看到面向配套 App 或终端用户而非 AI 模型。工具说明self.get_system_info返回描述系统的 JSON 数据self.reboot延时 1 秒后重启设备通过Application::Reboot调度执行self.upgrade_firmware从url下载固件并安装随后重启设备self.screen.get_info返回屏幕宽、高及是否单色仅 LVGL 板卡self.screen.snapshot将屏幕截图为 JPEG 并以 multipart/form-data 上传到url仅 LVGL 且CONFIG_LV_USE_SNAPSHOTy时注册quality参数范围 1-100默认 80self.screen.preview_image从url下载图片并在屏幕预览显示self.assets.set_download_url设置 assets 分区的下载地址持久化到 Settings以self.reboot为例其实现通过app.Schedule回到主线程延时 1 秒后调用app.Reboot()self.screen.snapshot则完整实现了截图 → JPEG 编码 → multipart 上传 → 校验 HTTP 200的链路见 main/mcp_server.cc。后端调用示例JSON-RPC 消息实战1. 获取工具列表{ jsonrpc: 2.0, method: tools/list, params: { cursor: , withUserTools: false }, id: 1 }cursor首次为空若响应含nextCursor需携带其值继续请求下一页。withUserTools设为true即可额外看到 user-only 工具。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. 重启设备user-only{ jsonrpc: 2.0, method: tools/call, params: { name: self.reboot, arguments: {} }, id: 4 }响应与错误处理调用成功的响应返回result.content文本或图片与isError: false{ jsonrpc: 2.0, id: 3, result: { content: [ { type: text, text: true } ], isError: false } }若工具不存在返回 JSON-RPC 错误{ jsonrpc: 2.0, id: 3, error: { code: -32601, message: Unknown tool: self.non_existent_tool } }参数缺失、类型不匹配或整数越界同样会以错误响应返回源码中DoToolCall会逐参数校验类型并捕获std::exception见 main/mcp_server.cc。传输层封装MCP 消息如何到达设备MCP 的 JSON-RPC 载荷并非裸发而是被包裹在 WebSocket/MQTT 传输层消息中整体结构如下见 docs/mcp-protocol.md{ session_id: ..., type: mcp, payload: { jsonrpc: 2.0, method: ..., params: { ... }, id: ..., result: { ... }, error: { ... } } }其中type固定为mcppayload遵循 JSON-RPC 2.0 规范。设备收到消息后main/application.cc 会调用McpServer::ParseMessage解析分发设备向外的回复则由Application::SendMcpMessage统一调度到主线程后经protocol_-SendMcpMessage发出并同步转发给注册的广播回调见 main/application.cc 与 main/protocols/protocol.cc。设备还支持主动通知notification如状态变化等事件可发送无id的notifications/...消息后端只处理不回复。ParseMessage对以notifications开头的方法直接忽略处理见 main/mcp_server.cc。注意事项与最佳实践命名与类型必须严格一致工具名、参数与返回值必须与设备端AddTool/AddUserOnlyTool注册的内容完全匹配否则会得到Unknown tool或参数校验错误新 IoT 控制优先走 MCP不要为个别功能另起私有协议统一使用 MCP 便于模型发现与后端维护危险操作务必用 user-only重启、固件升级、截图上传等操作应注册为 user-only 工具避免 AI 模型自主触发配套 App 通过withUserToolstrue显式拉取后由用户点击触发description 即模型提示词把动作枚举、使用前提、返回值语义写进描述能显著提升 AI 调用工具的准确率关注条件注册与编译开关内置工具依赖硬件能力背光、摄像头、LVGL与CONFIG_LV_USE_SNAPSHOT等 Kconfig 选项后端不应假设工具列表固定不变而应每次动态tools/list发现。更多关于线上协议、初始化握手与分页细节请继续阅读 mcp-protocol.md设备端各板卡的自定义工具实现可参考main/boards/下各板卡目录中的InitializeTools。【免费下载链接】xiaozhi-esp32An MCP-based chatbot | 一个基于MCP的聊天机器人项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询