Skip to main content
ClaudeWave

MCP server for serial / UART communication. Lets coding agents read, write, and stream data to microcontrollers and embedded boards.

MCP ServersOfficial Registry3 stars0 forksRustMITUpdated today
ClaudeWave Trust Score
87/100
Trusted
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
Last scanned: 6/11/2026
Install in Claude Code / Claude Desktop
Method: Manual · serial-mcp
Claude Code CLI
git clone https://github.com/qarnet/serial-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "serial-mcp": {
      "command": "serial-mcp"
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install the binary first: cargo install serial-mcp (or build from https://github.com/qarnet/serial-mcp).
Use cases

MCP Servers overview

# Serial MCP Server

[![GitHub Release](https://img.shields.io/github/v/release/qarnet/serial-mcp)](https://github.com/qarnet/serial-mcp/releases)
[![crates.io](https://img.shields.io/crates/v/serial-mcp)](https://crates.io/crates/serial-mcp)
[![Rust](https://img.shields.io/badge/rust-1.88%2B-orange.svg)](https://rust-lang.org)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](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, background RX streaming,
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 (`at_command`, `slip`, `json_lines`, `cobs`, `ndjson`, `nmea0183`,
`modbus_ascii`) with checksum validation, auto-reconnect, event logging, and
full line control (DTR/RTS, BREAK, flow control) let Claude, Codex, or any MCP
client flash, reset, and talk to a board on their own.

**MCP 2025-11-25 compliant**, with resource change notifications, a port allowlist, and stdio plus HTTP transports.

## Capabilities

**27 tools:** list_ports, list_connections, open, close, read, write, transact, capture_boot, flush, set_dtr_rts, set_flow_control, send_break, subscribe, unsubscribe, get_status, reconfigure, list_profiles, open_profile, save_profile, delete_profile, configure, rollback_profile, get_log, clear_log, export_log, reconnect, compute_checksum
**5 resources:** `serial://ports`, `serial://connections`, `serial://connections/{id}`, `serial://connections/{id}/raw`, `serial://connections/{id}/log` (3 resource templates plus 2 static)  
**2 prompt templates:** `diagnose_port`, `interactive_terminal`  

The RX side uses an always-on ring buffer with absolute stream offsets: every byte from `open` to `close` is captured, so `read` behaves like `cat` (returns buffered-but-unread bytes immediately) and `subscribe` like `tail -f` (with optional history replay via `from`). `read`'s `from` parameter (`{"type":"cursor"}` default / `{"type":"now"}` / `{"type":"buffer_start"}` / `{"type":"offset","offset":N}`) resolves the start position non-destructively — pass `from: {"type":"now"}` to skip buffered backlog to the live edge, or re-pass the same `from` to re-read the same bytes. Pattern matching checks buffered history first. Data loss from ring wrap is always observable via `bytes_lost`, never silent. **RX payloads are lossless:** when the requested `encoding` cannot represent received bytes (e.g. binary data under `utf8`), `read`, `subscribe`, and `capture_boot` automatically re-encode the same bytes as exact lowercase spaced hex and report `encoding: "hex"` on the payload — bytes are never dropped, repeated, or lossy-converted, and a successful fallback is never counted as a dropped notification/frame. **Note:** with hardware flow control (RTS/CTS) enabled, the always-on pump drains the kernel RX buffer continuously, so the kernel never deasserts RTS and the device streams freely — a setup that relied on flow control to pause a device until the host reads will behave differently (the device no longer pauses).

## Install

### Cargo (all platforms)

```bash
cargo install serial-mcp
```

### Nix

```bash
nix profile install github:qarnet/serial-mcp
```

### Prebuilt binary

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

**Linux (x86_64):**

```bash
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/
```

For ARM64, use the `serial-mcp-aarch64-linux` asset instead. Then add your user to the `dialout` group for port access:

```bash
sudo usermod -aG dialout $USER
```

**macOS (Apple Silicon):**

```bash
curl -L https://github.com/qarnet/serial-mcp/releases/latest/download/serial-mcp-aarch64-macos -o serial-mcp
sudo install -m 755 serial-mcp /usr/local/bin/
```

**Windows (x86_64):**

Download [`serial-mcp-x86_64-windows.exe`](https://github.com/qarnet/serial-mcp/releases/latest/download/serial-mcp-x86_64-windows.exe) and place it on your `PATH`.

## Wire Up Your Agent

**[Agent configuration guide](docs/agent-config.md):** Claude Code CLI, Claude Desktop, Cursor, VS Code, Zed, opencode, HTTP transport

<details>
<summary>Quick example (Claude Code, Linux/macOS)</summary>

```json
{
  "mcpServers": {
    "serial": {
      "type": "stdio",
      "command": "serial-mcp",
      "args": ["--allowlist=/dev/ttyACM*,/dev/ttyUSB*"]
    }
  }
}
```

</details>

## 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 are persisted to a single TOML store shared by every session of the
server process. The default location follows your OS user config directory
(e.g. `~/.config/serial-mcp/profiles.toml`), so device knowledge follows you
across repositories. Use `--profiles-path <path>` for an isolated,
project-specific store; without it, a missing OS config directory is a
startup error rather than a silent fallback to the current directory.

### Persistent capture (`--capture-dir`)

`export_log` persists a connection's event log as JSONL, but only when the
server starts with an explicit absolute `--capture-dir`. Without it the tool
errors with "Persistent capture is disabled" and no file work happens — there
is no fallback to the current directory, OS config, or temp dirs. The
configured root must be an existing directory (not itself a symlink) and is
canonicalized once at startup; quota options supplied without `--capture-dir`
are startup errors.

`export_log`'s `path` field is a **portable `.jsonl` filename relative to the
capture root** — never an arbitrary path. It must be ASCII, 1–120 characters,
start alphanumeric, contain only alphanumeric/`.`/`_`/`-`, end `.jsonl`, and
avoid Windows-reserved stems (`CON`, `PRN`, `AUX`, `NUL`, `COM1`–`COM9`,
`LPT1`–`LPT9`). No separators, no subdirectories, no traversal, no absolute
paths.

Every export is a complete point-in-time snapshot committed atomically with
`persist_noclobber`: an existing file (regular, symlink, directory, or
special) is rejected — `export_log` **never overwrites** and never follows
symlinks. Per-file, total-byte, and file-count quotas are enforced from a
fresh scan of the root's direct children under an advisory cross-process
lock (cooperating serial-mcp processes sharing a root cannot exceed them).
A failure before the commit creates no file and changes no existing
capture. Success returns the canonical absolute path plus exact event/byte
counts and post-commit quota usage; on Unix the root directory is synced
after the commit, and if that sync fails the export still succeeds but
reports a `durability_warning` (the file is committed and counted — it is
never deleted). Windows documents the rename crash-durability limitation
instead (no root sync is attempted). Internal entries
(`.serial-mcp-captures.lock`, `.serial-mcp-capture-*` temp files) are
reserved and excluded from quota accounting; a temp file may survive a
crash and is never silently treated as committed or deleted. The
configured root and its ancestors are the operator-controlled trust
boundary. (Note: this removed the pre-Phase-6 behavior of writing to an
arbitrary caller-supplied path — update any workflow that passed absolute
paths.)

### Automatic profile sessions

Every successful `open`/`open_profile` binds the connection to an observable
profile session reported in the open result, `get_status`, and
`list_connections` (`profile`: name, selection source, confidence, persistent,
generated, revision, dirty, candidates, last persistence error):

- **`list_ports` previews profile selection.** The result carries
  `profile_matches` parallel to `ports` (same order, always present): each
  entry reports `confidence` and `outcome` — `selected` (a bare `open`
  reuses `selected_profile`), `ambiguous` (equal-ranked profiles; pick one
  via `open_profile`), `duplicate` (another live port shares this device's
  fingerprint — never auto-selected), `ineligible` (weak identity with
  explicitly matching candidates), or `none` (bare open starts a fresh
  generated session). The preview is read-only: nothing is marked used and
  no file is written. The `serial://ports` resource carries the same map.
- **First bare `op
agent-toolsarduinoclaudecodexembeddedmcpmcp-servermicrocontrollermodel-context-protocolopencoderustserialserial-mcp-serverserial-portuart

What people ask about serial-mcp

What is qarnet/serial-mcp?

+

qarnet/serial-mcp is mcp servers for the Claude AI ecosystem. MCP server for serial / UART communication. Lets coding agents read, write, and stream data to microcontrollers and embedded boards. It has 3 GitHub stars and was last updated today.

How do I install serial-mcp?

+

You can install serial-mcp by cloning the repository (https://github.com/qarnet/serial-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is qarnet/serial-mcp safe to use?

+

Our security agent has analyzed qarnet/serial-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains qarnet/serial-mcp?

+

qarnet/serial-mcp is maintained by qarnet. The last recorded GitHub activity is from today, with 1 open issues.

Are there alternatives to serial-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy serial-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: qarnet/serial-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/qarnet-serial-mcp)](https://claudewave.com/repo/qarnet-serial-mcp)
<a href="https://claudewave.com/repo/qarnet-serial-mcp"><img src="https://claudewave.com/api/badge/qarnet-serial-mcp" alt="Featured on ClaudeWave: qarnet/serial-mcp" width="320" height="64" /></a>

More MCP Servers

serial-mcp alternatives