stm32-stlink-mcp

stm32-stlink-mcp

MCP server for debugging STM32 microcontrollers over ST-LINK using STM32CubeCLT tools (GDB, ST-LINK_gdbserver, STM32_Programmer_CLI) with session management, flashing, breakpoints, memory/register access, and expression evaluation.

Category
Visit Server

README

stm32-stlink-mcp

MCP server for debugging STM32 microcontrollers over ST-LINK, built on STMicroelectronics' own STM32CubeCLT toolset — ST-LINK_gdbserver, STM32_Programmer_CLI, and arm-none-eabi-gdb (driven via GDB/MI2). No OpenOCD, J-Link, or probe-rs involved.

Architecture

A debug session is a pair of child processes, exactly mirroring ST's own documented workflow (UM2576, "STM32CubeIDE ST-LINK GDB server"):

 arm-none-eabi-gdb  --interpreter=mi2  --(TCP, target extended-remote)-->  ST-LINK_gdbserver  --(USB)-->  ST-LINK  --(SWD)-->  STM32

arm-none-eabi-gdb is driven in MI2 mode so the server gets source-level stepping, symbolic breakpoints, and symbol-aware expression evaluation for free, instead of hand-rolling the GDB Remote Serial Protocol. ST-LINK_gdbserver owns the USB handle to the probe for the lifetime of the session; flashing via gdb's load (MI: -target-download) is transparently delegated by the server to STM32CubeProgrammer, so no session teardown is needed to reflash. A standalone one-shot flash (flash_standalone, no session required) invokes STM32_Programmer_CLI directly and therefore conflicts with an already-open session on the same probe — see the tool description.

Setup

npm install
npm run build

Requires STM32CubeCLT to be installed and its bin/ directories reachable — either already on PATH (the CLT installer does this by default) or via STMCP_CUBECLT_PATH / per-tool overrides. Run npm run doctor to check.

Running

node dist/index.js serve     # starts the MCP server on stdio (default mode)
node dist/index.js doctor    # pre-flight check: tool resolution, connected probes, udev rules
node dist/index.js doctor --json

Registering with an MCP client

{
  "mcpServers": {
    "stm32-stlink": {
      "command": "node",
      "args": ["<path-to-this-repo>/stmcp/dist/index.js"]
    }
  }
}

Configuration (environment variables)

Variable Default Purpose
STMCP_GDBSERVER_PATH / STMCP_PROGRAMMER_CLI_PATH / STMCP_ARM_GDB_PATH — Per-binary override (highest priority)
STMCP_CUBECLT_PATH — CubeCLT install root; subpaths resolved via STM32CubeCLT_metadata.sh -j
STMCP_STLINK_SERIAL — Default probe serial (omit to auto-select if exactly one is attached)
STMCP_DEFAULT_DEVICE STM32G431CBTx Default MCU device string
STMCP_DEFAULT_INTERFACE swd swd or jtag
STMCP_DEFAULT_FREQUENCY_KHZ 4000 SWD/JTAG clock
STMCP_MAX_SESSIONS 1 Concurrent debug session cap
STMCP_GDBSERVER_READY_TIMEOUT_MS 8000 How long to wait for "Waiting for debugger connection..."
STMCP_LOG_LEVEL info error | warn | info | debug
STMCP_LOG_FILE — Optional log file (stderr always used regardless — stdout is reserved for MCP framing)
STMCP_ALLOW_FLASH_ERASE false Enables the erase path
STMCP_ALLOW_MEMORY_WRITE true Enables memory_write
STMCP_ALLOW_FLASH_ADDRESS_WRITE false Allows memory_write to target the flash address window (normally blocked — use the flash tools instead)
STMCP_ALLOWED_FILE_PATHS (unrestricted) Comma-separated allowlist roots for ELF/bin file arguments
STMCP_MAX_FILE_SIZE_BYTES 16777216 Max size for file arguments
STMCP_FLASH_RANGE_START / STMCP_FLASH_RANGE_END 0x08000000 / 0x08020000 Flash address window for the write guard (default: 128KB, STM32G431CB)

Tools

Domain Tool Purpose
Probe list_probes List connected ST-LINK probes
Session debug_connect Spawn gdbserver+gdb, load ELF symbols, connect
Session debug_disconnect Clean session teardown
Session debug_session_status Session info (one, or all)
Flash flash_standalone One-shot flash via STM32_Programmer_CLI, no session needed
Flash flash_load_in_session Reflash via gdb load inside an open session
Execution debug_run Resume/continue
Execution debug_halt Interrupt
Execution debug_reset Reset (monitor reset [halt])
Execution debug_step Step over/into/out
Breakpoints breakpoint_set / breakpoint_clear / breakpoint_list By file:line, symbol, or *addr
Memory memory_read / memory_write Raw memory access (write is guarded)
Registers register_read / register_write Named core registers
Registers read_fault_registers One-call Cortex-M SCB fault register dump (CFSR/HFSR/... decoded)
Expressions evaluate_expression Symbol-aware evaluation via gdb MI

Deferred to v2

SVD peripheral register tools (memory_read/write + evaluate_expression already reach everything by address), live/streaming memory polling, a plugin system, per-chip memory-region allowlists, arbitrary gdb monitor passthrough, and option-bytes/RDP tools (bricking-capable, intentionally out of scope).

RTT

RTT (SEGGER Real Time Transfer — live, non-halting console/variable tracing) is intentionally not implemented in this server. ST-LINK_gdbserver's GDB/MI stub has no non-stop mode, so reading memory through this server's debug_connect session requires halting the core first — which defeats RTT's purpose. The correct mechanism is direct AP memory access that never halts the core (confirmed by reading ST's own STM32CubeMonitor source, which uses exactly this, and by STM32_Programmer_CLI's -r32fast).

That's what strtt already does, and strtt-mcp wraps it as its own MCP server (strtt_start/strtt_stop/strtt_status/strtt_read/strtt_write). Register it alongside this server rather than through it:

{
  "mcpServers": {
    "stm32-stlink": { "command": "node", "args": ["<...>/mcp-server/dist/index.js"] },
    "strtt": {
      "command": "node",
      "args": ["<path-to-strtt-repo>/mcp/dist/index.js"],
      "env": { "STRTT_BIN": "<path-to-strtt-binary>" }
    }
  }
}

Start strtt_start with tcp: true to connect through the shared ST-LINK Server instead of claiming the USB device directly — this lets it run concurrently with an open debug_connect session here, since GdbServerProcess always passes -t/--shared to ST-LINK_gdbserver. Without tcp: true, strtt and an open debug session will contend for the same probe.

Hardware verification runbook

With an ST-LINK and target attached:

node dist/index.js doctor                     # confirm probe + tools resolve
npx @modelcontextprotocol/inspector node dist/index.js   # interactive tool testing

Then, via the inspector or an MCP client:

  1. list_probes → the probe's serial appears.
  2. debug_connect { elfPath, device, interface: "swd", serial } → returns a sessionId.
  3. breakpoint_set { sessionId, location: "main" } → returns a breakpoint number.
  4. debug_run { sessionId } → halts with reason: "breakpoint-hit".
  5. register_read { sessionId, registers: ["pc","sp","lr","r0"] }.
  6. evaluate_expression { sessionId, expression: "<a known global>" }.
  7. read_fault_registers { sessionId } → benign/zero flags right after reset.
  8. debug_disconnect { sessionId } → confirm no orphaned processes: ps aux | grep -E 'ST-LINK_gdbserver|arm-none-eabi-gdb'.
  9. flash_standalone { file, reset: "hard", run: true } with no session open.
  10. Negative test: open a session, then call flash_standalone on the same serial → expect DEVICE_BUSY.

Note: debug_connect halts the target's CPU. Don't attach to a board that's actively driving actuators/outputs in a way where an unplanned halt would be unsafe, without first confirming that's OK.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured