GDB/SWD MCP server over a smolmux broker: breakpoints, memory, Cortex-M fault decode, board probing.
Runs on your machine from its package; the steps are below.

Not assessed yet.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally
This server runs on your machine over stdio, but its source registry didn't list a distribution package. Check the source repository for setup instructions.
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.

One broker holds an ESP32-S3's UART. The monitor (top) watches it live. In the
bottom pane a script sends temp and gets the reply on the same wire, resets
the board and waits for its prompt, then esptool reads the flash ID through
with-port: the broker suspends, esptool runs, the broker resumes, and the
monitor never loses the port.
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.
0600 under your private
state directory, and smolmux refuses to write it through a symlink or to a
file owned by another user)--auth-token, the broker generates a token into a
0600 file in $XDG_RUNTIME_DIR (or /tmp), so other local users and processes
cannot connect; your own smolmux-monitor / smolmux-mcp read it
automatically, and smolmux-cli token prints 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-auth turns both protections off.smolmux-mcp / smolmux-gdb-mcp attach to a running broker; optional in-process --mcp sink for single-process stdiobootdelay=0 U-BootPrerequisites: Linux, a C11 compiler, CMake 3.21+, Python 3 with
kconfiglib (the configure step
generates the feature header with it). libpcre2-8 is optional; without it
regex matching falls back to POSIX.
# Debian/Ubuntu
sudo apt install build-essential cmake python3 python3-pip libpcre2-dev
pip install kconfiglib # or in a venv; Debian's system Python may need
# --break-system-packages
cmake -B build && cmake --build build -j$(nproc)
./build/smolmux /dev/ttyUSB0
Connect a client:
# Needs a running broker (above). Auto-discovers the socket from the port name.
./build/smolmux-monitor /dev/ttyUSB0
Day-to-day workflows (profiles, logs, U-Boot break-in, multi-wire boards): docs/daily-driver.md. Intent router: docs/START-HERE.md.
cmake -B build && cmake --build build -j$(nproc) # Default (all features)
ctest --test-dir build # Run tests
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=OFF
Developer benchmarks (e.g. the output coalescer harness) are off by default:
cmake -B build -DSM_BUILD_BENCH=ON && cmake --build build --target bench_coalesce
Interactive configuration:
cmake --build build --target menuconfig
cmake -B build -DSM_MUSL_STATIC=ON # Fully static musl binary (zero runtime deps)
cmake -B build -DSM_STATIC=ON # Static linking (except glibc)
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 help
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}
┌───────────┐ ┌───────────┐
│ 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.
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.
with-port <cmd> suspends the port, runs an external tool like a flasher, then always resumes)-e, e.g. -e esc or -e ^A)serial_send_command, serial_read, serial_boot_status, serial_add_autoresponder, ...). Alternative: broker --mcp sink embeds MCP in-process.--gdb link - 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 include
smolmux-gdb://board-probing and probe_unknown_board. Built when
SM_ENABLE_GDB is on; chip-ID validated on a SAM C21 Xplained Pro.smolmux-mcp / smolmux-gdb-mcp with Claude Code, Claude Desktop, or Cursor./dev/serial/rpi-console etc.).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.
MIT. cJSON is vendored under its own MIT license
(deps/cJSON/LICENSE).