关于 OpenOCD Debugger
OpenOCD Debugger 是通过 OpenOCD 调试微控制器的 MCP 服务,面向使用 MCP 兼容客户端的固件开发者。它结合执行控制、状态检查、按名称读取变量与外设寄存器,并提供可配置的安全限制。
主要功能
- 01烧录并验证固件映像
- 02暂停、继续、单步和复位目标
- 03条件断点与监视点
- 04按 ELF 符号名读取变量
- 05依据 CMSIS-SVD 解码外设寄存器
- 06对高风险操作设置权限门控
适用场景
- 01烧录并重新启动微控制器固件
- 02用监视点追查内存写入
- 03在 CPU 不暂停时观察变量
- 04读取具名外设寄存器和位域
MCP 相关
向 MCP 客户端提供基于 OpenOCD 的固件烧录、执行控制、断点、内存访问及变量和外设寄存器检查。服务还可启动 OpenOCD,并对操作应用安全权限限制。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
OpenOCD MCP 服务
直接从 AI 助手调试微控制器。这是一个MCP 服务,可驱动 OpenOCD,让任何兼容 MCP 的 AI 都能烧录固件、控制执行并检查正在运行的目标设备,还能按名称读取变量和外设寄存器,而非使用原始地址。
描述
通过调试探针(ST-Link、J-Link、CMSIS-DAP 等)连接到目标设备后, 你的 AI 助手可以:
- 烧录固件 — 编程并验证
.elf/.bin/.hex镜像 - 控制执行 — 暂停、继续、单步执行、复位
- 检查状态 — 读取/写入 CPU 寄存器和内存
- 设置断点 — 硬件和软件断点,包括条件断点 (仅在表达式为真时暂停)和命中次数断点
- 监视内存 — 硬件观察点,在读取/写入/访问某个地址时暂停
- 按名称读取变量 — 从固件的
.elf符号中读取(例如read_variable uart_rx_count) - 实时监视变量 — 在一段时间内采样变量的窗口,不会暂停 CPU;根据 DWARF 自动识别类型,可展开结构体/数组(有符号整数/浮点数/指针/枚举)
- 按名称读取外设寄存器 — 从 CMSIS-SVD 文件读取,并解码为具名位域(例如
RCC.CR、GPIOA.MODER) - 安全保护 — 权限层(只读模式、受控擦除闪存、闪存路径/大小限制),避免 Agent 意外损坏目标设备
此服务不依赖特定芯片——它适用于 OpenOCD 支持的任何目标设备;只需指定芯片配置以及(可选的)SVD/ELF 文件。它还可以代你启动 OpenOCD,并自动下载适用于你平台的 OpenOCD,无需手动安装其他内容。
支持的 AI 客户端
任何兼容 MCP 的客户端都可使用。经测试且确认可用的客户端:
| 客户端 | 平台 |
|---|---|
| Claude Code | 命令行 / IDE |
| Claude Desktop | macOS / Windows |
| Cursor | IDE |
| Windsurf | IDE |
| Cline | VS Code 扩展 |
| Continue | VS Code / JetBrains |
| Zed | 编辑器 |
| VS Code + GitHub Copilot | IDE(Agent 模式) |
| Gemini CLI | 命令行 |
安装
前置条件: Python 3.10+,以及已连接到目标设备的调试探针。
克隆项目,并将软件包安装到虚拟环境中:
git clone https://github.com/microhenrio/openocd-mcp
cd openocd-mcp
python -m venv .venv
安装软件包(会创建 openocd-mcp 命令):
# Windows
.venv\Scripts\python -m pip install -e .
# macOS / Linux
.venv/bin/python -m pip install -e .
Windows 快捷方式: 运行
setup.bat——它会创建环境、安装软件包, 并自动将其注册到 Claude Code。
OpenOCD 会自动获取:首次连接时,会下载适用于你操作系统/架构的构建版本并缓存(经校验和验证)。你也可以提前运行 openocd-mcp install-openocd 获取,或者设置 OPENOCD_BIN 环境变量来使用已有安装。
在 AI 客户端中注册
服务可执行文件为:
# Windows
<repo>\.venv\Scripts\openocd-mcp.exe
# macOS / Linux
<repo>/.venv/bin/openocd-mcp
Claude Code
# Windows
claude mcp add --scope user openocd -- "%CD%\.venv\Scripts\openocd-mcp.exe"
# macOS / Linux
claude mcp add --scope user openocd -- "$PWD/.venv/bin/openocd-mcp"
重启 Claude Code,然后使用 claude mcp list 验证。
Claude Desktop
将以下内容添加到 claude_desktop_config.json(编辑 → 设置 → 开发者 → 编辑配置):
{
"mcpServers": {
"openocd": {
"command": "/path/to/.venv/bin/openocd-mcp"
}
}
}
重启 Claude Desktop。
Cursor
将以下内容添加到 ~/.cursor/mcp.json(或项目中的 .cursor/mcp.json):
{
"mcpServers": {
"openocd": {
"command": "/path/to/.venv/bin/openocd-mcp"
}
}
}
重启 Cursor。
Windsurf
将以下内容添加到 ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"openocd": {
"command": "/path/to/.venv/bin/openocd-mcp"
}
}
}
重启 Windsurf。
Cline (VS Code)
打开 Cline 面板 → MCP 服务 → 添加服务 → 手动,然后输入:
{
"openocd": {
"command": "/path/to/.venv/bin/openocd-mcp"
}
}
Continue (VS Code / JetBrains)
将以下内容添加到 ~/.continue/config.json:
{
"mcpServers": [
{
"name": "openocd",
"command": "/path/to/.venv/bin/openocd-mcp"
}
]
}
VS Code + GitHub Copilot
将以下内容添加到工作区中的 .vscode/mcp.json(或用户的 settings.json):
{
"servers": {
"openocd": {
"type": "stdio",
"command": "/path/to/.venv/bin/openocd-mcp"
}
}
}
在 VS Code 中通过 聊天 → Agent 模式 启用。
更新
MCP 不提供自更新工具;更新需要在终端中运行命令,可以自行操作,也可以请拥有 shell 访问权限的 AI(例如 Claude Code)代为操作。更新后,请重启 AI 客户端,以便加载新的服务;如果更新时客户端正处于会话中,可能需要先停止旧的 openocd-mcp 进程(进程运行时,文件锁可能会阻止重新安装)。
PyPI 安装(pip install openocd-mcp 或 uvx):
pip install -U openocd-mcp
# uvx caches by default — force a refresh:
uvx --refresh openocd-mcp
可编辑的 git 克隆安装(setup.bat / 本仓库的说明所配置的安装方式):
git pull
# only needed if dependencies changed:
.venv/bin/python -m pip install -e . # or .venv\Scripts\python on Windows
使用 pip show openocd-mcp 检查已安装的版本。
如何使用
1. 指定芯片
每个固件项目都会告知服务正在调试的目标。在项目根目录中创建一个
openocd-mcp.json(模板见
openocd-mcp.example.json):
{
"target_cfg": "target/stm32g0x.cfg",
"svd_file": "path/to/STM32G0B0.svd",
"elf_file": "path/to/build/firmware.elf"
}
target_cfg/interface_cfg— OpenOCD 配置(相对于其 scripts 目录)。 默认使用 ST-Link 探针;请为你的芯片设置target_cfg。transport—"swd"或"jtag"。在 Cortex-M 上使用 J-Link 时设置为"swd"(并设置interface_cfg: "interface/jlink.cfg");使用 ST-Link 时留空。svd_file— 芯片的 CMSIS-SVD 文件(启用按名称访问外设寄存器)。elf_file— 固件构建输出文件(启用按名称访问变量)。
Windows 上使用 J-Link: OpenOCD 通过 libusb 连接 J-Link,因此请使用 Zadig 将 J-Link 的调试接口绑定到 libusbK(或 WinUSB)(一次即可,选择 Interface 2 / MI_02)。 较新的 SEGGER 软件(v7.x+)与 libusbK 兼容,因此 OpenOCD 和 SEGGER 工具可以共存。ST-Link 无需此步骤。
也可以直接告诉 AI 你使用的芯片,它会为你配置会话。你可以随时使用 show_config 查看当前设置。
2. 描述你的需求
连接好开发板后,描述你的需求——AI 会选择合适的工具:
| 你说…… | 执行的操作 |
|---|---|
| “连接并暂停目标” | 如果需要则启动 OpenOCD,连接目标并暂停 CPU |
| “状态如何?” | 报告运行或暂停状态,以及当前程序计数器 |
“读取变量 sensor_value” | 在 .elf 中查找该变量,并从芯片读取其值 |
“将 motor_enabled 设置为 1” | 按变量名写入该变量 |
“实时监视 tick_count 2 秒” | 调用 watch_variables——反复采样该变量 而不暂停 CPU,并直接在聊天中返回随时间变化的数值表 |
“读取 GPIOA.MODER” | 读取寄存器并解码其命名位域 |
“列出 RCC 寄存器” | 列出 SVD 中的寄存器 |
“在 0x08001234 处设置断点,然后复位并运行” | 设置断点并复位 |
“在 0x08001234 处设置断点,条件是 r0 为 42” | 设置条件断点(使用 [get_reg r0] == 42) |
“在 0x08001234 处设置断点,命中 5 次后触发” | 设置命中计数断点 |
“监视对 0x20000000 的写入” | 设置硬件数据观察点 |
“烧录 build/firmware.elf 并运行” | 编程、验证并重新启动 |
“转储 0x20000000 处的 64 字节 RAM” | 读取内存 |
你无需按名称调用工具——只需描述目标,AI 就会将其映射到相应的底层工具。
3. 条件断点和观察点
条件断点仅在条件成立时暂停——适合捕获持续运行的代码中的特定情况。条件是 TCL 表达式,可使用两个辅助函数:
get_reg <name>— CPU 寄存器的值(例如get_reg r0、get_reg pc)get_mem <addr> [width]— 内存中的值(例如get_mem 0x20000000)
只需描述意图;AI 会构建条件:
| 你说…… | 使用的条件 |
|---|---|
“仅当 r0 > 100 时,在 0x08001234 处设置断点” | expr {[get_reg r0] > 100} |
“当 0x20000005 处的字节为 0xFF 时,在 parse_packet 处设置断点” | expr {[get_mem 0x20000005 8] == 0xFF} |
“第 10 次命中时,在 0x08001234 处停止” | incr ::hits; expr {$::hits >= 10} |
条件为假时,服务会自动恢复运行并继续执行,直到条件为真(或你将其停止)。
观察点会在 CPU 访问某个内存位置时暂停 CPU——非常适合查找导致变量损坏的代码:
- “监视对
0x20000000的写入” - “监视地址
0x20000010的所有读写操作”
实时监视变量
有两种独立的方式可以在不暂停 CPU 的情况下监视变量 — 一种由 AI 触发,另一种由你自己运行:
watch_variables(MCP 工具) | openocd-watch(独立 GUI) | |
|---|---|---|
| 触发方式 | 在聊天中询问 AI | 在终端中自行运行命令 |
| 输出 | 返回到聊天中的样本文本表格 | 实时更新的窗口,带树状视图 |
| 持续时间 | 单次运行:采集 N 个样本后返回 | 持续运行,直到你关闭它 |
| 结构体/数组 | 仅显示扁平值 | 可展开,按 DWARF 类型解析 |
向 AI 提出请求,快速、限定范围地查看某个值随时间的变化,例如:“监视 tick_count 10 个样本”“每隔 200ms 采样一次 sensor_value,持续 2 秒”。这会直接调用 watch_variables 工具;除了加载 ELF 之外,无需额外设置。
自行运行 GUI,进行不设时限的实时查看,尤其适合查看结构体/数组。这是一个独立应用,会自行连接 OpenOCD,因此可以与驱动同一目标的 AI 会话同时正常工作 — 但它不是 MCP 工具,所以 AI 无法替你打开它;请直接运行:
openocd-watch tick_count sensor_value --elf path/to/firmware.elf
# or, if elf_file is set in openocd-mcp.json:
openocd-watch tick_count sensor_value
它会在不暂停 CPU 的情况下采样变量,并在窗口中刷新树状视图。使用输入框添加条目(按 Enter 或点击 Add),选择一行后点击 Remove(或按 Delete 键)即可移除。每个条目都会自动解析,可以是:
- 变量名(
uwTick、commsService)→ 在 ELF 中查找;如果是结构体、联合体或数组,会显示展开三角形,并根据 DWARF 自动识别类型,显示其成员/元素(有符号数、浮点数、指针、枚举、位域、嵌套结构体)。枚举会显示符号名称(STATE_HEATING (1)),而 C 位域只显示自身的位,而非整个存储字; - 十六进制地址,可选大小(
0x20000000、0x20000000:2)→ 直接读取。
Format 下拉菜单可切换值的显示方式 — Auto(按 C 类型)/ Hex / Decimal / Signed / Float (f32) / Binary — 并立即重新渲染。使用 --interval 更改轮询速率,使用 --format 设置初始格式,或使用 --samples N 输出无界面的打印结果。需要 Tkinter(随标准 Python 一同提供)和包含类型信息的调试构建(-g)。
如果 OpenOCD 尚未运行,添加 --autostart,窗口就会为你启动 OpenOCD(并在关闭时停止它)— 完全独立,无需 AI 客户端或 .bat 文件:
openocd-watch uwTick xTickCount --elf path/to/firmware.elf --autostart --target target/stm32g0x.cfg
CPU 核心寄存器(
r0、pc、sp,……)需要暂停目标运行 — 需要时,AI 会先暂停目标。内存、变量和外设寄存器都映射到内存中,可以在 CPU 运行时读取(实时监视窗口就是这样做的)。会话中的首次connect会自动启动 OpenOCD。
安全性 / 权限
会对修改操作进行限制,防止 Agent 意外损坏目标。 读取始终允许;这些限制适用于写入、烧录、擦除和原始命令逃生通道。
| 权限 | 默认值 | 限制范围 |
|---|---|---|
read_only | false | 总开关 — 禁止所有写入/烧录/擦除/原始命令 |
allow_memory_write | true | write_memory、write_variable、write_register、write_peripheral_register |
allow_flash | true | flash_write(编程) |
allow_flash_erase | false | flash_erase_sector(具有破坏性 — 需主动启用) |
allow_raw_command | true | run_command(可绕过其他限制) |
flash_allowed_paths | [](任意路径) | 限制 flash_write 仅可操作这些目录中的文件 |
flash_max_bytes | 0(无限制) | 拒绝烧录大于此大小的文件 |
可通过以下三种方式设置(后设置的优先):
- 在
openocd-mcp.json中设置permissions对象(参见openocd-mcp.example.json)。 - 在运行时使用
set_permissions工具 — 例如,让 AI“将目标设为只读”或“允许本次会话擦除闪存”。 - 使用
OPENOCD_MCP_READONLY=1环境变量(强制只读)。
被阻止的调用会返回清晰的 BLOCKED: … 消息,说明需要启用哪项权限。
show_config 会列出当前生效的权限。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。