serial-mcp-server — MCP server for Claude Code: serial ports and UART
Hands an AI agent a live serial connection: open a port, send a command, read the reply, toggle DTR.
claude mcp add --env SERIAL_MCP_MAX_CONNECTIONS=<SERIAL_MCP_MAX_CONNECTIONS> --env SERIAL_MCP_PLUGINS=<SERIAL_MCP_PLUGINS> --env SERIAL_MCP_MIRROR=<SERIAL_MCP_MIRROR> --env SERIAL_MCP_MIRROR_LINK=<SERIAL_MCP_MIRROR_LINK> --env SERIAL_MCP_TOOL_SEPARATOR=<SERIAL_MCP_TOOL_SEPARATOR> --transport stdio serial-mcp-server -- uvx serial-mcp-serverWhat serial-mcp-server does
The server keeps connection state and talks to the client over stdio. On top of pyserial it exposes tools for listing ports, opening and closing with baud rate, parity, stop bits and encoding, then reading and writing as text, hex or base64. Text protocols get readline and read-until-delimiter calls. DTR and RTS can be set or pulsed, which is how you reset a board or drop it into a bootloader.
Beyond raw bytes, the agent can lean on protocol specs and device plugins. A spec spells out the command set and output format; a plugin turns common operations into one call. Plugins stay off until SERIAL_MCP_PLUGINS is set to all or a comma-separated list of names. There is also PTY mirroring, so screen, minicom or your own script can watch the session the agent is using. That part is macOS and Linux only.
You need Python 3.11 or newer. Up to 10 connections can be open at once; change that with SERIAL_MCP_MAX_CONNECTIONS. Cursor rejects dots in tool names, so set SERIAL_MCP_TOOL_SEPARATOR to _ in its config — skip it and the tools will not register there.
What it helps with
- locate a connected board and find its port
- read a boot banner right after reset
- replay a command sequence and check the output
- work out an unfamiliar protocol from device replies
- script reset and bootloader entry instead of doing it by hand
Example prompts for the agent
- List the serial ports and connect to
/dev/ttyUSB0at 115200 baud. - Send
ATto the port and return everything up to the newline. - Pulse DTR, wait for the prompt, then show me the startup output.
How to install serial-mcp-server
Platform CLI
claude mcp add --env SERIAL_MCP_MAX_CONNECTIONS=<SERIAL_MCP_MAX_CONNECTIONS> --env SERIAL_MCP_PLUGINS=<SERIAL_MCP_PLUGINS> --env SERIAL_MCP_MIRROR=<SERIAL_MCP_MIRROR> --env SERIAL_MCP_MIRROR_LINK=<SERIAL_MCP_MIRROR_LINK> --env SERIAL_MCP_TOOL_SEPARATOR=<SERIAL_MCP_TOOL_SEPARATOR> --transport stdio serial-mcp-server -- uvx serial-mcp-serverReplace <…> with your own values. uvx runs the command named after the package; if the README names another one, use uvx --from serial-mcp-server <command>
Platform CLI
codex mcp add serial-mcp-server --env SERIAL_MCP_MAX_CONNECTIONS=<SERIAL_MCP_MAX_CONNECTIONS> --env SERIAL_MCP_PLUGINS=<SERIAL_MCP_PLUGINS> --env SERIAL_MCP_MIRROR=<SERIAL_MCP_MIRROR> --env SERIAL_MCP_MIRROR_LINK=<SERIAL_MCP_MIRROR_LINK> --env SERIAL_MCP_TOOL_SEPARATOR=<SERIAL_MCP_TOOL_SEPARATOR> -- uvx serial-mcp-serverReplace <…> with your own values. uvx runs the command named after the package; if the README names another one, use uvx --from serial-mcp-server <command>
Config file
{
"mcpServers": {
"serial-mcp-server": {
"command": "uvx",
"args": [
"serial-mcp-server"
],
"env": {
"SERIAL_MCP_MAX_CONNECTIONS": "<SERIAL_MCP_MAX_CONNECTIONS>",
"SERIAL_MCP_PLUGINS": "<SERIAL_MCP_PLUGINS>",
"SERIAL_MCP_MIRROR": "<SERIAL_MCP_MIRROR>",
"SERIAL_MCP_MIRROR_LINK": "<SERIAL_MCP_MIRROR_LINK>",
"SERIAL_MCP_TOOL_SEPARATOR": "<SERIAL_MCP_TOOL_SEPARATOR>"
}
}
}
}Replace <…> with your own values. uvx runs the command named after the package; if the README names another one, use uvx --from serial-mcp-server <command>
Config file
{
"servers": {
"serial-mcp-server": {
"type": "stdio",
"command": "uvx",
"args": [
"serial-mcp-server"
],
"env": {
"SERIAL_MCP_MAX_CONNECTIONS": "<SERIAL_MCP_MAX_CONNECTIONS>",
"SERIAL_MCP_PLUGINS": "<SERIAL_MCP_PLUGINS>",
"SERIAL_MCP_MIRROR": "<SERIAL_MCP_MIRROR>",
"SERIAL_MCP_MIRROR_LINK": "<SERIAL_MCP_MIRROR_LINK>",
"SERIAL_MCP_TOOL_SEPARATOR": "<SERIAL_MCP_TOOL_SEPARATOR>"
}
}
}
}Replace <…> with your own values. uvx runs the command named after the package; if the README names another one, use uvx --from serial-mcp-server <command>
Platform CLI
gemini mcp add -e SERIAL_MCP_MAX_CONNECTIONS=<SERIAL_MCP_MAX_CONNECTIONS> -e SERIAL_MCP_PLUGINS=<SERIAL_MCP_PLUGINS> -e SERIAL_MCP_MIRROR=<SERIAL_MCP_MIRROR> -e SERIAL_MCP_MIRROR_LINK=<SERIAL_MCP_MIRROR_LINK> -e SERIAL_MCP_TOOL_SEPARATOR=<SERIAL_MCP_TOOL_SEPARATOR> serial-mcp-server uvx serial-mcp-serverReplace <…> with your own values. uvx runs the command named after the package; if the README names another one, use uvx --from serial-mcp-server <command>
Step by step, with commands for each platform: How to add an MCP server to Claude Code, Codex, Cursor, VS Code, Gemini CLI and more
Questions about serial-mcp-server
How do I install serial-mcp-server in Claude Code?
Register it with claude mcp add serial-mcp-server -- uvx serial-mcp-server. To pass environment variables use the longer form: `claude mcp add --env SERIAL_MCP_MAX_CONNECTIONS=<SERIAL_MCP_MAX_CONNECTIONS> --env SERIAL_MCP_PLUGINS=<SERIAL_MCP_PLUGINS> --env SERIAL_MCP_MIRROR=<SERIAL_MCP_MIRROR> --env SERIAL_MCP_MIRROR_LINK=<SERIAL_MCP_MIRROR_LINK> --env SERIAL_MCP_TOOL_SEPARATOR=<SERIAL_MCP_TOOL_SEPARATOR> --transport stdio serial-mcp-server -- uvx serial-mcp-server`.
What does serial-mcp-server do?
It gives the agent serial tools: discover ports, connect, read and write, toggle DTR and RTS. Protocol specs and plugins let it reason about a device instead of only moving bytes.
Why does Cursor need a separator setting?
It disallows dots in tool names. Put _ into SERIAL_MCP_TOOL_SEPARATOR in .cursor/mcp.json; otherwise the tools are rejected.