ESP IoT Solution 的 MCP C SDK 工具与数据 API 深度指南
2026/9/19 18:39:09 网站建设 项目流程

ESP IoT Solution 的 MCP C SDK 工具与数据 API 深度指南

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

本篇技术指南以 docs/zh_CN/mcp/tooling_and_data.rst 为骨架,系统讲解 ESP IoT Solution 中mcp-c-sdk组件的三类核心接口:工具(Tool)定义与执行接口、公共属性(Property)接口、数据值(Value)接口。读完本文,你将掌握如何在 ESP32 设备上注册可被 AI Agent 发现与调用的 MCP 工具、为工具声明带类型校验与范围约束的参数 Schema,并构造符合 MCP 规范的多内容块工具调用结果,从而为端侧设备接入 Model Context Protocol 打下坚实基础。

前置阅读:本文属于 MCP 系列文档中的"工具与数据"篇,建议先阅读 core_and_manager.rst 了解 MCP 实例的创建与管理流程,再结合 prompt_resource_completion.rst 了解资源、提示与补全接口。

接口总览:三组 API 的职责划分

原文档将本节划分为三个子接口,各自对应独立头文件:

接口类别文档章节头文件职责
工具接口(Tool APIs)工具接口include/esp_mcp_tool.h工具对象创建、元数据配置、属性绑定、执行结果构建、工具列表管理
属性接口(Property APIs)属性接口include/esp_mcp_property.h属性(工具入参 Schema)的创建、类型声明、默认值与范围约束
数据值接口(Data Value APIs)数据值接口include/esp_mcp_data.h统一的值对象(bool/int/float/string),用于回调返回值

三者层次分明:数据值是回调函数的返回值载体,属性定义了工具入参的结构,工具则把属性与回调绑定为一个可被tools/call调用的完整单元。其对应实现位于 src/esp_mcp_tool.c、src/esp_mcp_property.c 与 src/esp_mcp_data.c,并可通过 test_apps/main/test_mcp_c_sdk.c 中的单元测试验证各接口的实际行为。

工具接口:从声明到执行的完整链路

工具对象与两种回调类型

工具在 SDK 中是不透明结构体esp_mcp_tool_t,其核心是执行回调。SDK 提供两档回调能力:

// 基础回调:接收入参属性列表,返回一个 MCP 值 typedef esp_mcp_value_t (*esp_mcp_tool_callback_t)(const esp_mcp_property_list_t *properties); // 扩展回调:可填充完整的 CallToolResult(多内容块、structuredContent、isError) typedef esp_err_t (*esp_mcp_tool_callback_ex_t)(const esp_mcp_property_list_t *properties, esp_mcp_tool_result_t *result);

基础回调(esp_mcp_tool_callback_t)适合返回单个文本结果的简单工具;扩展回调(esp_mcp_tool_callback_ex_t)则面向需要返回图片、音频、资源链接、结构化数据或显式错误标记的复杂工具。回调入参properties可能为 NULL,实现时需做防御性处理(见 esp_mcp_tool.h)。

创建工具:基础版与扩展版

esp_mcp_tool_t *esp_mcp_tool_create(const char *name, const char *description, esp_mcp_tool_callback_t callback); esp_mcp_tool_t *esp_mcp_tool_create_ex(const char *name, const char *title, const char *description, esp_mcp_tool_callback_ex_t callback);
  • namedescription均不可为 NULL,二者会被内部strdup复制(见 esp_mcp_tool.c),因此调用方可安全复用栈上字符串。
  • esp_mcp_tool_create_ex额外接受可空的title显示标题;扩展回调通过callback_ex字段存储,执行时优先于基础回调(见 esp_mcp_tool.c)。
  • 任一步内存分配失败都会返回 NULL,调用方需检查返回值。

工具的元数据配置

创建之后,可通过以下 Setter 为工具补充 MCP 规范中的可选元数据(均接受 NULL 以清除,见 esp_mcp_tool.h):

函数作用说明
esp_mcp_tool_set_title设置显示标题对应 MCP 工具title字段
esp_mcp_tool_set_icons_json设置图标元数据传入 JSON 数组/对象字符串,序列化时解析为icons字段
esp_mcp_tool_set_output_schema_json设置输出 JSON Schema必须为 JSON 对象,序列化为outputSchema
esp_mcp_tool_set_annotations_json设置注解元数据JSON 对象,序列化为annotations
esp_mcp_tool_set_task_support设置任务支持模式仅接受"required""optional""forbidden"三者之一,非法值返回ESP_ERR_INVALID_ARG

其中esp_mcp_tool_set_task_support的取值校验在 esp_mcp_tool.c 中硬编码实现;当设置非空时,JSON 序列化会输出execution: { "taskSupport": ... }字段,用于向客户端声明该工具在任务增强(task-augmented)模式下的支持程度。

为工具绑定属性 Schema

esp_err_t esp_mcp_tool_add_property(esp_mcp_tool_t *tool, esp_mcp_property_t *property); esp_err_t esp_mcp_tool_remove_property(esp_mcp_tool_t *tool, esp_mcp_property_t *property);

工具内部持有一个属性列表tool->properties。绑定属性后,工具被序列化为tools/list响应时会自动生成inputSchema(类型固定为"object"additionalProperties: false),并将所有没有默认值的属性自动列入required数组——该逻辑由esp_mcp_tool_required_props_cb实现,逐属性检查has_default_value标记(见 esp_mcp_tool.c 与 esp_mcp_tool.c)。这意味着:想让某个入参可选,只需在创建属性时提供默认值。

完整的 JSON 序列化由esp_mcp_tool_to_json完成(见 esp_mcp_tool.c),返回的字符串由调用方负责cJSON_free释放。

工具执行:esp_mcp_tool_call 的内部流程

esp_mcp_tool_call(tool, properties)是工具执行的统一入口(见 esp_mcp_tool.c),其流程为:

  1. 创建结果构建器esp_mcp_tool_result_create()
  2. 若设置了扩展回调callback_ex,直接调用之;回调返回非ESP_OK时自动置isError=true,若内容为空则追加"Tool execution failed"文本块;
  3. 否则走基础回调:将返回的esp_mcp_value_t按类型(bool/int/float/string)转换为文本内容块——布尔输出"true"/"false",整数与浮点分别用%d%g格式化,字符串原样输出;
  4. 最终把结果构建器序列化为包含contentisError(以及可选的structuredContent)的 JSON-RPC 结果对象并返回字符串。

工具结果构建器:构造丰富的 CallToolResult

扩展回调通过esp_mcp_tool_result_t构建结果。其内部实现是一个 cJSON 内容数组 + 可选的structuredContent对象(见 esp_mcp_tool.c)。构建器提供以下 API:

函数生成的内容块序列化说明
esp_mcp_tool_result_create/_destroy创建/销毁构建器
esp_mcp_tool_result_set_is_error设置isError应用级错误标记
esp_mcp_tool_result_add_texttext输出{type:"text", text}
esp_mcp_tool_result_add_image_base64image输出{type:"image", mimeType, data}
esp_mcp_tool_result_add_audio_base64audio输出{type:"audio", mimeType, data}
esp_mcp_tool_result_add_resource_linkresource_link输出{type:"resource_link", uri, name?, description?, mimeType?}
esp_mcp_tool_result_add_embedded_resource_textresource内嵌文本资源{type:"resource", resource:{uri, mimeType, text}}
esp_mcp_tool_result_add_embedded_resource_blobresource内嵌 Base64 资源{type:"resource", resource:{uri, mimeType, blob}}
esp_mcp_tool_result_set_structured_json设置structuredContent,必须为合法 JSON 对象,否则返回ESP_ERR_INVALID_ARG

资源占用限制(默认值):为保护嵌入式设备内存,SDK 在未通过 Kconfig 配置时使用默认上限——文本内容块最大 8192 字节(CONFIG_MCP_TOOL_RESULT_TEXT_MAX_LEN),图片/音频等 Base64 块最大 65536 字节(CONFIG_MCP_TOOL_RESULT_BLOB_MAX_LEN),超限会返回ESP_ERR_INVALID_SIZE(见 esp_mcp_tool.c 与 esp_mcp_tool.c)。

工具列表:线程安全的注册与查询

esp_mcp_tool_list_*系列 API(见 esp_mcp_tool.h 与 esp_mcp_tool.c)提供工具集合管理,内部使用 FreeRTOS 互斥量保护:

  • esp_mcp_tool_list_create/esp_mcp_tool_list_destroy:创建/销毁列表(销毁时递归销毁所有工具);
  • esp_mcp_tool_list_add_tool/esp_mcp_tool_list_remove_tool:增删工具(基于SLIST单向链表);
  • esp_mcp_tool_list_find_tool:按名称查找工具;
  • esp_mcp_tool_list_foreach:遍历回调;
  • esp_mcp_tool_list_is_empty:判空。

多线程场景下这些操作均受互斥保护,且同名工具重复添加会返回ESP_ERR_INVALID_STATE——在 test_apps/main/test_mcp_c_sdk.c 的thread_test_task中可以看到 4 个线程并发注册工具的测试,重复注册时调用方需自行销毁重复的工具对象。

属性接口:声明工具入参的 Schema

属性类型枚举

属性支持的六种类型定义在 esp_mcp_property.h:

typedef enum esp_mcp_property_type_e { ESP_MCP_PROPERTY_TYPE_BOOLEAN, // 布尔 ESP_MCP_PROPERTY_TYPE_INTEGER, // 整数 ESP_MCP_PROPERTY_TYPE_FLOAT, // 浮点 ESP_MCP_PROPERTY_TYPE_STRING, // 字符串 ESP_MCP_PROPERTY_TYPE_ARRAY, // JSON 数组 ESP_MCP_PROPERTY_TYPE_OBJECT, // JSON 对象 ESP_MCP_PROPERTY_TYPE_MAX, // 保留 } esp_mcp_property_type_t;

创建属性:类型工厂 + 范围约束

创建函数分为两组(见 esp_mcp_property.h):

带默认值的工厂——esp_mcp_property_create_with_bool/int/float/string/array/object,分别对应六种类型。其中:

  • 字符串默认值不可为 NULL;
  • 数组与对象默认值必须是合法 JSON 字符串;
  • 带默认值的属性在工具序列化时不会进入required列表。

带范围约束的工厂——用于整数参数的校验:

  • esp_mcp_property_create_with_range(name, min, max):无默认值,创建整数属性并声明最小/最大值;
  • esp_mcp_property_create_with_int_and_range(name, default, min, max):带默认值的整数 + 范围,默认值必须落在[min, max]内。

范围约束会被写入工具序列化后的inputSchema.properties.<name>,使 AI 客户端在调用前就能感知合法的参数区间;SDK 层面同时提供内置参数校验(类型检查 + 范围约束),参见 README.md 中 "Parameter Validation" 能力说明。

从属性列表读取入参

工具回调收到的esp_mcp_property_list_t *properties需通过以下 getter 取值(见 esp_mcp_property.h):

bool esp_mcp_property_list_get_property_bool(const esp_mcp_property_list_t *list, const char *name); int esp_mcp_property_list_get_property_int(const esp_mcp_property_list_t *list, const char *name); float esp_mcp_property_list_get_property_float(const esp_mcp_property_list_t *list, const char *name); const char *esp_mcp_property_list_get_property_string(const esp_mcp_property_list_t *list, const char *name); const char *esp_mcp_property_list_get_property_array(const esp_mcp_property_list_t *list, const char *name); const char *esp_mcp_property_list_get_property_object(const esp_mcp_property_list_t *list, const char *name);

注意取值语义:

  • 数值类型在"属性不存在或类型不匹配"时返回安全默认值(false/0/0.0f),不会报错,因此在回调中无法仅凭返回值区分"缺参"与"值为 0",如需严格校验应在工具描述中约束客户端行为;
  • 字符串、数组、对象 getter 返回的是内部指针,调用方不得 free;找不到时返回 NULL,回调需做 NULL 检查。

数据值接口:回调返回值的统一载体

值类型与数据联合体

esp_mcp_value_t由类型字段 + 数据联合体构成(见 esp_mcp_data.h):

typedef enum { ESP_MCP_VALUE_TYPE_INVALID = -1, // 错误态 ESP_MCP_VALUE_TYPE_BOOLEAN, // 布尔 ESP_MCP_VALUE_TYPE_INTEGER, // 有符号 32 位整数 ESP_MCP_VALUE_TYPE_FLOAT, // 32 位浮点 ESP_MCP_VALUE_TYPE_STRING // 字符串 } esp_mcp_value_type_t; typedef union { bool bool_value; int int_value; float float_value; char *string_value; // 指向动态分配内存 } esp_mcp_value_data_t; typedef struct { esp_mcp_value_type_t type; esp_mcp_value_data_t data; } esp_mcp_value_t;

只有与type对应的联合体成员才是有效的,访问前务必确认类型。对于STRING类型,string_value指向由 SDK 内部strdup动态分配的内存,由esp_mcp_value_destroy()负责释放。

创建与销毁

esp_mcp_value_t esp_mcp_value_create_bool(bool value); esp_mcp_value_t esp_mcp_value_create_int(int value); esp_mcp_value_t esp_mcp_value_create_float(float value); esp_mcp_value_t esp_mcp_value_create_string(const char *value); esp_err_t esp_mcp_value_destroy(esp_mcp_value_t *value);
  • esp_mcp_value_create_string会复制输入字符串,调用方随后可安全释放或修改原始字符串;当入参为 NULL 或内存分配失败时返回类型为ESP_MCP_VALUE_TYPE_INVALID的值,使用前务必检查该类型(见 esp_mcp_data.h)。
  • esp_mcp_value_destroy会释放字符串内存,销毁后不可再使用该值结构。

综合示例:一个带范围校验的音量控制工具

结合 README.md 的 Quick Start 与测试用例(test_mcp_c_sdk.c 中的各类回调),完整落地一个工具:

#include "esp_mcp_engine.h" #include "esp_mcp_mgr.h" #include "esp_mcp_tool.h" #include "esp_mcp_property.h" #include "esp_mcp_data.h" static int current_volume = 50; // 基础回调:读取 int 属性并返回 bool 值 static esp_mcp_value_t set_volume_callback(const esp_mcp_property_list_t *properties) { int volume = esp_mcp_property_list_get_property_int(properties, "volume"); if (volume < 0 || volume > 100) { ESP_LOGE(TAG, "Invalid volume value: %d", volume); return esp_mcp_value_create_bool(false); } current_volume = volume; return esp_mcp_value_create_bool(true); } // 扩展回调:演示多内容块 + 结构化结果 static esp_err_t read_status_callback(const esp_mcp_property_list_t *properties, esp_mcp_tool_result_t *result) { char buf[64]; snprintf(buf, sizeof(buf), "{\"volume\":%d}", current_volume); ESP_RETURN_ON_ERROR(esp_mcp_tool_result_add_text(result, "Current volume status:"), TAG, "add text"); ESP_RETURN_ON_ERROR(esp_mcp_tool_result_set_structured_json(result, buf), TAG, "set structured"); return ESP_OK; } void app_main(void) { esp_mcp_t *mcp = NULL; ESP_ERROR_CHECK(esp_mcp_create(&mcp)); // 基础工具:入参带范围约束,无默认值 -> 自动进入 required esp_mcp_tool_t *tool = esp_mcp_tool_create( "audio.set_volume", "Set audio speaker volume (0-100)", set_volume_callback ); esp_mcp_tool_add_property(tool, esp_mcp_property_create_with_range("volume", 0, 100)); ESP_ERROR_CHECK(esp_mcp_add_tool(mcp, tool)); // 扩展工具:结构化输出 esp_mcp_tool_t *tool2 = esp_mcp_tool_create_ex( "audio.get_status", "Get Audio Status", "Query current audio status", read_status_callback ); ESP_ERROR_CHECK(esp_mcp_add_tool(mcp, tool2)); esp_mcp_mgr_handle_t mcp_handle = 0; esp_mcp_mgr_config_t config = MCP_SERVER_DEFAULT_CONFIG(); config.instance = mcp; ESP_ERROR_CHECK(esp_mcp_mgr_init(config, &mcp_handle)); ESP_ERROR_CHECK(esp_mcp_mgr_start(mcp_handle)); }

上述代码串联了本文全部三类接口:属性声明volume入参并带[0,100]范围约束,工具绑定回调并注册到 MCP 实例,数据值作为回调返回载体。客户端通过tools/list即可发现audio.set_volume与其自动生成的inputSchema,通过tools/call传入{"volume": 80}即可触发回调执行。

深入阅读与验证

  • 完整 Quick Start 与能力矩阵:components/mcp-c-sdk/README.md,其中包含tools/list分页(cursor + limit,上限 128)、任务增强调用(params.task)等协议层行为说明;
  • 可运行示例:examples/mcp/mcp_server 与 examples/mcp/mcp_client 展示了服务端工具注册与客户端调用的完整工程;
  • 单元测试:test_apps/main/test_mcp_c_sdk.c 覆盖了 bool/int/float/string 回调、多类型属性取值、扩展回调内容块、并发注册等场景,是验证 API 语义的最佳参考;
  • 协议与版本:SDK 默认面向 MCP 协议2025-11-25,同时保留2024-11-05的兼容(Kconfig 可选),详见组件 README 与 Kconfig。

以上即工具与数据 API 的完整解析:从工具声明、参数 Schema、执行回调到结果构建,每一环都有源码实现与测试佐证,可直接支撑你在 ESP32 上开发可被 AI 调用的 MCP 服务。

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询