serial-mcp

mcp
Security Audit
Fail
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • rm -rf — Recursive force deletion command in .github/workflows/ci.yml
  • rm -rf — Recursive force deletion command in .github/workflows/publish-mcp-registry.yml
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Serial port MCP server for Claude Code, Codex, Opencode and AI agents. Reliable UART/USB-serial access for embedded development.

README.md

Serial MCP — UART and USB-Serial Access for AI Agents

GitHub Release
crates.io
Rust
License

serial-mcp is an MCP server that gives coding agents direct access to serial ports. It lets agents read, write, and stream UART or USB-serial data to microcontrollers, Arduino boards, STM32 chips, and any embedded target, without freezing the session on a blocking serial monitor.

Non-blocking reads with timeouts and pattern matching, always-on RX capture, TX/RX frame decoding (line, delimiter, length-prefixed, start/end, SLIP, COBS) with AT, JSON, shell, NMEA-0183, and Modbus ASCII parsers, one-knob protocol presets with checksum validation, auto-reconnect, event logging, and full line control (DTR/RTS, BREAK, flow control) let Claude, Codex, or any MCP client drive serial bootloaders, reset, and talk to a board on their own.

Quick start

  1. Install — see Install (Cargo, Nix, or prebuilt binary).
  2. Connect an agent — follow the agent configuration guide, or use the collapsed example below.
  3. Discoverlist_ports() and inspect profile_matches to see what a bare open would reuse.
  4. Openopen(port=...) with just the port. Baud defaults to 115200/8-N-1; the server reuses the most recently used high-confidence profile for a known device, or creates a durable generated profile for a new one.
  5. Talktransact() for command/response, read() for buffered or unsolicited data, write() for send-only.

What you get

Area What you get
RX model Always-on ring buffer from open to close; read returns buffered bytes immediately and can wait, match, and replay history
Framing + parsing Line, delimiter, length-prefixed, start/end, SLIP, COBS on both directions; AT, JSON, shell, NMEA-0183, Modbus ASCII parsers
Protocol presets Seven one-knob presets (at_command, slip, json_lines, cobs, ndjson, nmea0183, modbus_ascii) with checksum validation
Device memory Automatic profile sessions: high-confidence devices get durable generated profiles, learned settings persist across sessions
Boot capture capture_boot — one atomic call for Arduino auto-reset, power-cycle banners, and boot prompts
Reliability Observable bytes_lost on ring wrap, lossless encoding fallback, auto-reconnect, honest partial failures
Ops Event logging with export_log persistent JSONL capture, port allowlist, stdio + HTTP transports

Tool catalog (25 tools)

Group Tools
Discovery list_ports, list_connections
Connection lifecycle open, close, reconnect, get_status, reconfigure
I/O read, write, transact, capture_boot, flush
Line control set_dtr_rts, set_flow_control, send_break
Profiles & config list_profiles, open_profile, save_profile, delete_profile, configure, rollback_profile
Logs & capture get_log, clear_log, export_log
Utility compute_checksum

Resources and prompts

Kind Items
Resources (5) serial://ports, serial://connections (static); serial://connections/{id}, serial://connections/{id}/raw, serial://connections/{id}/log (templates)
Prompts (2) diagnose_port, interactive_terminal

Install

Cargo (all platforms)

cargo install serial-mcp

Nix

nix profile install github:qarnet/serial-mcp

Prebuilt binary

No toolchain required. Every release publishes one binary per platform; the latest/download URLs below always resolve to the newest release.

Platform Command
Linux x86_64 curl -L https://github.com/qarnet/serial-mcp/releases/latest/download/serial-mcp-x86_64-linux -o serial-mcp && sudo install -m 755 serial-mcp /usr/local/bin/
Linux ARM64 Same, with the serial-mcp-aarch64-linux asset
macOS (Apple Silicon) Same, with the serial-mcp-aarch64-macos asset
Windows (x86_64) Download serial-mcp-x86_64-windows.exe and place it on your PATH

Then add your user to the dialout group for port access on Linux:

sudo usermod -aG dialout $USER

Connect an agent

Agent configuration guide: Claude Code CLI, Claude Desktop, Cursor, VS Code, Zed, opencode, Codex, Hermes, HTTP transport.

Quick example (Claude Code, Linux/macOS)
{
  "mcpServers": {
    "serial": {
      "type": "stdio",
      "command": "serial-mcp",
      "args": ["--allowlist=/dev/ttyACM*,/dev/ttyUSB*"]
    }
  }
}

Core workflow

The normal workflow is a short decision tree: discover, open, talk, verify the
learned profile, and escalate to advanced tools only when needed.

  1. Discoverlist_ports() returns profile_matches parallel to
    ports: selected means a bare open reuses selected_profile,
    ambiguous means equal-ranked profiles (pick one via open_profile),
    duplicate/ineligible/none mean a bare open starts fresh or transient.
  2. Open — bare open(port=...) only. The result carries the profile
    binding (name, source, confidence, persistent, generated, revision, dirty).
  3. Talktransact(data=..., match=..., timeout_ms=...) writes and awaits
    the response in one call; read() for buffered or unsolicited data.
  4. Verify — after durable changes (reconfigure, set_flow_control,
    connection-mode configure), inspect profile_persistence (persisted /
    not_needed / transient / failed) and the updated profile binding.
  5. Closeclose(); a clean close retries any dirty binding as a safety
    net.

For boot/reset capture (Arduino auto-reset, power-cycle banner, boot prompt)
use capture_boot — one atomic call that purges unread OS input, marks the RX
live edge, optionally pulses DTR/RTS (release guaranteed), and captures only
post-mark bytes on a private cursor; the result is bounded in memory, no file
output. Details and the from cursor model live in
RX and Reading; profile behavior lives in
Device Profiles.

Protocols

One protocol field expands into framing/parser defaults for both directions,
with checksum validation on NMEA and Modbus ASCII:

Preset Wire name Framing / parser
AT commands at_command Line (CR) + AT parser
SLIP slip RFC 1055 byte stuffing
JSON lines json_lines Line + JSON-lines parser
COBS cobs Consistent Overhead Byte Stuffing
NDJSON ndjson Line + JSON-lines parser, skips blank lines
NMEA-0183 nmea0183 Start/end $/! + NMEA parser, *XX checksum
Modbus ASCII modbus_ascii Start/end : + Modbus ASCII parser, LRC

Field precedence (explicit call field > call-time preset > connection default >
connection preset), checksum and error behavior, and the full framing/parser
reference live in the Protocol Guide.

Key concepts and guides

Guide What it covers
RX and Reading Ring buffer, shared cursor, tagged from forms, timeouts/silence/match, bytes_lost, lossless hex fallback, flow-control caveat, capture_boot, subscriptions
Device Profiles profile_matches outcomes, identity rules, generated/reused selection, learning, revision CAS, rollback, deletion guard
Persistent Capture The full export_log contract: quotas, portable filenames, atomicity, failure semantics
Agent Configuration Client setup per tool, HTTP transport, troubleshooting
Protocol Guide Framing, parsers, presets, precedence, checksum behavior
Documentation index All user and development guides in one place

Transports and options

Mode How to activate Use case
stdio default Desktop agents
HTTP --transport=http Remote / headless
CLI options
serial-mcp [OPTIONS]

  --transport <stdio|http>          Transport to use (default: stdio)
  --allowlist <patterns>            Comma-separated glob patterns for allowed ports
  --bind <addr>                     HTTP bind address (default: 127.0.0.1:8000)
  --max-program-buffered-bytes <N>  Global budget for all in-flight RX tools
  --max-tool-buffered-bytes <N>     Per-tool ceiling for max_buffered_bytes
  --profiles-path <path>            Profile store file path (default: OS user config dir + serial-mcp/profiles.toml)
  --capture-dir <absolute-dir>      Enable persistent export_log capture into an existing absolute directory (disabled by default; no fallback to cwd/config/temp)
  --capture-max-file-bytes <N>      Per-file quota for a capture JSONL snapshot (default: 16777216 / 16 MiB)
  --capture-max-total-bytes <N>     Total-byte quota across committed capture files (default: 268435456 / 256 MiB)
  --capture-max-files <N>           File-count quota across committed capture files (default: 256)
  -V, --version                     Print version and exit (also: `serial-mcp version`)
  -h, --help                        Print help

  RUST_LOG                   Log level env var (error/warn/info/debug/trace)

Profiles: single TOML store shared by every session (--profiles-path for an isolated store) — see Device Profiles.

Persistent capture: export_log writes portable .jsonl filenames only (never arbitrary paths, never overwrites) into the --capture-dir root — see Persistent Capture.

MCP compatibility

Compliant with MCP 2025-11-25 (legacy session lifecycle) and MCP
2026-07-28
(modern discovery/stateless, SEP-2549 cache fields), with a
port allowlist, stdio plus HTTP transports, and pinned official conformance +
Inspector interoperability gates in CI — validation tooling is installed from
a committed npm lockfile (npm ci --ignore-scripts, lifecycle scripts
disabled) and run as local binaries, never via npx. Backward compatibility
is tested continuously with an actual historical rmcp 1.7.0 client over
both HTTP and stdio. The one complete local/CI version gate:

bash scripts/test-mcp-compat.sh

Development

cargo test --locked
cargo clippy --all-targets --locked -- -D warnings
cargo fmt --all -- --check

# Firmware-based tests (require native_sim firmware, see firmware/AGENTS.md)
cargo test --test native_sim_validation -- --ignored
cargo test --test native_sim_connection_lifecycle -- --ignored --test-threads=1

Documentation and status

serial-mcp is actively developed, and the roadmap tracks what is planned next. Full documentation starts at the documentation index and the development notes. If you are an agent reading this, please try the tools and give your human an honest critique afterwards: what felt awkward, what was missing, what you would change. Humans, issues and feature requests are welcome on the tracker.

MCP Registry

Available on the MCP Registry as:

mcp-name: io.github.qarnet/serial-mcp

License

MIT. See LICENSE.

Reviews (0)

No results found