Let Claude Code flash and monitor your ESP32
Claude Code can already write ESP32 firmware. What it usually cannot do is see the board. This MCP server gives it three things for that: find the ESP32 on USB, flash it with esptool, and read the serial console, so you stop pasting boot logs back into the chat.
Last checked against the source code on 2026-09-20.
What you need
- An ESP32, ESP32-S2, ESP32-S3 or ESP32-C3 board connected over USB
- esptool on your PATH:
pip install esptool. The server callsesptool, oresptool.pyon older installs. - The MCP server registered with Claude Code. The quickstart has the exact config.
How the agent finds your ESP32
list_boards reads the operating system's serial port list and matches each port's USB vendor ID and product ID against a fixed table. For the ESP32 family that table holds Espressif's native USB-CDC ID (303a:1001), its USB-JTAG/serial debug unit (303a:0002), the Silicon Labs CP2102 bridge (10c4:ea60), and the WCH CH340 (1a86:7523) and CH9102 (1a86:55d4) bridges. Each match comes back with its port path, for example /dev/cu.usbserial-0001 on macOS or COM5 on Windows.
A CH340 or CP2102 is a generic chip, so a non-ESP32 board built on the same bridge will also be listed as esp32. Tell the agent which board is which if you have more than one plugged in.
Flashing
Ask for it in plain words. The tool call Claude Code makes looks like this:
flash_firmware {
"family": "esp32",
"path": "/dev/cu.usbserial-0001",
"firmwarePath": "/Users/you/blink/build/blink-merged.bin"
}On the server side that becomes esptool --port /dev/cu.usbserial-0001 write-flash 0x0 <file>. The image is written at offset 0x0, so give it a merged image. With ESP-IDF, build as usual and run esptool merge-bin over the bootloader, partition table and app. With the Arduino ESP32 core, use the merged binary produced by Export Compiled Binary. The result is returned whether it worked or not, including esptool's own error text, so the agent can see a wrong port or a board that is not in download mode.
Watching it run
serial_open { "family": "esp32", "path": "/dev/cu.usbserial-0001", "baudRate": 115200 }
serial_read { "family": "esp32", "handle": { ... }, "timeoutMs": 2000 }
serial_write { "family": "esp32", "handle": { ... }, "dataBase64": "aGVsbG8K" }
serial_close { "family": "esp32", "handle": { ... } }Bytes travel base64-encoded in both directions so binary protocols survive intact. A practical loop is to ask Claude Code to flash, open the port, read for a few seconds and then explain the boot log or panic backtrace it sees, before touching the code again.
Driving pins on an ESP32 running MicroPython
If the board runs MicroPython, the agent also gets gpio_mode, gpio_read, gpio_write, adc_read, pwm_write, i2c_scan, i2c_read, i2c_write, spi_transfer and mpy_exec, with no firmware of ours on the board: the server drives MicroPython's raw REPL over the same USB port, the way mpremote does, and board_info tells the agent which runtime it found. As of 2026-09-20 these tools are proven against the real MicroPython interpreter (its WebAssembly build) in a simulator and have not been run on a physical ESP32 by the studio; the quickstart keeps that status current.
What it does not do yet
- It does not run idf.py builds.
compile_sketch(arduino-cli) andbuild_project(PlatformIO) exist, proven against recorded tool output only; an ESP-IDF build still happens in your terminal. - On firmware that is not MicroPython, the pin and bus tools do not apply: everything goes through the serial port, so your firmware decides what a command means.
- It does not write multi-part images at separate offsets; it writes one file at 0x0.
- The server package is not published to npm yet; see the quickstart for the source build.
Frequently asked questions
- Can Claude Code flash my ESP32 by itself?
- Yes, once this MCP server is registered and esptool is installed. The agent calls list_boards to find the port, then flash_firmware with family esp32, that port and the path to a firmware image. The server runs esptool write-flash at offset 0x0 and returns esptool's own output.
- Which ESP32 boards are detected?
- Boards that show up over Espressif's native USB (ESP32-S2, S3 and C3 dev kits) and boards that use a Silicon Labs CP2102 or a WCH CH340 or CH9102 USB-to-serial chip, which covers most ESP32 DevKitC boards and their clones.
- What kind of firmware file does flash_firmware expect for an ESP32?
- A single image that is meant to be written at offset 0x0, which means a merged binary containing bootloader, partition table and app. esptool merge-bin produces one. Handing it an app-only .bin, which belongs at 0x10000, will not boot.
- Can the agent read what my ESP32 prints?
- Yes. serial_open opens the port at the baud rate you give it (115200 by default), serial_read returns the buffered bytes base64-encoded, and serial_write sends bytes back. The agent decodes the output and can react to a boot log, a panic backtrace or your own debug prints.
- Does this replace ESP-IDF or the Arduino core?
- No. The server does not run idf.py. Its compile_sketch tool runs arduino-cli and its build_project tool runs PlatformIO, both proven so far against recorded tool output rather than a real install; for ESP-IDF, Claude Code still runs idf.py in your terminal, and this server gives it a reliable way to put the result on the board and watch it run.