mcpField
S
STM32 GDB Debugger

STM32 GDB Debugger

本地服务
github.com开发工具21 周前更新

关于 STM32 GDB Debugger

STM32 GDB Debugger 是用于真实硬件 STM32 固件调试的 MCP 服务,面向嵌入式开发者和编码 Agent。它返回解码后的结构化调试证据,包括故障和 RTOS 分析,而非原始 GDB 输出。

主要功能

  1. 01通过 GDB Server 烧录并运行固件
  2. 02控制执行并管理断点
  3. 03检查内存、寄存器和外设
  4. 04分析 HardFault、堆栈和 FreeRTOS
  5. 05采集 RTT、SWO 和 UART 日志

适用场景

  1. 01在已连接的 STM32 板上启动固件
  2. 02将 HardFault 追踪到源码位置
  3. 03检查 FreeRTOS 任务、堆栈和队列
  4. 04回放调试场景并导出报告

MCP 相关

该 MCP 服务向 MCP 客户端提供 STM32 调试工具,通过 GDB 驱动 OpenOCD、J-Link GDB Server 或 st-util。工具返回解码结果和建议的后续操作,用于固件检查、故障诊断、日志采集、回放和报告生成。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"zeraissh-stm32-gdb": {
"command": "uvx",
"args": [
"stm32-gdb-mcp"
],
"env": {
"STM32_GDB_MCP_COMPACT": "<STM32_GDB_MCP_COMPACT>"
}
}
}
}
启动命令uvx stm32-gdb-mcp
需要配置的环境变量
STM32_GDB_MCP_COMPACTSet to 1 to expose only the core tools; every other tool stays reachable through call(tool, args).

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypistm32-gdb-mcp0.15.1

工具

86

收录的工具列表 · 更新于 2 周前

参数类型必填说明
probestring否可选的 OpenOCD 探针类型:stlink、jlink 或 cmsis-dap。未指定时依次使用配置文件中的值,或唯一检测到的探针。
serialstring否探针/ST-Link 序列号,用于选择特定开发板(支持并行多目标)。自动添加为 'adapter serial <serial>'。
sessionstring否可选的调试会话名称。省略时使用默认目标。
speed_khzinteger否推断 server_args 时使用的 OpenOCD 适配器时钟(默认值为 4000)。
hub_channelinteger否使用配置文件的 hub.map 中记录的 usb_location,在此 hub 通道上占用探针。若未指定,则依次使用 hub.channel,或标签与此会话名称匹配的映射条目。
server_argsarray否服务器的可选参数,例如 ['-f', 'interface/stlink.cfg', '-f', 'target/stm32f4x.cfg']
server_typeenum否调试服务器后端的类型。openocd | stlink | jlink
usb_locationstring否按物理 USB 位置选择探针,例如 '1-1.4'。对于无法报告序列号的多个探针(大多数克隆版 ST-Link),可用此方式选择其中一个;与集线器隔离不同,此方式不会断开任何设备——两个会话可以同时调试两块开发板。此值会添加为 'adapter usb location <value>'。通常建议使用 hub_channel,由它查找此位置。

详细介绍

STM32 GDB MCP 服务 / STM32 GDB MCP 服务器

PyPI Python Downloads MCP Registry mcprush CI License: MIT

一个 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 解码外设寄存器——✓
日志—RTTRTT、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、ESP32STM32(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 / 安装

ClientOne command
Claude Code(工具 + skills + 常驻规则)/plugin marketplace add Zeraissh/stm32-gdb-mcp,然后 /plugin install stm32-debug-kit@zeraissh-stm32
Cursor / VSCode / Codex / Windsurf / Traepython 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,否则不会有任何内容离开本机。该调用会通过你自己的 gh CLI 登录,在 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 label is matched against the debug session name, exactly. It is not a free-form nickname: the channel is selected only when the session was started as session="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 还是纯内存的, 因此服务器每次重启后都要重新加载。
  • set replaces a nested block; it does not merge into it. debug_profile(action=set, hub={...}) keeps every OTHER profile field, but the hub block you pass replaces the stored one whole — so writing hub={map: {3: {label: TC}}} after hub(action=discover, apply=true) throws away the probe identity discovery had written there, and a serial-less probe has no other identity. Pass merge=true to 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: allow on 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 hub block (after each tool call, plus a 2 s heartbeat). Cutting power or data on a channel where any server has a live GDB server needs confirm=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 no hub block 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's detect_probe cache. / 写操作最多排队 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 指引 — 三层引导

  1. 内联 — 大多数结果都包含 suggested_next_actions(下一轮的步骤)/ 大多数结果直接给出下一步动作。
  2. 常驻 — 服务端的 instructions 会自动注入 / 服务器自动注入调试闭环与关键规则。
  3. 按需 — 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/*

硬件验证在带有 stm32 标签的可自托管 runner 上运行;常规 CI 不依赖硬件 (lint、测试、编译和打包)。

硬件验证运行在带 stm32 标签的自托管 runner;普通 CI 不依赖硬件,只执行 lint、测试、 编译检查和发行包验证。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。