ai embedded debugging

    AI-Assisted Embedded Debugging: Giving Claude Access to Your Serial Port with MCP

    How to let an AI assistant read your device log and send commands over UART using the Model Context Protocol: what it is good at, what it cannot do, the safety rules, and an open-source serial terminal built for it.

    ·XTELL Engineering Team

    The assistant can read your code, but not what the device says

    Most firmware debugging follows the same loop. Flash a build, reset the board, read what comes out of the UART, form a guess, change the code, flash again. AI coding assistants are now good at the middle of that loop: they can read the source, reason about a stack trace and propose a fix. What they cannot do on their own is see the device. The log lives in a terminal window on your desk, and you copy and paste fragments of it into the chat.

    That copy-and-paste step is where the loop slows down. Logs are long, the interesting line is rarely the last one, and a fault that needs three resets to reproduce is tedious to relay by hand. Giving the assistant direct access to the serial port removes the middleman: it can open the port, reset the target, capture the boot sequence, and read exactly the lines it needs.

    What the Model Context Protocol adds

    The Model Context Protocol (MCP) is an open standard that lets an AI assistant call tools exposed by a separate program. The assistant sees a list of tools with descriptions and parameters, decides when to use them, and receives the results as text. Claude Desktop, Claude Code, Cursor and several other clients support it.

    A serial MCP server turns the port into a handful of tools: list the ports on the machine, connect at a baud rate, send data (text or hexadecimal), read what has been received, and stop. Everything else in this article is about making that small set of tools useful in real embedded work rather than in a demo.

    Why we built a version with a window

    Serial MCP servers already exist, and most of them are headless: the assistant talks to the port and you see nothing. We built our own for our bench work and chose the opposite design. The tool is a full serial terminal with a graphical window, and the MCP server is an extra way to drive the same window.

    That has three practical consequences.

    • You and the assistant look at the same thing. The log scrolls on your screen as the assistant works. If it connects at the wrong baud rate and the output is garbage, you see it immediately instead of reading about it afterwards.
    • You can take over at any moment. Type a command yourself, change the filter, pause the scroll, then hand control back. Nothing is hidden inside a background process.
    • Several devices, several windows. Each window can be named, so a bench with a gateway board and a sensor node on two ports stays readable, and the assistant addresses a port by name.

    What a debugging session looks like

    The following is an illustrative session, not a recorded project. It shows the shape of the interaction.

    You tell the assistant: "The board reboots every few seconds. Connect to COM3 at 115200, capture about 30 seconds, and tell me why." The assistant lists the ports, connects, and reads the received buffer. It sees the boot banner repeat, finds the line before each repeat, and reports that every cycle ends with the same panic message and a backtrace address, preceded by a low-voltage warning from the power manager. It then reads the relevant source files, matches the backtrace to a function, and suggests that the radio is being started before the supply has settled.

    The useful part is not that the assistant guessed right; it may not. The useful part is that capture, triage and cross-referencing with the code happen in one place, in seconds, with the evidence still on your screen for you to check.

    Four things that make the difference in practice

    Filters keep the assistant's context small

    A device that prints thousands of lines will exhaust a model's context long before it reaches the fault. A live filter, by substring or regular expression, lets the assistant read only the lines that matter: errors, one subsystem's tag, a particular transaction. In our tool the filter sees every incoming line even when the window is too busy to draw them all, so an error in a burst is not lost.

    Time ranges turn a log into an investigation

    Each line carries a millisecond timestamp, and the read tools accept a start and an end time. "Show me the five seconds before the reset" is a precise request rather than a scroll through the whole buffer. For intermittent faults this is the difference between a useful capture and a haystack.

    Save to file for evidence

    Long soak tests and rare faults need a record that survives the session. The tool can stream the received data to a file while the assistant works, so the capture can be attached to a ticket or compared with the next run.

    Bursts must not freeze the window

    This one we learned the hard way. Our first version drew every line to the screen as it arrived, and when a device suddenly sent a large burst of dense data the window stopped responding. The fix was to parse for a bounded time on each tick, draw a whole batch in one operation, and keep everything beyond what can be drawn in the buffer and the saved file, with a visible note saying how many lines were not drawn. A debugging tool that locks up at exactly the moment the device misbehaves is worse than no tool. We now test it against synthetic bursts of several megabytes per second.

    What it is good at, and what it is not

    It works well for boot log triage, for checking the exchange with AT-command modules, for confirming that a protocol conversation matches the specification, for reading panic dumps against source, and for long captures where something has to be found rather than watched.

    It does not replace the instruments. A UART log says what the firmware decided to print; it does not show a rail that sags, a signal with a slow edge or a bus held low by a misbehaving peripheral. Those need an oscilloscope, a logic analyser or a debug probe, and the assistant cannot operate them. Treat the assistant as a fast reader of evidence the firmware chose to emit, and keep the hardware tools for hardware problems.

    Safety rules we follow

    • The assistant can send arbitrary bytes. Never connect it to hardware where an unexpected command could cause harm: motor drivers on live power, heaters, anything with a bootloader that accepts an erase command.
    • Start read-only. Let it observe first. Allow sending only once you trust the setup, and keep an eye on the window while it does.
    • Keep secrets out of the log. Device logs sometimes print keys, tokens or credentials. Whatever the assistant reads becomes part of its context.
    • Verify before acting. Treat the assistant's diagnosis as a hypothesis with evidence attached, not a verdict.

    Try it

    The tool is called xtell-serial. It is open source under the Apache 2.0 licence, runs on Windows, and has an English and Chinese interface. The source, the executables and the setup guide are on GitHub.

    To connect it to Claude Code, register the MCP executable once:

    claude mcp add xtell-serial C:\path\to\xtell-serial-mcp.exe

    Claude Desktop, Cursor and other clients take the same executable in their MCP configuration; the repository documents each. Then ask your assistant to connect to a port and read what the board prints.

    Where this fits in our work

    We write firmware, Linux BSPs and drivers, and the hardware underneath them, and a serial console is the first window we open on almost every board. If you are bringing up a new design, chasing an intermittent fault, or need a team that covers the board, the firmware and the cloud side together, see our firmware development service and our guide to embedded software testing.

    Need Professional Services?

    Contact us for customized solutions and quotes