Skip to main content
Glama
serial-hub-mcp

serial-hub-mcp

by yhuan416

serial-hub-mcp

A serial-port MCP server that is also a hub: one process can hold multiple local UARTs and (in upcoming releases) remote serial bridges such as an ESP32-S3 acting as a wireless UART dongle.

The byte plane is intentionally boring and transparent: bytes in, bytes out, no framing, no prompt/regex interpretation. Content judgement is left to the agent. Logs are split by line for retrieval, but the raw hex is always the source of truth.

Features

  • Two transports: stdio (default) and stateless MCP Streamable HTTP (--http), with optional Bearer auth plus unauthenticated /health and /info endpoints.

  • Local serial via serialport: list_ports, open by path, profile, sn/vid/pid, configurable baud/parity/flow control.

  • Byte-accurate I/O: read (cat), transact (write + wait, ignores pre-write noise), receive (windowed capture), dump_to_file (stream to disk).

  • Control lines: DTR/RTS (with pulse for reset sequences) and BREAK.

  • Durable logs: per-connection in-memory ring + JSONL partitions on disk, queryable by seq/time/direction/content, with retention and eviction reporting.

  • Profiles: save connection parameters and reuse them with open({profile}).

  • Hub-ready concurrency: calls are serialized per connection_id and run concurrently across different connections.

  • Remote link seam: open({transport:"remote", endpoint:"tcp://host:port"}) is part of the public contract. The RPC contract is defined; the ESP32 bridge adapter is not yet implemented.

Status: 0.1.x — local serial is production-ready; the remote bridge contract and endpoint registry are landing incrementally.

Related MCP server: UART MCP Server

Install

npm install -g serial-hub-mcp
# or run without installing
npx serial-hub-mcp

Requirements: Node.js >= 18. On Linux, add your user to the dialout group (or otherwise grant read access to /dev/ttyUSB*, /dev/ttyACM*).

MCP client configuration

stdio (default)

{
  "mcpServers": {
    "serial": {
      "command": "serial-hub-mcp"
    }
  }
}

Streamable HTTP

Start the server with --http, then point clients at the MCP endpoint. The exact client config shape varies; for clients that accept a URL and headers:

{
  "mcpServers": {
    "serial-hub": {
      "type": "http",
      "url": "http://127.0.0.1:8787/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

HTTP mode

serial-hub-mcp --http                      # 127.0.0.1:8787/mcp
serial-hub-mcp --http --host 0.0.0.0 --port 8787
SERIAL_HUB_MCP_HTTP_TOKEN=secret serial-hub-mcp --http
  • Stateless Streamable HTTP: every request gets its own MCP server instance while sharing the same connection manager / log router / queue, so connections persist across requests.

  • GET /health and GET /info are unauthenticated and contain no secrets.

  • The server listens on loopback by default. If you bind a non-loopback address without SERIAL_HUB_MCP_HTTP_TOKEN, it prints a warning — anyone who can reach the port can operate the serial ports.

  • The token is compared with a constant-time check and sent as Authorization: Bearer <token>.

Tools

Tool

Purpose

list_ports

Enumerate local serial ports (path, VID/PID, serial number)

open

Open a connection (transport / port / profile / `sn

close

Close a connection

get_status

Connection state, counters, control-line levels

write

Send bytes (utf8 / hex / base64, optional newline)

read

Read bytes since the cursor (optional wait / match / min bytes)

transact

Write then wait for a response in one step (AT/Modbus friendly)

receive

Capture a window until match / max bytes / idle / budget

dump_to_file

Stream RX to a file (no large payloads through MCP)

set_dtr_rts

Set DTR/RTS, optionally pulse (reset/bootloader)

send_break

Send a BREAK for a given duration

profile_list/save/delete

Reusable named connection profiles

log_query/stats/clear

Search, inspect and clear per-connection logs

service_info

Service name, version, changelog

Quick start

list_ports()
open({ port: "/dev/ttyUSB0", baud_rate: 115200, newline: "crlf" })
transact({ connection_id: "...", data: "AT", match: "OK" })
receive({ connection_id: "...", start: "flush", reset: "dtr", budget_ms: 15000 })
dump_to_file({ connection_id: "...", budget_ms: 30000 })
close({ connection_id: "..." })

For remote hubs:

open({ transport: "remote", endpoint: "tcp://esp32s3-01:7000" })

endpoint is the reserved slot for the link adapters. The planned registry maps endpoint schemes (tcp, udp, kcp, mqtt, ws, ...) to adapters; see the design docs.

Configuration

All paths use XDG defaults and can be overridden:

Env var

Default

Purpose

SERIAL_HUB_MCP_LOGS_DIR

$XDG_CACHE_HOME/serial-hub-mcp/logs

Log partitions

SERIAL_HUB_MCP_LOG_MEM

1000

In-memory log entries per process

SERIAL_HUB_MCP_LOG_RETAIN_BYTES

67108864 (64 MiB/conn)

Disk retention; <=0 disables eviction

SERIAL_HUB_MCP_LOG_PART_BYTES

8388608 (8 MiB)

Partition roll size

SERIAL_HUB_MCP_PROFILES_DIR

$XDG_CONFIG_HOME/serial-hub-mcp

Profiles

SERIAL_HUB_MCP_DUMPS_DIR

$XDG_CACHE_HOME/serial-hub-mcp/dumps

dump_to_file output

SERIAL_HUB_MCP_HTTP

unset

1 enables HTTP mode (same as --http)

SERIAL_HUB_MCP_HTTP_HOST

127.0.0.1

HTTP bind host

SERIAL_HUB_MCP_HTTP_PORT

8787

HTTP bind port

SERIAL_HUB_MCP_HTTP_PATH

/mcp

MCP endpoint path

SERIAL_HUB_MCP_HTTP_HEALTH_PATH

/health

Health endpoint (unauthenticated)

SERIAL_HUB_MCP_HTTP_INFO_PATH

/info

Service info endpoint (unauthenticated)

SERIAL_HUB_MCP_HTTP_TOKEN

unset

Optional Bearer token for /mcp

Data and log model

  • RX is accumulated in a chunked buffer with an absolute consume cursor. The buffer is bounded (rx_buffer_size, 4 MiB default); the oldest bytes are dropped and counted in rx_dropped.

  • Logs are line-oriented for retrieval (\n, trailing \r stripped); TX is recorded once per write. Non-UTF-8 content is still available as raw hex.

  • Each log entry is { seq, ts, conn, dir, offset, line, hex, bytes }. seq is per log source; the hub never renumbers it.

Design

  • Hub architecture — layering, pull-only data flow, per-source sequencing, durable-log authority, concurrency, endpoint registry plan.

  • Remote link protocol — host ↔ ESP32 bridge RPC contract (READ/TRANSACT/LOG_*), framing, sequence/offset semantics, error codes.

Development

npm install
npm test          # unit tests + stdio/HTTP smoke (no hardware required)
npm run lint      # eslint + prettier check
npm run smoke     # MCP handshake + tool enumeration only
npm run smoke:http

License

MIT. See LICENSE.

Available Tools

18 tools
close关闭串口B

关闭一个之前打开的串口连接。

Inputs: connection_id (required).

dump_to_fileRX 直落盘(大流量抓取)A

把 Rx(可选先清缓冲)边收边写入文件,返回文件路径与结尾预览——大流量/长日志不经过 MCP 搬运。 结束条件优先级:match(字节) 出现 > 达到 max_bytes > 静默 idle_timeout_ms > budget_ms 耗尽。默认文件按天归档到 ~/.cache/serial-hub-mcp/dumps/。

Inputs: connection_id (required), dir, path, flush, +5 more.

get_status连接状态A

查看指定连接(或多个连接)的打开状态、波特率、收发字节数、剩余未读字节。connection_id 省略则列出全部连接。

Inputs: connection_id.

list_ports列出串口A

枚举系统检测到的串口。返回每个端口的路径、厂商、序列号、USB VID/PID 等。打开前先调用此工具确认存在的端口。

Inputs: no named parameters.

log_clear清空串口日志A

清空指定连接(或全部)的日志:内存 + 已落盘文件。清空后不可恢复,谨慎使用。

Inputs: connection_id.

log_query检索串口日志A

检索串口日志条目。日志按行切分(\n / \r\n),每条含全局 seq 索引、epoch 时间戳 ts、方向 dir(rx/tx)、内容 line/hex/bytes。支持按连接、方向、索引范围(seq_from/seq_to)、时间范围(time_from/time_to)、内容子串(contains)、正则(regex)过滤。存储:内存保留最近 N 条,最旧溢出到磁盘(每连接分片 JSONL,超保留上限自动淘汰最旧分片);检索时内存+磁盘都查。返回 entries(含 count/truncated)与 earliest_seq/retention(earliest_seq 之后的历史才完整,淘汰过的更早部分不可回溯)。

Inputs: dir, limit, order, regex, +6 more.

log_stats串口日志统计A

查看日志存储统计:各连接的日志总条数、内存/磁盘分布、分区/淘汰信息、时间范围、目录路径;省略 connection_id 则给出全局汇总。

Inputs: connection_id.

open打开串口A

打开一个串口连接。定位端口三选一:port(路径)/ profile(命名参数)/ sn|vid|pid(按设备标识自动找)。transport=remote 时改用 endpoint(ESP32 无线串口桥,如 tcp://esp32s3-01:7000),不使用 port/sn/vid/pid。baud_rate 默认 115200;data_bits 默认 8;stop_bits 默认 1;parity 默认 none;flow_control 默认 none。newline 设置发送默认追加的换行(write/transact 未显式指定时的默认)。成功后返回 connection_id,后续 read/write/transact 用它。

Inputs: sn, pid, vid, port, +10 more.

profile_delete删除连接 profileC

删除指定命名 profile。

Inputs: name (required).

profile_list列出连接 profileA

列出已保存的串口连接 profile(port/波特率/换行/prompt 等参数),open({profile:name}) 一条复用。

Inputs: no named parameters.

profile_save保存连接 profileB

把常见连接参数存为命名 profile,供 open({profile}) 一条复用。字段与 open 一致:transport/endpoint/port/baud_rate/data_bits/stop_bits/parity/flow_control/rx_buffer_size/newline/prompt/regex/note。

Inputs: name (required), note, port, regex, +10 more.

read读取串口数据A

读取串口已到达的数据。默认立即返回所有未读字节(cat 语义)。wait_ms>0 时等待新数据;min_bytes 指定等待的最少字节数。match + match_encoding 指定匹配串:一旦缓冲里出现匹配即返回(含匹配部分)。返回 text/hex/bytes 及 matched/timed_out。

Inputs: connection_id (required), match, wait_ms, min_bytes, +1 more.

receive统一接收窗口(持续收流量直到结束)A

持续消费全部到达流量,直到命中 match(字节)、达到 max_bytes、静默 idle_timeout_ms、或 budget_ms 耗尽。结束时不丢弃流量——期间所有字节如实带回,由 matched/stopped_reason 说明命中情况;内容判读交给 agent。start=cursor 从当前游标起;start=flush 先清缓冲(干净窗口)再开始;可选 reset 复位(配合 start=flush 抓启动日志)。抓 boot 示例:receive({start:'flush', reset:'dtr', budget_ms:15000})。

Inputs: connection_id (required), match, reset, start, +5 more.

send_break发送 BREAK 信号A

向串口发送 BREAK 信号并释放(保持 duration_ms 后释放)。常用于唤醒/复位只认 BREAK 的设备。duration_ms 默认 300。

Inputs: connection_id (required), duration_ms.

service_infoA

返回服务信息:服务名/版本/端点/(可选)变更摘要(changelog),用于确认部署版本与接入方式。

Inputs: no named parameters.

set_dtr_rts设置 DTR/RTS 控制线A

设置串口 DTR/RTS 调制解调控制线电平。未传的线保持不动。pulse_ms>0 时先设为给定值、保持该时长后自动反转(一次完成"拉低→放高"之类的复位时序,如 Arduino 自动复位)。需要多拍精确时序(如 ESP32 进下载模式)时,可分多次调用本工具逐拍设置。返回最终 dtr/rts 电平。

Inputs: connection_id (required), dtr, rts, pulse_ms.

transact收发交互(写+读)A

写入数据后等待回包,在一步内完成,是 AT/Modbus/GRBL 等请求响应式交互的推荐入口。写后只关心"写之后到达"的字节(忽略此前已缓冲的噪声)。timeout_ms 限时等待;match + match_encoding 指定响应结束标志。返回 text/hex/bytes 及 matched/timed_out。交互终端推荐 newline=crlf + match=提示符,避免把字面换行当命令。

Inputs: data (required), connection_id (required), match, newline, +3 more.

write发送串口数据A

向串口发送数据(只发不收)。data 为字符串,encoding 决定解码方式:utf8(默认,直接按文本)、hex(如 "AF 01")、base64。成功后返回写入字节数。如需"发完等回包"请用 transact。newline 未写时用 open 时的默认。发一行命令建议 newline=crlf,避免把字面换行当命令。

Inputs: data (required), connection_id (required), newline, encoding.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 18 tools

    Disambiguation3/5

    read, receive, dump_to_file, and transact all consume serial data with overlapping parameters (match, max_bytes, timeouts), so an agent must read carefully to choose among them—especially read vs receive. The descriptions do differentiate them (cat semantics vs consume-until-condition vs one-shot request/response vs write-to-file), which keeps it from being worse, but the read-side surface is crowded.

    Naming Consistency4/5

    Almost everything is snake_case and grouped predictably (log_query/log_stats/log_clear, profile_list/profile_save/profile_delete). The main deviation is bare verbs (open, close, read, write, receive, transact) mixed with verb_noun names (list_ports, get_status, send_break), and service_info is noun-first, but the overall pattern remains readable.

    Tool Count4/5

    18 tools is on the heavy side but each maps to a real facet of serial work: connection lifecycle, I/O, profiles, logging, modem control, and file dumping. Nothing feels gratuitously duplicated, though the read-path tools (read/receive/dump_to_file/transact) add some bulk.

    Completeness4/5

    Coverage is strong: port enumeration, open/close, read/write/transact, profile CRUD, log query/stats/clear, DTR/RTS with pulse, BREAK, status, and file dump—no obvious dead ends for the stated scope. Minor gaps like fetching a single profile by name or exporting logs are workarounds an agent can handle via profile_list and log_query.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      Enables 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
      -
    • A
      license
      A
      quality
      D
      maintenance
      Enables AI assistants to communicate with serial port devices, supporting port management, data transmission in text/binary modes, interactive terminal sessions, and automatic reconnection.
      14
      12
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables LLMs to communicate with hardware devices via serial ports. Provides tools for listing ports, opening/closing connections, reading/writing data, and controlling serial signals.
      8
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Allows 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.
      27
      65 PyPI
      27
      MIT