embeddedCI documentation

BenchPod MCP server

embeddedci-mcp is an MCP server that exposes the BenchPod SDK as tools, so an AI agent can drive a real hardware-in-the-loop bench: power a target board, flash it over SWD, capture its UART, and emulate or decode an I2C sensor. It's a thin consumer of the SDK — every tool maps directly to a BenchPod method.

Install

pip install embeddedci-mcp        # pulls the embeddedci SDK from PyPI

# or run it without installing, straight from PyPI:
uvx embeddedci-mcp --help

uvx (from uv) downloads and runs the server in one step without a permanent install — which is what the client config below uses.

Run

# stdio — the usual case, launched by an MCP client as a subprocess:
embeddedci-mcp --transport stdio

# streamable HTTP — for a remote bench:
embeddedci-mcp --transport http --host 0.0.0.0 --port 8000

# preset a default connection so the connect tool needs no argument:
embeddedci-mcp --connection /dev/tty.usbserial-0001
embeddedci-mcp --connection 192.168.1.213        # wifi/TCP, default port 8080

The connection can also come from the BENCHPOD_CONNECTION environment variable.

Client configuration

Claude Desktop / Cursor

Add the server to claude_desktop_config.json (Claude Desktop) or mcp.json (Cursor):

{
  "mcpServers": {
    "benchpod": {
      "command": "uvx",
      "args": ["embeddedci-mcp"],
      "env": { "BENCHPOD_CONNECTION": "192.168.1.213" }
    }
  }
}

Use "command": "embeddedci-mcp" instead if it's installed on your PATH.

Claude Code

claude mcp add benchpod -- uvx embeddedci-mcp

Tools

GroupTools
Lifecycle / statusconnect, disconnect, ping, status
Powerpower_on, power_off, target_power, target_status
Flashflash
UARTcapture_uart, power_cycle_and_capture
I2C sensorenable_i2c_sensor, set_i2c_sensor, disable_i2c_sensor, i2c_sensor_status, i2c_sensor_regs, i2c_sensor_la_decoded, i2c_read_register
Pull-upsenable_pullup, disable_pullup, pullup_status
Low-levelcommand, gpio_set, capture_adc, signal_generate, measure

Device/firmware failures come back as {"ok": false, "error": ..., "error_type": ...} rather than raising, so the agent can reason about them. Two resources are also exposed: benchpod://wiring (the default channel → DUT pin map) and benchpod://help (the canonical HIL workflow order).

Example agent flow

1. connect("192.168.1.213")
2. flash(swclk=11, swdio=12, nreset=3, target="target/stm32f4x.cfg",
         file="app.elf", target_power=1)
3. enable_pullup([1, 2]); enable_i2c_sensor(sda=2, scl=1,
         temperature_c=22.5, pressure_pa=101000)
4. power_cycle_and_capture(rx=5, tx=4, delay=1.5, duration=6.0, until_regex="APP_OK")
5. i2c_read_register(address=0x76, register=0xD0)   # confirm the DUT probed the sensor