keil-mdk-mcp
by lideshengstu
README.md
# keil-mdk-mcp
[]()
[]()
[]()
[-purple)]()
**English**: An MCP (Model Context Protocol) server that lets AI agents build, flash and debug STM32 projects compiled with Keil MDK-ARM on Windows. Build/flash run the official `UV4.exe` command line; debugging uses a separate pyOCD/ST-Link backend. Every result is evidence-based — this project explicitly refuses to fake unverified capabilities.
> **状态声明(请务必阅读)**:这是一个**可运行但范围受限**的交付版本。
> 已真实验证:MCP stdio 接入、29 个工具、Keil 完整/增量编译、编译日志解析、真实 `.axf` 的 ELF/DWARF 符号解析、ST-Link USB 枚举、安全拒绝路径。
> **未做硬件验收**:烧录、MCU 连接/复位、断点命中、实时变量/寄存器读取均未在真实板子上验证。
> **未实现且不会假装实现**:原生 µVision UVSOCK/DDE 控制、源码级单步(into/over/out)、调用栈回溯、局部变量与任意 C 表达式求值。相关工具返回明确的 `E_NOT_IMPLEMENTED` / 未验证错误,绝不返回伪造的成功。
详细能力边界见 [docs/capability_matrix.md](docs/capability_matrix.md),官方接口调研记录见 [docs/official_interfaces.md](docs/official_interfaces.md)。
## 它解决什么问题
AI Agent 写嵌入式代码时缺的不是语法,而是**执行反馈**:不知道 Keil 报错在哪一行,不知道固件是否真的在板子上跑起来。本服务把这条反馈链封装成 MCP 工具:
- 用官方 `UV4 -b/-r` 编译工程,返回**结构化的错误/警告(文件、行号、列号)**
- 编译成功判定采用**三重证据**:进程退出码(官方 ERRORLEVEL 表)+ 日志权威汇总行 + 预期产物文件存在且非空(重编译还要求产物指纹变化)——不是搜索日志里有没有 "Error" 字符串
- 通过 pyOCD 直接连接 ST-Link,提供运行控制、硬件断点、寄存器/PC 读取、全局/静态变量读取(从 DWARF 符号定位地址后**实时读取目标内存**,运行中拒绝读取,绝不用缓存值冒充)
- 所有硬件操作有明确的确认门和串行化保护
## 与调试后端的重要说明
调试走 **pyOCD 直接连接 ST-Link**(Arm 官方开源调试器),这是**独立调试器**,不是控制正在运行的 µVision 调试窗口。两者不能同时占用同一个探针。调研结论:µVision 存在官方 UVSOCK 远程接口,但其 SDK/线协议未能在本次开发中取得可验证的文档正文,因此本服务诚实地不实现它(stub 永远返回未实现错误),留作后续方向。
## 环境要求
| 组件 | 要求 |
|---|---|
| OS | Windows 10/11 |
| Python | 3.11+(实测 3.13) |
| Keil MDK | µVision 5(`UV4.exe`,实测 5.24),ARMCC 或 ARMCLANG |
| 调试器 | ST-Link(pyOCD 支持 CMSIS-DAP/J-Link 等,未逐一实测) |
| MCP 客户端 | 任何支持 stdio MCP 的客户端(Workbuddy / Claude Desktop / Cursor 等,客户端 UI 未逐一实测) |
## 安装
推荐虚拟环境(不污染全局 Python):
```powershell
git clone https://github.com/<YOUR_USERNAME>/keil-mdk-mcp.git
cd keil-mdk-mcp
py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install ".[debug,dev]"
```
只使用编译/日志功能(不调试)可以省略 pyOCD:
```powershell
.\.venv\Scripts\python.exe -m pip install .
```
离线自测:
```powershell
.\.venv\Scripts\python.exe -m pytest -q
```
## MCP 客户端配置(stdio)
以 Workbuddy / Claude Desktop 等支持 `mcpServers` JSON 的客户端为例,见 [config/workbuddy.mcp.example.json](config/workbuddy.mcp.example.json):
```json
{
"mcpServers": {
"keil": {
"command": "C:\\absolute\\path\\to\\.venv\\Scripts\\python.exe",
"args": ["C:\\absolute\\path\\to\\keil-mdk-mcp\\run_server.py"],
"env": {
"PYTHONUTF8": "1",
"KEIL_UV4_PATH": "D:\\Keil_v5\\UV4\\UV4.exe",
"KEIL_DEFAULT_PROJECT": "D:\\path\\to\\your\\project\\MDK-ARM\\app.uvprojx",
"KEIL_ALLOWED_ROOTS": "D:\\path\\to\\your\\project",
"KEIL_ALLOW_FLASH": "false"
}
}
}
}
```
关键环境变量:
| 变量 | 说明 |
|---|---|
| `KEIL_UV4_PATH` | `UV4.exe` 绝对路径(不设则自动探测常见安装位置) |
| `KEIL_DEFAULT_PROJECT` | 默认 `.uvprojx`,设置后其所在目录自动加入路径白名单 |
| `KEIL_ALLOWED_ROOTS` | 路径白名单(分号分隔多个),覆盖工程与编译产物目录;未配置且无默认工程时拒绝读文件 |
| `KEIL_ALLOW_FLASH` | 烧录总开关,**默认 false**;开启后仍需 `confirm=true` |
| `KEIL_ARTIFACTS_DIR` | 编译日志、会话 JSONL 的输出目录(默认 `<repo>/artifacts`) |
| `KEIL_DEBUG_BACKEND` | 调试后端,目前仅 `pyocd` |
## 快速上手(接入后第一轮)
1. `keil_get_environment` —— 检查 UV4 / Python 包 / 安全配置
2. `keil_get_project_info` —— 解析 Target、器件、编译器、输出配置
3. `keil_build` / `keil_rebuild` —— 编译,返回退出码 + 结构化诊断 + 产物指纹
4. `keil_get_build_log` / `keil_parse_build_errors` —— 查看日志与错误定位
5. `keil_diagnose_connection` —— 枚举 ST-Link(只枚举 USB,不连接 MCU)
## 工具清单(29 个)
环境/工程:`keil_get_environment` `keil_get_project_info` `keil_get_status`
编译/日志:`keil_build` `keil_rebuild` `keil_get_build_log` `keil_parse_build_errors`
下载/会话:`keil_flash` `keil_start_debug` `keil_stop_debug` `keil_run` `keil_halt` `keil_reset`
断点:`keil_set_breakpoint` `keil_remove_breakpoint` `keil_list_breakpoints`
单步:`keil_step_instruction`(指令级);`keil_step_into/over/out` **未实现,明确返回错误**
观察:`keil_read_variable` `keil_read_variables` `keil_get_registers` `keil_get_pc` `keil_get_execution_state`;`keil_get_call_stack` **未实现**
诊断:`keil_get_last_error` `keil_get_session_log` `keil_diagnose_connection`
每个工具的参数、默认值、返回 JSON 示例与错误码见 [docs/tools.md](docs/tools.md) 与 [artifacts 之外的 schema 说明](docs/tools.md)。
## 安全模型
- **烧录/连接调试器/复位**需要宿主配置开启(`KEIL_ALLOW_FLASH=true`)**且**调用时带 `confirm=true`——两者缺一不可。`confirm=true` 是结构化门槛,请同时在你的 MCP 客户端保留人工审批。
- 路径白名单 + 绝对路径校验,阻止相对路径穿越;解析后按真实路径校验。
- 所有子进程调用使用**参数数组**(`shell=False`),拒绝执行工程里已启用的 User Program 自定义命令(`E_UNSAFE_PROJECT`)。
- 全部编译/烧录/调试操作共用**单 worker + 串行锁**:并发请求返回 `E_BUSY`,超时操作不释放所有权(`E_SESSION_FAULTED` 直到 worker 结束并断开会话),不会出现两个工具同时操作目标。
- 每个探针只能有一个服务实例;**没有跨进程探针锁**,不要与打开的 µVision 或其他调试软件同时占用 ST-Link。
- pyOCD 侧禁用自动解锁(保护芯片不被意外擦除)、断开后自动恢复运行、内存/寄存器缓存、自动加载项目目录下的用户脚本与配置。
## 返回格式
所有工具返回 MCP `structuredContent` JSON:
```json
{"ok": true, "error_code": "OK", "data": {"status": "success", "exit_code": 0}}
```
```json
{"ok": false, "error_code": "E_CONFIRMATION_REQUIRED",
"error": "flash overwrites MCU memory; obtain human authorization and reissue with confirm=true", "data": {}}
```
完整错误码表见 [docs/tools.md](docs/tools.md)。
## 架构
```text
run_server.py 绝对路径启动入口(stdio)
src/keil_mcp/
server.py MCP 工具定义 / 参数 schema / structured output
keil_adapter.py UV4 官方命令行封装 / 超时与进程树清理 / 证据判定
session_manager.py 单 worker 串行事务 / 超时隔离 / JSONL 操作日志
safety.py 路径白名单 / 文件类型 / 硬件确认门
config.py 环境变量与默认值
result.py 统一 JSON 结果结构
parsers/ 编译日志(ARMCC/ARMCLANG) / 工程XML / ELF-DWARF 符号与行表
debug_backends/ pyOCD 后端 / UVSOCK 明确未实现 stub
```
## 已验证 / 未验证(诚实清单)
| 能力 | 状态 |
|---|---|
| MCP stdio、29 工具注册、structured output | 真实验证 |
| Keil `-b` / `-r` 编译 + 日志解析(0 错误 0 警告 + 产物) | 真实验证(STM32F103C8 工程) |
| 真实 `.axf` 的 ELF/DWARF 符号、行表、函数解析 | 真实验证 |
| ST-Link USB 枚举 | 真实验证 |
| 烧录 `UV4 -f` | 实现未验(默认关闭;缺擦除/编程/校验日志证据时返回未验证错误) |
| pyOCD 会话/运行控制/断点/寄存器/变量 | 实现未验(41 项测试含 mock 回归;需板级验收) |
| UVSOCK/DDE、源码级单步、调用栈、局部变量 | 未实现,明确报错 |
测试细节见 [docs/test_report.md](docs/test_report.md)。
## License
[MIT](LICENSE)。本仓库仅包含项目源码与文档;Keil、pyOCD、CMSIS 等第三方组件各自遵循其许可。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues