关于 STM32 GDB Debugger
STM32 GDB Debugger 是用于真实硬件 STM32 固件调试的 MCP 服务,面向嵌入式开发者和编码 Agent。它返回解码后的结构化调试证据,包括故障和 RTOS 分析,而非原始 GDB 输出。
主要功能
- 01通过 GDB Server 烧录并运行固件
- 02控制执行并管理断点
- 03检查内存、寄存器和外设
- 04分析 HardFault、堆栈和 FreeRTOS
- 05采集 RTT、SWO 和 UART 日志
适用场景
- 01在已连接的 STM32 板上启动固件
- 02将 HardFault 追踪到源码位置
- 03检查 FreeRTOS 任务、堆栈和队列
- 04回放调试场景并导出报告
MCP 相关
该 MCP 服务向 MCP 客户端提供 STM32 调试工具,通过 GDB 驱动 OpenOCD、J-Link GDB Server 或 st-util。工具返回解码结果和建议的后续操作,用于固件检查、故障诊断、日志采集、回放和报告生成。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
86收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| probe | string | 否 | 可选的 OpenOCD 探针类型:stlink、jlink 或 cmsis-dap。未指定时依次使用配置文件中的值,或唯一检测到的探针。 |
| serial | string | 否 | 探针/ST-Link 序列号,用于选择特定开发板(支持并行多目标)。自动添加为 'adapter serial <serial>'。 |
| session | string | 否 | 可选的调试会话名称。省略时使用默认目标。 |
| speed_khz | integer | 否 | 推断 server_args 时使用的 OpenOCD 适配器时钟(默认值为 4000)。 |
| hub_channel | integer | 否 | 使用配置文件的 hub.map 中记录的 usb_location,在此 hub 通道上占用探针。若未指定,则依次使用 hub.channel,或标签与此会话名称匹配的映射条目。 |
| server_args | array | 否 | 服务器的可选参数,例如 ['-f', 'interface/stlink.cfg', '-f', 'target/stm32f4x.cfg'] |
| server_type | enum | 否 | 调试服务器后端的类型。openocd | stlink | jlink |
| usb_location | string | 否 | 按物理 USB 位置选择探针,例如 '1-1.4'。对于无法报告序列号的多个探针(大多数克隆版 ST-Link),可用此方式选择其中一个;与集线器隔离不同,此方式不会断开任何设备——两个会话可以同时调试两块开发板。此值会添加为 'adapter usb location <value>'。通常建议使用 hub_channel,由它查找此位置。 |
详细介绍
STM32 GDB MCP 服务 / STM32 GDB MCP 服务器
一个 MCP 服务,让 AI Agent 在真实硬件上调试 STM32 固件——通过 GDB + OpenOCD/ST-Link/J-Link 烧录固件、设置断点、检查内存/寄存器/RTOS、排查 HardFault 并进行性能分析,返回已解码的结构化证据,而非原始 GDB 文本。
让 AI Agent 在真实硬件上调试 STM32:通过 GDB + OpenOCD/ST-Link/J-Link 烧录、打断点、检查 内存/寄存器/RTOS、定位 HardFault、进行性能采样,返回已解码的结构化证据,而非原始 GDB 文本。
uvx stm32-gdb-mcp # any MCP client: command "uvx", args ["stm32-gdb-mcp"]
需要在 PATH 中安装 arm-none-eabi-gdb(或 gdb-multiarch)和 GDB 服务(OpenOCD / J-Link / st-util);stm32-gdb-mcp-check-env 会输出适用于你操作系统的安装命令。有关在 Claude Code、Cursor、VSCode 等客户端中一键设置的方法,请参阅安装。
/ 需要 PATH 中有 arm-none-eabi-gdb(或 gdb-multiarch)和一种 GDB 服务;
stm32-gdb-mcp-check-env 会给出本机系统的安装命令。各客户端的一键安装见下方 Install。
为什么选择这个服务 / 为什么选它
| 通用 GDB MCP 服务 | 基于 probe-rs 的服务 | stm32-gdb-mcp | |
|---|---|---|---|
| 输出内容 | 原始 GDB 文本 | 结构化 | 已解码 + suggested_next_actions / 下一步建议 |
| HardFault → 源码行 | — | ✓ | ✓,并附栈分析 |
| FreeRTOS 任务、栈、队列 / RTOS 感知 | — | — | ✓ |
| 从 SVD 解码外设寄存器 | — | — | ✓ |
| 日志 | — | RTT | RTT、SWO、UART |
| 符号化 PC 采样 | — | — | ✓ |
一键启动(flash_and_run、debug_until)/ 组合工具 | — | 部分 | ✓ |
| 回放 + 调试报告 | — | — | ✓ |
| 多板机架、可编程 USB 集线器 | — | — | ✓ |
| 调试器 | 任意 GDB 远程调试器 | probe-rs 调试器 | ST-Link、J-Link、通过 OpenOCD 的 CMSIS-DAP / J-Link GDB Server / st-util |
| 目标芯片 | 任意 | Cortex-M、RISC-V、ESP32 | STM32(Cortex-M) |
如果需要 RISC-V 或 ESP32,请选择基于 probe-rs 的服务;如果要调试 STM32,并希望 Agent 用更少的调用从症状定位到根因,请选择本项目。 / 需要 RISC-V 或 ESP32 时选 probe-rs 系;调试 STM32、希望 Agent 用更少调用从现象走到根因时选本项目。
What you get / 能力一览
| Bring-up & flash / 启动与烧录 | detect_probe, suggest_server_args, build_firmware, flash_and_run, self_check, reset_target |
| Execution / 执行控制 | run_and_wait(结构化停止事件), run_for_duration(运行/采样后暂停并采集), breakpoint, step, halt/continue, debug_until |
| Inspect / 状态检查(需暂停) | capture_state, read_memory/read_variable, read_registers, frame, read_peripheral_register |
| Fault triage / 故障诊断 | reconstruct_fault_context(故障 PC → 源码), diagnose_fault, analyze_stack |
| RTOS / 实时系统 | detect_rtos, read_freertos, snapshot(scope=rtos) |
| Observe / 可观测性 | logging(RTT/SWO/UART), setup_swo(无需额外解码器的 printf), sample_pc(符号化采样器) |
| Determinism / 可复现性 | run_scenario(回放), batch, get_session 日志/指标, export_debug_report |
| Multi-board / 多板卡 | 任意工具传 session="name";使用 list_sessions/close_session 管理 |
Two cross-cutting goals: low comprehension cost (decoded outputs, suggested_next_actions)
and minimal repro steps (composites like flash_and_run / debug_until collapse 5–15 calls
into one). Compact mode keeps the visible surface small; every tool remains reachable through
call(tool, args), and tool_help exposes hidden schemas.
两个贯穿目标是:通过解码结果和 suggested_next_actions 降低理解成本,并通过
flash_and_run、debug_until 等组合工具把多次调用压缩为一次,缩短复现路径。
compact 模式只展示核心工具;所有隐藏工具仍可由 call(tool, args) 调用,并可用
tool_help 查询完整说明与 schema。
Install / 安装
| Client | One command |
|---|---|
| Claude Code(工具 + skills + 常驻规则) | /plugin marketplace add Zeraissh/stm32-gdb-mcp,然后 /plugin install stm32-debug-kit@zeraissh-stm32 |
| Cursor / VSCode / Codex / Windsurf / Trae | python scripts/deploy.py --project "<firmware dir>" --ide vscode,cursor |
| Manual / 手动配置(任意 MCP 客户端) | pip install -e .,再将客户端指向 stm32-gdb-mcp |
deploy.py installs the server, writes the IDE's MCP config, and drops a project-aware rules
file into your firmware project. Per-client config snippets + the rules template are in
docs/install-ides.md. Compact mode is on by default.
PyPI/console installs also expose stm32-gdb-mcp-check-env, stm32-gdb-mcp-install,
and stm32-gdb-mcp-deploy.
deploy.py 会安装服务器、写入 IDE 的 MCP 配置,并在固件项目中生成带项目上下文的规则文件。
各客户端配置片段和规则模板见 docs/install-ides.md。默认启用 compact
模式;PyPI/console 安装还会提供上述三个辅助命令。
stm32-gdb-mcp-check-env --json also reports the imported module version/path, installed
distribution version, and all four console scripts. Use stm32-gdb-mcp-deploy --upgrade
when those installation fields drift. / stm32-gdb-mcp-check-env --json 还会报告当前导入
模块的版本/路径、已安装发行版本和四个 console script;这些安装字段发生漂移时,使用
stm32-gdb-mcp-deploy --upgrade 修复。
Requirements / 环境要求:PATH 中需要 arm-none-eabi-gdb(Debian/Ubuntu 上的
gdb-multiarch 也可以,或用 STM32_GDB_MCP_GDB 指定任意支持 ARM 的 GDB),以及至少一种 GDB
Server(openocd / JLinkGDBServerCL / st-util)。运行 stm32-gdb-mcp-check-env(或
python setup_env.py)检查;缺什么,它会打印本机系统(Windows scoop / macOS brew /
Linux apt、pacman)对应的一行安装命令。
Needs arm-none-eabi-gdb (or gdb-multiarch, or any ARM-capable GDB named by
STM32_GDB_MCP_GDB) plus one GDB server; stm32-gdb-mcp-check-env prints the install
command for whatever is missing on your OS.
插件会运行和连接什么 / 插件会运行和连接什么
Claude Code 插件(stm32-debug-kit)会在你的本机运行所有内容:
- MCP 服务:
python scripts/run_mcp_server.py,通过 stdio 运行本仓库src/中的服务器。运行它的 Python 需要安装pyproject.toml中的依赖(pip install -e .或pip install stm32-gdb-mcp)。 - SessionStart hook:
python hooks/session_start.py会向会话上下文输出一段简短说明。它不会读取或发送任何内容。 - 启动的进程:
arm-none-eabi-gdb(或上文指定的 GDB)、GDB 服务(openocd、JLinkGDBServerCL或st-util),以及在你要求构建时运行的cmake/make。这些进程通过 USB 与调试探针通信,并通过localhost上的 TCP 彼此通信。 - 本地端口:GDB 服务端口位于
localhost;可选的 USB Hub 守护进程和看板仅在127.0.0.1上提供服务(默认端口为 8765)。只有在工具读取 UART 日志时才会打开串口。 - 文件:读取你的固件工程(ELF、SVD、构建文件)。只在工具指定的位置写入文件(调试报告、保存的调试配置),此外还会在系统临时目录的
stm32-gdb-mcp/下写入少量锁文件和状态文件。 - 网络:除非 Agent 调用
report_issue,否则不会有任何内容离开本机。该调用会通过你自己的ghCLI 登录,在Zeraissh/stm32-gdb-mcp上提交 GitHub issue。issue 包含 Agent 编写的描述、MCP 版本和环境摘要,以及本次会话的工具调用记录和指标。没有遥测。
30 秒快速上手 / 快速上手
detect_probe() # USB evidence; auto-select only one probe
debug_profile(action=set, mcu="STM32L431", probe="stlink", elf_path="build/app.elf", svd_path="STM32L4.svd")
suggest_server_args(mcu="STM32L431") # probe omitted -> use profile probe
start_debug_session(server_type="openocd") # server_args omitted -> infer from profile mcu/probe
self_check() # ALWAYS first: byte order, core, family
flash_and_run(file_path="build/app.elf", run_to="main")
breakpoint(action=set, location="my_func", condition="state == BAD")
run_and_wait() # structured stop event + next actions
run_for_duration(duration_sec=30, capture={"expressions": ["rx_count"]})
run_for_duration(duration_sec=60, sample={"interval_ms": 500, "expressions": ["rx_count", "state"]})
reconstruct_fault_context() # on a crash: faulting PC → file:line
detect_probe 会读取物理 USB 设备,为相同型号的探针保留各自的序列号,并且绝不会在连接了多个探针时擅自选择。 / detect_probe 读取真实 USB 设备,同型号探针按
序列号分别保留;连接多个探针时绝不会擅自选择。
完整的工具参考(按 action=/what= 归并的精简工具族)见
skills/stm32-debug/reference/tool-map.md。服务器
还会发送常驻的 instructions,因此任何 MCP 客户端都无需设置即可获得调试闭环。
完整工具索引见 skills/stm32-debug/reference/tool-map.md,
其中按 action= / what= 归并工具族。服务器还会发送常驻 instructions,因此任意 MCP
客户端连接后都能获得同一套调试闭环。
关键规则(目标必须配合) / 关键规则
- 读取要求内核已暂停。 若读取返回
target_unresponsive,先执行halt_execution。 / 读取要求内核已暂停。 若返回target_unresponsive,先执行halt_execution。 run_for_duration(sample=...)是尽力而为的低速调试器轮询。它本身不会暂停目标,但某些探针或 MCU 可能无法在目标运行时读取表达式;需要更高采样率或可靠采集时,请使用 SWO 或固件环形缓冲区记录遥测数据。 /run_for_duration(sample=...)是尽力而为的低速调试器轮询;某些探针或 MCU 无法在运行中读取 表达式。需要更高采样率或可靠采集时,请使用 SWO 或固件环形缓冲。- 断点超时表示路径没有到达——不要原样重试。暂停后执行
capture_state,通过breakpoint(action=list)确认命中次数(hit_count=0即可确认),读取门控标志,设置更早的断点或驱动前置条件。 / 断点超时表示路径没有到达。 不要原样重试;暂停后采集状态、确认 命中次数、读取门控条件,再前移断点或驱动前置条件。 - 写操作受保护(option bytes/IWDG/WWDG 默认禁止)——使用
write_guard(action=policy)放行。 / 写操作受保护。 option bytes、IWDG、WWDG 默认禁止,需用write_guard(action=policy)显式放行。 - 绝不要强杀 OpenOCD(会导致 ST-Link USB 卡死)——请使用
recover_session。SWD 连接是独占的。 / 不要强杀 OpenOCD。 使用recover_session;同一探针的 SWD 调试连接是独占的。 - 探针卡死后必须进行物理重新枚举。 安装可选的
[hub]extra 并使用 SmartUSBHub 后,hub(action=power)会断开 VBUS,hub(action=data)会断开 USB 数据线,因此重新插拔也能通过工具调用完成。没有 Hub 时仍需人工拔插。 / 卡死的探针必须物理重新枚举。 装上可选的[hub]extra 并接可编程 USB Hub 后,hub(action=power)可断 VBUS、hub(action=data)可断数据线,那次插拔就变成一次工具调用; 没有 Hub 时仍然只能靠人手拔插。
可编程 USB Hub(可选) / 可编程 USB Hub(可选)
pip install 'stm32-gdb-mcp[hub]'
然后将会话指向对应端口(从 1 开始,与 Hub 上的丝印编号一致):
{"action": "set", "hub": {"channel": 2, "guard": "confirm"}}
hub(action=describe) 是只读的;带 ADC 的型号还会返回各端口的电压/电流。默认的 confirm 模式下,hub(action=power/data/cycle) 必须显式传入 confirm=true;而且只要调用方自己的会话在该端口上运行着 GDB 服务,任何模式(包括 guard: allow)都强制要求确认:烧录中途断电正是把板子变砖的做法。注意检查范围:在 local 模式下,它只会检查发起调用的会话,因此不会发现另一个会话正在该通道上烧录。使用共享 Hub 守护进程时(默认;见下文),则会检查所有服务器上的所有已注册会话。
有三个入口会自行确认,这是刻意设计的:点名调用它们本身就代表确认;相关决定也会记录在 hub(action=describe) 返回的同一审计日志中。reset_target(strategy="cold") 和 recover_session 的恢复阶梯会在断电前先停止 GDB 会话,而不是在会话仍然活跃时直接拔掉 VBUS。
hub(action=discover) 在有活跃会话时会直接拒绝运行——但 force=true 会完全绕过联锁,因此这是唯一需要你自行承担风险的地方。脚本化 CI 可设置 guard: allow。 /
hub(action=describe) 是只读的,带 ADC 的型号还会返回每端口电压/电流。默认 confirm
模式下,hub(action=power/data/cycle) 必须显式传 confirm=true;调用方自己的会话在该端口
上有活跃 GDB 服务时,任何模式(含 guard: allow)下都强制要求——烧录中途断电正是把板子变砖的
方式。注意这条检查的范围:local 模式下它只看发起调用的那个会话,不会发现另一个会话正在该
通道上烧录;使用共享 Hub 守护进程时(默认,见下文)则能看到所有服务器登记的全部会话。
有三处入口会自行确认,这是刻意设计的——点名调用它们本身就是确认,且其决定同样进入
hub(action=describe) 返回的审计日志。reset_target(strategy="cold") 与 recover_session
的恢复阶梯会先停掉 GDB 会话再断电,而不是从活跃会话脚下拔掉 VBUS;hub(action=discover)
在有活跃会话时直接拒绝运行——但 force=true 会完全绕过该联锁,那是唯一真正需要你自己
负责的地方。CI 脚本可设 guard: allow。
Selecting a channel on a multi-board rack / 多板机架下的通道选择
hub: {channel: N} above pins one session to one port. With several boards, map the
whole rack once instead and let each session pick its own channel: /
上面的 hub: {channel: N} 把一个会话钉在一个端口上。多块板时改为一次性描述整个机架,
让每个会话各自选中自己的通道:
# bench_hub.yaml
hub:
port: COM7 # omit to auto-scan / 省略则自动扫描
guard: confirm
map:
3: {label: TC}
4: {label: AGS}
{"action": "load", "path": "bench_hub.yaml"}
Three things about this that are easy to get wrong: / 其中有三点很容易搞错:
- A
labelis matched against the debug session name, exactly. It is not a free-form nickname: the channel is selected only when the session was started assession="TC". This is the only way to select a channel for a serial-less probe —hub(action=discover, apply=true)keys those by USB port, which identifies a channel but cannot select one. /label是与调试会话名精确比对的,不是自由昵称:只有会话以session="TC"启动时才会 选中该通道。对于无序列号的探针这是唯一可行的选择方式——hub(action=discover, apply=true)只能按 USB 端口给它们建 key,那能认出通道,却无法选中通道。 - The debug profile is per-session. Loading the config into one session does not make
the map visible to another; the hub call then fails with
hub_unavailable: hub channel unmapped. Load it into each session:debug_config(action=load, path="bench_hub.yaml", session="TC"). The profile is also in-memory only, so this is re-run after every server restart. / 调试 profile 是按会话隔离的。 在一个会话里加载配置,另一个会话看不到该映射,此时 hub 调用会以hub_unavailable: hub channel unmapped失败。需要给每个会话都加载一次:debug_config(action=load, path="bench_hub.yaml", session="TC")。profile 还是纯内存的, 因此服务器每次重启后都要重新加载。 setreplaces a nested block; it does not merge into it.debug_profile(action=set, hub={...})keeps every OTHER profile field, but thehubblock you pass replaces the stored one whole — so writinghub={map: {3: {label: TC}}}afterhub(action=discover, apply=true)throws away the probe identity discovery had written there, and a serial-less probe has no other identity. Passmerge=trueto deep-merge into the stored block instead; leave it off when you mean to drop a stale channel, because replacing is the only way to remove one. /set对嵌套块是整块替换,不是合并。 顶层其他字段会保留,但传入的hub块会整块覆盖已 存的内容——在hub(action=discover, apply=true)之后再写hub={map: {3: {label: TC}}}, 会把 discovery 写入的探针身份一并丢掉(无序列号探针没有别的身份可用)。需要合并请加merge=true;要删除过期通道则保持默认的替换语义,因为那是唯一的删除方式。
When it works, the result carries channel_source: "map_label" — check that field rather
than assuming the right port was chosen. /
生效时结果会带 channel_source: "map_label"——请以该字段为准,不要想当然认为选对了端口。
Several MCP servers on one rack / 多个 MCP 服务器共用一个 Hub
The hub's control port opens in one process at a time, so by default the first hub call
spawns a small hub daemon that owns it, and every MCP server talks to that instead.
Nothing changes in how you call hub(...). /
Hub 控制口同一时间只能被一个进程打开。因此默认情况下,第一次调用 hub 会拉起一个Hub 守护进程
独占它,所有 MCP 服务器都改为与守护进程通信;hub(...) 的用法完全不变。
- Reads are shared. Writes lock only the channels they touch: a power cycle on CH1 never
interleaves with another switch on CH1, but a switch on CH4 runs alongside it. Exclusive
isolation locks the whole rack, and
hub(action=discover)holds a rack-wide lease for its whole run, so no other server's switch can corrupt the map. Waiting is FIFO among conflicting requests, so a rack-wide request is never starved. / 读取共享;写操作只锁住 涉及的通道:CH1 的电源循环不会与 CH1 上的其他开关交错,但 CH4 的操作可以同时进行。exclusive 隔离锁住整个机架;hub(action=discover)在整个运行期间持有全机架租约,其他服务器的开关无法 插入。冲突请求按先来后到排队,整机架请求不会被饿死。 - Each server's guard mode stays its own (
guard: allowon a CI server does not relax anyone else), and the audit trail records which server did what. / 每个服务器的 guard 模式各自独立,审计日志记录是哪台服务器执行的操作。 - What a server switched off is restored when it exits — or when the daemon finds its PID gone. / 某服务器断开的电源/数据线,在它退出(或守护进程发现其进程已消失)时自动恢复。
- Cross-server interlock. Every server registers its sessions that have a
hubblock (after each tool call, plus a 2 s heartbeat). Cutting power or data on a channel where any server has a live GDB server needsconfirm=true, whatever the guard mode, and the refusal names that session and server.hub(action=discover)refuses while any server on the rack is live. A session with nohubblock cannot be mapped to a channel and so is not protected. / 跨服务器互锁:每个服务器都会登记带hub配置的会话(每次工具调用后 同步登记,另有 2 秒心跳)。只要任一服务器在该通道上有活跃 GDB,断电/断数据就必须confirm=true(与 guard 模式无关),拒绝信息会指出是哪个服务器的哪个会话;任一服务器有活跃 会话时hub(action=discover)拒绝运行。没有hub配置的会话无法映射到通道,因此不受保护。 - A write waits at most 30 s behind another server's write, then is refused (not run late)
with the name of what held the hub; one that did wait reports
queued_ms. Every switch also invalidates every server'sdetect_probecache. / 写操作最多排队 30 秒,超时则拒绝执行 (而不是延后执行)并指出占用者;排过队的结果带queued_ms。每次切换都会让所有服务器的detect_probe缓存失效。 - The daemon exits after 10 idle minutes unless it still owes a channel. / 空闲 10 分钟且无待恢复通道时,守护进程自动退出。
python -m mcp_server.hub_daemon status # URL, version, connected servers
python -m mcp_server.hub_daemon stop # restores what clients switched off
python -m mcp_server.hub_daemon serve --config bench_hub.yaml # run it yourself, foreground
STM32_GDB_MCP_HUB_MODE=auto (default) uses the daemon and falls back to in-process when
the [hub] extra is absent or the daemon cannot start; daemon never falls back; local
is the old single-process behaviour. Everything binds to 127.0.0.1; writes need the token
in the per-user state file. /
STM32_GDB_MCP_HUB_MODE=auto(默认)使用守护进程,未安装 [hub] extra 或守护进程无法启动时
退回进程内模式;daemon 不回退;local 为原来的单进程行为。全部仅监听 127.0.0.1,写操作需
要用户私有状态文件中的 token。
Live dashboard / 实时看板
hub(action=dashboard) # -> data.url, e.g. http://127.0.0.1:8765/
A read-only page: per-port power/data state, live V/I/P with a 1/5/15-minute history
(power-off spans shaded), and a timeline of hub actions. With the daemon it is the
daemon's page, showing every connected MCP server and what each still owes; in local
mode it runs inside this server (state=off stops it) and lists its debug sessions. /
只读页面:各端口电源/数据线状态、电压电流功率及 1/5/15 分钟历史(断电区间灰色)、hub 操作时间线。
使用守护进程时就是守护进程的页面,显示所有已连接的 MCP 服务器及其待恢复通道;local 模式下
在本服务器内运行(state=off 停止),并列出本服务器的调试会话。
Response shape / 响应结构
Every tool returns a stable JSON envelope inside the MCP TextContent transport:
{ "ok": true, "data": {}, "error": null, "raw_response": null, "suggested_next_actions": [] }
Human-readable text lives in data.message / error.message; raw GDB output stays in
raw_response when it aids diagnosis. Errors carry a code (e.g. target_unresponsive).
可读消息位于 data.message / error.message;仅在有助于诊断时保留原始 GDB 输出到
raw_response。错误包含稳定的 code,例如 target_unresponsive。现代 MCP 客户端还会收到
内容相同的原生 structuredContent,错误结果设置 isError=true。
Agent 指引 — 三层引导
- 内联 — 大多数结果都包含
suggested_next_actions(下一轮的步骤)/ 大多数结果直接给出下一步动作。 - 常驻 — 服务端的
instructions会自动注入 / 服务器自动注入调试闭环与关键规则。 - 按需 — skills:
stm32-debug(启动调试、HardFault、挂起、 最小复现、可重放场景)和stm32-instrument(写入时的 SWO/ITM 跟踪)。在其他 IDE 中,同样的指导通过规则文件(AGENTS.md)提供。 / 按需加载两项 skill;其他 IDE 通过AGENTS.md等规则文件获得同样指导。
可复现配置
加载 YAML 调试配置文件,让不同客户端的会话保持一致:
debug_config(action=load, path="mcp/board.yaml")。
加载 YAML 调试 profile 可让不同客户端复现同一会话:
debug_config(action=load, path="mcp/board.yaml")。
mcu: STM32L431CCUx
probe: stlink
server_type: openocd
server_args: ["-f", "interface/stlink.cfg", "-f", "target/stm32l4x.cfg"]
elf_path: build/app.elf
svd_path: STM32L4.svd
相对路径 elf_path、svd_path、project_root 和 swo.file 均以 YAML 文件所在目录为基准解析。启动会话、日志、复位和烧录工具在省略对应参数时,都会使用已加载的配置文件。
相对的 elf_path、svd_path、project_root 和 swo.file 均以 YAML 所在目录为基准解析。
随后启动会话、日志、复位和烧录工具会在省略对应参数时自动使用该 profile。
加载配置文件、连接并运行强制身份检查,只需一次 MCP 往返:
batch(steps=[
{"tool": "debug_config", "args": {"action": "load", "path": "mcp/board.yaml"}},
{"tool": "start_debug_session", "args": {}},
{"tool": "self_check", "args": {}}
], stop_on_error=true)
以上配方在一次 MCP 往返中完成“加载配置 -> 连接 -> 自检”,任一步失败即停止。
J-Link、OpenOCD 以及不执行烧录的 L151/L431/U535 HIL 配置见 examples/configs/。 /
J-Link、OpenOCD 及不烧录的 L151/L431/U535 HIL 配置见 examples/configs/。
开发
pip install -e ".[dev]"
python -m ruff check . && python -m pytest && python -m compileall src tests
python -m build && python scripts/check_dist_contents.py dist/*
docs/install-ides.md— 各 IDE 的安装说明与规则模板 / 各 IDE 安装与规则模板docs/TROUBLESHOOTING.md— 常见故障与恢复 / 常见故障与恢复docs/hil-validation.md— 硬件在环验证 / 硬件在环验证(STM32_GDB_MCP_HIL=1)CONTRIBUTING.md、SECURITY.md、docs/release.md
硬件验证在带有 stm32 标签的可自托管 runner 上运行;常规 CI 不依赖硬件
(lint、测试、编译和打包)。
硬件验证运行在带 stm32 标签的自托管 runner;普通 CI 不依赖硬件,只执行 lint、测试、
编译检查和发行包验证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。