PlatformIO for AI agents: build, flash, serial monitor, tests, crash decoding, size reports.
PlatformIO for AI agents MCP server that supports build, flash, and serial monitoring workflows, along with running tests and performing crash decoding and size reporting. The server is associated with topics including ai-agents, claude-code, embedded, esp32, mcp, and platformio.
๐ ๏ธ Key Features
Build
Flash
Serial monitor
Tests
Crash decoding
Size reports
๐ Use Cases
Integrate PlatformIO build and flash steps into AI agent workflows
Monitor serial output during embedded development
Diagnose failures via crash decoding
Report or review firmware size
โก Developer Benefits
Centralizes PlatformIO-related tasks for MCP-based tooling
Supports embedded and ESP32-focused workflows
โ ๏ธ Limitations
Available server fields do not specify transport, authentication, supported targets beyond the provided topics, or detailed tool interfaces.
Give your AI coding agent hands on real hardware.
An MCP server for PlatformIO: build, flash (serial or OTA), watch serial, run tests, decode crashes and core dumps, check partition tables, watch heap and power, debug over GDB, shrink firmware.
Tools
Python native ยท no Node ยท one line to install ยท works with Claude Code, Claude Desktop, Cursor, Codex, Windsurf, Cline
โก 60-second install
You need uv (curl -LsSf https://astral.sh/uv/install.sh | sh). Then:
bash
uvx platformio.mcp install --claude-code # or --cursor --claude-desktop --codex --windsurf
No PlatformIO on this machine? Add --with-platformio and the server brings PlatformIO Core along. Optional extras: platformio.mcp[coredump] adds the ESP32 core-dump analyzer, platformio.mcp[power] adds the Nordic PPK2 driver.
Use "args": ["platformio.mcp[platformio]"] to bundle PlatformIO Core.
As a plugin (Claude Code, Cursor: server + a skill that teaches the loop)
The repo follows the Open Plugins layout: .mcp.json, skills/platformio/SKILL.md, rules/platformio.mdc, plugin.json.
bash
claude plugin marketplace add powerdragonfire/platformio.mcp # Claude Code
claude plugin install platformio@platformio.mcp
Already have PlatformIO?
The server finds platformio / pio on your PATH or in ~/.platformio/penv. Override with PLATFORMIO_MCP_PIO=/path/to/pio. Run uvx platformio.mcp doctor to see what the agent will see.
Agent: null pointer on line 22 of display_task.cpp, tft_ is used before begin(). Fixing, rebuilding, flashing again.
code
PASS: flashed env view in 14.2s and saw 'setup done' on /dev/cu.usbserial-0001 after 2.1s of boot output.
No 40 KB build logs in the context window. No human reading the serial monitor. The agent gets a verdict, a file and a line.
๐ The loop the agent runs
flowchart LR
A[pio_project_envs] --> B[edit code]
B --> C[pio_build]
C -- errors with file:line --> B
C -- ok --> D[pio_flash_and_verify]
D -- PASS --> E([done])
D -- FAIL: decoded backtrace --> B
D -- TIMEOUT --> F[pio_monitor_capture]
F --> B
Status, parsed errors and warnings (file, line, column), RAM/Flash %, last 40 lines, full log path. Extra targets like buildfs, erase. OTA over Wi-Fi to ArduinoOTA boards. Port failures come back classified (busy, permission, missing, no response) with the fix
Background sessions with a ring buffer, cursor reads, and wait_for regex; or a one-shot capture with nothing to manage. Port diagnosis: who holds it (our session, another process), permissions, the fix
โ Verify
pio_test ยท pio_check
Unity tests with per-case pass/fail and messages; cppcheck / clang-tidy defects by severity with CWE ids
Registry search and dependency changes that keep platformio.ini in sync; an audit for name collisions, unpinned specs, leftovers, and circular dependencies
Hardware-in-the-loop pass/fail; crash dumps resolved to file:line; where every byte of flash and RAM goes
๐พ Flash layout
pio_partition_table ยท pio_coredump
ESP32 partition CSV checks (alignment, overlap, fit, OTA slots) and a diff against the table actually on the chip; core dump pulled from flash and decoded
๐ Runtime
pio_memory_watch ยท pio_power_profile
Heap and stack telemetry parsed from serial with a leak verdict and per-task headroom; current draw from a serial meter or a Nordic PPK2 with sleep/active split and battery estimate
๐ Debug
pio_debug_start / cmd / stop / list
A live GDB session over pio debug: breakpoints, step, backtrace, variables, with MI records parsed into structured results
Every tool returns ok, a one-paragraph summary written for the model, structured fields, and a log_path to the full output. Long output stays on disk under ~/.platformio-mcp/logs (newest 200 files kept).
The tools that go beyond the CLI
What it does
Under the hood
๐ pio_flash_and_verify
Flash, open the port, read until expect matches (pass), a crash signature matches (fail, auto-decoded), or the timeout passes (timeout)
pio run -t upload + pyserial; fail_on defaults to Guru Meditation, HardFault, abort(), assert failed, watchdog, brownout, heap corruption
๐ฉบ pio_decode_backtrace
Turn an ESP32 Backtrace: 0x400d... dump or a Cortex-M pc/lr dump into function, file, line, inlined frames, cause, reset reason
Toolchain located from pio project metadata, then <target>-addr2line -pfiaC on firmware.elf; fixes Xtensa A0 window bits
๐ pio_size_report
Why is the firmware this big? Flash/RAM %, loaded sections, biggest symbols with file:line, per-file totals, regex filter
pio run -t checkprogsize (partition-aware) + GNU size -A + nm -S -C -l --size-sort
๐พ pio_partition_table
Catch the silent ESP32 corruption where an app-only flash leaves an old partition table on the chip; alignment, overlap, OTA slot, and app-fit checks
Parses the env's partition CSV; read_device=true reads 0x8000 with esptool read_flash and diffs
๐งฏ pio_coredump
Pull the core dump from the coredump partition after a crash and decode task, registers, and backtrace
Average/min/max/p95 current, sleep vs active split, energy, battery-life estimate
A serial meter (INA219 sketch, USB meter log) or a Nordic PPK2 (platformio.mcp[power])
๐ pio_debug_*
Breakpoints, step, backtrace, and variable inspection through the debug probe
pio debug --interface=gdb driven over GDB/MI with parsed *stopped events
๐ pio_upload_ota
Flash over Wi-Fi with failures mapped to the fix (wrong password, no ArduinoOTA.handle(), firewall, no OTA slot)
pio run -t upload --upload-port <ip> (espota auto-switch) or espota.py directly
๐ pio_port_diagnose
Why the upload cannot open the port: our session, another process, permissions, or a board not in bootloader mode
lsof/fuser + pio device list; never kills anything
๐ pio_deps_check
Library name collisions where lib_deps order silently picks the winner, unpinned specs, leftovers, cycles
Manifests in .pio/libdeps and lib/, plus the LDF dependency graph with build=true
๐ Safety policy
Set PLATFORMIO_MCP_POLICY in the server's env, or pass --policy to install:
Policy
Can build
Can flash / erase / write serial
Use it for
full (default)
โ
โ
Your own bench
build_only
โ
โ
Shared labs, CI, "look but don't touch"
read_only
โ
โ
Code review, onboarding, untrusted prompts
MCP clients also prompt before each tool call. Policies are the second layer, not the only one.
โ๏ธ Settings
Variable
Purpose
Default
PLATFORMIO_MCP_POLICY
full, build_only, read_only
full
PLATFORMIO_MCP_PROJECT_DIR
Project used when a tool is called without project_dir
server's cwd
PLATFORMIO_MCP_PIO
Explicit path to the pio executable
auto-detect
PLATFORMIO_MCP_LOG_DIR
Where full command logs go
~/.platformio-mcp/logs
PLATFORMIO_MCP_MAX_LOGS
How many log files to keep
200
๐ Serial monitor notes
Sessions talk to the port with pyserial directly, because PlatformIO's own monitor needs an interactive terminal. PlatformIO monitor filters such as esp32_exception_decoder therefore do not apply; pio_decode_backtrace does that job. Baud and port default from monitor_speed / monitor_port in platformio.ini when project_dir is passed, otherwise the single detected dev board at 115200. Opening the port resets most dev boards, which is why pio_flash_and_verify sees the boot log from the top.
๐ ๏ธ Development
bash
git clone https://github.com/powerdragonfire/platformio.mcp && cd platformio.mcp
uv sync
uv run pytest # unit tests, no hardware or network
uv run pytest -m integration # builds the bundled native fixture with your PlatformIO
uv run platformio-mcp doctor # what the agent's pio_system_info sees
npx @modelcontextprotocol/inspector uv run platformio-mcp # poke tools interactively
To use your checkout in Claude Code instead of the PyPI release:
bash
claude mcp add platformio -- uv run --directory /path/to/platformio.mcp platformio-mcp
Bug reports from real boards are the most useful thing you can send. Use the issue forms, ask questions in Discussions, and read CONTRIBUTING.md before opening a PR. Issues tagged good first issue are scoped for newcomers.
๐ญ Prior art
jl-codes/platformio-mcp is a TypeScript server with the same goal, a web dashboard, and a GPIO pin audit. This project exists for people who want a Python-only install through uvx, one that can bundle PlatformIO itself, and crash decoding, size budgeting, partition checks, core dumps, OTA, live GDB, and memory/power profiling built in.
License
MIT
Install
Configuration
Environment variables
PLATFORMIO_MCP_POLICYdefault full
full (default), build_only, or read_only
PLATFORMIO_MCP_PROJECT_DIR
Default project directory when a tool is called without project_dir
PLATFORMIO_MCP_PIO
Explicit path to the pio executable (auto-detected otherwise)