stm32-mcp
# stm32-mcp
Headless Model Context Protocol (MCP) server driving the official STMicroelectronics STM32 toolchain from the command line.
Automates project creation, pin configuration, HAL code generation, compilation, diagnostics parsing, and hardware flashing for AI coding assistants—including **Claude Code** and **Google Antigravity**—without launching a GUI.
[](LICENSE)
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)
[](test/)
---
## Quick Start
### 1. Install & Build
This package is currently built from source:
```bash
git clone https://github.com/irrumi/stm32-mcp.git
cd stm32-mcp
npm install
npm run build
npm test
```
### 2. Configure Your AI Client
#### Claude Code
Add to your project or user configuration:
```json
{
"mcpServers": {
"stm32": {
"command": "node",
"args": ["<ABSOLUTE_PATH_TO_STM32_MCP>/dist/index.js"]
}
}
}
```
Or install the packaged manifest:
```bash
claude plugin add <ABSOLUTE_PATH_TO_STM32_MCP>
```
#### Google Antigravity
Add to `~/.gemini/antigravity/mcp_config.json` (or workspace MCP settings):
```json
{
"mcpServers": {
"stm32": {
"command": "node",
"args": ["C:/path/to/stm32-mcp/dist/index.js"]
}
}
}
```
Install the firmware development skill:
```bash
# Windows PowerShell
Copy-Item -Recurse -Path ".\skills\stm32-firmware" -Destination "$HOME\.gemini\antigravity\skills\"
```
#### Generic MCP Clients (Cursor, Claude Desktop)
Add to your MCP client config (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"stm32": {
"command": "node",
"args": ["/path/to/stm32-mcp/dist/index.js"]
}
}
}
```
---
## What Happens When You Run It
In your AI chat, ask your assistant:
> *"Run stm32_doctor to check my STM32 toolchain health."*
The assistant calls `stm32_doctor` and receives structured JSON:
```json
{
"status": "ok",
"discovery": {
"cubeIdePath": "C:\\ST\\STM32CubeIDE_1.19.0\\STM32CubeIDE\\stm32cubeidec.exe",
"cubeMxJarPath": "C:\\ST\\STM32CubeIDE_1.19.0\\STM32CubeIDE\\plugins\\...\\STM32CubeMX.jar",
"programmerCliPath": "C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe",
"gccPath": "C:\\ST\\STM32CubeIDE_1.19.0\\STM32CubeIDE\\plugins\\...\\arm-none-eabi-gcc.exe",
"installedFamilies": [
{ "family": "F1", "version": "1.8.6", "path": "C:\\Users\\user\\STM32Cube\\Repository\\STM32Cube_FW_F1_V1.8.6" }
],
"stlinkDetected": true
},
"problems": [],
"recommendations": []
}
```
When building a project (`stm32_build`), instead of dumping thousands of raw log lines, the server parses GCC output and returns structured diagnostics with Flash and RAM usage:
```json
{
"success": true,
"summary": "Build completed successfully for blinky-f103/Debug. (0 errors, 0 warnings)\nMemory usage: Flash: 4548 bytes, RAM: 1592 bytes.",
"diagnostics": [],
"memory": {
"text": 4528,
"data": 20,
"bss": 1572,
"total": 6120,
"flashBytes": 4548,
"ramBytes": 1592
}
}
```
---
## Why stm32-mcp?
Developing embedded firmware on STM32 has traditionally relied on desktop graphical interfaces: the Eclipse-based **STM32CubeIDE** and the Java-based **STM32CubeMX**.
AI coding assistants cannot interact with desktop GUIs, and driving the ST command-line utilities directly presents severe practical obstacles:
1. **Path-Encoding Crashes**: ST's legacy CLI tools fail or produce corrupted builds when file paths contain non-ASCII characters (e.g. Cyrillic or accented Latin) on Windows.
2. **Headless Build Complexity**: The Eclipse CDT headless builder requires specific console binaries (`stm32cubeidec.exe`), isolated workspace arguments (`-data`), and explicit target MCU metadata in `.cproject`.
3. **Destructive Regeneration**: Running STM32CubeMX code generation permanently wipes application logic unless code is strictly isolated inside matching `/* USER CODE BEGIN */` and `/* USER CODE END */` comments.
4. **Context Window Exhaustion**: Compiler stdout often exceeds 10,000 lines of build chatter, wasting tokens and degrading agent reasoning.
`stm32-mcp` wraps the entire ST toolchain in a clean, typed Model Context Protocol interface with pre-flight path validation, safe code-block patching, structured diagnostics, and safety confirmation gates.
---
## Architecture & Workflow
```mermaid
flowchart LR
Agent["AI Coding Agent<br/>(Claude Code / Antigravity / Cursor)"] <-->|"MCP (JSON-RPC stdio)"| Server["stm32-mcp Server"]
Server --> Doctor["Toolchain Discovery<br/>(Auto-detects IDE, MX, CLI, GCC)"]
Server --> CubeMX["STM32CubeMX (-q)<br/>Headless Code Generation"]
Server --> CubeIDE["Eclipse CDT Builder<br/>Headless Compilation"]
Server --> Programmer["STM32_Programmer_CLI<br/>Target Flashing (SWD/JTAG)"]
CubeIDE --> Parser["Diagnostics & Memory Parser<br/>Flash / RAM Metrics"]
Programmer --> Hardware["Target STM32 Hardware<br/>(Blue Pill, Nucleo, Discovery)"]
```
---
## Key Features
- **100% Headless Operation**: Never launches a GUI. Executes STM32CubeMX in quiet script mode (`-q`), Eclipse CDT via the console runner (`stm32cubeidec.exe`), and flashing via `STM32_Programmer_CLI.exe`.
- **Structured Compiler Diagnostics**: Parses GCC warnings, errors, and notes into typed `{ severity, file, line, column, message }` records. Reports Flash and RAM memory metrics from `arm-none-eabi-size`.
- **Pre-Flight ASCII Path Guard**: Intercepts and rejects non-ASCII paths immediately with diagnostic guidance before invoking external ST tools.
- **Safe User Code Injection**: `stm32_patch_user_code` validates marker pairing and balance before modifying files, guaranteeing that CubeMX regeneration never destroys application logic.
- **Safety Confirmation Gates**: Destructive operations (`stm32_clean` and `stm32_flash`) require explicit `confirm: true` to prevent unintended file deletion or unwanted hardware programming.
- **Zero Credential Scraping**: Never requests, stores, or scrapes ST account logins. If an MCU firmware package is missing, the tool returns a direct link and folder location for manual download.
---
## Tool Reference
The server exposes 9 dedicated MCP tools:
| Tool | Parameters | Description |
| :--- | :--- | :--- |
| `stm32_doctor` | _(none)_ | Reports paths, tool versions, installed MCU HAL firmware packages, and ST-LINK probe connectivity. |
| `stm32_create_project` | `name`, `mcu`, `path`, `pins?`, `clock?`, `debug?` | Generates a complete STM32 project: `.ioc`, CDT `.project` / `.cproject`, linker script, and startup assembly. |
| `stm32_read_project` | `projectPath` | Reads and parses `.ioc` configuration, returning configured pins, peripherals, clocks, and FreeRTOS status. |
| `stm32_configure_pins` | `projectPath`, `pins` | Idempotently updates pin assignments, modes, and labels in `.ioc` and regenerates project code. |
| `stm32_generate_code` | `projectPath` | Runs STM32CubeMX in headless script mode to generate HAL initialization and peripheral code. |
| `stm32_patch_user_code` | `file`, `section`, `content`, `mode?` | Safely inserts code inside matching `/* USER CODE BEGIN <section> */` blocks (`mode: "replace" \| "append"`). |
| `stm32_build` | `projectPath`, `configuration?`, `clean?` | Headless compilation via CubeIDE builder; returns structured diagnostics and Flash/RAM usage. |
| `stm32_clean` | `projectPath`, `confirm: boolean` | Deletes build output folders (`Debug/`, `Release/`). Requires `confirm: true`. |
| `stm32_flash` | `elfPath`, `confirm: boolean`, `port?`, `reset?` | Programs target MCU via ST-LINK (`port: "SWD"`, `reset: true`). Requires `confirm: true`. |
---
## End-to-End Walkthrough: Blinky on STM32F103
A verified reference project is included at [`examples/blinky-f103`](examples/blinky-f103/). Here is the typical workflow:
### 1. Verify Environment
```json
// Tool: stm32_doctor
{}
```
### 2. Create Project
```json
// Tool: stm32_create_project
{
"name": "blinky-f103",
"mcu": "STM32F103C8Tx",
"path": "C:/projects/stm32/blinky-f103",
"debug": "swd"
}
```
### 3. Configure Status LED Pin
```json
// Tool: stm32_configure_pins
{
"projectPath": "C:/projects/stm32/blinky-f103",
"pins": [
{ "pin": "PC13", "mode": "GPIO_Output", "label": "LED_STATUS" }
]
}
```
### 4. Generate HAL Initialization Code
```json
// Tool: stm32_generate_code
{
"projectPath": "C:/projects/stm32/blinky-f103"
}
```
### 5. Add Non-Blocking Superloop Logic
```json
// Tool: stm32_patch_user_code
{
"file": "C:/projects/stm32/blinky-f103/Core/Src/main.c",
"section": "WHILE",
"mode": "replace",
"content": " static uint32_t last_tick = 0;\n if (HAL_GetTick() - last_tick >= 500) {\n last_tick = HAL_GetTick();\n HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);\n }"
}
```
### 6. Build Firmware
```json
// Tool: stm32_build
{
"projectPath": "C:/projects/stm32/blinky-f103",
"configuration": "Debug"
}
```
### 7. Flash Target Microcontroller
```json
// Tool: stm32_flash
{
"elfPath": "C:/projects/stm32/blinky-f103/Debug/blinky-f103.elf",
"port": "SWD",
"reset": true,
"confirm": true
}
```
---
## Supported Environments & Prerequisites
### System Requirements
- **Node.js**: >= 20.0.0
- **Operating Systems**: Windows 10/11 (primary target), Linux, macOS
- **STM32CubeIDE**: 1.15.0 through 1.19.0 (installed at default path `C:\ST\STM32CubeIDE_*` or `/opt/st/stm32cubeide`)
- **STM32Cube MCU Packages**: Download target packages (e.g. `STM32Cube_FW_F1_V1.8.6`) from [st.com](https://www.st.com) and extract into `~/STM32Cube/Repository`.
### Environment Variable Overrides
If tools are installed in custom locations, set the corresponding environment variables:
| Variable | Target Executable / Directory |
| :--- | :--- |
| `STM32CUBEIDE_PATH` | Directory containing `stm32cubeidec.exe` |
| `STM32CUBEMX_PATH` | Path to `STM32CubeMX.jar` or launcher executable |
| `STM32_PROGRAMMER_CLI` | Path to `STM32_Programmer_CLI.exe` |
| `STM32_REPOSITORY` | Path to `~/STM32Cube/Repository` firmware directory |
---
## Safety & Process Security
- **Process Execution**: All external commands are executed using `child_process.spawn` with discrete argument arrays and `shell: false`. Shell interpolation is strictly prevented.
- **Safety Gates**: Deleting build artifacts (`stm32_clean`) or programming hardware flash (`stm32_flash`) requires an explicit `confirm: true` parameter.
- **Path Sanitization**: All file paths are validated against ASCII characters prior to filesystem or process execution.
---
## Repository Structure
```
stm32-mcp/
├── .claude-plugin/ # Claude Code plugin manifest
├── antigravity/ # Google Antigravity MCP configuration & docs
├── examples/
│ └── blinky-f103/ # Reference STM32F103 Blue Pill project
├── skills/
│ └── stm32-firmware/ # Agent skill definitions and firmware lifecycle guide
├── src/
│ ├── discovery.ts # ST toolchain auto-discovery
│ ├── index.ts # CLI entry point (stdio transport)
│ ├── server.ts # MCP server setup & tool registration
│ ├── ioc/ # .ioc parser, writer, and CDT project generator
│ ├── parsers/ # GCC diagnostic & size output parsers
│ ├── patcher/ # Safe USER CODE block extraction and patching
│ ├── tools/ # 9 MCP tool implementations
│ └── utils/ # ASCII path validator & safe process spawn
├── test/ # 45 Vitest unit and integration tests
├── CONTRIBUTING.md # Contribution guide & architecture rules
└── package.json
```
---
## Development & Testing
```bash
# Run unit and integration tests
npm test
# Build TypeScript to dist/
npm run build
# Run in watch mode during development
npm run watch
```
See [CONTRIBUTING.md](CONTRIBUTING.md) for architecture rules, coding standards, and guidelines for adding MCU presets.
---
## License
[MIT](LICENSE) © [irrumi](https://github.com/irrumi)TDQS
Scored across 9 tools
Each tool maps to a distinct lifecycle phase: diagnose, create, configure pins, generate, patch user code, build, clean, flash, and read project state. Even create_project and generate_code are clearly separated by whether an .ioc already exists, so an agent can select appropriately.
All tools share a consistent stm32_ prefix and use snake_case, with the majority following verb_noun pattern (create_project, configure_pins, generate_code, patch_user_code, read_project). The stm32_doctor name is the main deviation, since it is noun-like rather than verb_object, but it remains recognizable and consistent with the set's style.
The set has 9 tools, which is well within the ideal range and matches the server's stated purpose of covering an STM32 project workflow from diagnostics through flashing. Each tool has a clear role and none feel redundant or superficial.
The tool surface covers the main project lifecycle well: create, configure, generate, patch, build, clean, flash, and read state. A minor gap is that clock or peripheral configuration cannot be changed after project creation except through existing pin configuration, and there is no explicit erase/reset tool, but these are workable limitations.