io.github.es617/serial-mcp-server MCP Server
io.github.es617/serial-mcp-server
AI agents interact with serial devices — list ports, connect, send, read, and automate test flows.
What is the io.github.es617/serial-mcp-server MCP server?
The Serial MCP Server is a stateful serial port server that lets AI agents like Claude communicate with serial devices (microcontrollers, embedded systems, hardware). It provides tools to list ports, open connections, send/read data, control hardware lines (DTR/RTS), and attach protocol specs so agents understand device-specific commands and formats.
This server bridges AI agents and serial hardware. Instead of manually typing commands into screen or minicom, you describe what you want to the agent — connect to a device, send a command sequence, read responses, toggle reset lines — and it handles the serial I/O. It supports raw serial operations, protocol specs (markdown files that teach the agent your device's command set), and plugins (Python shortcuts for high-level device operations). Useful for embedded development, hardware testing, firmware iteration, and automating serial test rigs.
How to install io.github.es617/serial-mcp-server
Copy-paste configuration for popular MCP clients.
SERIAL_MCP_MAX_CONNECTIONSMaximum simultaneous open serial connections (default 10)
SERIAL_MCP_PLUGINSPlugin policy: 'all' or comma-separated plugin names. Unset = disabled.
SERIAL_MCP_MIRRORPTY mirror mode: 'off' (default), 'ro' (read-only), or 'rw' (read-write). macOS/Linux only.
SERIAL_MCP_MIRROR_LINKBase path for PTY symlinks (default /tmp/serial-mcp when mirror is enabled). Connections get numbered: /tmp/serial-mcp0, /tmp/serial-mcp1, etc.
SERIAL_MCP_TOOL_SEPARATORTool name separator character (default '.'). Set to '_' for clients that reject dots (e.g. Cursor).
Tools & capabilities
Tools this server exposes to the agent.
serial.list_ports— List available serial ports on the system.serial.open— Open a serial connection with configurable baud rate, parity, stop bits, and encoding.serial.close— Close an open serial connection.serial.connection_status— Check the status of a serial connection.serial.read— Read data from a serial connection in text, hex, or base64 format.serial.write— Write data to a serial connection.serial.readline— Read a line of text from a serial connection.serial.read_until— Read data until a specific delimiter is encountered.serial.flush— Flush input and output buffers.serial.set_dtr— Set or clear the DTR (Data Terminal Ready) control line.serial.set_rts— Set or clear the RTS (Request To Send) control line.serial.pulse_dtr— Pulse the DTR line (useful for hardware reset).serial.pulse_rts— Pulse the RTS line.serial.connections.list— List all active serial connections.serial.spec.template— Generate a template for a protocol spec.serial.spec.register— Register a protocol spec for a device.serial.spec.list— List registered protocol specs.serial.spec.attach— Attach a protocol spec to a connection.serial.spec.get— Retrieve a registered protocol spec.serial.spec.read— Read a protocol spec file.
Use cases
- Connect to a microcontroller, send boot commands, and read the startup banner conversationally without manual terminal commands.
- Automate embedded device testing — reset via DTR, wait for prompt, run a command sequence, validate output, and log results.
- Develop and debug serial protocols by letting the agent probe unknown devices, discover command sets, and infer message formats.
- Iterate on firmware by attaching a protocol spec so the agent understands your evolving command set and boot modes.
- Build manufacturing bring-up or CI hardware smoke tests that run serial test sequences automatically.
io.github.es617/serial-mcp-server MCP server FAQ
It's an MCP server that gives AI agents (Claude, Copilot, etc.) tools to interact with serial devices — list ports, open connections, send/read data, control hardware lines, and understand device protocols via specs and plugins.
Yes, it's open-source under the MIT License. Install via pip: `pip install serial-mcp-server`.
Run `pip install serial-mcp-server`, then `claude mcp add serial -- serial_mcp`. For VS Code/Copilot, add a `.vscode/mcp.json` file with the server config. For Cursor, use `.cursor/mcp.json` and set `SERIAL_MCP_TOOL_SEPARATOR=_`.
No authentication is required. It communicates over stdio and uses pyserial for cross-platform serial access on macOS, Windows, and Linux.
Specs are markdown files that describe your device's command set and message format — they teach the agent what the byte stream means. Plugins are Python shortcuts for high-level device operations (e.g., `read_temp`, `upload_firmware`). Both are optional; you can start with raw serial tools.
Yes, but be aware: plugins execute arbitrary code, writes affect real devices, and bad commands can cause hardware damage. Review agent-generated plugins before loading, use `SERIAL_MCP_PLUGINS=name1,name2` to allow only specific plugins, and consider tool approval carefully.
README (reference)
Source of truth, from the repository.
Serial MCP Server
<!-- mcp-name: io.github.es617/serial-mcp-server -->
A stateful serial port Model Context Protocol (MCP) server for developer tooling and AI agents. Works out of the box with Claude Code, VS Code with Copilot, and any MCP-compatible runtime. Communicates over stdio and uses pyserial for cross-platform serial on macOS, Windows, and Linux.
Example: Let Claude Code list available serial ports, connect to your microcontroller, reset it via DTR, and read the boot banner from your hardware.
Demo
Video walkthrough — connecting to a serial device, sending commands, reading responses, and creating plugins.
Why this exists
If you’ve ever copy-pasted commands into screen or minicom, guessed baud rates, toggled DTR to kick a bootloader, and re-run the same test sequence 20 times — this is for you.
You have a serial device. You want an AI agent to talk to it — open a port, send commands, read responses, debug protocols. This server makes that possible.
It gives any MCP-compatible agent a full set of serial tools: listing ports, opening connections, reading, writing, line-oriented I/O, control line manipulation — plus protocol specs and device plugins, so the agent can reason about higher-level device behavior instead of just raw bytes.
The agent calls these tools, gets structured JSON back, and reasons about what to do next — without you manually typing commands into a terminal for every step.
What agents can do with it:
- Develop and debug — connect to your device, send commands, read responses, and diagnose issues conversationally (boot banners, prompts, error codes).
- Iterate on new firmware — attach a protocol spec so the agent understands your command set, boot modes, and output format as they evolve.
- Automate test flows — reset device via DTR, wait for prompt, run a command sequence, validate output.
- Explore unknown devices — probe command sets, discover prompts, infer message formats.
- Build serial automation — long-running test rigs, manufacturing bring-up, CI hardware smoke tests.
Who is this for?
- Embedded engineers — faster iteration on serial protocols, conversational debugging, automated test sequences
- Hobbyists and makers — interact with serial devices without writing boilerplate; let the agent help reverse-engineer simple protocols
- QA and test engineers — build repeatable serial test suites with plugin tools
- Support and field engineers — diagnose serial device issues interactively without specialized tooling
- Researchers — automate data collection from serial devices, explore device capabilities systematically
Quickstart (Claude Code)
pip install serial-mcp-server
# Register the MCP server with Claude Code
claude mcp add serial -- serial_mcp
Then in Claude Code, try:
<p align="center"><img src="https://raw.githubusercontent.com/es617/serial-mcp-server/main/docs/assets/scan.gif" alt="Scanning serial ports" width="600"></p>"List available serial ports and connect to the one on /dev/ttyUSB0 at 115200 baud."
What the agent can do
Once connected, the agent has full serial capabilities:
- List ports to find available serial devices
- Open and close connections with configurable baud rate, parity, stop bits, and encoding
- Read and write data in text, hex, or base64 format
- Line-oriented I/O — readline and read-until-delimiter for text protocols
- Control lines — set or pulse DTR and RTS for hardware reset and boot mode entry
- Flush input and output buffers
- Attach protocol specs to understand device-specific commands and data formats
- Use plugins for high-level device operations instead of raw reads/writes
- Create specs and plugins for new devices so future sessions start "knowing" your protocol
- PTY mirroring — attach screen, minicom, or custom scripts to the same serial session the agent is using
The agent can coordinate multi-step flows automatically — e.g., toggle reset, wait for prompt, send init sequence, stream output.
At a high level:
Raw Serial → Protocol Spec → Plugin
You can start with raw serial tools, then move up the stack as your device protocol becomes understood and repeatable.
Install (development)
# Editable install from repo root
pip install -e .
# Or with uv
uv pip install -e .
MCP is a protocol — this server works with any MCP-compatible client. Below are setup instructions for the most common ones.
Add to Claude Code
# Standard setup
claude mcp add serial -- serial_mcp
# Or run as a module
claude mcp add serial -- python -m serial_mcp_server
# Enable all plugins
claude mcp add serial -e SERIAL_MCP_PLUGINS=all -- serial_mcp
# Enable specific plugins only
claude mcp add serial -e SERIAL_MCP_PLUGINS=mydevice,ota -- serial_mcp
# Debug logging
claude mcp add serial -e SERIAL_MCP_LOG_LEVEL=DEBUG -- serial_mcp
Add to VS Code / Copilot
Add to your project's .vscode/mcp.json (or create it):
{
"servers": {
"serial": {
"type": "stdio",
"command": "serial_mcp",
"args": [],
"env": {
"SERIAL_MCP_PLUGINS": "all"
}
}
}
}
Adjust env to match your needs — set SERIAL_MCP_PLUGINS to specific plugin names, or add SERIAL_MCP_MIRROR for PTY mirroring.
Add to Cursor
Add to your project's .cursor/mcp.json (or create it). Cursor does not support dots in tool names, so SERIAL_MCP_TOOL_SEPARATOR must be set to _:
{
"mcpServers": {
"serial": {
"command": "serial_mcp",
"args": [],
"env": {
"SERIAL_MCP_PLUGINS": "all",
"SERIAL_MCP_TOOL_SEPARATOR": "_"
}
}
}
}
Environment variables
| Variable | Default | Description |
|---|---|---|
SERIAL_MCP_MAX_CONNECTIONS | 10 | Maximum simultaneous open serial connections. |
SERIAL_MCP_PLUGINS | disabled | Plugin policy: all to allow all, or name1,name2 to allow specific plugins. Unset = disabled. |
SERIAL_MCP_MIRROR | off | PTY mirror mode: off, ro (read-only), or rw (read-write). macOS and Linux only. |
SERIAL_MCP_MIRROR_LINK | /tmp/serial-mcp | Base path for PTY symlinks. Connections get numbered: /tmp/serial-mcp0, /tmp/serial-mcp1, etc. |
SERIAL_MCP_LOG_LEVEL | WARNING | Python log level (DEBUG, INFO, WARNING, ERROR). Logs go to stderr. |
SERIAL_MCP_TRACE | enabled | JSONL tracing of every tool call. Set to 0, false, or no to disable. |
SERIAL_MCP_TRACE_PAYLOADS | disabled | Include write data in traced args (stripped by default). |
SERIAL_MCP_TRACE_MAX_BYTES | 16384 | Max payload chars before truncation (only applies when TRACE_PAYLOADS is on). |
SERIAL_MCP_TOOL_SEPARATOR | . | Character used to separate tool name segments. Set to _ for MCP clients that reject dots in tool names (e.g. Cursor). |
Tools
| Category | Tools |
|---|---|
| Serial Core | serial.list_ports, serial.open, serial.close, serial.connection_status, serial.read, serial.write, serial.readline, serial.read_until, serial.flush, serial.set_dtr, serial.set_rts, serial.pulse_dtr, serial.pulse_rts |
| Introspection | serial.connections.list |
| Protocol Specs | serial.spec.template, serial.spec.register, serial.spec.list, serial.spec.attach, serial.spec.get, serial.spec.read, serial.spec.search |
| Tracing | serial.trace.status, serial.trace.tail |
| Plugins | serial.plugin.template, serial.plugin.list, serial.plugin.reload, serial.plugin.load |
Protocol Specs
Specs are markdown files that describe a serial device's protocol — connection settings, message format, commands, and multi-step flows. They live in .serial_mcp/specs/ and teach the agent what the byte stream means.
Without a spec, the agent can still open a port and exchange data. With a spec, it knows what commands to send, what responses to expect, and what the data means.
You can create specs by telling the agent about your device — paste a datasheet, describe the protocol, or just let it explore and document what it finds. The agent generates the spec file, registers it, and references it in future sessions. You can also write specs by hand.
Plugins
Plugins add device-specific shortcut tools to the server. Instead of the agent composing raw read/write sequences, a plugin provides high-level operations like mydevice.read_temp or ota.upload_firmware.
The agent can also generate Python plugins (with your approval). It explores a device, writes a plugin based on what it learns, and future sessions get shortcut tools — no manual coding required.
To enable plugins:
# Enable all plugins
claude mcp add serial -e SERIAL_MCP_PLUGINS=all -- serial_mcp
# Enable specific plugins only
claude mcp add serial -e SERIAL_MCP_PLUGINS=mydevice,ota -- serial_mcp
Editing an already-loaded plugin only requires serial.plugin.reload — no restart needed.
Tracing
Every tool call is traced to .serial_mcp/traces/trace.jsonl and an in-memory ring buffer (last 2000 events). Tracing is on by default — set SERIAL_MCP_TRACE=0 to disable.
Event format
Two events per tool call:
{"ts":"2025-01-01T00:00:00.000Z","event":"tool_call_start","tool":"serial.read","args":{"connection_id":"s1"},"connection_id":"s1"}
{"ts":"2025-01-01T00:00:00.050Z","event":"tool_call_end","tool":"serial.read","ok":true,"error_code":null,"duration_ms":50,"connection_id":"s1"}
connection_idis extracted from args when present- Write
datais stripped from traced args by default (enable withSERIAL_MCP_TRACE_PAYLOADS=1)
Inspecting the trace
Use serial.trace.status to check config and event count, and serial.trace.tail to retrieve recent events — no need to read the file directly.
PTY Mirror
When the MCP server owns a serial port, most OSes prevent any other process from opening it. PTY mirroring creates a virtual clone port that external tools (screen, minicom, logic analyzers, custom scripts) can connect to simultaneously.
# Enable read-only mirror
claude mcp add serial \
-e SERIAL_MCP_MIRROR=ro \
-- serial_mcp
# After opening a connection, the response includes the mirror path:
# { "mirror": { "pty_path": "/dev/ttys004", "link": "/tmp/serial-mcp0", "mode": "ro" } }
# In another terminal:
screen /tmp/serial-mcp0 115200
| Mode | Behavior |
|---|---|
off | No mirror (default). Only the MCP server can access the port. |
ro | External tools see all serial data but cannot write to the device. |
rw | External tools can both see data and write to the device. |
Platform: macOS and Linux only. On Windows, setting SERIAL_MCP_MIRROR to ro/rw logs a warning and is silently ignored.
Try without an agent
You can test the server interactively using the MCP Inspector — no Claude or other agent needed:
npx @modelcontextprotocol/inspector python -m serial_mcp_server
Open the URL with the auth token from the terminal output. The Inspector gives you a web UI to call any tool and see responses in real time.
Known limitations
- Single-client only. The server handles one MCP session at a time (stdio transport). Multi-client transports (HTTP/SSE) may be added later.
- Exclusive access. Without PTY mirroring, the MCP server must own the serial port exclusively.
Safety
This server connects an AI agent to real hardware. That's the point — and it means the stakes are higher than pure-software tools.
Plugins execute arbitrary code. When plugins are enabled, the agent can create and run Python code on your machine with full server privileges. Review agent-generated plugins before loading them. Use SERIAL_MCP_PLUGINS=name1,name2 to allow only specific plugins rather than all.
Writes affect real devices. A bad command sent to a serial device can trigger unintended behavior, disrupt other connected systems, or cause hardware damage (e.g., wiping flash, entering bootloader mode, triggering actuators). Consider what the agent can reach.
Use tool approval deliberately. When your MCP client prompts you to approve a tool call, consider whether you want to allow it once or always. "Always allow" is convenient but means the agent can repeat that action without further confirmation.
This software is provided as-is under the MIT License. You are responsible for what the agent does with your hardware.
License
This project is licensed under the MIT License — see LICENSE for details.
Acknowledgements
This project is built on top of the excellent pyserial library for cross-platform serial communication in Python.
Related MCP servers

io.github.es617/ble-mcp-server
Let AI agents interact with real BLE hardware — scan, connect, read, write, and subscribe to notifications.

io.github.es617/dbgprobe-mcp-server
Let AI agents interact with debug probes—connect, flash, read/write memory, and reset embedded targets.
Give AI agents read/write access to your Obsidian vault locally or via cloud-synced CouchDB.

esa
Official MCP server for esa.io—connect AI assistants to your team's documentation and knowledge base.
Context-aware reminders that surface when your situation matches, not at a fixed time.
View repository →