Skip to main content

MCP server for serial device communication

Project description

serial-mcp

MCP server for serial port communication. Lets LLMs talk to hardware — microcontrollers, routers, modems, embedded Linux, anything with a UART.

Why use this and not any of the many others out there?

  1. Real useful tools that the LLM can use like waiting/expecting data.
  2. Better test suite, and I test the commands myself.
  3. I actually use this day to day for real hardware hacking.
image

What it does

Exposes serial ports as MCP tools so an AI assistant can:

  • Discover connected USB-serial adapters and identify them by VID/PID
  • Connect to devices with configurable baud rate, data bits, stop bits, parity
  • Send commands and wait for responses (with regex-based expect patterns)
  • Read/write raw hex for binary protocols (Modbus, bootloader commands, etc.)
  • Control hardware signals (DTR/RTS) — reset Arduinos, enter ESP32 bootloader mode
  • Auto-detect baud rate by trying common rates and scoring readability
  • Transfer files with XMODEM (checksum or CRC-16)
  • Log received data to a file for capture / postmortem analysis
  • Manage multiple sessions simultaneously across different ports

Install

With uv (recommended)

Install globally so the serial-mcp command is available everywhere:

uv tool install serial-mcp

Or from a local clone:

uv tool install /path/to/serial-mcp

With pip

pip install serial-mcp

From source (editable)

git clone https://github.com/alxgmpr/serial-mcp.git
cd serial-mcp
uv pip install -e .

Configure

Claude Code

claude mcp add serial-mcp -- serial-mcp

That's it. Verify with claude mcp list.

If you installed from source instead of globally, use the full path:

claude mcp add serial-mcp -- python3 -m serial_mcp.server

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "serial": {
      "command": "serial-mcp"
    }
  }
}

With uvx (no install)

{
  "mcpServers": {
    "serial": {
      "command": "uvx",
      "args": ["serial-mcp"]
    }
  }
}

Tools

All tools are prefixed with serial_ to avoid name collisions with other MCP servers. Each tool includes MCP annotations (readOnlyHint, destructiveHint, etc.).

Port discovery

Tool Description
list_serial_ports List available serial ports with USB metadata (VID/PID, manufacturer)
serial_detect_baud Auto-detect baud rate by trying common rates and scoring ASCII readability

Connection management

Tool Description
serial_open Open a serial connection (baud, data bits, stop bits, parity, timeout)
serial_close Close a connection
serial_change_settings Change baud/parity/etc. on a live connection without closing it
serial_list_sessions List all open sessions
serial_status Detailed connection health, byte counts, uptime

Read / write (text)

Tool Description
serial_command Send a string, wait for response. Supports expect regex for prompt detection
serial_write Fire-and-forget text write
serial_read Read buffered data (advances cursor)
serial_read_since Read historical data since a timestamp (non-destructive)
serial_wait_for Block until a regex pattern appears in incoming data

Read / write (binary)

Tool Description
serial_write_hex Write raw bytes as hex ("AA 55 01 03")
serial_read_hex Read buffered data as hex string

Hardware signals

Tool Description
serial_set_signals Control DTR/RTS (reset micros, enter bootloader, etc.)
serial_get_signals Read DTR, RTS, CTS, DSR, RI, CD
serial_send_break Send a serial break (interrupt U-Boot, Cisco ROMMON, etc.)

Session utilities

Tool Description
serial_clear_history Flush the receive buffer and free memory

Logging

Tool Description
serial_log_start Capture all received data to a file (like minicom's capture)
serial_log_stop Stop logging and return file path, byte count, and duration

File transfer

Tool Description
serial_xmodem_send Send a file via XMODEM (checksum or CRC-16 mode)
serial_xmodem_receive Receive a file via XMODEM (checksum or CRC-16 mode)

The reader thread is paused for the duration of an XMODEM transfer so the protocol has exclusive port access — serial_read and logging won't capture anything during the transfer.

Prompts

Three prompts are registered to guide common workflows:

Prompt Description
scan_devices Walk through identifying all connected serial devices by VID/PID
detect_baud_rate Run baud detection on a port and interpret the results
interactive_shell Open a connection and probe for the device prompt

Usage examples

Interactive shell on a Linux device

1. list_serial_ports()                        → find /dev/ttyUSB0
2. serial_open(port="/dev/ttyUSB0")           → connect at 115200 8N1
3. serial_command(data="", expect="[$#]")     → get the shell prompt
4. serial_command(data="uname -a", expect="\\$")

Arduino / microcontroller

1. list_serial_ports()                        → find /dev/ttyACM0
2. serial_open(port="/dev/ttyACM0", baud_rate=9600)
3. serial_command(data="STATUS", timeout=2)
4. serial_set_signals(dtr=False)              → reset the board
5. serial_set_signals(dtr=True)
6. serial_wait_for(pattern="Ready", timeout=5)

Unknown baud rate

1. serial_detect_baud(port="/dev/ttyUSB0")    → recommends 9600
2. serial_open(port="/dev/ttyUSB0", baud_rate=9600)

Binary protocol (Modbus, etc.)

1. serial_open(port="/dev/ttyUSB0", baud_rate=9600)
2. serial_write_hex(hex_string="01 03 00 00 00 0A C5 CD")
3. serial_read_hex(timeout=2)

ESP32 bootloader entry

1. serial_open(port="/dev/ttyUSB0", baud_rate=115200)
2. serial_set_signals(dtr=False, rts=True)
3. serial_set_signals(dtr=True, rts=False)
4. serial_set_signals(dtr=False)
5. serial_wait_for(pattern="waiting for download", timeout=3)

How it works

Each serial_open() call creates a SerialSession with a background thread that continuously reads from the port into a timestamped ring buffer (default 10MB cap). This means:

  • No data loss — bytes are captured even between tool calls
  • Non-destructive readsserial_read_since() can replay history without advancing the cursor
  • Pattern matchingserial_command() and serial_wait_for() scan the buffer for regex matches in real-time
  • Multiple sessions — each port gets its own thread and buffer

All tools are async. Blocking serial I/O runs in asyncio.to_thread() so the event loop stays free.

Testing

Run the unit tests (no hardware required — they use a MockSerial fixture):

uv pip install -e ".[dev]"
pytest -v

Smoke-test the live server with the MCP Inspector:

DANGEROUSLY_OMIT_AUTH=true npx @modelcontextprotocol/inspector -- python3 -m serial_mcp.server

Set command to python3 and args to -m serial_mcp.server in the inspector UI, then connect.

Requirements

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyserial_mcp-0.4.0.tar.gz (43.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyserial_mcp-0.4.0-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file pyserial_mcp-0.4.0.tar.gz.

File metadata

  • Download URL: pyserial_mcp-0.4.0.tar.gz
  • Upload date:
  • Size: 43.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyserial_mcp-0.4.0.tar.gz
Algorithm Hash digest
SHA256 0a352fe0fb1a657f84e7397cce23b79f6f90af5785c3fc11073fe53a8fa47ce5
MD5 f95ab64fbd03a63b4a60810f3d9e2935
BLAKE2b-256 88354791f4abe7595befbab4777c9e062b9522b2e763f8287e1c6bf647b7481d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyserial_mcp-0.4.0.tar.gz:

Publisher: release.yml on alxgmpr/serial-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyserial_mcp-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: pyserial_mcp-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyserial_mcp-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9dbeb8ee4c567cdd723b52190a0bebc2980116e08eb1f4cbf3b295962257ea69
MD5 1cb4c493cbc2a1c2c768754dc6d235ad
BLAKE2b-256 08d94a19bf85aa4cc1497b8cf10f32946e73b1ce719f748c7878e394695f933f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyserial_mcp-0.4.0-py3-none-any.whl:

Publisher: release.yml on alxgmpr/serial-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page