platformio.mcp
Give your AI coding agent hands on real hardware.
An MCP server for PlatformIO: build, flash, watch serial, run tests, decode crashes, shrink firmware.
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:
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.
Any other MCP client (Cline, Zed, Continue, ...)
uvx platformio.mcp install --print
{ "mcpServers": { "platformio": { "command": "uvx", "args": ["platformio.mcp"] } } }
Use "args": ["platformio.mcp[platformio]"] to bundle PlatformIO Core.
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.
🎬 What it looks like
You: flash the
viewenv and make sure it boots.Agent →
pio_flash_and_verify(env="view", expect="setup done")FAIL: firmware flashed but the boot log matched the failure pattern: 'Guru Meditation Error: Core 1 panic'ed (LoadProhibited)'. Cause: LoadProhibited. 3/3 addresses resolved: DisplayTask::run() (display_task.cpp:22) <- DisplayTask::run() (display_task.cpp:23) <- vPortTaskWrapper (port.c:143)Agent: null pointer on line 22 of
display_task.cpp,tft_is used beforebegin(). Fixing, rebuilding, flashing again.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
🧰 The 29 tools
| Group | Tools | What the agent gets back |
|---|---|---|
| 🔍 Discover | pio_system_info · pio_list_boards · pio_board_info · pio_list_devices |
PlatformIO version and policy; ~1,700 boards with MCU, clock, RAM and flash sizes; serial ports with the likely dev boards flagged |
| 📁 Project | pio_project_init · pio_project_envs · pio_project_metadata |
A real pio project init (never a hand-written ini); every env with board, framework, monitor and upload settings; defines and include paths |
| 🔨 Build & flash | pio_build · pio_upload · pio_clean · pio_list_targets · pio_run_target |
Status, parsed errors and warnings (file, line, column), RAM/Flash %, last 40 lines, full log path. Extra targets like buildfs, erase |
| 📟 Serial | pio_monitor_start / read / write / stop / list · pio_monitor_capture |
Background sessions with a ring buffer, cursor reads, and wait_for regex; or a one-shot capture with nothing to manage |
| ✅ Verify | pio_test · pio_check |
Unity tests with per-case pass/fail and messages; cppcheck / clang-tidy defects by severity with CWE ids |
| 📦 Packages | pio_pkg_search / install / uninstall / list / outdated / update |
Registry search and dependency changes that keep platformio.ini in sync |
| 🧠 Analyse | pio_flash_and_verify · pio_decode_backtrace · pio_size_report |
Hardware-in-the-loop pass/fail; crash dumps resolved to file:line; where every byte of flash and RAM goes |
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 three 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 |
🔒 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
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:
claude mcp add platformio -- uv run --directory /path/to/platformio.mcp platformio-mcp
Changes are tracked in CHANGELOG.md.
🤝 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 and size budgeting built in.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file platformio_mcp-0.1.0.tar.gz.
File metadata
- Download URL: platformio_mcp-0.1.0.tar.gz
- Upload date:
- Size: 35.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2b6c2b99f6079de5cb8062265e99df3082c50565c130d3a5f4fd2a6bc89e7cf
|
|
| MD5 |
10b6abcd38a8970b184e7774be8e04e0
|
|
| BLAKE2b-256 |
8a927f80c8a871d5dad97be9dcd146336ff2e923aec25993214c4f838351476c
|
File details
Details for the file platformio_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: platformio_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 44.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a9211be572194bf49e500d2652ec80ccb82385d34379ad1b653c631235cb7c6
|
|
| MD5 |
92aff22d1760bf3cb8f13d2addc0de7d
|
|
| BLAKE2b-256 |
2ba181827f692c002be93ffe4b5d2804379d11d6daf8081552bfb5116832056f
|