PlatformIO MCP

Herhangi bir PlatformIO kartı (ESP32, Arduino, STM32, RP2040) için gömülü firmware derleyin, yükleyin ve hata ayıklayın: ayrıştırılmış derleyici hataları, seri önyükleme günlüğüne karşı yükleme sonrası doğrulama, dosya:satır düzeyinde çökme geri izi çözümleme, firmware boyut raporları, birim testleri, statik analiz. Python, uvx, Node yok.

Dokümantasyon

platformio.mcp

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.

CI PyPI Python 3.12+ Tools MIT

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. Optional extras: platformio.mcp[coredump] adds the ESP32 core-dump analyzer, platformio.mcp[power] adds the Nordic PPK2 driver.

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.

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.

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.

🎬 What it looks like

You: flash the view env 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 before begin(). 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 40 tools

GroupToolsWhat the agent gets back
🔍 Discoverpio_system_info · pio_list_boards · pio_board_info · pio_list_devicesPlatformIO version and policy; ~1,700 boards with MCU, clock, RAM and flash sizes; serial ports with the likely dev boards flagged
📁 Projectpio_project_init · pio_project_envs · pio_project_metadataA real pio project init (never a hand-written ini); every env with board, framework, monitor and upload settings; defines and include paths
🔨 Build & flashpio_build · pio_upload · pio_upload_ota · pio_clean · pio_list_targets · pio_run_targetStatus, 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
📟 Serialpio_monitor_start / read / write / stop / list · pio_monitor_capture · pio_port_diagnoseBackground 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
✅ Verifypio_test · pio_checkUnity tests with per-case pass/fail and messages; cppcheck / clang-tidy defects by severity with CWE ids
📦 Packagespio_pkg_search / install / uninstall / list / outdated / update · pio_deps_checkRegistry search and dependency changes that keep platformio.ini in sync; an audit for name collisions, unpinned specs, leftovers, and circular dependencies
🧠 Analysepio_flash_and_verify · pio_decode_backtrace · pio_size_reportHardware-in-the-loop pass/fail; crash dumps resolved to file:line; where every byte of flash and RAM goes
💾 Flash layoutpio_partition_table · pio_coredumpESP32 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
📈 Runtimepio_memory_watch · pio_power_profileHeap 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
🐞 Debugpio_debug_start / cmd / stop / listA 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 doesUnder the hood
🚀 pio_flash_and_verifyFlash, 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_backtraceTurn an ESP32 Backtrace: 0x400d... dump or a Cortex-M pc/lr dump into function, file, line, inlined frames, cause, reset reasonToolchain located from pio project metadata, then <target>-addr2line -pfiaC on firmware.elf; fixes Xtensa A0 window bits
📊 pio_size_reportWhy is the firmware this big? Flash/RAM %, loaded sections, biggest symbols with file:line, per-file totals, regex filterpio run -t checkprogsize (partition-aware) + GNU size -A + nm -S -C -l --size-sort
💾 pio_partition_tableCatch the silent ESP32 corruption where an app-only flash leaves an old partition table on the chip; alignment, overlap, OTA slot, and app-fit checksParses the env's partition CSV; read_device=true reads 0x8000 with esptool read_flash and diffs
🧯 pio_coredumpPull the core dump from the coredump partition after a crash and decode task, registers, and backtraceesptool read_flash + optional esp-coredump info_corefile (platformio.mcp[coredump])
📈 pio_memory_watchLeak, fragmentation, and stack-headroom verdicts from what the firmware already printsParses Free heap:, heap_caps_print_heap_info, vTaskList, uxTaskGetStackHighWaterMark lines; least-squares slope
🔋 pio_power_profileAverage/min/max/p95 current, sleep vs active split, energy, battery-life estimateA 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 probepio debug --interface=gdb driven over GDB/MI with parsed *stopped events
🌐 pio_upload_otaFlash 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_diagnoseWhy the upload cannot open the port: our session, another process, permissions, or a board not in bootloader modelsof/fuser + pio device list; never kills anything
📚 pio_deps_checkLibrary name collisions where lib_deps order silently picks the winner, unpinned specs, leftovers, cyclesManifests 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:

PolicyCan buildCan flash / erase / write serialUse 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

VariablePurposeDefault
PLATFORMIO_MCP_POLICYfull, build_only, read_onlyfull
PLATFORMIO_MCP_PROJECT_DIRProject used when a tool is called without project_dirserver's cwd
PLATFORMIO_MCP_PIOExplicit path to the pio executableauto-detect
PLATFORMIO_MCP_LOG_DIRWhere full command logs go~/.platformio-mcp/logs
PLATFORMIO_MCP_MAX_LOGSHow many log files to keep200

📝 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.

🤝 Contributing

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