UNPKG

jlink-mcp

Version:

MCP server for SEGGER J-Link debug probes — LLM-driven embedded debugging with RTT, GDB server, and Trice/Pigweed support

335 lines (262 loc) 14 kB
<p align="center"> <img src="https://img.shields.io/badge/MCP-Server-blue?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyem0wIDE4Yy00LjQyIDAtOC0zLjU4LTgtOHMzLjU4LTggOC04IDggMy41OCA4IDgtMy41OCA4LTggOHoiLz48L3N2Zz4=" alt="MCP Server"> <img src="https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript"> <img src="https://img.shields.io/badge/J--Link-SEGGER-00979D?style=for-the-badge" alt="J-Link"> <img src="https://img.shields.io/badge/ARM-Cortex--M-0091BD?style=for-the-badge" alt="ARM Cortex-M"> </p> <h1 align="center">jlink-mcp</h1> <p align="center"> <strong>Give AI hands to touch silicon.</strong><br> An MCP server that lets LLMs debug embedded devices through SEGGER J-Link probes. </p> <p align="center"> <a href="https://github.com/Klievan/jlink-mcp/stargazers"><img src="https://img.shields.io/github/stars/Klievan/jlink-mcp?style=flat-square" alt="GitHub Stars"></a> <a href="https://github.com/Klievan/jlink-mcp/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Klievan/jlink-mcp?style=flat-square" alt="License"></a> <a href="https://www.npmjs.com/package/jlink-mcp"><img src="https://img.shields.io/npm/v/jlink-mcp?style=flat-square&color=cb0000" alt="npm"></a> <a href="https://www.npmjs.com/package/jlink-mcp"><img src="https://img.shields.io/npm/dt/jlink-mcp?style=flat-square&color=cb0000" alt="npm downloads"></a> <a href="https://marketplace.visualstudio.com/items?itemName=Klievan.jlink-mcp"><img src="https://img.shields.io/visual-studio-marketplace/v/Klievan.jlink-mcp?style=flat-square&label=VSCode" alt="VSCode Marketplace"></a> <a href="https://smithery.ai/server/@Klievan/jlink-mcp"><img src="https://smithery.ai/badge/@Klievan/jlink-mcp" alt="Smithery"></a> <a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-Compatible-green?style=flat-square" alt="MCP Compatible"></a> </p> --- ## What is this? **jlink-mcp** connects AI assistants (Claude, Copilot, etc.) to your embedded hardware via [SEGGER J-Link](https://www.segger.com/products/debug-probes/j-link/) debug probes using the [Model Context Protocol](https://modelcontextprotocol.io). Instead of manually typing J-Link commands, your AI assistant can: - **Read registers and memory** to understand device state - **Flash firmware** and reset devices - **Stream RTT logs** and search them by level/module/regex - **Diagnose crashes** by auto-decoding ARM Cortex-M fault registers - **Control execution** — halt, step, resume, breakpoints - **Start GDB servers** for full debugging sessions > Also supports **OpenOCD** (ST-Link, CMSIS-DAP, FTDI) and **Black Magic Probe** backends. ## Quick Start ### Claude Desktop Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "jlink": { "command": "node", "args": ["/path/to/jlink-mcp/out/mcp/standalone.js"], "env": { "JLINK_DEVICE": "nRF52840_XXAA" } } } } ``` ### Claude Code Add `.mcp.json` to your project root: ```json { "mcpServers": { "jlink": { "command": "node", "args": ["out/mcp/standalone.js"], "cwd": "/path/to/jlink-mcp", "env": { "JLINK_DEVICE": "nRF52840_XXAA" } } } } ``` ### VSCode Extension Install the extension (requires VSCode 1.99+). It auto-registers the MCP server via the native `vscode.lm` API. Configure the device in settings: ``` jlinkMcp.jlink.device = "nRF52840_XXAA" ``` Copilot Chat and Claude in VSCode will automatically discover all 31 tools. ### From Source ```bash git clone https://github.com/Klievan/jlink-mcp.git cd jlink-mcp npm install npm run compile JLINK_DEVICE=nRF52840_XXAA node out/mcp/standalone.js ``` ## Tools (31) ### Workflow Tools (start here) | Tool | Description | |------|-------------| | `start_debug_session` | **One-call setup.** Starts GDB server + connects RTT + returns boot log. | | `snapshot` | Captures full device state: registers, fault status, stack dump, RTT output. | | `diagnose_crash` | Auto-reads and decodes ARM Cortex-M fault registers (CFSR, HFSR, MMFAR, BFAR) with exception stack frame. | ### Device Control | Tool | Description | |------|-------------| | `device_info` | Probe type, target CPU, compact register summary | | `halt` | Halt CPU | | `resume` | Resume CPU | | `reset` | Reset device (optionally halt after reset) | | `step` | Single-step one instruction | ### Memory & Registers | Tool | Description | |------|-------------| | `read_memory` | Read memory at address (clean hex dump output) | | `write_memory` | Write 32-bit value to address | | `read_registers` | All CPU registers in compact format | | `read_register` | Read specific register (PC, SP, R0-R12, etc.) | ### Flash | Tool | Description | |------|-------------| | `flash` | Flash .hex/.bin/.elf firmware to device | | `erase` | Erase entire flash | ### Breakpoints | Tool | Description | |------|-------------| | `set_breakpoint` | Set hardware breakpoint at address | | `clear_breakpoints` | Clear all breakpoints | ### GDB Server | Tool | Description | |------|-------------| | `gdb_server_start` | Start probe's GDB server | | `gdb_server_stop` | Stop GDB server + disconnect RTT | | `gdb_server_status` | GDB server, RTT, and proxy status | ### RTT (Real-Time Transfer) | Tool | Description | |------|-------------| | `rtt_connect` | Connect to RTT telnet port | | `rtt_disconnect` | Disconnect from RTT | | `rtt_read` | Read recent log lines (ANSI stripped, Zephyr format parsed) | | `rtt_search` | **Filter logs** by level (`err`/`wrn`/`inf`/`dbg`), module, or regex | | `rtt_send` | Send data to device via RTT down-channel | | `rtt_clear` | Clear RTT buffer | ### Telnet Proxy (Trice / Pigweed) | Tool | Description | |------|-------------| | `telnet_proxy_start` | Start TCP proxy that tees RTT for external detokenizers | | `telnet_proxy_stop` | Stop proxy | | `telnet_proxy_status` | Proxy connection status | | `telnet_proxy_read` | Read raw proxy buffer | ### Advanced | Tool | Description | |------|-------------| | `probe_command` | Execute raw probe commands | | `get_config` | Current probe and server configuration | ## Multi-Probe Support jlink-mcp supports multiple debug probe backends through a common `ProbeBackend` abstraction: | Backend | Probe Hardware | Status | RTT Support | |---------|---------------|--------|-------------| | **J-Link** | SEGGER J-Link, J-Link OB, J-Link EDU | Production | Yes | | **OpenOCD** | ST-Link, CMSIS-DAP, FTDI, J-Link (via OpenOCD) | Beta | No | | **Black Magic Probe** | BMP (built-in GDB server on serial) | Beta | No | | **probe-rs** | All probe-rs supported probes | Planned | Planned | ### Selecting a Backend ```bash # J-Link (default) PROBE_TYPE=jlink JLINK_DEVICE=nRF52840_XXAA node out/mcp/standalone.js # OpenOCD with ST-Link PROBE_TYPE=openocd \ OPENOCD_INTERFACE=interface/stlink.cfg \ OPENOCD_TARGET=target/stm32f4x.cfg \ node out/mcp/standalone.js # Black Magic Probe PROBE_TYPE=blackmagic \ BMP_SERIAL_PORT=/dev/ttyACM0 \ node out/mcp/standalone.js ``` ## Architecture ``` ┌─────────────────────────────────────────────────────┐ MCP Client (Claude, Copilot, any MCP client) └──────────────────────┬──────────────────────────────┘ JSON-RPC over stdio ┌──────────────────────▼──────────────────────────────┐ jlink-mcp ┌──────────┐ ┌──────────┐ ┌───────────────────┐ 31 Tools 4 Resources 4 Prompts └────┬─────┘ └────┬─────┘ └───────┬───────────┘ ┌────▼──────────────▼────────────────▼───────────┐ ProbeBackend ┌─────────┐ ┌─────────┐ ┌──────────────────┐ J-Link OpenOCD Black Magic Probe └────┬────┘ └────┬────┘ └────────┬─────────┘ └───────┼───────────┼───────────────┼─────────────┘ ┌───────▼───┐ ┌─────▼────┐ ┌───────▼──────────┐ RTTClient TelnetProxy ProcessManager └───────────┘ └──────────┘ └──────────────────┘ └─────────────────────────────────────────────────────┘ ┌────────────▼────────────┐ Debug Probe (USB) Target MCU (SWD/JTAG) └─────────────────────────┘ ``` ### Source Layout ``` src/ ├── probe/ ├── backend.ts # ProbeBackend abstract class + shared utilities ├── jlink.ts # SEGGER J-Link implementation ├── openocd.ts # OpenOCD implementation ├── blackmagic.ts # Black Magic Probe implementation └── factory.ts # Probe creation from config ├── mcp/ ├── server.ts # MCP server (31 tools, 4 resources, 4 prompts) └── standalone.ts # Standalone entry (stdio transport) ├── rtt/ └── rtt-client.ts # RTT client with ANSI stripping + Zephyr log parsing ├── telnet/ └── telnet-proxy.ts # TCP proxy for Trice/Pigweed detokenizer ├── utils/ ├── config.ts # VSCode settings / env var config ├── logger.ts # Logging └── process-manager.ts # Child process lifecycle └── extension.ts # VSCode extension + MCP provider registration ``` ## Design Decisions (LLM-Optimized) This server was built by having an AI use it against real hardware, then fixing every friction point: - **Output parsing** strips 40+ lines of J-Link connection banners. Only data comes back. - **Registers** are compact: `Core: PC=0xBF54 SP=0x20062880 ...` instead of 65 raw lines. - **FP registers** only shown if non-zero (they're usually all zeros). - **RTT output** has ANSI escape codes stripped and Zephyr log format parsed into structured fields. - **Composite tools** (`start_debug_session`, `snapshot`, `diagnose_crash`) replace multi-step workflows with single calls. - **Fault decoding** is automatic — reads CFSR/HFSR/MMFAR/BFAR and explains each bit. - **`rtt_search`** lets you find errors without reading the entire log. ## Environment Variables ### J-Link | Variable | Default | Description | |----------|---------|-------------| | `PROBE_TYPE` | `jlink` | Probe backend: `jlink`, `openocd`, `blackmagic` | | `JLINK_DEVICE` | `Unspecified` | Target device (e.g., `nRF52840_XXAA`, `STM32F407VG`) | | `JLINK_INSTALL_DIR` | Auto-detect | Path to SEGGER J-Link installation | | `JLINK_INTERFACE` | `SWD` | Debug interface: `SWD` or `JTAG` | | `JLINK_SPEED` | `4000` | Connection speed in kHz | | `JLINK_SERIAL` | | J-Link serial number (multi-probe) | | `JLINK_GDB_PORT` | `2331` | GDB server port | | `JLINK_RTT_PORT` | `19021` | RTT telnet port | ### OpenOCD | Variable | Default | Description | |----------|---------|-------------| | `OPENOCD_BINARY` | `openocd` | Path to openocd binary | | `OPENOCD_INTERFACE` | `interface/stlink.cfg` | Interface config file | | `OPENOCD_TARGET` | `target/stm32f4x.cfg` | Target config file | | `OPENOCD_GDB_PORT` | `3333` | GDB server port | | `OPENOCD_TELNET_PORT` | `4444` | Telnet command port | ### Black Magic Probe | Variable | Default | Description | |----------|---------|-------------| | `BMP_GDB_PATH` | `arm-none-eabi-gdb` | Path to GDB binary | | `BMP_SERIAL_PORT` | `/dev/ttyACM0` | BMP serial port | | `BMP_TARGET_INDEX` | `1` | Target index after scan | ## Prerequisites - **[SEGGER J-Link Software](https://www.segger.com/downloads/jlink/)** installed (JLinkExe, JLinkGDBServer) - A J-Link debug probe connected to an ARM Cortex-M target - Node.js 18+ For other backends: OpenOCD or arm-none-eabi-gdb as appropriate. ## Contributing Adding a new probe backend: 1. Create `src/probe/yourprobe.ts` implementing `ProbeBackend` 2. Add a case to `src/probe/factory.ts` 3. That's it — all 31 MCP tools work automatically ## License MIT - see [LICENSE](LICENSE) --- <p align="center"> Built by <a href="https://github.com/thesprkfactory">The Sprk Factory</a> </p>