Skip to main content
Glama
qarnet
by qarnet

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.

Related MCP server: embedded-serial-mcp

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.

{
  "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

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.

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
3dRelease cycle
21Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    MCP server that lets LLMs talk to serial devices: microcontrollers, routers, modems, embedded Linux, anything with a UART.
    23
    5
    MIT
  • A
    license
    -
    quality
    C
    maintenance
    A professional MCP server for serial port communication, enabling AI assistants to list, connect, send/receive data, and manage serial connections with embedded systems, IoT devices, and hardware debugging hardware.
    1
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    MCP server for serial port communication. Provides tools to open, read, write, and manage serial ports through the Model Context Protocol.
    10

View all related MCP servers

Related MCP Connectors

  • MCP server wrapping the Tesla Fleet API and TeslaMate API

  • Zero-install remote MCP server for proof-of-existence file attestation.

  • Remote MCP server for full read/write access to a Zotero library

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/qarnet/serial-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server