Give Codex a clean, guarded control surface for CircuitPython boards.
This project is a starter MCP server for controlled access to CircuitPython boards across Windows, Linux, and macOS. It is built for the common edit-deploy-reset loop: inspect the board, update files, read serial output, and recover quickly when code needs to be interrupted.
| Capability | What Codex can do |
|---|---|
| Board discovery | Find mounted CIRCUITPY drives and matching serial ports. |
| Safe file access | Read, list, and write files without escaping the board root. |
| Fast deploys | Replace code.py or deploy a specific support file. |
| Serial control | Read serial output, interrupt running code, and soft-reset the board. |
| Cross-platform shape | Keep the same MCP tools while swapping OS-specific discovery adapters. |
The shared project chat was available only as a title and generic metadata; the conversation body was not exposed by the public page. This repo therefore starts from the implied board-control goal and keeps the scope narrow until the missing details are pasted or otherwise made available.
Clone the repo, enter the project folder, and install dependencies:
git clone https://github.com/neusse/Codex-Circuitpython-MCP.git
cd Codex-Circuitpython-MCP
uv syncOn macOS or Linux, the same commands work in a shell with git and uv installed:
git clone https://github.com/neusse/Codex-Circuitpython-MCP.git
cd Codex-Circuitpython-MCP
uv syncRegister this server with Codex as a local stdio MCP server. Run the command from the repo root after uv sync.
Windows PowerShell:
codex mcp add circuitpython-pico -- uv --directory "$PWD" run circuitpython-mcpmacOS or Linux:
codex mcp add circuitpython-pico -- uv --directory "$(pwd)" run circuitpython-mcpVerify the Codex MCP entry:
codex mcp list
codex mcp get circuitpython-picoRestart Codex or start a new Codex session after adding the server. The tools should appear as pico_status, pico_deploy_code, pico_deploy_file, pico_reset, pico_serial_read, pico_serial_interrupt, pico_list_files, and pico_read_file.
Only one process can own the board serial port at a time. Close other serial monitors before using serial tools such as pico_reset or pico_serial_read.
Run tests:
uv run pytestRun the MCP server over stdio:
uv run circuitpython-mcpFor development with the MCP Inspector:
uv run mcp dev src/circuitpython_mcp/server.pyThis is one MCP server with platform-specific board discovery adapters under src/circuitpython_mcp/platforms.
| Platform | Drive discovery | Serial discovery |
|---|---|---|
| Windows | Drive labels such as G:\ with label CIRCUITPY |
pyserial, usually COM* |
| Linux | Mounts under /media/$USER, /run/media/$USER, or /mnt named CIRCUITPY |
pyserial, usually /dev/ttyACM* or /dev/ttyUSB* |
| macOS | Mounts under /Volumes/CIRCUITPY |
pyserial, usually /dev/cu.usbmodem* |
The MCP tool names stay the same on every platform. Only drive and serial discovery change underneath.
Quick inventory:
| Tool | Short description |
|---|---|
pico_status |
Show detected board drives, serial ports, and board boot information. |
pico_deploy_code |
Replace code.py on the CircuitPython drive. |
pico_deploy_file |
Write a named UTF-8 file to the CircuitPython drive. |
pico_reset |
Soft-reset the board over serial with Ctrl-C/Ctrl-D. |
pico_serial_read |
Read serial output for a short time window. |
pico_serial_interrupt |
Send Ctrl-C to stop the running board program. |
pico_list_files |
List files and directories on the CircuitPython drive. |
pico_read_file |
Read a UTF-8 file from the CircuitPython drive. |
list_circuitpython_drives |
Compatibility alias to list mounted CIRCUITPY drives. |
list_serial_ports |
Compatibility alias to list local serial ports. |
read_board_file |
Compatibility alias to read a board file by explicit root. |
write_board_file |
Compatibility alias to write a board file by explicit root. |
These are the Pico-focused tools expected from the original project direction:
pico_status
Returns detected CIRCUITPY drives, serial ports, and boot_out.txt content when exactly one board drive is present.
pico_deploy_code(content, root=None)
Writes text to code.py on the CircuitPython drive. If root is omitted, the server uses the only detected CIRCUITPY drive.
pico_deploy_file(path, content, root=None)
Writes a UTF-8 text file to the CircuitPython drive. The path is confined to the board root.
pico_reset(port=None, read_seconds=2.0)
Soft-resets the CircuitPython board over serial by sending Ctrl-C, Ctrl-C, then Ctrl-D. If port is omitted, the server uses the only detected serial port.
pico_serial_read(port=None, duration_seconds=1.0)
Reads serial output for the requested duration.
pico_serial_interrupt(port=None, read_seconds=1.0)
Sends Ctrl-C to interrupt the running CircuitPython program and returns any serial output captured afterward.
pico_list_files(root=None, path=".", recursive=False)
Lists files and directories on the CircuitPython drive. The path is confined to the board root.
pico_read_file(path, root=None)
Reads a UTF-8 text file from the CircuitPython drive. The path is confined to the board root.
Compatibility aliases are also exposed:
list_circuitpython_drives
Returns mounted volumes that look like CircuitPython devices. Windows checks drive labels, Linux checks common removable-media mount locations, and macOS checks /Volumes/CIRCUITPY.
list_serial_ports
Returns serial ports reported by pyserial, including description, hardware id, vendor id, product id, manufacturer, product, serial number, and location when available.
read_board_file(root, path)
Reads a UTF-8 text file from a discovered board root. The path is confined to the board root and cannot escape with .. or an absolute path.
write_board_file(root, path, content)
Writes UTF-8 text to a board file, creating parent directories as needed. It uses the same root confinement as reads.
The file tools reject paths that resolve outside the board root. This keeps the server from becoming a general local filesystem tool. Serial tools are limited to read, interrupt, and soft reset; there is not yet a general arbitrary REPL execution tool.
- confirm the exact workflow from the original chat
- decide whether this should stay focused on board files and serial control or grow additional workflow integrations
- decide whether to add a guarded REPL command tool
- add install notes for Codex MCP configuration once the server surface is stable