serial-mcp
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.
Serial port MCP server for Claude Code, Codex, Opencode and AI agents. Reliable UART/USB-serial access for embedded development.
Serial MCP — UART and USB-Serial Access for AI Agents
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
- Install — see Install (Cargo, Nix, or prebuilt binary).
- Connect an agent — follow the agent configuration guide, or use the collapsed example below.
- Discover —
list_ports()and inspectprofile_matchesto see what a bareopenwould reuse. - Open —
open(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. - Talk —
transact()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.
- Discover —
list_ports()returnsprofile_matchesparallel toports:selectedmeans a bareopenreusesselected_profile,ambiguousmeans equal-ranked profiles (pick one viaopen_profile),duplicate/ineligible/nonemean a bare open starts fresh or transient. - Open — bare
open(port=...)only. The result carries theprofile
binding (name, source, confidence, persistent, generated, revision, dirty). - Talk —
transact(data=..., match=..., timeout_ms=...)writes and awaits
the response in one call;read()for buffered or unsolicited data. - Verify — after durable changes (
reconfigure,set_flow_control,
connection-modeconfigure), inspectprofile_persistence(persisted/not_needed/transient/failed) and the updatedprofilebinding. - Close —
close(); 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 |
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 MCP2026-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.
- CHANGELOG.md
- AGENTS.md, contributor guidelines
MCP Registry
Available on the MCP Registry as:
mcp-name: io.github.qarnet/serial-mcp
License
MIT. See LICENSE.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found