---
title: Resources
description: MCP resources for polling target state
---

mcjtag exposes 7 MCP resources that provide read-only access to target state. Resources use the `jtag://` URI scheme and can be polled by MCP clients without invoking tool calls.

## How Resources Work

Resources are distinct from tools in several ways:

- **Read-only** -- they reflect current state without side effects
- **No parameters** -- the URI fully identifies the resource (except for templated URIs)
- **Polling-friendly** -- clients can read resources repeatedly to monitor changes
- **Error handling** -- resources return a dict with an `error` key if something goes wrong, rather than raising exceptions

All resources require an active OpenOCD connection. If the server is not connected, every resource returns:

```json
{"error": "Not connected to OpenOCD. Use connect or start_openocd first."}
```

---

## Resource Reference

### jtag://target/state

Current target execution state and program counter.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `name` | `str` | Target name (e.g. `"stm32f1x.cpu"`) |
| `state` | `str` | Execution state: `halted`, `running`, `reset`, `debug-running` |
| `pc` | `str \| null` | Program counter as hex (e.g. `"0x08001234"`), null if not halted |
| `halted` | `bool` | Whether the target is halted |

```json
{
  "name": "stm32f1x.cpu",
  "state": "halted",
  "pc": "0x08001234",
  "halted": true
}
```

---

### jtag://registers/all

All CPU register values. The target must be halted for this resource to succeed.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `registers` | `dict[str, str]` | Map of register name to hex value |
| `count` | `int` | Number of registers returned |

Register values are formatted with width-appropriate hex padding (e.g., 32-bit registers as `0x00000000`).

```json
{
  "registers": {
    "r0": "0x00000000",
    "r1": "0x20000100",
    "sp": "0x20004ff0",
    "lr": "0x080011a5",
    "pc": "0x08001234",
    "xPSR": "0x61000000"
  },
  "count": 21
}
```

---

### jtag://flash/banks

Flash bank topology and metadata.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `banks` | `list[dict]` | List of flash bank descriptors |
| `count` | `int` | Number of flash banks |

Each bank contains:

| Field | Type | Description |
|-------|------|-------------|
| `index` | `int` | Bank index (0-based) |
| `name` | `str` | Flash driver name |
| `base` | `str` | Base address (hex) |
| `size` | `int` | Total size in bytes |
| `target` | `str` | Associated target name |

```json
{
  "banks": [
    {
      "index": 0,
      "name": "stm32f1x",
      "base": "0x08000000",
      "size": 65536,
      "target": "stm32f1x.cpu"
    }
  ],
  "count": 1
}
```

---

### jtag://jtag/chain

JTAG scan chain enumeration with TAP details.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `taps` | `list[dict]` | List of TAP descriptors |
| `count` | `int` | Number of TAPs discovered |

Each TAP contains:

| Field | Type | Description |
|-------|------|-------------|
| `name` | `str` | TAP name (e.g. `"stm32f1x.cpu"`) |
| `idcode` | `str` | JTAG IDCODE (hex) |
| `ir_length` | `int` | Instruction register length in bits |
| `enabled` | `bool` | Whether the TAP is enabled |

```json
{
  "taps": [
    {
      "name": "stm32f1x.cpu",
      "idcode": "0x1ba01477",
      "ir_length": 4,
      "enabled": true
    }
  ],
  "count": 1
}
```

---

### jtag://svd/peripherals

List of peripherals from the currently loaded SVD file.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `svd_loaded` | `bool` | Whether an SVD file is loaded |
| `svd_path` | `str` | Path to the loaded SVD file (only if loaded) |
| `peripherals` | `list[str]` | Peripheral names (empty list if no SVD loaded) |

If no SVD file has been loaded, `svd_loaded` will be `false` and `peripherals` will be an empty list:

```json
{
  "svd_loaded": false,
  "peripherals": []
}
```

After loading an SVD file via `svd_inspect(svd_path=...)`:

```json
{
  "svd_loaded": true,
  "svd_path": "/path/to/STM32F103.svd",
  "peripherals": ["GPIOA", "GPIOB", "GPIOC", "USART1", "USART2", "SPI1", "I2C1", "TIM1", "RCC", "FLASH"]
}
```

---

### jtag://svd/\{peripheral\}

Decoded register values for a specific peripheral. This is a **templated resource** -- replace `{peripheral}` with the actual peripheral name.

**URI examples:**

- `jtag://svd/GPIOA`
- `jtag://svd/USART1`
- `jtag://svd/RCC`

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `peripheral` | `str` | Peripheral name |
| `registers` | `dict[str, dict]` | Map of register name to decoded register |

Each register contains:

| Field | Type | Description |
|-------|------|-------------|
| `address` | `str` | Register address (hex) |
| `raw_value` | `str` | Raw 32-bit value read from hardware (hex) |
| `fields` | `list[dict]` | Decoded bitfields |

Each bitfield contains:

| Field | Type | Description |
|-------|------|-------------|
| `name` | `str` | Field name from SVD |
| `value` | `int` | Extracted value |
| `width` | `int` | Field width in bits |
| `offset` | `int` | Bit offset within the register |
| `description` | `str` | Field description from SVD |

Requires a loaded SVD file. Returns `{"error": "No SVD file loaded"}` if no SVD is available.

```json
{
  "peripheral": "GPIOA",
  "registers": {
    "CRL": {
      "address": "0x40010800",
      "raw_value": "0x44444444",
      "fields": [
        {
          "name": "MODE0",
          "value": 0,
          "width": 2,
          "offset": 0,
          "description": "Port mode bits"
        },
        {
          "name": "CNF0",
          "value": 1,
          "width": 2,
          "offset": 2,
          "description": "Port configuration bits"
        }
      ]
    }
  }
}
```

---

### jtag://transport/info

Active transport protocol and debug adapter information.

**Returns:**

| Field | Type | Description |
|-------|------|-------------|
| `transport` | `str` | Active transport (e.g. `"swd"`, `"jtag"`) |
| `adapter` | `str` | Adapter/probe identifier |
| `speed_khz` | `int \| null` | Adapter clock speed in kHz (null if unavailable) |
| `available_transports` | `list[str]` | All transports the adapter supports |

```json
{
  "transport": "swd",
  "adapter": "cmsis-dap",
  "speed_khz": 1000,
  "available_transports": ["swd", "jtag"]
}
```

---

## Resources vs. Tools

Use resources when you want to passively observe state. Use tools when you need to perform actions or need parameterized queries.

| Need | Use |
|------|-----|
| Check if target is halted | Resource: `jtag://target/state` |
| Halt the target | Tool: `target_control(action="halt")` |
| See all register values | Resource: `jtag://registers/all` |
| Read specific registers | Tool: `read_registers(names=["pc", "sp"])` |
| Check what peripherals are available | Resource: `jtag://svd/peripherals` |
| Decode a specific register with bitfields | Tool: `svd_inspect(peripheral="GPIOA", register="CRL")` |
