list_devices
Scan for connected PROBES — the debuggers plugged into this machine, not target chips. Despite the name it does not list target devices; use search_devices for those. Shows probe serial numbers and whether one is reachable.
無需輸入參數。

io.github.Klievan由 GitHub 帳號 Klievan 發布v0.8.0更新於 Oct 29, 2026
Debug embedded firmware on real hardware: J-Link probes, Cortex-M faults, RTT logs, GDB.
讓 AI 助理透過 SEGGER J-Link 偵錯器偵錯 ARM Cortex-M 嵌入式韌體:暫存器、記憶體、燒錄、RTT 日誌、故障分析與 GDB。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
參照 儲存庫 中的啟動說明。
Give AI hands to touch silicon.
An MCP server that lets LLMs debug embedded devices through SEGGER J-Link probes.
[MCP Server] [TypeScript] [J-Link] [ARM Cortex-M]
[GitHub Stars] [License] [npm] [npm downloads] [VS Code Marketplace] [Latest release] [MCP Compatible] [CI] [Hardware tested]
Real MCP tool calls against a real nRF52840-DK. Reproduce it yourself: npm run demo
Your firmware just crashed. One tool call:
Fault decoded, exception frame unwound, faulting instruction named, and the device's own log correlated — from one call, without a human reading a datasheet to find out what bit 24 of CFSR means.
Point it at your target's CMSIS-SVD file and peripheral registers stop being hex:
0x400 means 1024 KB of flash — but only if you know that, and an LLM guessing
at bit layouts is exactly the failure this avoids. The addresses come from the
vendor's own description, and the meanings from its enumerations.
Both transcripts are verbatim output from an nRF52840-DK in this project's hardware test suite.
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:
Also supports OpenOCD (ST-Link, CMSIS-DAP, FTDI) and Black Magic Probe backends.
You need the SEGGER J-Link software
— that is what this server drives — a probe connected to an ARM Cortex-M
target, and Node 18+. For the other backends, OpenOCD or arm-none-eabi-gdb
instead.
Claude Code — from the plugin marketplace. This brings the
embedded-debugging skill along with the server, which is what stops an
assistant guessing at your hardware:
Any other agent — point it at this repository and ask it to set itself up:
Install the MCP server at https://github.com/Klievan/jlink-mcp and configure it for my board.
It will find what it needs here. If you would rather do it by hand, the server
is on npm and needs no build step: npx -y jlink-mcp, with JLINK_DEVICE set
to your target. mcp-config.json is a config you can paste.
VS Code — install the extension. It registers the server for Copilot Chat, Claude, and any MCP-aware client, so there is nothing to configure.
Nix / NixOS — run directly from the flake without installing:
Or add jlink-mcp and jlink-mcp-skills to your system configuration or flake:
Note for NixOS users: Add your preferred probe tools (
segger-jlink/segger-jlink-headless,openocd, orgdb) toenvironment.systemPackagesor yourdevShell.segger-jlinkrequiresnixpkgs.config.allowUnfree = true;andservices.udev.packages = [ pkgs.segger-jlink ];for probe USB permissions.
Ask for check_setup. One call, and it says what is missing and what to do:
You do not need your device's exact part number up front. search_devices
searches all 9800 that J-Link supports, by part number, manufacturer, or core.
Set jlinkMcp.svdPath to your target's SVD — the same file Cortex-Debug takes
as svdFile. Vendors publish one per part.
Attach a real GDB client for symbol-aware work — backtraces, variable inspection, and stepping by source line rather than by instruction.
A J-Link serves one client at a time, so a GDB server left running blocks everything else — and the usual way that happens is an assistant starting one through MCP and nobody noticing. The extension cannot detect that by remembering what it did: the MCP server runs in a separate process, so an LLM-started server is invisible to it.
So it watches the GDB port instead, which is true whoever is responsible. When something is listening the status bar turns amber and reads J-Link · MCP · 47m — who started it, and how long ago. Those are the two facts that turn "something has the probe" into "the assistant has had it since before lunch". Clicking offers to stop it.
The tooltip carries the rest: device, ports, whether RTT is up, and why it matters. And it never claims an uptime it did not watch — a server that was already running when the window opened is reported as known about for that long, not up for it.
It will not kill a process it cannot identify as a J-Link GDB server. A listening port proves something is there, not that it is ours.
The tools tell a model what it can do. They do not tell it what is worth doing, and two things go wrong constantly without that: models never think to load the ELF, so every backtrace is bare addresses; and they reason about what the hardware should be doing instead of spending one call asking it.
skills/embedded-debugging/SKILL.md is a Claude Code skill that covers both —
the two files that change everything (ELF for names, SVD for meanings), the
halt/read/resume rule, workflows for crashes, hangs, peripherals and silent
devices, and a table of beliefs paired with the tool call that actually checks
each one.
Claude Code picks it up if you install this repo as a plugin
(.claude-plugin/plugin.json), or you can copy the directory into
.claude/skills/ in your firmware project. MCP itself has no notion of skills
— its portable equivalent is prompts, and this server ships four.
Its claims are tested. test/hil/s04-symbols.test.ts proves on real silicon
that a backtrace without symbols has no function names, that loading the ELF
gives them, and that a symbols-only load does not reprogram the device.
jlink-mcp supports multiple debug probe backends through a common ProbeBackend abstraction:
This server was built by having an AI use it against real hardware, then fixing every friction point.
read_registers would give youRaw JLinkExe output for halt; regs — 77 lines, of which about six carry
information. Every token here costs context, and the register values are buried
in the middle:
Three lines. Same information, grouped by what you would ask for:
Both captured from the same board. The rest of the design follows the same rule — return what was asked for, and nothing else:
start_debug_session, snapshot, diagnose_crash) replace multi-step workflows with single calls.rtt_search lets you find errors without reading the entire log.RAM = K256 rather than guessing what 0x100 means in that
field of that register.Most of what can go wrong between an LLM and a debug probe fails quietly: a tool returns success with an empty payload, a parser drops half a line, a session dies and the next command reports something plausible instead. None of that is visible from reading the code, and a test suite that asserts "the call did not error" passes on all of it.
So this project runs a hardware tier: 58 tests against a real nRF52840-DK on a self-hosted runner, driving the actual MCP server over stdio exactly as a client would. It covers probe discovery, flash and verify, halt/step/resume under a live GDB session, memory and peripheral reads, RTT streaming and filtering, and crash diagnosis against faults injected on demand.
It has caught bugs that had been shipping green, including:
diagnose_crash reporting "No faults detected" during real crashes — the
memory-dump parser was dropping half of every linereset reporting success while doing nothing at all — the GDB server is a
synchronous remote and refuses commands while the target runs, so every
command of the reset sequence was rejected in turn and the failure discardedGDB_RUNNING, when the question it meant to ask was whether the GDB server
was runningEvery one of those reported success. That is the point of the hardware tier, and the reason the suites assert on parsed content rather than on the call having returned without error — a suite that checked for errors would have passed on all of them.
Raw probe output captured during those runs is committed as golden transcripts, so a fast unit tier replays real device bytes in seconds on any machine — no probe required to catch a format regression.
Adding a new probe backend:
src/probe/yourprobe.ts implementing ProbeBackendsrc/probe/factory.tsMIT - see LICENSE
Built by The Sprk Factory
來源:README.md,提交 ad0c023
Scan for connected PROBES — the debuggers plugged into this machine, not target chips. Despite the name it does not list target devices; use search_devices for those. Shows probe serial numbers and whether one is reachable.
無需輸入參數。
Check that everything needed to debug is in place: the probe software, a connected probe, a target device name, and the optional files that make output readable. Run this first when anything fails, or when starting on a machine for the first time.
無需輸入參數。
Point the server at a CMSIS-SVD file for the target at runtime, so peripheral reads come back with named fields and decoded values instead of raw hex. Mirrors set_device — you do not have to restart with SVD_PATH set.
path必填Tell the server where the firmware's RTT control block is (its _SEGGER_RTT symbol), at runtime. Without it RTT cannot be recovered after a reset or flash, and a stopped stream is indistinguishable from a quiet device. Mirrors set_device.
address必填Search the device names this J-Link installation accepts, by part number, manufacturer, or core. Use this before set_device instead of guessing a part number — the name must match exactly, and a wrong one fails in a way that looks like broken hardware.
limitquery必填Set the target device name at runtime. Required before any debugging commands will work. The name must match J-Link's exactly — use search_devices to find it rather than guessing a part number. Examples: 'nRF52840_XXAA', 'nRF5340_xxAA_APP', 'STM32F407VG', 'STM32L476RG'.
device必填Set the debug probe serial number at runtime. Required when multiple probes are connected to select which one to communicate with. Run list_devices to see connected serial numbers.
serialNumber必填One-call setup: starts GDB server via SEGGER J-Link, connects RTT (if supported), waits for initial output. This is the recommended first tool to call. If no device is configured, use list_devices and set_device first.
無需輸入參數。
Capture complete device state: CPU registers (compact), fault status, recent RTT output, and stack dump.
rttLinesAuto-read and decode ARM Cortex-M fault registers (CFSR, HFSR, MMFAR, BFAR), exception stack frame, and recent errors.
無需輸入參數。
Halt the target and read its registers via SEGGER J-Link. Returns the probe name and a compact register summary. Leaves the target HALTED — call resume when you are done.
無需輸入參數。
Halt the target CPU
無需輸入參數。
Resume the target CPU
無需輸入參數。
Reset the target device. Halting leaves the core stopped at the reset vector, which is where you want it before flashing, or to watch startup run.
haltstrategyStep one CPU instruction
無需輸入參數。
Read memory from the target. Returns clean hex dump.
length必填address必填Write a 32-bit value to memory
value必填address必填Read all CPU registers (compact format, FP only if non-zero).
無需輸入參數。
Read a specific CPU register by name
register必填Flash firmware to the target device
filePath必填baseAddressErase target flash memory
無需輸入參數。
List the target's peripherals and base addresses, from its CMSIS-SVD description. Requires an SVD file to be configured.
filterRead every register of a peripheral from the target and decode each one's bit fields by name. This is read_memory plus the meaning of what was read.
registersperipheral必填Decode a value into named bit fields using the target's SVD. Reads from the device unless a value is supplied — useful for interpreting a number you already have.
valueregister必填peripheral必填Set a hardware breakpoint
address必填Clear all breakpoints, including any left armed in the debug hardware by an earlier session
無需輸入參數。
Start SEGGER J-Link GDB server
無需輸入參數。
Stop SEGGER J-Link GDB server and disconnect RTT
無需輸入參數。
Get GDB server, RTT, and telnet proxy status
無需輸入參數。
Connect a GDB client to the running GDB server. Enables source-level debugging: backtraces, variable inspection, conditional breakpoints, stepping by source line. Optionally load an ELF file for symbol info.
hostportelfFileSend any GDB command and get the response. For execution commands (continue, step, next, finish, until), blocks until the target stops or times out. If the target doesn't stop, use gdb_wait to poll. Examples: 'bt' (backtrace), 'info threads', 'print myVar', 'break main', 'continue', 'next', 'step', 'finish', 'info registers', 'x/10xw 0x20000000'
command必填timeoutPoll for target stop after a continue/step that timed out. Returns the stop reason (breakpoint hit, signal, finished stepping, etc.) when the target halts.
timeoutLoad an ELF file into GDB. By default loads symbols only (for source-level debugging: backtraces with file:line, variable names). Set flash=true to also program it onto the target.
flashelfFile必填Get a stack backtrace. With debug symbols loaded, shows function names, file paths, and line numbers.
fullDisconnect the GDB client (does not stop the GDB server)
無需輸入參數。
Connect to RTT
無需輸入參數。
Disconnect from RTT
無需輸入參數。
Read RTT log lines (clean, parsed Zephyr format). Non-destructive — reading does not consume the buffer. Returns the NEWEST lines by default; oldest:true returns the start of the buffer. Note the buffer spans reflashes: its oldest lines may be from firmware you have since replaced. rtt_clear drops them.
countoldestSearch/filter RTT logs by level, module, or regex
countlevelmodulepatternSend data to device via RTT down-channel
data必填Read SEGGER's RTT control block on the target: is it initialised, how much has the firmware written, and how much has the probe collected. Use this when RTT is silent — it separates a quiet device from a probe that stopped collecting, which look identical from rtt_read.
addressClear RTT buffer
無需輸入參數。
Start a TCP relay that re-serves the RTT stream on another port, so an external decoder (Trice, Pigweed, or your own) can consume it alongside this server. It relays bytes; it does not decode them.
無需輸入參數。
Stop telnet proxy
無需輸入參數。
Get telnet proxy status
無需輸入參數。
Read raw data from telnet proxy buffer
linesExecute raw SEGGER J-Link commands
commands必填Get current probe and server configuration
無需輸入參數。
已滿足適用檢查項的 90%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
> diagnose_crash
## Crash Diagnosis
### CPU StateCore: PC=0x000000B8 SP=0x2003FFA8 R0=0x0000000A R1=0x000007FF R2=0x00000001 ...Status: XPSR=0x21000003 CONTROL=0x00000000 PRIMASK=0x00000000 ...Stack: MSP=0x2003FFA8 PSP=0x00000000
⚠ CPU is in exception handler (IPSR=0x00000003)
### Fault RegistersCFSR=0x01000000 HFSR=0x40000000 DFSR=0x00000000 MMFAR=0xe000edf8 BFAR=0xe000edf8
### Decoded Faults## UsageFault (UFSR): - UNALIGNED: Unaligned memory access## HardFault (HFSR): - FORCED: Forced HardFault (escalated from configurable fault)
### Exception Stack Frame R0 = 0x0000000A R1 = 0x000007FF R12 = 0x00000000 LR = 0x000001F5 PC = 0x00000254 xPSR = 0x21000000
→ Faulting instruction at PC=0x00000254
### Recent Errors/Warnings from RTT [WRN] sensor_drv: sample out of range, clamping seq=2> read_peripheral FICR
FICR @ 0x10000000INFO.PART @ 0x10000100 = 0x00052840 (read-only) [31:0] PART 0x52840 → N52840INFO.RAM @ 0x1000010C = 0x00000100 (read-only) [31:0] RAM 0x100 → K256INFO.FLASH @ 0x10000110 = 0x00000400 (read-only) [31:0] FLASH 0x400 → K1024/plugin marketplace add Klievan/jlink-mcp/plugin install jlink-mcp# Run standalone MCP servernix run github:Klievan/jlink-mcp
# Or in an MCP client configuration (e.g. Claude Desktop / Claude Code)# "command": "nix", "args": ["run", "github:Klievan/jlink-mcp", "--"]# flake.nix inputsinputs.jlink-mcp.url = "github:Klievan/jlink-mcp";
# In your packages:inputs.jlink-mcp.packages.''${system}.jlink-mcpinputs.jlink-mcp.packages.''${system}.jlink-mcp-skillsNot ready to debug yet.
OK probe software — J-Link software found at /Applications/SEGGER/JLinkBLOCK probe — none detected (Connecting to J-Link via USB...FAILED). Check the USB cable.BLOCK target device — not set. Find the exact name with search_devices, then set_device.note SVD — not loaded, so peripheral reads stay raw hex. Set SVD_PATH to a CMSIS-SVD file.# J-Link (default)PROBE_TYPE=jlink JLINK_DEVICE=nRF52840_XXAA node out/mcp/standalone.js
# OpenOCD with ST-LinkPROBE_TYPE=openocd \ OPENOCD_INTERFACE=interface/stlink.cfg \ OPENOCD_TARGET=target/stm32f4x.cfg \ node out/mcp/standalone.js
# Black Magic ProbePROBE_TYPE=blackmagic \ BMP_SERIAL_PORT=/dev/ttyACM0 \ node out/mcp/standalone.js┌─────────────────────────────────────────────────────┐│ 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)│ └─────────────────────────┘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 (45 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 registrationSEGGER J-Link Commander V9.70 (Compiled Aug 19 2026 12:16:13)DLL version V9.70, compiled Aug 19 2026 12:15:25Connecting to J-Link ...O.K.Firmware: J-Link OB-nRF5340-NordicSemi compiled Jun 11 2026 13:12:28Hardware version: V1.00J-Link uptime (since boot): 0d 00h 34m 29sS/N: 1050298247License(s): RDI, FlashBP, FlashDL, JFlash, GDB...30 more lines of connect banner...PC = 00000044, CycleCnt = 00EB67E5R0 = 20000000, R1 = 9D56C547, R2 = 00000000, R3 = 00000000...FPS0 = 00000000, FPS1 = 00000000, FPS2 = 00000000, FPS3 = 00000000...28 more lines of zeroed FP registers...Core: PC=0x00000046 SP=0x20010000 R0=0x20000000 R1=0x01D43416 R2=0x00000000 ...Status: XPSR=0x01000000 CONTROL=0x00000000 PRIMASK=0x00000000 BASEPRI=0x00000000Stack: MSP=0x20010000 PSP=0x00000000npm test # ~257 tests, seconds, no hardwarenpm run test:hil # hardware tier; needs HIL=1 and a probe