lager CLI.
Connecting an agent
Point any MCP-compatible client at the box:Out of the box the MCP server is for discovery and planning only — it does
not run code or drive hardware. Two opt-in environment variables extend it past
that; see Optional tool gates. To execute a test, the
agent writes a Python file locally. It then runs the file with
lager python path/to/test.py --box <box-ip>, which syncs the project to the box
and runs it with full project context. Pass the box’s IP
address to --box — the same IP you connected to the MCP server on. Local box
names are just client-side aliases, so the IP is the only identifier both sides
can rely on. To make this concrete, discover_bench() echoes the address you
actually connected on as box_address and hands back a ready-to-run
lager python … --box <that-address> command.The URL above assumes a box that publishes its ports, which is the default. A box
started with
start_box.sh --no-publish (or LAGER_NO_PUBLISH=1) does not publish
port 8100 on the host. The MCP server still runs and binds 0.0.0.0:8100 inside
the container. It is reachable only on the internal lagernet Docker network,
where a reverse proxy owns the host ports. On such a box, point the client at the
container’s lagernet address, because <box-ip>:8100 will not connect. Do not
route port 8100 through the proxy, because the MCP server performs no
authentication.The mode persists across restarts in /etc/lager/no_publish, and
start_box.sh --publish clears it. At the end of each run, start_box.sh
reports which mode the box is in.What the agent sees
The server exposes two kinds of things: resources (read-only context the agent reads) and tools (callable functions).Resources
Tools
By default the tool surface is read-only. The seven tools above do not drive
hardware (set a voltage, toggle a GPIO, flash firmware) or mutate the box. All of
that lives in the test script the agent writes and runs with
lager python, or in
dedicated CLI commands.This default holds only while both gates below are off.Optional tool gates
Two environment variables, both off unless explicitly set, register additional tools when the box’s MCP server starts. Each widens what a connected agent can do to the box, so treat them as deployment decisions rather than conveniences.LAGER_MCP_ALLOW_CONTROL
Adds three scoped tools. These read bench state and power-cycle a hub port — they
do not execute arbitrary code.
LAGER_MCP_ALLOW_EXEC
Prompts
The server also registers a few prompts. These are slash-command-style entry points that steer a client (e.g. Cursor) through the discover → plan → write → run workflow. They do no work themselves. Each returns an instruction that the agent follows with the tools above.The recommended agent workflow
1
Orient
Read
lager://dut/overview.md (or call discover_dut()) to learn what the
box tests, the MCU and peripherals, the subsystems, and which documents to
fetch.2
Discover
Call
discover_bench() to enumerate nets, instruments, and capabilities.
Call discover_bench(net_name) for detail on a specific net, including its
subsystem and the schematic sheet it lives on.3
Plan
Call
plan_firmware_test(...) to get a phased plan with API references and
document pointers per step.4
Write & Run
Author a Python test file using
from lager import Net, NetType. Identify
the box by the IP address you connected to the MCP server on — local box
names are arbitrary client-side aliases. --box accepts a raw IP, so no
registration is needed: run lager python path/to/test.py --box <box-ip>.
The runnable can also be a folder (entrypoint main.py), which syncs
and imports everything in it — handy for shipping reusable helper modules:
lager python path/to/test_dir --box <box-ip>. (Optionally,
lager boxes add --name <name> --ip <box-ip> --user <ssh-user> registers a
friendly alias; all three options are required.)5
Analyse & iterate
Review the CLI output, adjust the script, and re-run it with
lager python.Where context comes from
The quality of everything above depends on the metadata you author once, at bench setup:- Per-net
purpose— set in the Net Manager TUI (lager nets tui), or withlager nets describe NAME --purpose "...". One sentence describing what each wire does on the DUT. - DUT context — set with
lager dut: the box’s purpose, MCU, subsystems, and references to schematics and datasheets.

