MCP Serial Server
FastMCP server for serial port access via Model Context Protocol.
Documentation | PyPI | Source
Features
- RS-232 Mode: Full modem control (RTS, DTR, CTS, DSR, RI, CD, break condition)
- RS-422 Mode: Full-duplex differential point-to-point (or 1-to-10 receivers) over long distances
- 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() or pass mode= to open_serial_port():
| Mode | Use Case | Tools |
|---|---|---|
| RS-232 | Point-to-point serial | get_modem_lines, set_modem_lines, pulse_line, send_break |
| RS-422 | Full-duplex differential links | check_rs422_support (plus all common tools) |
| RS-485 | Multi-drop bus (Modbus) | set_rs485_mode, rs485_transact, rs485_scan_addresses |
Tools
Common (all 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, RS-422, 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 |
transact |
Send command + read response in one call (any mode) |
configure_serial |
Change port settings (including default line ending) |
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-422 Mode
| Tool | Description |
|---|---|
check_rs422_support |
Detect RS-422 adapter capabilities (chip, differential pairs) |
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://server/info |
Server version, repo links, connection count |
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 |
serial://log |
Server-wide log buffer |
serial://{port}/log |
Per-port traffic log (if enabled) |
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. configure_serial(port="/dev/ttyUSB0", line_ending="crlf") # auto-append \r\n
4. transact(port="/dev/ttyUSB0", data="AT") # send + read in one call
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-422 Differential Link
1. open_serial_port(port="/dev/ttyUSB0", baudrate=9600, mode="rs422")
2. configure_serial(port="/dev/ttyUSB0", line_ending="crlf")
3. transact(port="/dev/ttyUSB0", data="READ TEMP") # full-duplex, no direction control
4. check_rs422_support(port="/dev/ttyUSB0")
RS-485 Modbus
1. open_serial_port(port="/dev/ttyUSB0", baudrate=9600, mode="rs485")
2. rs485_scan_addresses(port="/dev/ttyUSB0") # discover devices
3. 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
Metadata
Release files for mcserial 2026.3.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mcserial-2026.3.5.tar.gz | 48.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcserial-2026.3.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 110.1 kB
Release files / mcserial-2026.3.5.tar.gz
| Download URL | mcserial-2026.3.5.tar.gz |
|---|---|
| Size | 48.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8913289576dd5713ed5d40e48cc92b64949a38e7a628d5eed6a62d4dd909626f
|
|
BLAKE2b-256 checksum How to use checksums |
14320421eb0b14402fc80cf11ccabec40ac89633162f68b733a7b7259bd00195
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mcserial-2026.3.5-py3-none-any.whl
| Download URL | mcserial-2026.3.5-py3-none-any.whl |
|---|---|
| Size | 61.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
60fc16107002354b41f388e829722cdca7b1ee11045c8752e9317d9cac089500
|
|
BLAKE2b-256 checksum How to use checksums |
3a5e3966e3e316a3ba2a9aa85a169c97bc0bc219e6f7bf192dee0efb208befaa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for mcserial 2026.3.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.