smolmux
smolmux
A portable C11 device multiplexer. Holds a device connection open (serial UART, GDB stub) and multiplexes access to multiple clients over Unix sockets using newline-delimited JSON.
Single static binary, low latency, small footprint - built for daily serial and GDB bring-up on Linux.
New here? docs/START-HERE.md is a one-screen router - find your intent (run it, bring up a new board with an AI agent, understand the architecture, hack on the code) and it points you to the right doc.
Example: probe an unknown board
One broker holds SWD; smolmux-gdb-mcp runs probe_unknown_board. On a
SAM C21 Xplained Pro that path decoded Cortex-M0+ from CPUID, named the
part via SAM DSU DID, rejected a false STM32 match, and wrote a starter
*.gdb-profile.json. Tools, register values, and profile shape:
docs/demo-samc21-probe-transcript.md.
Day-to-day serial (multi-client, U-Boot break-in, flasher handoff): docs/daily-driver.md.
Related MCP server: serial-mcp
Features
Serial UART, GDB MI, and serial-over-TCP (telnet + RFC2217) device links via vtable polymorphism
Multiple concurrent clients over Unix sockets with role-based access (observer/controller/takeover)
Expect engine - concurrent regex matching on the device byte stream with timeouts
Anomaly detection - pattern-based crash/error detection with cooldown and incident tracking
Output history - timestamped ring buffer for replay by late-joining clients
Structured logging - JSONL I/O log + human-readable text log with rotation (the I/O log records everything sent to and from the device, including anything typed at a login prompt — it is created
0600under your private state directory, and smolmux refuses to write it through a symlink or to a file owned by another user)Network sinks - TCP and WebSocket for remote access (loopback by default). The wire protocol is cleartext, and any client that completes the handshake gets full control of the device — console writes, pins, BREAK, SysRq, GDB. On loopback without
--auth-token, the broker generates a token into a0600file in$XDG_RUNTIME_DIR(or/tmp), so other local users and processes cannot connect; your ownsmolmux-monitor/smolmux-mcpread it automatically, andsmolmux-cli tokenprints it. For remote use, keep the bind on loopback and reach it over an SSH tunnel or WireGuard rather than exposing the port; smolmux refuses to serve a non-loopback TCP bind with no--auth-token.--insecure-no-authturns both protections off.MCP servers - standalone
smolmux-mcp/smolmux-gdb-mcpattach to a running broker; optional in-process--mcpsink for single-process stdioBoot tracking & autoresponder - ordered boot stages, stall events, standing expect->send rules
Autoboot interrupt - broker-side key flood (and optional DTR/RTS reset) for
bootdelay=0U-BootDevice profiles / board manifests - JSON configs for prompts, anomalies, multi-wire boards
Auto-reconnect - exponential backoff recovery on USB-serial disconnect
Build-time feature selection - Kconfig-based; UART-only builds carry no GDB/TCP/WebSocket code
Quick start
cmake -B build && cmake --build build -j$(nproc)
./build/smolmux /dev/ttyUSB0Connect a client:
# Needs a running broker (above). Auto-discovers the socket from the port name.
./build/smolmux-monitor /dev/ttyUSB0Day-to-day workflows (profiles, logs, U-Boot break-in, multi-wire boards): docs/daily-driver.md. Intent router: docs/START-HERE.md.
Build
cmake -B build && cmake --build build -j$(nproc) # Default (all features)
ctest --test-dir build # Run testsFeature profiles
cp configs/defconfig.minimal .config && cmake -B build # UART only, no sinks/watcher
cp configs/defconfig.uart .config && cmake -B build # UART + MCP sink + watcher
cp configs/defconfig.embedded .config && cmake -B build # Embedded target profile
cp configs/defconfig.full .config && cmake -B build # Everything (GDB, TCP, WS, MCP, watcher)Or toggle features directly:
cmake -B build -DSM_ENABLE_GDB=OFF -DSM_ENABLE_SINK_WS=OFFDeveloper benchmarks (e.g. the output coalescer harness) are off by default:
cmake -B build -DSM_BUILD_BENCH=ON && cmake --build build --target bench_coalesceInteractive configuration:
cmake --build build --target menuconfigStatic builds
cmake -B build -DSM_MUSL_STATIC=ON # Fully static musl binary (zero runtime deps)
cmake -B build -DSM_STATIC=ON # Static linking (except glibc)Usage
smolmux <port> [options]
Options:
-b, --baud <rate> Baud rate (default: 115200)
-s, --socket <path> Unix socket path
-l, --log-dir <dir> I/O log directory
(default: $XDG_STATE_HOME/smolmux or
~/.local/state/smolmux)
-t, --text-log-dir <dir> Text log directory
-p, --profile <path> Device profile JSON file
--board <name> Group this wire under a board (for discovery)
--role <label> This wire's role on the board (console, swd, ...)
--gdb Use GDB MI link instead of UART
--gdb-path <path> Path to gdb binary (default: gdb)
--gdb-target <spec> GDB target (e.g., localhost:3333)
--serial-tcp <host:port> Connect to a serial-over-TCP device server
(ser2net, socat, terminal server; telnet +
RFC2217 baud/DTR/RTS/break control)
--mcp Enable in-process MCP stdio sink (prefer standalone
smolmux-mcp against a daemon broker for daily use)
--tcp-port <port> Enable TCP sink (default: 5555)
--tcp-bind <addr> TCP bind address (default: 127.0.0.1)
--auth-token <token> Require token in hello from TCP clients
(prefer env SMOLMUX_AUTH_TOKEN - hidden from ps)
--auth-token-file <path> Read the token from a file
--insecure-no-auth Serve TCP/WS with no token. Without it, a
loopback listener gets a generated token
(0600 file; smolmux-cli token prints it) and
a non-loopback --tcp-bind is refused.
--ws-port <port> Enable WebSocket sink (default: 5556)
--no-text-log Disable text log
--no-io-log Disable JSONL I/O log
--no-reconnect Don't auto-reconnect on disconnect
--wait-device <seconds> Wait for the device path before open
--gdb-allow-shell Permit GDB shell/python/eval (off by default)
--list-ports List available serial ports and exit
--list-profiles List available device profiles and exit
--help-protocol Show wire protocol documentation
-v, --verbose Enable debug logging
-V, --version Show version
-h, --help Show this helpWire protocol
Newline-delimited JSON over Unix sockets (also TCP/WS sinks). Binary data is base64-encoded. Message set covers session control, expect, history, anomaly, boot stages, autoboot flood, and autoresponder.
Full reference: ./build/smolmux --help-protocol (always matches this binary).
Client -> Broker: hello, send, send_expect, takeover, release, status, pin_control, set_baud, suspend, resume, history_request, incidents_request, configure_anomaly, interrupt_autoboot, configure_autoresponder, autoresponders_request
Broker -> Client: welcome, output, input_echo, expect_result, status_response, error, history_response, incidents_response, anomaly, autoboot_result, boot_stage, boot_stall, autoresponders_response, autoresponder_fired, suspended, resumed, link_down, link_up
Example session:
-> {"type":"hello","name":"my-tool","role":"controller","protocol_version":1}
<- {"type":"welcome","broker_version":"x.y.z","protocol_version":1,"port":"/dev/ttyUSB0","baud":115200,"your_role":"controller"}
-> {"type":"send","id":"1","data":"dW5hbWUgLWEK"}
<- {"type":"output","data":"TGludXggNC4xOS4w...","timestamp":1709654321.123}Architecture
┌───────────┐ ┌───────────┐
│ uart link │ │ gdb link │ <- device-facing, compiled in/out via Kconfig
└─────┬─────┘ └─────┬─────┘
│ │
▼ ▼
┌──────────────────────────────┐
│ smolmux core │ <- epoll event loop, message bus,
│ history · logging · anomaly │ role enforcement, expect engine
└──┬───────┬───────┬───────┬───┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────┐┌─────┐┌─────┐┌──────┐
│ unix ││ tcp ││ ws ││ mcp │ <- sinks, also compiled in/out
│socket││sink ││sink ││ sink │
└──────┘└─────┘└─────┘└──────┘See DESIGN.md for full architecture documentation.
Dependencies
Required: cJSON (vendored, single file)
Auto-detected: PCRE2 (libpcre2-8). Used as the regex engine when
present, because it bounds backtracking internally; the build falls back to
POSIX ERE automatically when it is absent, so it is never required. Force
either way with -DSM_ENABLE_PCRE2=ON (error if missing) or
-DSM_ENABLE_PCRE2=OFF.
Core has zero required external dependencies beyond POSIX + cJSON.
Companion tools
smolmux-cli - command-line client (send commands, read output;
with-port <cmd>suspends the port, runs an external tool like a flasher, then always resumes)smolmux-monitor - interactive terminal client with escape sequences (prefix key then a command; prefix defaults to Ctrl-], change with
-e, e.g.-e escor-e ^A)smolmux-mcp - standalone MCP server: connects to a running broker and exposes serial tools (
serial_send_command,serial_read,serial_boot_status,serial_add_autoresponder, ...). Alternative: broker--mcpsink embeds MCP in-process.smolmux-gdb-mcp - standalone MCP server for GDB debugging: 21 tools over a broker holding a
--gdblink - breakpoints, stepping, backtrace, name-labeled registers, memory, expression eval, fault-register decode (where the core has them), peripheral reads,gdb_interrupt, and unknown-board probing on ARM Cortex-M today (gdb_identify_target/gdb_generate_profile; other architectures are planned). Resources and prompts includesmolmux-gdb://board-probingandprobe_unknown_board. Built whenSM_ENABLE_GDBis on; chip-ID validated on a SAM C21 Xplained Pro.smolmux-watcher - daemon that monitors for anomalies and saves incident reports to disk
Related Documentation
Start here - One-screen intent router (daily use, new board, architecture, hacking).
MCP setup - Register
smolmux-mcp/smolmux-gdb-mcpwith Claude Code, Claude Desktop, or Cursor.Daily driver - Recommended build, runtime flags, U-Boot break-in, boot stages, boards, coexistence with flashers.
Board Exploration Workflow - Runbook for a fresh board (manually or with an AI agent): wires, SWD identify, console, peripherals.
Board Bring-up Template - Copy-per-board fact-capture template.
Persistent Serial Device Names - Stable names for UART dongles (
/dev/serial/rpi-consoleetc.).Hardware validation matrix - What is validated on real hardware vs not yet proven.
Free vs Pro
Everything in this repository is MIT-licensed - full source, wire protocol, generic device profiles, build system. Build it yourself and you have the complete product.
smolmux Pro is convenience, not a feature gate: prebuilt static binaries
(x86_64 + aarch64, musl, zero runtime dependencies), the curated profile pack
with per-profile notes, and 6 months of email support. One-time purchase
($79). MCP setup for zip paths is docs/MCP-SETUP-FULL.md (also in
this public tree).
Buy smolmux Pro - $79 one-time - download includes current static binaries and the profile pack.
License
MIT. cJSON is vendored under its own MIT license
(deps/cJSON/LICENSE).
Available Tools
9 toolsserial_boot_statusARead-only
Report cold-boot progress: which boot stages the device has reached, the furthest stage, and whether the boot has stalled. Requires the device profile to declare boot_stages; otherwise reports none.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, destructiveHint=false, openWorldHint=false), so the bar is lower. The description still adds real behavioral context beyond them: what information is returned and the graceful-degradation case when boot_stages is undeclared ('reports none'). No rate limits or auth details, but none are relevant for a local read.
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 tight sentences with zero waste. The core purpose is front-loaded and the prerequisite is placed second, so the agent reads the important part first.
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?
With no output schema, the description carries the return-value burden and discharges it by naming the three reported facts plus the fallback behavior. For a no-parameter, read-only query this is fully sufficient.
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 takes zero parameters, so the schema has nothing to document and the baseline of 4 applies. The description correctly adds no parameter detail because there is nothing to describe.
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 gives a specific verb ('Report') and a narrowly scoped resource ('cold-boot progress'), then enumerates exactly what is reported: stages reached, furthest stage, and stall status. This is clearly distinct from siblings such as serial_port_status or serial_read, so an agent can select it without ambiguity.
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 states a concrete applicability condition: the device profile must declare boot_stages, otherwise the tool reports none. That tells the agent when this tool is meaningful, though it does not explicitly contrast with alternative tools or state when not to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_generate_reportBRead-only
Generate a status report for the serial device.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds only that the output is a "status report" for the serial device, without disclosing scope, contents, or whether the report is generated fresh or cached. With annotations carrying the behavioral burden, this is adequate 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?
A single short sentence with the resource front-loaded and no filler. It is efficient, though the sentence is so terse that it sacrifices specificity rather than achieving tightness.
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?
There is no output schema, so the description ideally should say what the report contains (port state, boot state, incidents?) — and it does not. With zero parameters and annotations covering safety, the definition is minimally viable but leaves the agent guessing about return content and sibling overlap.
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 takes zero parameters, so per the baseline there is nothing for the description to compensate for. Schema coverage is 100% on an empty object, and the description correctly implies no input is required.
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 verb ("Generate") and resource ("status report for the serial device"), which is clear on its own. However, it does nothing to distinguish itself from closely related siblings such as serial_port_status, serial_boot_status, and serial_get_incidents, leaving ambiguity about what this report covers versus those.
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 on when to use this tool versus serial_port_status, serial_boot_status, or serial_get_incidents, nor any stated prerequisites or exclusions. The agent must infer the usage scenario entirely from the name and one-line description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_get_incidentsBRead-only
Get detected anomalies/crashes from the broker.
| Name | Required | Description | Default |
|---|---|---|---|
| seconds | No | If > 0, only return incidents from the last N seconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered without description help. The description adds the useful fact that incidents are sourced "from the broker" and are pre-detected, but says nothing about ordering, caps, or empty-result behavior.
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?
One sentence with no filler and the verb front-loaded. It is appropriately short for a single-parameter read tool, though the trailing "from the broker" is mildly ambiguous.
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?
A simple read with one fully documented optional parameter and annotations covering safety. With no output schema, the description could have said what an incident record contains and whether results are bounded, so it is adequate but leaves a real 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 description coverage is 100%, so the single optional 'seconds' parameter is fully documented in the schema itself. The description adds no filtering syntax or default behavior beyond that, so the baseline 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 clear verb+resource combination: retrieve detected anomalies/crashes. The scope word "detected" implies pre-filtered incidents rather than raw output, which usefully separates it from serial_read and serial_output_history. However, it never names a sibling or explains how it differs from those log-oriented tools.
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 when-to-use guidance, no prerequisites, and no alternatives are named. An agent must infer from the name alone whether to call this instead of serial_output_history or serial_generate_report when investigating a crash.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_list_portsBRead-only
List serial ports with by-id and USB VID/PID when available. Bridge chips name the adapter, not the MCU.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint=false, and destructiveHint=false, which covers the safety profile. The description adds that by-id and USB VID/PID are provided when available, and explains that bridge chips name the adapter rather than the MCU. That is useful behavioral context beyond annotations, but it stops short of describing output shape or ordering. With annotations carrying the safety burden, a 3 is appropriate.
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, front-loaded with the action. The second sentence is a useful caveat rather than filler, though it could be tightened. No waste.
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 zero-param read-only list tool with annotations covering safety, the description is adequate. It explains what the listing contains and a gotcha about bridge chips, but does not describe return format or ordering, which would help an agent consume the result. Without an output schema, some of that burden remains on the description.
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?
Zero parameters, so baseline is 4. The description cannot add parameter meaning because there are none, and nothing about parameter semantics is missing or misleading.
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?
Clear verb+resource: 'List serial ports'. The second sentence adds content about what data is included (by-id, USB VID/PID) and a caveat about bridge chips. It does not differentiate from siblings like serial_port_status, which could also enumerate ports — no explicit distinction is drawn.
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 on when to use this versus alternatives such as serial_port_status or serial_read. The agent has to infer that this is for discovery. There is no exclusion or selection criteria stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_monitorBRead-only
Monitor serial output for a duration, returning output and anomalies.
| Name | Required | Description | Default |
|---|---|---|---|
| duration_seconds | No | How long to monitor (max 300 seconds, default 30). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds that monitoring is time-bounded and that anomalies are surfaced, which is real behavioral context beyond the annotations, but it says nothing about how anomalies are detected, whether monitoring blocks, or what happens if the port is busy.
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?
One sentence, front-loaded with the verb and resource, with the return value appended. Nothing is padded or redundant.
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?
With no output schema, the description carries the burden of describing the return, and 'output and anomalies' is too vague to know what an agent will actually receive or how to interpret anomalies. For a single-optional-param read tool with full annotations the rest is adequate, but the return contract is under-specified.
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 single parameter is fully documented (max 300, default 30), so the baseline is 3. The description's phrase 'for a duration' merely restates the parameter without adding format or interaction detail.
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 verb ('monitor') and resource ('serial output') and adds scope ('for a duration') plus the return payload ('output and anomalies'). It implicitly separates itself from serial_read (one-shot) and serial_wait_for (pattern wait), but never names a sibling, so an agent must infer the boundary.
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 when-to-use guidance, no when-not-to-use, and no mention of alternatives among the eight serial_* siblings. An agent cannot tell from this text whether to pick serial_monitor, serial_read, or serial_wait_for for a given need.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_output_historyARead-only
Non-destructive history. With since_seq: JSON cursor page. Without: prose by time/bytes. serial_read is drain-only.
| Name | Required | Description | Default |
|---|---|---|---|
| seconds | No | If > 0, return output from the last N seconds (prose). | |
| max_bytes | No | With since_seq: max raw bytes in this page (default broker cap). | |
| since_seq | No | Cursor from a prior history response: lossless page as JSON (cursor/dropped/has_more/chunks). Prefer this over serial_read. | |
| last_bytes | No | If > 0, return the last N bytes of output (prose). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral value by disclosing the mode-dependent return shapes (JSON cursor page with cursor/dropped/has_more/chunks vs prose by time/bytes), which annotations cannot convey.
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?
Four front-loaded fragments with zero filler, and the non-destructive framing leads. It is dense to the point of being terse, but every clause carries information.
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?
With no output schema, the description does the work of describing both return formats (JSON cursor page vs prose), and the four params are fully covered by the schema. Adequate for a read-only history tool, though it could note pagination/cursor-reuse behavior more explicitly.
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 in detail. The description only echoes the since_seq vs time/bytes split already present in the schema, adding no syntax or format nuance beyond it.
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 resource (history) and a defining trait (non-destructive), and names the sibling it is not by noting 'serial_read is drain-only'. The agent can tell this retrieves past output rather than draining it, though the phrase 'Non-destructive history' never literally says 'serial output' and leans on the tool name for context.
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?
Gives clear mode-selection guidance: 'With since_seq' yields a cursor page while 'Without' yields prose by time/bytes. The contrast with serial_read ('drain-only') implies when to prefer this tool for non-destructive retrieval, but it stops short of an explicit when-not-to-use rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_port_statusARead-only
Get the current status of the serial port and connected clients.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=false, and destructiveHint=false, so the safety profile is fully covered by structured data. The description adds only that 'connected clients' are part of the status, which hints at return content but says nothing about format, freshness, or error behavior on a disconnected port.
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 eleven-word sentence that front-loads the verb and resource with no filler or redundancy. Nothing could be removed without losing meaning.
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?
With no output schema and no annotations beyond read-only flags, the description carries the burden of describing what 'status' actually returns. It names the two subjects (port, connected clients) but gives no field-level detail, so an agent cannot predict the response shape. Adequate but with a clear 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?
The tool takes zero parameters, so the baseline is 4 and there is nothing for the description to disambiguate. Schema coverage is also 100%, leaving no parameter gap to fill.
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 ('Get') and resource ('status of the serial port and connected clients'), so the agent knows exactly what operation it performs. It does not, however, distinguish itself from near-siblings like serial_boot_status or serial_list_ports, which an overloaded agent would have to disambiguate itself.
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?
Usage context is only implied - reading current status - with no explicit when-to-use guidance, no exclusions, and no routing to alternatives such as serial_boot_status or serial_list_ports. The agent must infer selection from the name and sibling set.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_readARead-only
Read buffered serial output without sending anything (session drain; prefer history for lossless capture).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, destructiveHint=false, openWorldHint=false), so the bar is lower, and the description still adds real behavioral context: this is a 'session drain' whose contents are consumed, versus history which is lossless. That drain/loss nuance is not expressed anywhere in the structured fields and is the most decision-relevant thing an agent needs to know.
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 the core action front-loaded and the alternative-route caveat tucked into a parenthetical. Every clause earns its place; nothing is padded or repeated from the schema.
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 zero-parameter, read-only tool with no output schema, the definition supplies the action, the consumption semantics, and the better alternative for lossless capture. It leaves the return format and whether the drain actually clears the buffer implicit, which is a minor gap given the tool's simplicity.
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 takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The absence of arguments is consistent with the description's claim that nothing is sent.
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 and resource ('Read buffered serial output') plus a scoping constraint ('without sending anything'), which is far more than a restatement of the name. It differentiates itself from serial_output_history by naming that sibling as the lossless alternative, though it does not distinguish itself from the other serial_* siblings (monitor, wait_for, status).
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 parenthetical 'prefer history for lossless capture' gives an explicit alternative and the condition that selects it, which is exactly the routing guidance an agent needs between two similar read tools. It stops short of a full when/when-not statement (e.g. no guidance relative to serial_monitor or serial_wait_for), so it is clear context rather than complete routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serial_wait_forARead-only
Wait for a regex in serial output without sending. Works for observers. Ends early on critical anomaly (ABORTED).
| Name | Required | Description | Default |
|---|---|---|---|
| pattern | Yes | Regex to match in device output (listen-only; no TX). | |
| timeout_ms | No | Max wait in ms (default 30000, clamp 100–3600000). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint and openWorldHint, so the safety profile is covered. The description adds a genuinely non-obvious behavioral trait — early termination on a critical anomaly (ABORTED) — which the annotations cannot express. It omits what happens on plain timeout, but the key runtime behavior is disclosed.
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 short, front-loaded sentences with no filler; the core purpose and the abnormal-exit condition both land immediately. Every clause carries information.
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?
With no output schema, the description should say what a successful wait yields (matched text, boolean, incident?) and what a timeout returns, since that determines how the agent branches. Annotations cover safety and the schema covers inputs, but return semantics are left unstated.
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 schema already documents the regex semantics (listen-only, no TX) and the timeout default and clamp range. The description's 'without sending' merely restates the schema's listen-only note, adding no new parameter meaning. Baseline 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 (wait) plus the resource and scope (a regex in serial output), and 'without sending' separates it from the write/monitor siblings. It does not name a specific sibling such as serial_read, so differentiation is implied rather than explicit.
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?
'Works for observers' hints at the context in which this is appropriate, but there is no explicit when-to-use versus serial_read or serial_monitor, and no stated prerequisites or exclusions. Usage must be inferred from the name and the listen-only note.
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.
9 tool updates
v0.4.0- First observed
serial_boot_status - First observed
serial_generate_report - First observed
serial_get_incidents - First observed
serial_list_ports - First observed
serial_monitor - First observed
serial_output_history - First observed
serial_port_status - First observed
serial_read - First observed
serial_wait_for
TDQS
Scored across 9 tools
Most tools target distinct capabilities (read/drain, history, monitor, wait_for, incidents, boot, status, list, report), and descriptions explicitly differentiate read vs history vs monitor. However serial_read, serial_output_history, and serial_monitor all surface serial output and could still be confused, and serial_port_status vs serial_list_ports overlap somewhat.
All tools share the predictable serial_ prefix, which makes the namespace cohesive. The suffix style varies (read, port_status, boot_status, wait_for, get_incidents, output_history, monitor, generate_report, list_ports), mixing noun_status and verb_noun forms, but it remains readable.
Nine tools is well within the ideal 3-15 range and each maps to a distinct observation/reporting concern for a serial device debugger. No obvious filler or redundancy in count.
The observation side is thorough (read, history, monitor, wait, incidents, boot, status, report), but repeated phrasing 'without sending anything' strongly implies a serial write/send capability that is absent, leaving an obvious gap for interactive control. No config/session-management operations beyond status either.
Maintenance
Related MCP Connectors
2,000+ MCP servers read at source level. Know what one does before you connect. Free, no key.
MCP Server for an Agent Task Marketplace
Free, read-only security scanner for remote MCP servers, before you connect them.
Security research canary remote MCP server for owned-account testing.
Related MCP Servers
- AlicenseAqualityCmaintenanceStateful MCP server for driving debug probes (J-Link) to flash, debug, and inspect embedded targets. Enables AI agents to perform flash, memory, breakpoint, and ELF/SVD-aware operations conversationally.4125 PyPI10MIT
- AlicenseAqualityAmaintenanceMCP server that lets LLMs talk to serial devices: microcontrollers, routers, modems, embedded Linux, anything with a UART.2350 PyPI7MIT
- FlicenseBqualityCmaintenanceMCP server for running shell commands on a Linux development board via UART serial.1-
- AlicenseNot gradedqualityAmaintenanceMCP server for Agentic Hardware-in-the-Loop testing, enabling AI agents to probe, flash, reset, and validate embedded firmware on real hardware via bounded MCP tools.1,560 PyPI17Apache 2.0