Skip to main content

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.

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.

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 view env and make sure it boots.

Agentpio_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 29 tools

GroupToolsWhat 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

platformio_mcp-0.1.0.tar.gz (35.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

platformio_mcp-0.1.0-py3-none-any.whl (44.5 kB view details)

Uploaded Python 3

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

Hashes for platformio_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b2b6c2b99f6079de5cb8062265e99df3082c50565c130d3a5f4fd2a6bc89e7cf
MD5 10b6abcd38a8970b184e7774be8e04e0
BLAKE2b-256 8a927f80c8a871d5dad97be9dcd146336ff2e923aec25993214c4f838351476c

See more details on using hashes here.

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

Hashes for platformio_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8a9211be572194bf49e500d2652ec80ccb82385d34379ad1b653c631235cb7c6
MD5 92aff22d1760bf3cb8f13d2addc0de7d
BLAKE2b-256 2ba181827f692c002be93ffe4b5d2804379d11d6daf8081552bfb5116832056f

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page