Three tools and two LEDs is the entire scope, and it is written as a teaching project — but it is a complete, working chain from an MCP client to hardware, with the standard Firmata sketch doing the board-side work so nothing has to be flashed twice. The port path in `main.py` is the one place everyone gets stuck; change it before you run anything.
A small, deliberately concrete MCP server: an assistant says "turn on the white LED" and a physical LED on your desk lights up. It talks to the board through pyfirmata2 over the Firmata protocol, so the Arduino runs a stock sketch rather than custom firmware, and the tools are three functions defined with FastMCP.
- The white LED on digital pin 12 switched on — `white_led_ON`
- The red LED on digital pin 11 switched on — `red_led_ON`
- Both switched off — `led_OFF`
- A pattern you can extend: the tools are plain Python functions marked with a decorator, so adding a pin or a behaviour is adding a function
An Arduino board, two LEDs with resistors, jumper wires and a USB cable. Upload the `StandardFirmata` sketch from the Arduino IDE's Firmata examples first — that is what lets Python drive the board. Python 3.12 or higher and `uv`, which installs `fastmcp` and `pyfirmata2` from the project file. The one edit you must make is the serial port in `main.py`: replace the sample device path with the port your board is on, which the Arduino IDE shows under Tools > Port and which looks like `COM3` on Windows or `/dev/ttyUSB0` on Linux.
One command — uvx arduino-mcp
