Logo/favicon: Replace crude rectangle with proper DE-9 connector geometry derived from EIA/TIA-574 specs (D-shaped shell, 5-over-4 pin layout, hex standoff mounting posts). Documentation: Rewrite all code examples from the MCP client perspective. Remove Python syntax highlighting, use JSON boolean conventions (true/false instead of True/False), and add framing notes explaining tool-call notation. Tutorials now guide users through natural language interaction with the assistant rather than direct function calls.
MCP Serial Server
FastMCP server for serial port access via Model Context Protocol.
Features
- RS-232 Mode: Full modem control (RTS, DTR, CTS, DSR, RI, CD, break condition)
- RS-485 Mode: Half-duplex bus communication with auto direction control
- File Transfer: X/Y/ZMODEM protocols for reliable file transfers
- Auto-baud Detection: Smart detection using 0x55 sync pattern analysis
- URL Handlers: Open remote/virtual ports (
socket://,rfc2217://,loop://,spy://,cp2110://) - Dynamic Resources: Read data via
serial://{port}/data - Full pyserial support (baudrate, parity, stop bits, flow control)
Installation
# With uvx (recommended)
uvx mcserial
# Or install directly
uv pip install mcserial
# With CP2110 HID-to-UART support
uv pip install mcserial[cp2110]
Usage with Claude Code
# Add to Claude Code
claude mcp add mcserial "uvx mcserial"
Modes
Ports open in RS-232 mode by default. Switch with set_port_mode():
| Mode | Use Case | Tools |
|---|---|---|
| RS-232 | Point-to-point serial | get_modem_lines, set_modem_lines, pulse_line, send_break |
| RS-485 | Multi-drop bus (Modbus) | set_rs485_mode, rs485_transact, rs485_scan_addresses |
Tools
Common (both modes)
| Tool | Description |
|---|---|
list_serial_ports |
Discover available ports (supports grep regex filtering) |
open_serial_port |
Open connection — local device or URL scheme (auto-detects baud if not specified) |
close_serial_port |
Close a connection |
set_port_mode |
Switch between RS-232 and RS-485 modes |
write_serial |
Send text data |
write_serial_bytes |
Send raw bytes (atomic single-syscall write) |
read_serial |
Read available data |
read_serial_line |
Read until newline |
read_serial_lines |
Batch read multiple lines |
read_until |
Read until custom terminator |
configure_serial |
Change port settings |
flush_serial |
Clear buffers |
cancel_read |
Interrupt pending read operation |
cancel_write |
Interrupt pending write operation |
set_flow_control |
Manually gate XON/XOFF or RTS/CTS flow |
set_low_latency_mode |
Enable kernel low-latency mode (Linux) |
get_connection_status |
List open connections with mode |
detect_baud_rate |
Auto-detect baud rate |
RS-232 Mode
| Tool | Description |
|---|---|
get_modem_lines |
Read CTS, DSR, RI, CD, RTS, DTR states + break condition |
set_modem_lines |
Control RTS and DTR outputs |
pulse_line |
Pulse RTS/DTR for reset sequences |
send_break |
Send timed break signal |
set_break_condition |
Hold/release break state |
RS-485 Mode
| Tool | Description |
|---|---|
set_rs485_mode |
Configure hardware RS-485 (DE/RE control) |
check_rs485_support |
Detect hardware RS-485 capability |
rs485_transact |
Send/receive with automatic turnaround |
rs485_scan_addresses |
Scan bus for responding devices |
File Transfer
| Tool | Description |
|---|---|
file_transfer_send |
Send file via XMODEM/YMODEM/ZMODEM |
file_transfer_receive |
Receive file via XMODEM/YMODEM/ZMODEM |
file_transfer_send_batch |
Send multiple files (YMODEM/ZMODEM) |
Protocols:
xmodem- 128-byte blocks, simple (1977)xmodem1k- 1024-byte blocksymodem- Batch mode with filename/sizezmodem- Streaming, auto-resume (recommended)
URL Handlers
The open_serial_port tool accepts URL schemes in addition to local device paths:
| Scheme | Description | Example |
|---|---|---|
socket:// |
Raw TCP socket — serial-to-ethernet bridges | socket://192.168.1.100:4001 |
rfc2217:// |
Telnet COM Port Control — remote baud/flow config | rfc2217://192.168.1.100:2217 |
loop:// |
Loopback — writes echo back as reads (testing) | loop:// |
spy:// |
Debug wrapper — logs all traffic to stderr | spy:///dev/ttyUSB0 |
cp2110:// |
Silicon Labs HID-to-UART (requires [cp2110] extra) |
cp2110:// |
hwgrep:// |
Open first port matching hardware pattern | hwgrep://FTDI |
alt:// |
Alternate port backend | alt:///dev/ttyUSB0 |
URL-opened ports skip auto-baud detection and exclusive access (not applicable to virtual/network ports).
Resources
| URI | Description |
|---|---|
serial://ports |
List available ports |
serial://{port}/data |
Read data from open port |
serial://{port}/status |
Port config and mode |
serial://{port}/raw |
Read as hex dump |
Environment Variables
| Variable | Default | Description |
|---|---|---|
MCSERIAL_DEFAULT_BAUDRATE |
9600 | Default baud rate |
MCSERIAL_DEFAULT_TIMEOUT |
1.0 | Read timeout (seconds) |
MCSERIAL_MAX_CONNECTIONS |
10 | Max concurrent ports |
Example Workflows
Basic RS-232
1. list_serial_ports() → find /dev/ttyUSB0
2. open_serial_port(port="/dev/ttyUSB0") # auto-detects baud
3. write_serial_bytes(port="/dev/ttyUSB0", data=[65, 84, 13, 10]) # AT\r\n
4. read_serial_lines(port="/dev/ttyUSB0") # batch read response
5. close_serial_port(port="/dev/ttyUSB0")
Filter Ports by Hardware
1. list_serial_ports(grep="FTDI") # find all FTDI devices
2. list_serial_ports(grep="CP210") # find Silicon Labs adapters
3. list_serial_ports(grep="VID:PID=0403:6001") # exact USB ID match
RS-485 Modbus
1. open_serial_port(port="/dev/ttyUSB0", baudrate=9600)
2. set_port_mode(port="/dev/ttyUSB0", mode="rs485")
3. rs485_scan_addresses(port="/dev/ttyUSB0") # discover devices
4. rs485_transact(port="/dev/ttyUSB0", data="\x01\x03...")
Network Serial (serial-to-ethernet bridge)
1. open_serial_port(port="socket://192.168.1.100:4001", baudrate=115200)
2. write_serial(port="socket://192.168.1.100:4001", data="AT\r\n")
3. read_serial(port="socket://192.168.1.100:4001")
Loopback Testing (no hardware needed)
1. open_serial_port(port="loop://", baudrate=9600)
2. write_serial(port="loop://", data="hello")
3. read_serial(port="loop://") # → "hello"
4. close_serial_port(port="loop://")
File Transfer
1. open_serial_port(port="/dev/ttyUSB0", baudrate=115200)
2. file_transfer_send(port="/dev/ttyUSB0", file_path="firmware.bin")
License
MIT
Description
Languages
Python
100%