# 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 ```bash # 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 ```bash # 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 blocks - `ymodem` - Batch mode with filename/size - `zmodem` - 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