AI语音智能体开发日记(五)为智能设备注入“灵魂”——详解MCP工具的注册与使用 相关链接AI语音智能体开发日记一如何为“小智”服务器启用并调试 License 功能-CSDN博客AI语音智能体开发日记二解决 Wi-Fi 配网小程序的兼容性问题-CSDN博客AI语音智能体开发日记三解决小程序配网中的蓝牙命名与MAC地址获取问题-CSDN博客AI语音智能体开发日记四在FreeRTOS中构建线程安全的UART2通信模块-CSDN博客AI语音智能体开发日记五为智能设备注入“灵魂”——详解MCP工具的注册与使用-CSDN博客AI语音智能体开发日记六为智能体注入旋律——七牛云音乐服务的接入与避坑指南-CSDN博客AI语音智能体开发日记七搞定功放控制——详解GX8006平台Mute电平配置-CSDN博客推荐链接AI语音智能体架构解析一系统架构全景图-CSDN博客AI语音智能体架构解析二大模型AI 的大脑-CSDN博客AI语音智能体架构解析三智控台指挥中心-CSDN博客AI语音智能体架构解析四AI 语音终端执行器官-CSDN博客AI语音智能体架构解析五小程序/APP遥控器-CSDN博客推荐链接AI 应用 图文 解说 (一) -- 百度智能云 实现 语音 聊天-CSDN博客AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手程序 -CSDN博客开发手记为智能设备注入“灵魂”——详解MCP工具的注册与使用在嵌入式开发中硬件驱动是设备的“躯体”而业务逻辑则是其“灵魂”。今天我们来深入探讨一下lightning项目中如何通过MCPMachine Control Protocol工具系统将简单的硬件指令封装成可供上层应用调用的、具有明确语义的功能模块。这个过程主要围绕project/ln_model_public/app/servers/qiniu/mcp_server/mcp_tools/smart_toilet/mcp_tools.c文件展开可以分为三个核心步骤定义工具语义、实现指令函数、以及注册工具。第一步定义工具语义 (Mcp的语义定义)MCP工具的核心思想是将一个功能抽象成一个结构体。这个结构体不仅包含了功能的名称更重要的是定义了它的自然语言描述和参数规范让AI或上层应用能够“理解”这个功能是做什么的以及如何使用它。以控制机械狗前进的mcp_tool_dog_forward为例1// 文件: mcp_tools.c 2 3const mcp_tool_t mcp_tool_dog_forward { 4 // 1. 工具的唯一标识名 5 .name dog.action.forward, 6 7 // 2. 工具的自然语言描述用于AI理解 8 .description 靠近的类似词语认为是前进控制机械狗向前行走。可指定持续时间单位秒例如‘向前3秒’。如果不指定时间默认前进1秒。最大支持10秒。, 9 10 // 3. 关联的处理函数 11 .call dog_forward_handler, 12 13 // 4. 是否在独立任务中执行对于有延时的操作必须为true 14 .call_in_task true, 15 16 // 5. 定义工具的参数列表 17 .properties { 18 { 19 .name duration, // 参数名 20 .type kPropertyTypeInteger, // 参数类型整数 21 .has_min_value true, // 是否有最小值 22 .min_value 1, // 最小值为1秒 23 .has_max_value true, // 是否有最大值 24 .max_value 10 // 最大值为10秒 25 }, 26 { .name NULL } // 参数列表结束标志 27 } 28};通过这样的定义一个名为dog.action.forward的工具就拥有了清晰的“身份”它知道自己是干什么的description需要什么参数properties以及具体由哪个函数来执行call。第二步实现指令函数 (Mcp工具指令函数)定义好语义后就需要实现具体的业务逻辑。dog_forward_handler函数就是mcp_tool_dog_forward的执行体。1// 文件: mcp_tools.c 2 3static cJSON *dog_forward_handler(mcp_property_t *args, int args_count) 4{ 5 int duration_sec 1; // 默认1秒 6 7 // 1. 解析参数遍历传入的参数列表查找名为 duration 的参数 8 for (int i 0; i args_count; i) { 9 mcp_property_t *prop args[i]; 10 if (strcmp(prop-name, duration) 0 prop-type kPropertyTypeInteger) { 11 duration_sec prop-value.ival; // 获取参数值 12 break; 13 } 14 } 15 16 // 2. 业务逻辑将秒转换为毫秒并进行FreeRTOS延时 17 int duration_ms duration_sec * 1000; 18 LOG(LOG_LVL_INFO, [MCP] Dog forward for %d seconds (%d ms)\r\n, duration_sec, duration_ms); 19 20 // 模拟前进动作例如通过UART发送指令 21 uint8_t cmd_buf[5] {0x55, 0x01, 0x00, 0x00, 0xAA}; // 示例指令帧 22 for(int i 0; i duration_sec * 10; i) { 23 // 构造并发送“前进”指令 24 cmd_buf[1] 0x02; 25 cmd_buf[4] cmd_buf[0] cmd_buf[1] cmd_buf[2] cmd_buf[3]; // 计算校验和 26 safe_cmd_uart_write((char*)cmd_buf, 5); 27 vTaskDelay(pdMS_TO_TICKS(100)); // 延时100ms 28 } 29 30 // 模拟停止动作 31 cmd_buf[1] 0x00; 32 cmd_buf[4] cmd_buf[0] cmd_buf[1] cmd_buf[2] cmd_buf[3]; 33 safe_cmd_uart_write((char*)cmd_buf, 5); 34 35 LOG(LOG_LVL_INFO, [MCP] Dog stop\r\n); 36 return NULL; 37}这个函数清晰地展示了MCP工具的执行流程参数解析从args数组中安全地提取出duration参数的值。逻辑执行根据参数值执行具体的硬件操作。在这里它通过一个循环持续调用我们之前实现的safe_cmd_uart_write函数向外部设备发送“前进”指令并在结束后发送“停止”指令。第三步注册工具 (Mcp的语义注册)定义和实现都完成后最后一步是将这些工具“注册”到MCP核心系统中使其生效。这个过程在mcp_tools_register_all函数中完成。1// 文件: mcp_tools.c 2 3static int mcp_tools_register_all(void) 4{ 5 int result 0; 6 // 将所有定义好的工具通过 mcp_core_register_tool 函数逐一注册 7 result | mcp_core_register_tool(mcp_tool_device_get_status); 8 result | mcp_core_register_tool(mcp_tool_device_set_volume); 9 // ... 其他工具 ... 10 result | mcp_core_register_tool(mcp_tool_dog_forward); // 注册“前进”工具 11 result | mcp_core_register_tool(mcp_tool_dog_backward); // 注册“后退”工具 12 result | mcp_core_register_tool(mcp_tool_dog_turn_left); // 注册“左转”工具 13 result | mcp_core_register_tool(mcp_tool_dog_turn_right); // 注册“右转”工具 14 // ... 更多工具 ... 15 16 return result; 17}这个函数就像一个总控开关在系统初始化时被调用将我们定义的所有“狗”的动作前进、后退、左转、右转等以及其他设备功能获取状态、设置音量等全部添加到MCP的工具列表中。总结通过“定义语义 - 实现函数 - 注册工具”这三步我们成功地将底层的硬件操作如UART通信封装成了一个个高级的、语义化的MCP工具。这种设计模式的优势非常明显高内聚低耦合每个工具都是一个独立的模块职责单一。易于扩展增加新功能时只需按照同样的模式定义、实现并注册一个新的工具即可无需修改核心框架。AI友好清晰的自然语言描述和参数定义为AI理解和调用设备功能提供了标准化的接口。这不仅是代码的组织方式更是一种让嵌入式设备变得更“智能”、更易于集成的优秀架构思想。