jlink-mcp
Give AI hands to touch silicon.
An MCP server that lets LLMs debug embedded devices through SEGGER J-Link probes.
What is this?
jlink-mcp connects AI assistants (Claude, Copilot, etc.) to your embedded hardware via SEGGER J-Link debug probes using the Model Context Protocol.
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):
{
"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:
{
"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
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
| 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
# 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 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:
- Create
src/probe/yourprobe.ts implementing ProbeBackend
- Add a case to
src/probe/factory.ts
- That's it — all 31 MCP tools work automatically
License
MIT - see LICENSE
Built by The Sprk Factory