Skip to main content
Glama
xhw949
by xhw949
README.md
# Debug_Mcp

**Read-only Cortex-M live-attach MCP for DWARF variables, symbols, memory and registers.**

`Debug_Mcp` is a JSON-lines stdio server that lets an MCP client inspect a running Cortex-M target through [pyOCD](https://github.com/pyocd/pyOCD). It is designed for firmware diagnosis when opening a debug session must not reset the target or change its run state.

The attach path is non-intrusive: `connect_mode=attach` is used with `auto_unlock=false` and no reset or halt on connect. A small number of inspection operations have a different target-state contract: `read_registers` and `snapshot` may briefly halt a running target, read coherent core state, and resume it.

> **Safety boundary:** this server exposes no variable-write, memory-write, flash, erase, breakpoint, reset, or run-control tools. Read-only does not mean non-halting for every operation; see [Target-state semantics](#target-state-semantics).

## Why this project

Firmware engineers often need live values, symbols, memory and register state while a device is already running. This project puts those reads behind a small, explicit interface that can be used from Claude Desktop, Claude Code, or another MCP client without requiring the client to drive a full debug workflow.

## Features

- **Non-resetting attach** through pyOCD using SWD or JTAG.
- **DWARF-based C variable resolution** for globals, members, arrays, pointers and selected bitfields/enums.
- **ELF symbol-table fallback** when DWARF type information is unavailable.
- **Memory and register inspection** with bounded reads.
- **Coherent snapshot mode** for reading registers and multiple variables together.
- **AXF/ELF/OUT discovery** under a project directory.
- **JSON-lines stdio protocol** with structured success and error responses.
- **Toolchain coverage** for debug artifacts produced by Keil MDK, GCC and IAR, subject to compatible debug information.

## Target-state semantics

| Operation | May halt a running target? | Notes |
|-----------|----------------------------|-------|
| `attach` | No | Uses attach mode; no reset or halt is requested on connect. |
| `status` | No | Reports the current target state. |
| `read_memory` | No explicit halt | Reads a bounded raw memory range. |
| `resolve_symbol` | No | Resolves an address from the debug artifact only. |
| `read_symbol` / `read_variable` / `read_variables` | No explicit halt | Resolve metadata, then read target memory. |
| `read_registers` | **Yes, briefly** | Halts only when the target is running, reads core registers, then resumes. |
| `snapshot` | **Yes, briefly** | Halts only when the target is running, reads registers and variables, then resumes. |
| `detach` / `shutdown` | No explicit reset or run-control | Closes the probe session. |

The server does not expose a write path. However, a memory read can still be inappropriate for some peripheral addresses, and a halted/resumed target can affect timing-sensitive firmware. Select addresses and operations with the target's safety requirements in mind.

## Operations

| Operation | Description |
|-----------|-------------|
| `attach` | Select a pyOCD probe and attach via SWD/JTAG. |
| `detach` | Close the pyOCD session and release the probe. |
| `status` | Return the connection state and target run state. |
| `read_memory` | Read raw bytes from target memory; limited to 256 bytes per request. |
| `resolve_symbol` | Look up a linker symbol address and size from the AXF/ELF/OUT file. |
| `read_symbol` | Resolve a symbol and read its stored bytes from target memory. |
| `read_variable` | Read one C variable or supported member/array/pointer expression. |
| `read_variables` | Batch-read up to 64 C variables. |
| `read_registers` | Read core registers; may briefly halt and resume a running target. |
| `snapshot` | Read registers and variables coherently; may briefly halt and resume. |
| `find_axf` | Recursively find `.axf`, `.elf` and `.out` files under a directory. |
| `shutdown` | Detach and exit. |

## C-expression support

The DWARF resolver supports expressions such as:

```text
symbol
symbol.member
symbol.arr[5]
symbol.member[2].subfield
ptr->field
*ptr
```

Function calls, address-of expressions, casts and arbitrary arithmetic are rejected. Pointer expressions require a live target-memory read.

## Requirements

- Python 3.10+
- `pyocd>=0.45.0`
- `pyelftools>=0.33`
- `cmsis-pack-manager>=0.6.0`
- `pylink-square>=1.7.0`
- A supported debug probe, such as J-Link, ST-Link or CMSIS-DAP
- A Cortex-M target and a matching debug artifact with symbols: `.axf`, `.elf` or `.out`

Install the Python dependencies from [`requirements.txt`](requirements.txt).

## Quick start

### 1. Install dependencies

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
```

On Windows PowerShell, activate the environment with:

```powershell
.\.venv\Scripts\Activate.ps1
```

### 2. Check available probes

```bash
python -m pyocd list
```

Record the probe serial number, for example `000123456789`.

### 3. Register the server in an MCP client

The server speaks JSON-lines over stdin/stdout. A minimal client configuration is:

```json
{
  "mcpServers": {
    "debug-mcp": {
      "command": "python",
      "args": ["C:/path/to/Debug_Mcp/live_attach.py"]
    }
  }
}
```

The pre-built `DebugMcp.exe` in the repository can also be used on Windows. For reproducible deployments, prefer a versioned GitHub Release artifact with a checksum once releases are enabled.

### 4. Example requests

```json
{"id":1,"operation":"attach","arguments":{"probe_serial":"000123456789","protocol":"swd","clock_hz":2000000}}
{"id":2,"operation":"read_variable","arguments":{"axf_file":"C:/firmware/project.axf","expression":"g_bms.pack[2].soc"}}
{"id":3,"operation":"read_registers","arguments":{}}
{"id":4,"operation":"shutdown","arguments":{}}
```

The exact values returned by reads depend on the selected probe, target state and matching debug artifact. A failed read is returned as an error; callers must not interpret a failed read as zero.

## Project layout

```text
live_attach.py   JSON-lines server and DWARF resolver
requirements.txt Runtime dependencies
DebugMcp.exe     Pre-built Windows artifact kept for convenience
LICENSE          MIT license
```

## Verification boundary

The repository can support host-side checks such as Python syntax compilation without a connected target. End-to-end validation is environment-dependent and requires all of the following:

1. A supported debug probe and driver installation.
2. A running Cortex-M target with a compatible SWD/JTAG connection.
3. The exact matching AXF/ELF/OUT artifact, including usable symbols or DWARF data.
4. A client that sends the JSON-lines protocol and checks both success and error responses.

The current repository includes a lightweight static syntax check in GitHub Actions. Hardware attach, target reads, halt/resume behavior and end-to-end protocol coverage are intentionally not claimed by that check.

## Known limitations

- `read_registers` and `snapshot` can briefly halt a running target; do not use them where that timing disturbance is unacceptable.
- Expression support is intentionally narrower than a full C evaluator.
- Peripheral memory reads may have target-specific side effects even though the server does not write.
- Debug-artifact and target compatibility must be checked by the caller; a source-level match alone is not sufficient.

## Contributing and security

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the change and verification boundary, and [`SECURITY.md`](SECURITY.md) for handling sensitive firmware/debug data.

## License

MIT - see [`LICENSE`](LICENSE).