---
title: MCP Resources
description: Read-only data endpoints exposed as MCP resources
sidebar:
  order: 6
---

import { Aside } from '@astrojs/starlight/components';

MCP resources are read-only data endpoints that clients can access without calling tools. They provide a way to passively observe port state and data, separate from the action-oriented tool interface.

<Aside type="note">
Resources are read-only. They do not modify port state, open connections, or send data. To interact with ports, use the [Common Tools](/reference/tools-common/).
</Aside>

---

## serial://ports

List all available serial ports on the system. Returns a Markdown-formatted list with device paths, descriptions, and open/closed status.

**URI:** `serial://ports`

**Example output:**
```markdown
# Available Serial Ports

- /dev/ttyUSB0 [OPEN]: USB-Serial Controller D
- /dev/ttyUSB1 [closed]: FT232R USB UART
- /dev/ttyACM0 [closed]: Arduino Mega 2560
```

This resource calls `list_serial_ports()` internally with default parameters (`usb_only=True`). For filtered results, use the `list_serial_ports` tool directly with the `grep` parameter.

---

## `serial://{port}/data`

Read available data from an open serial port. Returns the data decoded as UTF-8 with a byte count prefix.

**URI pattern:** `serial://{port}/data`

**Example URIs:**
```
serial:///dev/ttyUSB0/data
serial://COM3/data
serial://loop:///data
```

**Example output:**
```
[42 bytes from /dev/ttyUSB0]
AT+GMR
OK
ESP8266 firmware v2.1
```

If no data is available in the port's input buffer, returns:
```
[No data available on /dev/ttyUSB0]
```

If the port is not open, returns an error message prompting you to use `open_serial_port` first.

<Aside type="caution">
Reading data from a resource consumes the bytes from the serial buffer. Once read, the data is no longer available for subsequent reads (via either resources or tools).
</Aside>

---

## `serial://{port}/status`

Get the current configuration and connection status for an open serial port. Returns a Markdown-formatted status report.

**URI pattern:** `serial://{port}/status`

**Example URIs:**
```
serial:///dev/ttyUSB0/status
serial://COM3/status
```

**Example output:**
```markdown
# Serial Port Status: /dev/ttyUSB0
- Mode: RS232
- Open: True
- Baudrate: 115200
- Bytesize: 8
- Parity: N
- Stopbits: 1
- Timeout: 1.0s
- Bytes waiting (in): 0
- Bytes waiting (out): 0
- CTS: True
- DSR: True
- RI: False
- CD: False
- RTS: True
- DTR: True
```

This resource provides a snapshot of all port settings, buffer counts, and modem line states in a single read. Useful for diagnostics without calling multiple tools.

---

## `serial://{port}/raw`

Read available data from an open serial port as a hex dump. Same as `serial://{port}/data` but returns raw bytes in hexadecimal format instead of decoded text.

**URI pattern:** `serial://{port}/raw`

**Example URIs:**
```
serial:///dev/ttyUSB0/raw
serial://COM3/raw
```

**Example output:**
```
[8 bytes from /dev/ttyUSB0]
01 03 04 00 64 00 c8 fa
```

Use this resource when working with binary protocols (Modbus, proprietary framing) where hex representation is more useful than decoded text.

<Aside type="caution">
Like the data resource, reading raw data consumes the bytes from the serial buffer.
</Aside>

---

## `serial://log`

Read the server-wide log buffer. Returns recent log entries as formatted text, useful for debugging server behavior and diagnosing issues.

**URI:** `serial://log`

**Example output:**
```
# mcserial Server Log (47 entries)

[2024-02-03T18:45:12] INFO server: Opened /dev/ttyUSB0 at 115200 baud
[2024-02-03T18:45:13] DEBUG /dev/ttyUSB0: TX 8 bytes
[2024-02-03T18:45:14] WARNING zmodem: Sanitized filename: "../etc/passwd" -> "etc_passwd"
[2024-02-03T18:45:15] ERROR server: Failed to open /dev/ttyUSB1: Permission denied
```

Log entries include:
- **Timestamp** in ISO-8601 format
- **Level**: DEBUG, INFO, WARNING, or ERROR
- **Source**: "server" for general events, or port name for port-specific events
- **Message**: Human-readable description of the event

Use `configure_logging()` to adjust the minimum log level and buffer size. The default level is INFO, which captures port open/close events and errors.

<Aside type="tip">
Setting the log level to DEBUG captures TX/RX byte counts for all read/write operations. This is useful for debugging communication issues without enabling full traffic logging.
</Aside>

---

## `serial://{port}/log`

Read the per-port traffic log (if enabled). Returns a history of TX/RX data in hex + ASCII format.

**URI pattern:** `serial://{port}/log`

**Example URIs:**
```
serial:///dev/ttyUSB0/log
serial://spy:///dev/ttyUSB0/log
```

**Example output:**
```
# Traffic Log: /dev/ttyUSB0 (23 entries)

[18:45:12.123] TX (8 bytes): 01 03 00 00 00 01 84 0a  |........|
[18:45:12.189] RX (7 bytes): 01 03 02 00 64 b8 44     |....d.D|
[18:45:13.001] TX (8 bytes): 01 03 00 01 00 01 d5 ca  |........|
```

Each entry shows:
- **Timestamp** with millisecond precision
- **Direction**: TX (transmitted) or RX (received)
- **Byte count**
- **Hex dump**: First 16 bytes in hexadecimal
- **ASCII preview**: Printable characters (non-printable shown as `.`)

<Aside type="note">
Traffic logging is not enabled by default. Enable it with `enable_traffic_log(port)` or by opening the port with `spy://` scheme.
</Aside>

<Aside type="caution">
Unlike the data resource, reading the traffic log does **not** consume any data. It's a read-only view of the capture buffer. The actual serial data remains in the serial buffer until read via tools or the data resource.
</Aside>

---

## URI Encoding

The `{port}` segment in resource URIs uses the device path directly. For paths containing special characters (like forward slashes in Linux device paths), the MCP client handles URL encoding:

| Device Path | Resource URI |
|-------------|-------------|
| `/dev/ttyUSB0` | `serial:///dev/ttyUSB0/data` |
| `COM3` | `serial://COM3/data` |
| `loop://` | `serial://loop:///data` |

The server URL-decodes the port parameter internally, so both encoded and unencoded paths work correctly.
