Skip to main content
Glama
embedded-mcp

embedded-mcp

by atillab1

embedded-mcp

Let an AI assistant read, command, and debug your microcontroller — over plain serial.

CI License: MIT Python 3.10+ MCP

embedded-mcp is a Model Context Protocol server. It gives an MCP-capable client (Claude Desktop, Claude Code, …) a small set of tools to talk to a real board over a serial port.

When you debug firmware, your AI pair can now see what the board prints and poke it back — instead of you copy-pasting the serial monitor by hand.

┌─────────────┐      MCP (stdio)      ┌───────────────┐     UART / USB-serial    ┌──────────────┐
│  AI client  │  ◄────────────────►   │  embedded-mcp │  ◄────────────────────►  │  your board  │
│  (Claude)   │                       │   (this repo) │       (pyserial)         │  STM32 / ...  │
└─────────────┘                       └───────────────┘                          └──────────────┘

Why

Embedded debugging is a loop of flash → watch the serial monitor → send a command → read the dump → decode a register against the datasheet. That loop is exactly the kind of tedious, context-heavy work an AI is good at — if you give it eyes and hands on the hardware. This server is those eyes and hands.

Related MCP server: mcp-serial-bridge

Tools

Tool

What it does

list_serial_ports

Discover available ports (COM5, /dev/ttyACM0, …).

read_serial

Passively read what the firmware is printing for N seconds.

send_command

Send a line to the device's UART shell and capture the reply.

decode_register

Turn a raw value (e.g. 0x4002) into named bit-fields.

decode_register_svd

Decode a register by name straight from a vendor CMSIS-SVD file.

list_flashers

Report which flashers are installed (st-flash / probe-rs / openocd).

flash_firmware

Flash a firmware image to the board (dry-run by default).

Install

git clone https://github.com/atillab1/embedded-mcp.git
cd embedded-mcp
pip install -e .

Use with Claude Desktop

Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "embedded-mcp": {
      "command": "embedded-mcp"
    }
  }
}

Restart Claude Desktop. Then just ask:

"List my serial ports, then read whatever COM5 is printing at 115200 for 5 seconds."

"Send status to the board on COM5 and tell me what it replies."

"Register RCC->CR read back as 0x4002. Decode it: bit 0 is HSION, bit 17 is HSEON, bit 25 is PLLRDY."

Example: decode a register

decode_register(value=0x4002, fields=[{"name":"HSION","bit":0},{"name":"HSEON","bit":17}], width=32)

{
  "value": 16386,
  "hex": "0x00004002",
  "binary": "00000000000000000100000000000010",
  "fields": [
    { "name": "HSION", "bits": "[0]",  "value": 0 },
    { "name": "HSEON", "bits": "[17]", "value": 0 }
  ]
}

Try it now (no hardware needed)

The register decoders work entirely offline — give them a quick spin:

python examples/demo.py

Flashing

flash_firmware shells out to a real flasher and is dry-run by default — it returns the exact command it would run, so you can review it before anything touches your board:

"Dry-run flashing build/app.bin to my STM32 with st-flash."

Flip dry_run=False to actually flash. Supported: st-flash (.bin), probe-rs (.elf, needs chip), openocd (.elf, needs openocd_target).

Safety notes

  • Tools open the port only for the duration of the call, then close it — they do not hold the port, so your normal IDE serial monitor can share it (one at a time).

  • Read durations are capped at 30s so a call can never hang the client.

  • flash_firmware is destructive; it defaults to a dry run and never flashes unless you explicitly pass dry_run=False.

  • This talks to whatever board is on the port. Don't point it at something you don't own.

Roadmap

  • Unit tests + GitHub Actions CI

  • Load a register map from an SVD file (decode_register_svd)

  • Flashing hook (flash_firmware via st-flash / probe-rs / openocd)

  • Streaming/continuous monitor (notifications instead of fixed windows)

  • SVD auto-discovery from the connected chip id

Contributions welcome — open an issue or PR.

Development

pip install -e .
pip install pytest
pytest -q

License

MIT © Atilla — see LICENSE.

Available Tools

7 tools
decode_registerA

Decode a raw register value into its named bit-fields.

A constant pain in embedded work: you read a register as 0x4002 and have to mentally line it up against the datasheet bit map. This does it for you.

Args: value: The raw register value (e.g. 0x4002). fields: A list of field descriptors. Each is either: {"name": "EN", "bit": 0} -> single bit {"name": "PRESC", "msb": 5, "lsb": 2} -> bit range [msb:lsb] width: Register width in bits (8, 16, 32...). Used only for display.

Returns the binary view plus each field's extracted value.

Inputs: value (required), fields (required), width. Returns: object

decode_register_svdA

Decode a register by name using a CMSIS-SVD chip description file.

Instead of typing out the bit map by hand (as decode_register needs), point this at the vendor's .svd file and name the peripheral + register. It reads the real bit-fields from the SVD and decodes your value against them.

Example: decode_register_svd(0x4002, "STM32F407.svd", "RCC", "CR")

Args: value: The raw register value you read back. svd_path: Path to a CMSIS-SVD file on this machine. peripheral: Peripheral name as in the SVD, e.g. "RCC". register: Register name as in the SVD, e.g. "CR". width: Register width in bits for display (default 32).

Inputs: value (required), register (required), svd_path (required), peripheral (required), +1 more. Returns: object

flash_firmwareA

Flash a firmware image onto the connected board.

DESTRUCTIVE: this overwrites the flash of whatever board is connected. For safety it defaults to dry_run=True, which only returns the exact command it would run without executing it. Set dry_run=False to actually flash.

Args: firmware_path: Path to the firmware (.bin for st-flash; .elf for probe-rs/openocd). tool: "auto" (pick the first installed) or "st-flash" / "probe-rs" / "openocd". address: Flash address for st-flash (default STM32 0x08000000). chip: Chip name for probe-rs, e.g. "STM32F407VG". openocd_target: OpenOCD target cfg, e.g. "target/stm32f4x.cfg". dry_run: If True (default), return the command instead of running it. timeout_seconds: Max time to wait when actually flashing (capped at 600s).

Inputs: firmware_path (required), chip, tool, address, +3 more. Returns: object

list_flashersA

Report which firmware-flashing tools are installed on this machine.

Call this before flash_firmware to see what's available (st-flash, probe-rs, openocd).

Inputs: no named parameters. Returns: object

list_serial_portsA

List the serial ports currently available on this machine.

Use this first to find out which port your board is on (e.g. "COM5" on Windows, "/dev/ttyACM0" on Linux). The other tools all take a port.

Returns one entry per port with its device name and a human description.

Inputs: no named parameters. Returns: result

read_serialA

Read whatever the device prints on port for seconds, then return it.

This opens the port, listens passively, and gives back everything it saw. Great for "what is my firmware logging right now?".

Args: port: Serial port name, e.g. "COM5" or "/dev/ttyACM0". baudrate: Bits per second. Must match your firmware (default 115200). seconds: How long to listen. Capped at 30s.

Inputs: port (required), seconds, baudrate. Returns: object

send_commandA

Send command to the device and capture its reply.

Writes the command (plus a line ending) to the port, then listens for the response for reply_seconds. Use this to drive a firmware's command shell (CLI over UART) — e.g. send "status" and read what comes back.

Args: port: Serial port name. command: The text to send (line ending added automatically). baudrate: Bits per second (default 115200). reply_seconds: How long to wait for the reply. Capped at 30s. line_ending: Appended to the command. "\n", "\r\n" or "" .

Inputs: port (required), command (required), baudrate, line_ending, +1 more. Returns: object

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.5/5.0

    Scored across 7 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose. Register decoding splits into two tools for different input methods (manual vs SVD), but they are unambiguous in their usage. Other tools cover flashing, serial interaction, and listing, with no overlapping functionalities.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in lowercase snake_case (e.g., decode_register, list_flashers). No mix of styles or vague verbs, making the set predictable and easy to navigate.

    Tool Count5/5

    With 7 tools, the server is well-scoped for embedded development workflows. It covers register decoding, firmware flashing, flasher detection, serial port listing, and serial communication without being overly numerous or sparse.

    Completeness4/5

    The tool set covers core embedded tasks (register decoding, flashing, serial interaction) but misses a few common operations like direct memory read/write or chip reset. These gaps are minor and the surface is largely complete for typical debugging.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to communicate with UART/serial devices, offering tools for port management, data read/write, and protocol handling.
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables AI agents to control serial port devices (modems, instruments, embedded boards) via MCP tools for listing ports, connecting, and sending/receiving commands.
      3
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Serial communication and protocol analysis MCP server that gives AI coding assistants direct access to serial ports for reading, writing, decoding, and capturing embedded device output.
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to communicate with serial devices such as Arduinos, ESP32s, USB-UART adapters, and RS-232 instruments by discovering ports, opening connections, sending commands, reading responses, and controlling reset lines.
      12
      1
      MIT