6.8 KiB
Velxio MCP Server
Velxio exposes a Model Context Protocol (MCP) server that allows AI agents (e.g. Claude, Cursor) to:
- Create and update circuits using a structured JSON format
- Import and export circuits in the Wokwi
diagram.jsonformat - Generate Arduino code from circuit definitions
- Compile projects and receive structured results (hex/binary, logs)
Tools
| Tool | Description |
|---|---|
compile_project |
Compile Arduino sketch files → Intel HEX / binary |
run_project |
Compile and mark artifact as simulation-ready |
import_wokwi_json |
Parse a Wokwi diagram.json → Velxio circuit |
export_wokwi_json |
Serialise a Velxio circuit → Wokwi diagram.json |
create_circuit |
Create a new circuit definition |
update_circuit |
Merge changes into an existing circuit |
generate_code_files |
Generate starter .ino code from a circuit |
Transport Options
1. stdio (Claude Desktop / CLI agents)
Run the MCP server as a child process:
cd backend
python mcp_server.py
Claude Desktop config (~/.claude/claude_desktop_config.json):
{
"mcpServers": {
"velxio": {
"command": "python",
"args": ["/absolute/path/to/velxio/backend/mcp_server.py"]
}
}
}
2. SSE / HTTP (web agents, Cursor IDE)
Run the MCP SSE server on a separate port (default: 8002):
cd backend
python mcp_sse_server.py --port 8002
MCP client config (SSE transport):
{
"mcpServers": {
"velxio": {
"url": "http://localhost:8002/sse"
}
}
}
Note: The SSE server runs separately from the main FastAPI backend (port 8001) to avoid Starlette version conflicts. Both can run simultaneously.
Setup
-
Install dependencies:
cd backend pip install -r requirements.txt -
Ensure arduino-cli is installed (required for
compile_project/run_project):arduino-cli version arduino-cli core update-index arduino-cli core install arduino:avr
Example Walkthroughs
Example 1 — Blink LED (from scratch)
Step 1 — Create a circuit:
{
"tool": "create_circuit",
"arguments": {
"board_fqbn": "arduino:avr:uno",
"components": [
{ "id": "led1", "type": "wokwi-led", "left": 150, "top": 100, "attrs": { "color": "red" } },
{ "id": "r1", "type": "wokwi-resistor", "left": 150, "top": 180, "attrs": { "value": "220" } }
],
"connections": [
{ "from_part": "uno", "from_pin": "13", "to_part": "led1", "to_pin": "A", "color": "green" },
{ "from_part": "led1", "from_pin": "C", "to_part": "r1", "to_pin": "1", "color": "black" },
{ "from_part": "r1", "from_pin": "2", "to_part": "uno", "to_pin": "GND.1", "color": "black" }
]
}
}
Step 2 — Generate code:
{
"tool": "generate_code_files",
"arguments": {
"circuit": "<result from Step 1>",
"sketch_name": "blink",
"extra_instructions": "Blink the red LED every 500ms"
}
}
Step 3 — Compile the generated code (edit the sketch content as needed):
{
"tool": "compile_project",
"arguments": {
"files": [
{
"name": "blink.ino",
"content": "void setup() { pinMode(13, OUTPUT); }\nvoid loop() { digitalWrite(13, HIGH); delay(500); digitalWrite(13, LOW); delay(500); }"
}
],
"board": "arduino:avr:uno"
}
}
Response:
{
"success": true,
"hex_content": ":100000000C9434000C943E000C943E000C943E...",
"binary_content": null,
"binary_type": null,
"stdout": "",
"stderr": ""
}
Example 2 — Import a Wokwi Circuit
Import:
{
"tool": "import_wokwi_json",
"arguments": {
"diagram_json": "{\"version\":1,\"author\":\"example\",\"editor\":\"wokwi\",\"parts\":[{\"type\":\"wokwi-arduino-uno\",\"id\":\"uno\",\"top\":0,\"left\":0,\"attrs\":{}},{\"type\":\"wokwi-led\",\"id\":\"led1\",\"top\":100,\"left\":200,\"attrs\":{\"color\":\"green\"}}],\"connections\":[[\"uno:13\",\"led1:A\",\"green\",[]]]}"
}
}
Response:
{
"board_fqbn": "arduino:avr:uno",
"components": [
{ "id": "uno", "type": "wokwi-arduino-uno", "left": 0, "top": 0, "rotate": 0, "attrs": {} },
{ "id": "led1", "type": "wokwi-led", "left": 200, "top": 100, "rotate": 0, "attrs": { "color": "green" } }
],
"connections": [
{ "from_part": "uno", "from_pin": "13", "to_part": "led1", "to_pin": "A", "color": "#00ff00" }
],
"version": 1
}
Example 3 — Export to Wokwi Format
{
"tool": "export_wokwi_json",
"arguments": {
"circuit": {
"board_fqbn": "arduino:avr:uno",
"components": [
{ "id": "led1", "type": "wokwi-led", "left": 200, "top": 100, "rotate": 0, "attrs": {} }
],
"connections": [
{ "from_part": "uno", "from_pin": "13", "to_part": "led1", "to_pin": "A", "color": "green" }
],
"version": 1
},
"author": "my-agent"
}
}
Response (Wokwi diagram.json format):
{
"version": 1,
"author": "my-agent",
"editor": "velxio",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
{ "type": "wokwi-led", "id": "led1", "top": 100, "left": 200, "rotate": 0, "attrs": {} }
],
"connections": [
["uno:13", "led1:A", "green", []]
]
}
Circuit Data Format
Velxio circuits are plain JSON objects:
{
"board_fqbn": "arduino:avr:uno",
"version": 1,
"components": [
{
"id": "led1",
"type": "wokwi-led",
"left": 200,
"top": 100,
"rotate": 0,
"attrs": { "color": "red" }
}
],
"connections": [
{
"from_part": "uno",
"from_pin": "13",
"to_part": "led1",
"to_pin": "A",
"color": "green"
}
]
}
Supported Board FQBNs
| Board | FQBN |
|---|---|
| Arduino Uno | arduino:avr:uno |
| Arduino Mega | arduino:avr:mega |
| Arduino Nano | arduino:avr:nano |
| Raspberry Pi Pico | rp2040:rp2040:rpipico |
| ESP32 DevKit | esp32:esp32:esp32 |
Common Component Types (Wokwi element names)
wokwi-led— LED (attrs:color)wokwi-resistor— Resistor (attrs:valuein Ω)wokwi-pushbutton— Push buttonwokwi-buzzer— Passive buzzerwokwi-servo— Servo motorwokwi-lcd1602— 16×2 LCD displaywokwi-neopixel— NeoPixel RGB LED
Sandboxing & Limits
- Compilation runs in a temporary directory cleaned up after each call.
- arduino-cli is invoked as a subprocess with no elevated privileges.
- There is no explicit CPU/memory timeout in the default configuration. For production deployments, set
COMPILATION_TIMEOUT_SECONDSin the environment and enforce it at the process level.
Running Tests
cd backend
pip install pytest pytest-asyncio
python -m pytest tests/test_mcp_tools.py -v