mcp-serial
Allows AI agents to interact with Arduino boards over a serial connection, including listing ports, opening a port, sending commands and queries, reading responses, resetting the board, and controlling DTR/RTS lines.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-serialfind my ESP32, reset it and show me the boot log"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-serial
Let AI agents talk to your hardware over a serial port.
(Versión en español: README.es.md)
mcp-serial is a Model Context Protocol server that gives
Claude Code, Claude Desktop, Cursor, or any MCP client a set of tools to find serial ports, open
them, send commands and read what comes back: Arduino, ESP32/ESP8266, STM32, USB-UART adapters,
RS-232 lab equipment, AT modems, anything that speaks UART.
Why
Debugging firmware means alt-tabbing between your editor and a serial monitor, copying stack
traces around by hand. With mcp-serial the agent that is editing your code can also reset the
board, read the boot log, spot the Guru Meditation Error, and go fix the line it points at, all
in one conversation.
You: find my ESP32, reset it and tell me why it keeps rebooting
Agent:
list_ports→/dev/cu.usbserial-0001(CP210x, 0x10C4:0xEA60) →open_portat 115200 →reset_device→ boot log showsGuru Meditation Error: Core 1 panic'ed (LoadProhibited)atPC: 0x400d1a2f… "That address is insideparse_packet()insrc/protocol.cpp; you dereferencebufbefore checking the length. Here's the fix."
Things it is good at:
Interactive firmware debugging: reset, capture boot logs, send CLI commands, watch output.
Bring-up of new boards: identify the port by VID/PID, try baud rates, check that the firmware answers.
Talking to instruments and modems:
ATcommand sets, SCPI over RS-232, custom ASCII protocols, raw hex frames.Sensor experiments: read a stream for a while, then let the agent summarize or plot it.
Related MCP server: UART MCP Server
Install
Requires Python 3.10+ and uv (or pipx).
# straight from GitHub (PyPI release coming)
uvx --from git+https://github.com/HumbertoBernal/mcp-serial mcp-serial --helpClaude Code
claude mcp add serial -- uvx --from git+https://github.com/HumbertoBernal/mcp-serial mcp-serialClaude Desktop, Cursor, Windsurf, and other JSON configs
{
"mcpServers": {
"serial": {
"command": "uvx",
"args": ["--from", "git+https://github.com/HumbertoBernal/mcp-serial", "mcp-serial"]
}
}
}To restrict which ports the agent may touch, add an environment variable (see Safety):
"env": { "MCP_SERIAL_ALLOWED_PORTS": "/dev/cu.usb*,/dev/ttyUSB*" }Tools
Tool | What it does |
| Enumerate serial ports with USB VID/PID, manufacturer, product and serial number. |
| Open a port (baud rate, data bits, parity, stop bits, encoding) and start buffering everything it sends. |
| Release the port for other programs. |
| Byte counters, unread bytes, uptime, and the error if the device disconnected. |
| Send a command and return the reply in one call: wait for a pattern ( |
| Send text (with configurable line ending) or raw hex bytes ( |
| Consume buffered data. Waits for the first byte up to |
| Block until a substring or regex appears, return everything up to and including it. |
| Peek at the last N lines received without consuming them. |
| Drop stale buffered data. |
| Pulse DTR/RTS to reboot Arduino / ESP32 style boards and capture the boot output. |
| Drive DTR and RTS manually (bootloader entry, custom reset circuits). |
There is also a serial://ports resource with the same information as list_ports.
Every port is read continuously by a background thread into a bounded buffer (1 MB per port) plus
a 2000-line history for tail, so nothing the device prints between two tool calls is lost.
device ──UART──▶ pyserial ──reader thread──▶ [ unread buffer ] ──▶ read / read_until / query
└──▶ [ line history ] ──▶ tailTry it without hardware
pyserial URL handlers work everywhere a port name is accepted:
loop://echoes back whatever you write:open_port("loop://"), thenquery("loop://", "PING")→PING.socket://192.168.1.50:23for network serial bridges (ESP-Link, ser2net, Moxa NPort).rfc2217://host:portfor RFC 2217 servers.
Try it with an Arduino
Flash examples/arduino_echo/arduino_echo.ino (any board,
115200 baud), then ask your agent:
open my Arduino and send it PING, TEMP? and HELP
The sketch answers PONG, a fake temperature, and a list of its commands, enough to check that
the whole chain works before pointing the agent at your real firmware.
Safety
The server only moves bytes between the agent and the port. It does not flash firmware, run programs, or touch files. Still, an agent that can write arbitrary bytes to a device can trigger whatever that device's protocol allows, so:
Allowlist ports with
MCP_SERIAL_ALLOWED_PORTS(comma-separated globs, e.g./dev/cu.usb*,COM3) or--allow GLOB(repeatable). Anything else is refused.Timeouts are capped at
MCP_SERIAL_MAX_TIMEOUTseconds (default 120) so a tool call can never hang the agent forever; reads are capped at 1 MB.At most 8 ports are open at a time, and everything is closed when the server shuts down.
Nothing is written to stdout except MCP traffic, so it is safe under stdio transport.
Flashing (esptool, avrdude) is on the roadmap as a separate, opt-in tool.
Running the server manually
mcp-serial # stdio (what MCP clients spawn)
mcp-serial --allow "/dev/cu.usb*" # restrict ports
mcp-serial --transport streamable-http --http-port 8000 # HTTP, for remote clientsDevelopment
git clone https://github.com/HumbertoBernal/mcp-serial
cd mcp-serial
uv sync --group dev
uv run pytest # tests use pyserial's loop:// device, no hardware needed
uv run ruff check .Test the server interactively with the MCP inspector:
npx @modelcontextprotocol/inspector uv run mcp-serialSee ROADMAP.md for what is planned and CONTRIBUTING.md if you want
to help. Issues with a hardware: label are great first contributions: test the server with a
board we have not tried and report what works.
License
Available Tools
12 toolsclear_bufferA
Discard all buffered unread data on a port (line history for tail is kept).
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden. It discloses the key behavioral nuance that tail line history is kept and that buffered unread data is discarded, but it does not mention prerequisites (e.g., port must be open) or whether the operation is destructive beyond the buffer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the action and immediately provides the relevant caveat about tail history. There is no filler, repetition, or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple one-parameter shape, an output schema for return values, and a clear description, the definition is nearly complete. It covers the core behavior and the tail interaction. The only minor gap is not stating that the port must be open, but this is low-risk for such a simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the port parameter is thoroughly described in the schema with examples and accepted URL formats. The description adds no additional parameter semantics, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Discard') and resource ('buffered unread data on a port'), and adds a clarifying caveat that tail line history is kept, which helps distinguish it from reset_device or close_port. The action is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: use this when you want to discard buffered unread data. However, it provides no explicit when-to-use guidance, no exclusions, and no comparison with sibling tools such as reset_device or read. The context is clear but entirely implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
close_portA
Close a port opened with open_port and release it for other programs.
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the burden. It discloses the main side effect — closing the port and releasing it for other programs — but is silent on failure modes, such as closing an already-closed or never-opened port, and on whether buffered data is flushed. The core behavior is clear, yet edge behavior is uncovered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the verb and resource, with every clause earning its place: 'opened with open_port' scopes it, and 'release it for other programs' explains the why. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (one required parameter, 100% schema coverage, output schema present), the description covers the tool's role and effect adequately. The only missing piece is error behavior, which is minor for such a simple companion tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the port parameter is already fully documented with examples and URL variants. The description adds no parameter-level detail, and at full coverage the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('close') and resource ('a port opened with open_port'), plus the purpose ('release it for other programs'). This clearly inverts open_port and stays distinct from read/write/port_status siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrasing 'opened with open_port' supplies clear context: it applies to a port previously opened by its counterpart tool. It doesn't enumerate exclusion conditions or list alternative tools, but the pairing with open_port leaves little ambiguity about when to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_portsC
List the serial ports currently present on this machine.
Use the description, manufacturer and vid/pid fields to identify the board
(e.g. 0x10C4:0xEA60 = CP210x on many ESP32 dev kits, 0x2341 = Arduino, 0x1A86 = CH340).
On macOS prefer the /dev/cu.* entry over /dev/tty.*.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the full burden of behavioral disclosure. It does not state output format, filtering, permissions, or side effects. The note about preferring /dev/cu.* over /dev/tty.* on macOS is a useful platform-specific behavior, but alone it does not provide significant transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The text is reasonably brief and front-loaded with the main action, but it includes malformed trailing text that appears to be an accidental copy of sibling names. Every sentence should earn its place; the trailing corruption and low-value generic sentence reduce the score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-argument list tool, the description covers the core action and adds useful field-level identification clues plus a macOS selection hint. However, output schema exists but is not shown, so return-value format is not described in the text; overall it is minimally viable for selecting and invoking this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so parameter semantics are fully satisfied. The description even adds value by explaining how to interpret the fields that will be returned (description, manufacturer, vid/pid) to identify the correct port.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description appears to be present; however, the text is truncated and garbled at the end ('...is_clear_buffer' from a sibling list spills into the description). It does not provide a clear statement of the tool's purpose. A one-sentence generic description like 'List serial ports' is further undercut by the corrupted trailing text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus alternatives. The only usable context is embedded in field-specific hints for identifying boards, which is post-selection guidance, not invocation reasoning.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_portA
Open a serial port and start buffering everything it sends.
Idempotent: opening an already-open port with the same settings just returns its status; different settings close and reopen it. The port stays open until close_port.
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| parity | No | N=none, E=even, O=odd, M=mark, S=space. | N |
| baudrate | No | Bits per second, e.g. 9600, 115200, 921600. | |
| bytesize | No | Data bits: 5, 6, 7 or 8. | |
| encoding | No | Text encoding used to decode/encode data (utf-8, latin-1, ascii...). | utf-8 |
| stopbits | No | 1, 1.5 or 2. |
Output Schema
| Name | Required | Description |
|---|---|---|
| port | Yes | |
| error | No | Set when the device disconnected or failed. |
| parity | Yes | |
| baudrate | Yes | |
| bytes_rx | Yes | |
| bytes_tx | Yes | |
| bytesize | Yes | |
| encoding | Yes | |
| stopbits | Yes | |
| uptime_s | Yes | |
| connected | Yes | |
| unread_bytes | Yes | Bytes buffered and not yet consumed by read/read_until/query. |
| dropped_bytes | Yes | Bytes discarded because the buffer overflowed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral disclosure, and it delivers: idempotency, reopen-on-different-settings, status return, buffering, and persistence until close_port are all stated explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences front-load the core operation, then add the idempotency and lifecycle caveats. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a stateful open operation with a fully self-documenting schema and an output schema, this is complete: the agent knows what it does, when it is safe to call again, and how the port lifecycle ends. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters. The description adds no parameter-specific detail beyond the generic phrase 'same settings,' so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific operation (open a serial port) and the resource, and immediately states the consequence (start buffering everything it sends). This cleanly separates it from siblings like close_port, port_status, and write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear lifecycle context: the port remains open until close_port, and an already-open port with different settings is closed and reopened. It doesn't explicitly list when not to use it or name alternatives, but the intended use is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
port_statusB
Show open ports with byte counters, buffered (unread) bytes and disconnect errors.
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | A specific open port, or omit for all open ports. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. The verb 'Show' plus the listed metrics communicates a read-only status operation, which is useful context. However, it does not mention whether the tool errors on unknown ports, whether it is safe to call repeatedly, or what exact shape the status information takes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that names the action, the target, and the three key output aspects. Every word contributes value and nothing is redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter status tool with an output schema, the description covers the essential semantics: it reports on open ports and names the metric categories returned. The only notable omission is usage context, but that is already penalized under usage guidelines, and the output schema covers return details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the lone 'port' parameter is already documented as 'A specific open port, or omit for all open ports.' The tool description adds no parameter-level meaning beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Show'), a resource ('open ports'), and the meaningful details it returns (byte counters, buffered bytes, disconnect errors). It is clear enough to be distinguished from action-oriented siblings like open_port or write, but it does not explicitly contrast with list_ports, so some sibling differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to use this tool versus alternatives. An agent has to infer that this is a status/diagnostic read, and there is no mention of exclusions, prerequisites, or when list_ports or read would be more appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queryA
Send a command and return its reply in one call. Best for request/response devices (AT modems, CLI firmware, 'PING' -> 'PONG' sketches).
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| regex | No | Interpret `expect` as a regex. | |
| expect | No | Return as soon as this substring/regex shows up in the reply (e.g. 'OK', '\n'). Omit to collect until the device goes quiet. | |
| command | Yes | Command text to send (newline is appended). | |
| newline | No | Line ending appended to the command. | |
| settle_ms | No | Without `expect`: stop once the line is silent for this many ms. | |
| timeout_s | No | Max seconds to wait for the reply. | |
| clear_first | No | Discard stale buffered data before sending, so the reply is clean. |
Output Schema
| Name | Required | Description |
|---|---|---|
| sent | Yes | |
| bytes | Yes | |
| error | No | |
| matched | No | Whether `expect` was seen; null when no `expect` was given. |
| response | Yes | |
| elapsed_s | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the burden. It discloses the one-call request/response behavior, but doesn't mention blocking behavior, timeouts, buffer clearing, or potential side effects on the device. It is honest but thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no redundant words. The core action is front-loaded, and the usage guidance follows immediately. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Between the 100% schema coverage and the presence of an output schema, the description doesn't need to explain return values. The focus on request/response use provides enough context for correct invocation; the only missing piece is guidance on edge cases or sibling differentiation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the individual parameter meanings are already fully documented. The tool description adds no additional parameter-level semantics beyond indicating that a command is sent and a reply returned.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Send a command and return its reply in one call.' This clearly distinguishes it from write/read-style siblings, and the request/response examples make its function concrete and unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Best for request/response devices' plus examples like AT modems and PING->PONG gives clear context for when to use it. It doesn't explicitly name alternatives or give when-not-to-use exclusions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
readC
Read and consume buffered data from the device (logs, sensor output, late replies).
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| as_hex | No | Also return the raw bytes as hex. | |
| max_bytes | No | Upper bound on returned bytes. | |
| settle_ms | No | After data starts arriving, keep collecting until the line is silent for this many ms (0 = return as soon as anything is available). Useful for multi-line replies. | |
| timeout_s | No | Seconds to wait for the first byte if nothing is buffered. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hex | No | Raw bytes as hex when as_hex=true. |
| text | Yes | Decoded data (undecodable bytes become U+FFFD). |
| bytes | Yes | |
| error | No | |
| timed_out | Yes | True if nothing arrived before the timeout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The word 'consume' adds some behavioral meaning by implying data is drained from the buffer. However, there are no annotations, and the description omits important behavior such as blocking/timeout semantics, whether data is removed from the device buffer, and how this interacts with clear_buffer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with an efficient parenthetical list of examples. It is front-loaded with the core action and contains no filler, though it is too sparse to cover the behavioral and usage context needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even with a rich schema and output schema present, the description leaves a major gap in helping the agent choose between read, read_until, tail, and query. With no annotations, the description carries the burden of explaining buffer consumption and blocking behavior, which it does not fulfill.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% parameter descriptions, so the baseline is 3. The description adds no parameter-specific meaning beyond mentioning the types of data returned; it does not compensate for or add to the schema explanations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Read and consume buffered data') on a clear resource ('the device') and gives concrete examples of what that data may be. It is understandable on its own, but it does not explicitly distinguish itself from closely related siblings like read_until, tail, and query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance about when to use this tool instead of read_until, tail, query, or clear_buffer. The phrase 'buffered data' implies a usage context, but the description never states exclusions or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_untilA
Wait until a pattern appears (e.g. 'OK', 'ready>', 'Temperature:') and return everything up to and including it. On timeout returns whatever arrived, with matched=false.
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| regex | No | Interpret `pattern` as a Python regex. | |
| pattern | Yes | Substring to wait for, or a regex when regex=true. | |
| timeout_s | No | Give up after this many seconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| bytes | Yes | |
| error | No | |
| matched | Yes | False if the timeout expired before the pattern appeared. |
| elapsed_s | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral disclosure burden. It meaningfully discloses the blocking-until-pattern behavior and the timeout contract ('returns whatever arrived, with matched=false'). It omits edge cases like an unopened port or buffer consumption, but the core runtime behavior is well covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core wait-and-return behavior and closed with the timeout contract. Every clause adds useful information and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Essential behavior is fully described: what it waits for, what it returns, and what happens on timeout. It does not mention prerequisites such as an already-open port, but the port parameter and sibling tools like open_port/port_status make that context available.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers 100% of the parameters, so the baseline is 3. The description adds only pattern examples and does not explain port, regex, or timeout semantics beyond what the schema already states. This is adequate but not enhanced.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Wait') and a concrete resource ('until a pattern appears'), then defines the return as 'everything up to and including it.' It also gives concrete examples of patterns ('OK', 'ready>', 'Temperature:'), making the tool's purpose unmistakable and distinct from a plain read or tail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly frames the tool as a blocking, pattern-terminated read and notes the timeout fallback, so an agent knows when this is the right call. It does not explicitly reference sibling alternatives or say when not to use it, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reset_deviceA
Reboot the board by pulsing DTR/RTS and return what it prints while booting. Only works on boards that wire those lines to reset (most USB dev boards do).
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| method | No | dtr = Arduino-style auto-reset; rts = ESP32/ESP8266 dev boards (EN pin); auto = both sequences (safe for either family). | auto |
| wait_s | No | Seconds to capture boot output after the reset (0 = do not read). |
Output Schema
| Name | Required | Description |
|---|---|---|
| hex | No | Raw bytes as hex when as_hex=true. |
| text | Yes | Decoded data (undecodable bytes become U+FFFD). |
| bytes | Yes | |
| error | No | |
| timed_out | Yes | True if nothing arrived before the timeout. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It discloses the mechanism, the side effect of rebooting, the return value, and a hardware compatibility limitation. It could add more about port availability during reset, but it is reasonably transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The action, mechanism, return behavior, and limitation are all front-loaded efficiently. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter tool with full schema coverage and an output schema, the description is largely sufficient. It covers the key caveat about board wiring. It does not mention whether the port must already be open, which would be useful, but this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the input schema already documents all parameters. The description adds no extra parameter-level detail, which is acceptable given the schema is complete. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: it reboots the board, explains the mechanism (pulsing DTR/RTS), and states the return behavior (boot output). This makes the tool's function immediately clear and distinguishable from siblings like set_control_lines or write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear usage condition: it only works on boards that wire DTR/RTS to reset, and notes that most USB dev boards do. It does not explicitly name alternatives or say when not to use it, but the prerequisite is stated clearly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_control_linesA
Set the DTR / RTS modem control lines manually (bootloader entry, custom reset circuits).
| Name | Required | Description | Default |
|---|---|---|---|
| dtr | No | Drive DTR high (true) or low (false). | |
| rts | No | Drive RTS high (true) or low (false). | |
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It states what lines are set but does not explain side effects, what happens when dtr/rts are null or omitted, whether the port must already be open, or how this interacts with subsequent reads/writes/resets. The word 'manually' adds some context but not enough behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no filler. The core operation appears first, and the use-case context is compactly parenthesized. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-parameter tool with full schema descriptions and an output schema, the definition is mostly adequate. However, behavioral gaps around null semantics and side effects, as well as the absence of explicit routing away from reset_device, leave the agent without enough context to confidently choose and invoke this tool in all scenarios.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with each parameter already documented in the schema, so the baseline is 3. The tool description adds no extra parameter meaning beyond the manual-line-control context; port examples and high/low semantics are already in the schema. It neither improves nor harms parameter clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Set'), the exact resource ('DTR / RTS modem control lines'), and the manual nature of the operation. The parenthetical context ('bootloader entry, custom reset circuits') reinforces the purpose and helps distinguish this low-level tool from higher-level operations like reset_device.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context for when this tool might be used, such as bootloader entry or custom reset circuits, but it does not explicitly state when to prefer this over alternatives like reset_device, nor does it provide exclusions or when-not-to-use guidance. Usage is implied rather than explicitly directed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tailA
Peek at the last lines received on a port WITHOUT consuming the read buffer. Good for checking what a device has been printing while you were doing other things.
| Name | Required | Description | Default |
|---|---|---|---|
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| lines | No | Number of most recent complete lines. |
Output Schema
| Name | Required | Description |
|---|---|---|
| lines | Yes | |
| partial | Yes | Bytes received after the last newline (an unfinished line). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it discloses the most important behavioral trait: it peeks without consuming the read buffer. It does not mention prerequisites like requiring an open port, but the non-destructive, read-only nature is clearly conveyed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no wasted words. The core behavior is front-loaded, and the second sentence adds a practical use case that earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has a complete input schema, and an output schema exists, so return details are covered elsewhere. The only meaningful gap is not explicitly stating that the port must already be open, but the read-buffer terminology and sibling tools make this reasonably inferable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already fully documents both parameters. The description adds no parameter-level detail beyond the schema; the word 'lines' aligns with the 'lines' parameter but adds no new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Peek') and resource ('last lines received on a port'), and immediately clarifies a distinguishing behavior: it does NOT consume the read buffer. This clearly separates it from read/read_until/query without needing to open the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence gives a clear context for when to use it: checking what a device has been printing while doing other things. It does not explicitly name alternatives or state when not to use it, but the intended use case is unmistakable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
writeA
Send raw bytes without waiting for a reply (use query for request/response).
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Text to send, or a hex string when as_hex=true. | |
| port | Yes | Port device from list_ports (e.g. /dev/cu.usbserial-0001, /dev/ttyUSB0, COM3), or a pyserial URL such as socket://host:port, rfc2217://host:port or loop://. | |
| as_hex | No | Treat `data` as hex bytes ('01 A0 FF'); newline is not appended. | |
| newline | No | Appended after text data. Use '\r\n' for CRLF devices, '' for none. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bytes_written | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full transparency burden. It does disclose the key trait that write does not wait for a reply, but it omits other important details such as requiring the port to be open, whether transmission is immediate, what happens on failure, and whether any output is produced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no redundant words; the core behavior and the routing alternative are front-loaded. Every part of the sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The schema and output schema cover the parameter mechanics and return shape, and the description covers the fire-and-forget mode. However, for a hardware write operation with no annotations, a prerequisite such as 'open the port first' is missing, and error conditions are not addressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters. The description adds no parameter-level detail beyond framing the payload as raw bytes, so it stays at the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete operation: 'Send raw bytes' with an explicit no-reply mode, and it distinguishes itself from 'query' in the same sentence. Even though the serial-port object is not named directly, the sibling set and port schema make the resource unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear when-to-use rule: use write when no reply is expected, and use query for request/response. This is direct routing guidance to one of the most relevant sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
12 tool updates
v0.1.0- First observed
clear_buffer - First observed
close_port - First observed
list_ports - First observed
open_port - First observed
port_status - First observed
query - First observed
read - First observed
read_until - First observed
reset_device - First observed
set_control_lines - First observed
tail - First observed
write
TDQS
Scored across 12 tools
Each tool targets a distinct serial-port operation: open/close/status/list are lifecycle, write/read/read_until/query/tail/clear_buffer handle data flow in clearly separated ways, and reset_device/set_control_lines cover control-line actions. The descriptions explicitly call out the consumption-vs-peek and reply-vs-no-reply distinctions, so an agent should not misselect.
Most tools follow verb_noun naming (open_port, list_ports, clear_buffer), but several are bare verbs (write, read, query, tail) and port_status uses a noun phrase instead of a verb. The mix is readable but not a consistent pattern.
Twelve tools is a well-scoped size for a serial-port server. Each operation has a distinct role and the count is neither bloated nor too thin.
The surface covers the full serial workflow: enumeration, open/close/status, raw write, buffered read, pattern waits, request/response queries, monitoring without consuming, buffer clearing, device reset, and manual control-line control. No major missing operation is apparent.
Maintenance
Related MCP Connectors
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Give your agent live data from Twitter, Reddit, the web and GitHub. No API keys, no scraping stack.
Discover, inspect and run 63,000+ agent tools from one balance. Pay per call, no subscriptions.
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with physical serial port devices across platforms (Windows COM/Linux tty) with support for asynchronous communication, URC pattern recognition, and structured logging.1-
- AlicenseAqualityCmaintenanceEnables AI assistants to communicate with serial port devices, supporting port management, data transmission in text/binary modes, interactive terminal sessions, and automatic reconnection.1412MIT
- AlicenseAqualityDmaintenanceEnables LLMs to communicate with hardware devices via serial ports. Provides tools for listing ports, opening/closing connections, reading/writing data, and controlling serial signals.8MIT
- AlicenseAqualityDmaintenanceAllows AI agents to interact with serial devices via RS232/UART, enabling port listing, connection, read/write, control line manipulation, and protocol specification for automated debugging and testing.2742 PyPI20MIT