Skip to main content
Glama
soundbytelabs

sbl-probe

Official

sbl-probe

Serial communication and protocol analysis MCP server. Gives AI coding assistants direct access to serial ports for reading, writing, decoding, and capturing embedded device output — no more copy-pasting from picocom.

Part of the Sound Byte Labs embedded tooling suite, alongside sbl-debugger for hardware debugging.

Installation

Create a virtual environment and install the package:

python3 -m venv .venv
source .venv/bin/activate

# Install
pip install -e .

# Or with test dependencies
pip install -e ".[dev]"

Related MCP server: embedded-serial-mcp

MCP Configuration

Register the server in your MCP client's config. For most clients, add to .mcp.json in your project root:

{
  "mcpServers": {
    "sbl-probe": {
      "type": "stdio",
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["-m", "sbl_probe"]
    }
  }
}

Important: Use the absolute path to the Python binary inside your virtual environment. For example: /home/you/sbl-probe-mcp/.venv/bin/python

Restart your MCP client and the tools are available immediately.

Tools

Connection Management

Tool

Description

list_ports

List available serial ports with USB metadata and by-id paths

open

Open a serial connection (port, baud, optional name)

close

Close a named connection

connections

List active connections with stats

Data I/O

Tool

Description

read

Read decoded frames using the active decoder (line-oriented by default)

read_raw

Read raw bytes in utf8, hex, or base64

write

Write data to a connection

Protocol Analysis

Tool

Description

set_decoder

Change the active decoder on a connection

decode_buffer

Run a decoder over a raw data buffer

list_decoders

List available decoder names

probe_baud

Auto-detect baud rate by scoring printable text across common rates

Capture & Replay

Tool

Description

capture_start

Start background capture into a ring buffer (with optional filter, trigger, pretrigger)

capture_stop

Stop capture, return summary stats

capture_read

Query captured frames (filter by regex, time range, last N)

capture_stats

Get frame counts grouped by pattern without reading all frames

capture_save

Save capture buffer to a JSON Lines file

capture_load

Load a previously saved capture

Architecture

sbl_probe/
├── server.py          # FastMCP server, tool wiring
├── transport/
│   ├── base.py        # Transport protocol (structural typing)
│   ├── serial.py      # pyserial wrapper
│   └── manager.py     # Named connection registry
├── decoders/
│   ├── base.py        # Frame dataclass + Decoder protocol
│   └── raw.py         # Line-oriented decoder
├── capture/
│   ├── buffer.py      # Thread-safe ring buffer with query support
│   ├── engine.py      # Background reader thread
│   └── storage.py     # JSON Lines save/load
└── tools/
    ├── connection.py   # list_ports, open, close, connections
    ├── data.py         # read, read_raw, write
    ├── protocol.py     # set_decoder, decode_buffer, list_decoders
    ├── capture.py      # capture_start/stop/read/stats/save/load
    └── diagnostics.py  # probe_baud

Key design decisions:

  • Threaded pyserial with asyncio.to_thread() — keeps the MCP event loop responsive without the complexity of pyserial-asyncio

  • Pluggable decoders — register new decoders by name, swap at runtime via set_decoder

  • Background capture — daemon thread feeds decoded frames into a ring buffer; query with regex, time range, or tail the last N frames

  • Ingress filtering — filter and trigger patterns on capture_start keep the buffer focused on what matters

  • Error dicts, not exceptions — tools return {"error": "..."} instead of crashing the server

Adding a Custom Decoder

from sbl_probe.decoders.base import Frame, Decoder
from sbl_probe.decoders import registry

class MyDecoder:
    @property
    def name(self) -> str:
        return "my_proto"

    def feed(self, data: bytes, timestamp: float) -> list[Frame]:
        # Parse data, return frames
        ...

    def reset(self) -> None:
        ...

registry.register("my_proto", MyDecoder)

Running Tests

pytest                    # 113 tests
pytest -v                 # verbose
pytest tests/test_capture.py  # just capture tests

Dependencies

  • mcp — Official Python MCP SDK (FastMCP)

  • pyserial — Serial port access

  • Python >= 3.11

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    MCP server that lets LLMs talk to serial devices: microcontrollers, routers, modems, embedded Linux, anything with a UART.
    23
    80 PyPI
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A professional MCP server for serial port communication, enabling AI assistants to list, connect, send/receive data, and manage serial connections with embedded systems, IoT devices, and hardware debugging hardware.
    1
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    A headless MCP server that enables AI tools (like Claude Code) to read and analyze serial logs from embedded boards (ESP32, STM32) for firmware debugging, with read-only tools for log retrieval and a built-in web viewer.
    6
    -
  • F
    license
    A
    quality
    D
    maintenance
    An MCP server that enables AI agents to read serial output from devices by buffering lines in the background and allowing polling for new output, preventing blocking on long-running serial monitors.
    3
    -