关于 ESP-IDF MCP
ESP-IDF MCP 是供 Agent 在连接的硬件上构建和测试 ESP-IDF 固件的本地 MCP 服务,涵盖编译、串口烧录与监控、芯片信息及硬件在环测试。
主要功能
- 01构建和清理 ESP-IDF 项目
- 02烧录固件并监控串口日志
- 03读取连接设备的芯片和闪存信息
- 04创建项目并浏览随附示例
- 05管理组件依赖并运行硬件测试
适用场景
- 01构建 ESP-IDF 项目固件
- 02向开发板烧录并检查启动输出
- 03查看已连接芯片的信息
- 04在真实硬件上运行 pytest-embedded 测试
MCP 相关
该服务向 MCP 客户端提供 ESP-IDF 项目、串口设备和硬件测试工具,还提供列出已连接串口的 project://devices 资源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
esp-idf-mcp
一个 Model Context Protocol(MCP)服务,可让 AI Agent 在真实硬件上构建、烧录和监控 ESP-IDF 项目——端到端覆盖从源代码到启动日志的完整流程。
Agent 不再只能 编写 固件代码,这个服务还打通了整个流程:编译 → 通过串口烧录 → 捕获启动日志 → 运行 pytest-embedded 硬件测试——全程无需离开 Agent 的工具集。
快速开始(Windows + Codex)
要求: ESP-IDF、Python 3.9 或更高版本,以及支持 MCP 的 Codex 客户端。只有烧录、串口监控和硬件在环测试需要连接开发板。
-
克隆此仓库,并将其安装到 Codex 将使用的 Python 环境中:
git clone https://github.com/Maty403/esp-idf-mcp.git cd esp-idf-mcp python -m pip install . -
将服务添加到 Codex。桌面应用、命令行和 IDE 扩展共用 MCP 配置。在终端中运行:
codex mcp add esp-idf -- esp-idf-mcp codex mcp list如果
esp-idf-mcp不在 PATH 中,请打开%USERPROFILE%\.codex\config.toml并添加以下内容,替换其中的两个路径。请使用运行pip install .时所用的同一个 Python 环境:[mcp_servers.esp-idf] command = "C:\\path\\to\\python.exe" args = ["C:\\path\\to\\esp-idf-mcp\\esp_idf_mcp.py"] -
重启 Codex,打开一个 ESP-IDF 项目,然后询问:“构建这个 ESP-IDF 项目。” 在桌面应用中,检查 设置 → MCP 服务,或输入
/mcp确认服务已连接。
演示工作流
打开 ESP-IDF 项目并连接开发板后,试试以下操作:
- “读取已连接芯片的信息并列出串口设备。”
- “构建这个项目。”
- “将这个项目烧录到 COM3,然后监控启动日志并总结应用程序的输出。”
请将 COM3 替换为你机器上显示的正确端口。烧录前请确认目标开发板和端口。
此服务的定位
一个由社区构建的本地 MCP 服务,适用于 ESP-IDF 硬件工作流。可用它让 AI Agent 在同一工作流中构建固件、与串口连接的开发板交互,并运行硬件在环测试。
功能对比
与 Espressif 的内置 ESP-IDF Tools MCP 服务相比(文档检查于 2026-10-26):
| 工作流 | 内置 ESP-IDF Tools MCP | esp-idf-mcp |
|---|---|---|
| 设置目标、构建、烧录、清理 | 支持 | 支持 |
| 创建项目 | 示例模板 | 最简模板或捆绑的 ESP-IDF 示例 |
| 监控设备 | 等待预期输出;保存完整串口日志 | 持久的读取/发送/关闭会话、增量和完整日志视图、波特率检测,以及 USB 重连处理 |
| 项目和设备上下文 | 项目配置、构建状态、已连接设备资源 | 已连接设备资源,以及芯片型号、版本、晶振、MAC 和闪存详情 |
| 组件和硬件测试 | 未列于内置 Tools MCP 工具集 | 浏览捆绑的示例、添加/移除组件依赖项,并运行 pytest-embedded 硬件测试 |
此表对比的是本地 Tools MCP 服务与本项目。Espressif 的独立 Documentation MCP 和 Component Registry MCP 服务提供文档和组件发现功能;它们可以与任一本地工具服务搭配使用。
功能
- ESP-IDF 零配置发现 — 自动定位 IDF 根目录、工具目录和 Python 虚拟环境(优先使用环境变量,否则选择
D:\esp、C:\esp或~/esp下最新的安装);工具链路径按版本通配符匹配,因此升级 ESP-IDF 或工具链时无需编辑脚本。 - 通过
idf.py build构建 — 与手动构建使用完全相同的路径,不会额外改写配置。因此,sdkconfig和sdkconfig.defaults保持官方上游语义:默认文件用于初始化新的sdkconfig(通用的sdkconfig.defaults,以及通用文件存在时的sdkconfig.defaults.<target>),而后续构建时,sdkconfig中已有的值优先。对sdkconfig的手动编辑会通过官方 ninjaRERUN_CMAKE流程生效。 - 一次调用完成烧录和自动监控 — 使用
esptool烧录(读取build/flash_args),等待硬复位启动完成,然后在该端口上打开持久监控会话并立即返回——开发板会复位,因此会话只保留最新的启动日志;使用monitor_read轮询。目标端口就是你传入的端口(省略时会自动检测,但只有在恰好连接了一个非 COM1 端口时才会检测——否则调用会拒绝执行并列出候选端口);烧录前只会关闭该端口的监控会话(若没有会话则跳过),不会影响其他开发板。 - 从真实硬件读取芯片信息 —
read_chip_info通过 esptool 报告芯片型号、版本、特性、晶振、MAC 地址,以及闪存厂商、设备和容量,然后硬复位开发板,使其重新进入运行中的应用。 - 自动检测波特率 — 每次串口采集都会从项目的
sdkconfig读取CONFIG_ESP_CONSOLE_UART_BAUDRATE(不使用硬编码默认值),因此日志不会乱码。 - 基于会话的串口监控 —
monitor_open/monitor_read/monitor_send/monitor_close:创建持久、非阻塞的会话,只需轮询获取新增行。monitor_close(session_id)只会释放你指定的会话,或者指定端口上的所有会话。每次烧录后,flash_project都会自动打开一个会话,因此启动日志随时可供轮询。会话会自动释放:在idle_release秒(默认 30,可在每次调用时覆盖)内没有读写操作后,端口就会释放,因此被遗弃的会话不会一直占用 COM 端口。 - 应用层日志视图 —
monitor_read从运行时标记main_task: Returned from app_main()开始输出:此前的所有内容(启动 ROM、引导加载程序和组件日志,以及你的app_main()初始化输出)都会折叠,并在标题中汇总为N lines folded before app start;标记及其后的所有行(你的任务、wifi、mqtt、普通printf)则逐行打印。不包含标记的增量内容若为普通续行,会原样打印;若仍处于启动阶段,则会折叠。 full应急选项 + 持久化完整日志 —monitor_read(full=True)会原样转储缓冲区中保留的所有内容(不拆分层级、不折叠、不改动时间戳),且不会消耗增量读取游标——两种读取模式互不影响。此外,每行串口日志都会写入会话日志文件(<project>/.esp_monitor_full.log),因此即使缓冲区淘汰日志、USB 重新枚举、开发板复位或会话关闭,历史记录也会保留。读取不会丢失信息——所有折叠内容都会在标题中计数,被淘汰的内容则保存在文件中。- 便于 Agent 使用的输出 — 在源头去除 ANSI 颜色转义,将相邻重复行合并为
<first line> *N,让重复内容紧邻其计数显示(比较时忽略行首的I (12345)前缀,因此不同毫秒记录的行也会合并);仅保留长输出中相关的尾部内容,并在标题中报告被淘汰或跳过的数量,而不是静默丢弃行。 - 可应对 USB 重新枚举 — 复位后,端口可能会消失再重新出现(ESP32-S2/USB-OTG);读取循环会在最多 10 s 内尝试重新连接,并清除过期的缓冲日志。
- 硬件在环测试 — 使用
pytest-embedded测试套件对真实开发板运行测试。 其中包含针对 Windowsusbser.sys的变通方案(仅 RTS 的控制传输需要重新断言 DTR),因此在 USB-CDC 端口和 CH340 风格的适配器上都能正常复位。
工具
| 工具 | 用途 |
|---|---|
build_project | idf.py build(与手动构建相同,不会重写配置) |
flash_project | 使用 esptool 烧录;省略 port 时会自动检测(仅当恰好连接一个非 COM1 端口时才会自动检测——否则调用会拒绝执行并列出候选端口);烧录前仅关闭该端口的监视器会话,然后在该端口上打开一个持久监视器会话(波特率取自 sdkconfig),供 monitor_read 使用 |
read_chip_info | 芯片型号、修订版、特性、晶振、MAC、闪存厂商/设备/容量 |
set_target | idf.py set-target(esp32、esp32s3、esp32c2……) |
create_project / list_examples | 创建新项目(最小模板或打包的官方示例);浏览已安装 IDF 随附的示例 |
add_dependency / remove_dependency | 管理 idf_component.yml 中的 ESP 组件管理器依赖项 |
clean_project | 增量清理或完全清理 |
monitor_open / monitor_read / monitor_send / monitor_close | 持久交互式串口会话;monitor_read 从 Returned from app_main() 开始(此前的所有内容折叠为一个计数),将相邻重复项折叠为 <first line> *N,提供 full=True,用于不受游标影响地转储所有保留内容;提供 timestamp=True 以保留毫秒前缀,并将每一行写入 <project>/.esp_monitor_full.log;monitor_close(session_id)(或直接传入端口名称)会释放且仅释放对应会话/端口;会话在 idle_release 秒(默认 120 秒)内没有读/写操作后会自动释放 |
run_pytest | 运行 pytest-embedded 硬件测试 |
project://devices(资源) | 列出已连接的串口 |
工具参考
每个工具向 Agent 完整公开的描述:
build_project(project_dir, timeout=600) — 通过 idf.py build 构建 ESP-IDF 项目(与手动构建相同)。timeout 限制整个构建过程的秒数(默认 600);超时后会终止进程树,并返回包含提取出的错误行的失败结果。每次调用都会明确给出 ✅/❌ 结果。完整输出始终写入 <project_dir>/.esp_build.log,每次运行都会重写该文件。配置不会被修改:sdkconfig.defaults 用于初始化新的 sdkconfig,而 sdkconfig 中已有的值优先。
flash_project(project_dir, port=None, monitor=True, wait_after_flash=2.0, timeout=600) — 直接使用 esptool 烧录已构建的项目(读取 build/flash_args)。烧录前会自动关闭目标端口上的监视器会话——无需手动调用 monitor_close。省略 port 时会自动检测,但仅当恰好连接一个非 COM1 端口时才会检测;若连接了多个端口,调用会拒绝执行并列出这些端口,因此绝不会将固件烧录到错误的开发板上。monitor=True 会在烧录后打开持久会话(波特率取自 sdkconfig);wait_after_flash 会等待硬复位启动完成后再打开监视器,从而让会话获取干净的启动日志。timeout 限制整个烧录过程的秒数(默认 600)。完整输出始终写入 <project_dir>/.esp_flash.log,每次运行都会重写该文件。
create_project(path, example='') — 在绝对路径 path 下创建新的 ESP-IDF 项目(该路径必须不存在或为空)。设置 example 后(例如 'get-started/hello_world'),项目会从已安装 IDF 随附的官方示例复制而来——使用 list_examples 浏览这些示例;如果找到根目录中的 project(),会将其名称改为新目录的名称。未设置 example 时,会通过 idf.py create-project 创建最小模板项目。两种方式都完全离线;若要将注册表组件引入新项目,请之后调用 add_dependency(组件会在下一次构建时下载)。
list_examples(category='') — 列出已安装 IDF 中附带的 ESP-IDF 官方示例。不带参数时,列出类别(get-started、wifi、peripherals 等);指定类别时,列出其中的示例,路径可直接用于 create_project(example=…)。
read_chip_info(port=None, baud=115200) — 通过 esptool 获取芯片型号、修订版本、功能、晶振频率、MAC 地址以及闪存厂商、设备和容量信息。开发板会短暂进入下载模式,之后硬件复位并恢复运行应用。此处无法获取 PSRAM 详情——请改用 monitor_open 读取启动日志。
monitor_open(port, reset=True, project_dir=None, idle_release=120, baud=0) — 打开持久串口监视器会话并立即返回(非阻塞)。reset=True 会先清空缓冲区,再对开发板进行硬件复位,因此会话从全新启动开始。baud > 0 时会直接使用指定波特率并跳过自动检测;默认 baud=0 时,会从 project_dir 的 sdkconfig(CONFIG_ESP_CONSOLE_UART_BAUDRATE,回退到 115200)自动检测波特率。project_dir 还会将会话的完整日志写入 <project_dir>/.esp_monitor_full.log(每次打开会话时都会从头重写;在会话期间,每行到达时都会立即写入,因此即使缓冲区淘汰、重新连接或开发板复位,历史记录也会保留;未指定项目目录时,会话不会保存完整日志文件)。会话 ID 为 PORT@BAUD(例如 COM17@115200)。idle_release 设置会话在没有 monitor_read/monitor_send 操作时的存续秒数(默认 120):超过此时长后,会话会自行停止并释放端口,因此即使客户端遗弃会话(MCP 客户端通常会让服务进程继续运行,而不关闭 stdio 管道),也不会一直占用 COM 端口——包括 USB 拔出后重新插入的情况,因为否则读取循环可能会再次占用端口。每次调用 monitor_read/monitor_send 都会重置计时器;若要跨越较长时间的暂停,请传入更大的值,或在完成后显式调用 monitor_close。如果调用报告 No session,只需再次调用 monitor_open——完整历史记录保存在日志文件中。
monitor_read(session_id, full=False, timestamp=False, max_lines=0, match='') — 读取自上次读取以来到达的行。输出从运行时标记 main_task: Returned from app_main() 开始:此标记之前的所有内容(启动日志和 app_main() 初始化信息)都会合并计数,报告为 N lines folded before app start;标记及之后的每一行都会逐行打印。相邻的重复行会合并为 <first line> *N,因此重复内容始终会与计数一起显示(比较时会忽略前缀 I (12345) ,因此即使行日志记录在不同毫秒,也会合并)。没有标记的增量内容,如果是普通的延续内容,则会按原样打印;如果仍处于启动阶段,则会被合并。full=True 会切换到与游标无关的完整转储:逐字输出环形缓冲区中保留的所有行(不合并、不分层,保留时间戳),且不会推进增量游标,因此合并视图和完整视图互不影响。max_lines 限制返回的尾部行数(0 = 返回所有保留内容)。适用时,标头会报告 M evicted by buffer cap 和 K older skipped (showing last T),并显示完整日志文件路径——从环形缓冲区淘汰的行不会丢失,而是保存在文件中。timestamp=True 会保留毫秒前缀(默认会将其移除,显示为 TAG: msg)。
match 按正则表达式筛选输出(不区分大小写,匹配去掉级别/毫秒前缀后的行文本;| 用于分隔多个选项,例如 match='heap|wifi|dhcp')。设置此参数后,会跳过应用启动日志折叠,仅返回匹配的行,适合从嘈杂的日志中提取某个主题。对诊断至关重要的行始终会通过筛选,即使它们没有匹配项:所有 ESP_LOG 错误级别行(E (…)),以及不带日志级别前缀的 panic 处理程序输出(Guru Meditation / panic'ed、abort() was called、assert failed、Backtrace:、堆栈金丝雀、看门狗和 brownout 触发信息、CORRUPT HEAP、核心转储、重置原因、Rebooting…)——筛选视图绝不会隐藏崩溃。未通过筛选的行仍会由增量游标读取;将 match 与 full=True 结合使用,可使用相同的筛选条件重新扫描缓冲区中保留的所有内容。
monitor_send(session_id, data, press_enter=True) — 向设备的串行输入端写入文本(shell 命令、菜单选项);press_enter 会追加 CRLF。
monitor_close(session_id) — 释放一个会话(COM17@115200),或释放裸端口上的所有会话(COM17)。没有全部释放模式。
set_target(project_dir, target) — 对 esp32 / esp32s3 / esp32c2 / … 执行 idf.py set-target。请注意,idf.py 会将现有的 sdkconfig 重命名为 sdkconfig.old,并为新目标生成一个全新的文件。
add_dependency(project_dir, dependency, component=None, path=None) / remove_dependency(project_dir, dependency) — 管理 ESP 组件管理器清单 idf_component.yml;组件会在下次构建时获取或移除。
clean_project(project_dir, full=False) — 执行 idf.py clean 或 fullclean(仅处理构建产物;绝不会修改 sdkconfig)。
run_pytest(project_dir, ...) — 针对真实开发板运行 pytest-embedded 硬件测试(烧录 + 交互 + 断言串行输出)。
资源 project://devices — 已连接串行端口的 JSON 列表。
要求
- ESP-IDF(在 Windows 上基于 v6.1 开发;只要自动检测或以下环境变量能找到安装位置,其他目录布局也适用)
- Python ≥ 3.9,需安装
mcp和pyserial - 任意 MCP 客户端(Claude Desktop、Cursor、VS Code 等)
设置
选项 A — 安装为软件包
pip install .
选项 B — 直接运行单个文件
只需将 MCP 客户端指向 esp_idf_mcp.py,并使用安装了 mcp + pyserial 的任意 Python(ESP-IDF 虚拟环境很适用)。
注册到 MCP 客户端
{
"mcpServers": {
"esp-idf": {
"command": "python",
"args": ["C:\\path\\to\\esp_idf_mcp.py"]
}
}
}
(如果通过 pip 安装,也可以不带参数,使用 "command": "esp-idf-mcp")
配置
启动时会自动定位 ESP-IDF:首先检查环境变量,然后查找 D:\esp\<ver>\esp-idf、C:\esp\<ver>\esp-idf 或 ~/esp/<ver>/esp-idf 下最新的安装版本。工具目录的备用位置依次为 C:\Espressif\tools 和 D:\espressif\tools。所有路径都可以从外部覆盖:
| 环境变量 | 含义 |
|---|---|
IDF_PATH | ESP-IDF 框架根目录(覆盖自动检测结果) |
IDF_PYTHON_ENV_PATH | ESP-IDF Python 虚拟环境(默认:<tools>\python\*\venv 下最新的环境) |
IDF_TOOLS_PATH | Espressif 工具目录(默认:C:\Espressif\tools,然后是 D:\espressif\tools) |
ESP_IDF_VERSION | 版本标签——从 IDF 目录名中提取并去掉开头的 v(v6.1 → 6.1),以便组件管理器解析 |
IDF_COMPONENT_MANAGER | 强制设为 1,以便 idf.py add-dependency 和托管组件正常解析 |
工具路径下的工具链目录(xtensa/riscv GCC、CMake、Ninja、ccache、idf-exe、esp-rom-elfs)会根据版本通配符匹配,并添加到 PATH 的前面。启动时会向 stderr 打印一行诊断信息(IDF_PATH=… TOOLS=… PYENV=…)。
典型 Agent 工作流
read_chip_info → set_target(esp32s3) → build_project → flash_project(port="COM17")
→ monitor_read(session_id) → iterate on code → run_pytest
支持
如果这个服务帮你减少了固件调试的反复折腾,请点个星,或请作者喝杯咖啡:
| 支付宝 | Binance Pay |
|---|---|
![]() | ![]() |
| 扫码支付 | 在 Binance 应用中扫码 |
| USDT(TRC-20) | USDT(BEP-20 / BSC) |
|---|---|
![]() | ![]() |
扫码,或复制地址:TL4j1mRbfjQBEGpqBbRTEYHvJABxCi3tkQ | 扫码,或复制地址:0x1572a9a6ce3da8b55c6cfc67e5b0557f3f10d423 |
USDT:仅可通过 BSC / BEP-20 转账——使用任意 EVM 钱包扫描该地址,或直接复制地址。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。



