lager CLI.
Connecting an agent
Point any MCP-compatible client at the box:The MCP server is for discovery and planning only — it does not run code or
drive hardware. To execute a test, the agent writes a Python file locally and
runs it 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.What the agent sees
The server exposes two kinds of things: resources (read-only context the agent reads) and tools (callable functions).Resources
| Resource | What it gives the agent |
|---|---|
lager://dut/overview.md | Read this first. A narrative briefing: what the box tests, the DUT MCU/peripherals, subsystems, and which documents to fetch. |
lager://dut/context | The full DUT context as structured JSON. |
lager://bench/identity | Box ID, hostname, version, and a per-DUT summary (purpose, MCU). |
lager://bench/netlist | Every net with type, roles, instrument, and metadata. |
lager://bench/interfaces | Protocol interfaces (SPI, I2C, UART) and their nets. |
lager://guide/overview | What Lager is and what a “net” is. |
lager://guide/workflow | The recommended orient → discover → plan → write → run loop. |
lager://guide/rtt-defmt | The core firmware-log workflow: streaming RTT and decoding defmt. Covers the dbg.session() scope, the reconnect-aware RTT reader and self-healing reset()/read_memory() (so you don’t write flash/reset workarounds), and the DA1469x post-flash reconnect exception. |
lager://reference/{net_type} | The full API reference for one net type as JSON (e.g. lager://reference/Debug) — methods, gotchas, and a runnable example snippet. |
lager://guide/api-quick-reference | Compact lager.Net API cheat sheet by net type. |
lager://guide/docs | Links to the full hosted docs (docs.lagerdata.com) and the llms.txt page index for anything not covered on-box. |
Tools
| Tool | Purpose |
|---|---|
discover_dut() | One call for orientation: DUT purpose, MCU, peripherals, subsystems, and document references. |
discover_bench(net_name?) | Enumerate hardware — nets, plus instruments with their channels, capabilities, and authored specs/ranges. With a net name, return that net’s full metadata, capabilities, parent subsystem, and relevant document references (and, if the net is unknown, the list of available net names). |
cite_schematic(net_name) | Return just the schematic/datasheet references and page hints relevant to one net. |
plan_firmware_test(firmware_description, test_goals) | Generate a phased test plan, scoped to relevant nets, with DUT context and document references attached. |
assess_suitability(test_type) | Check whether the bench can run a given test type. |
get_test_example(query) | Find runnable example scripts by net type, pattern, or keyword. |
box_manage(action) | health check or reload the bench config from disk. |
The tool surface is intentionally read-only. There are no tools that 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.Prompts
The server also registers a few prompts — slash-command-style entry points that steer a client (e.g. Cursor) through the discover → plan → write → run workflow. They don’t do work themselves; each returns an instruction the agent follows using the tools above.| Prompt | What it does |
|---|---|
write_lager_test(what_to_test) | Walks the agent through discovering the bench/DUT, planning, writing a test, and running it over the CLI. |
explore_bench() | Orients on what the box is, what it tests, and what it can run. |
assess_test_feasibility(test_description) | Checks whether the bench has the capabilities for a described test. |
The recommended agent workflow
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.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.Plan
Call
plan_firmware_test(...) to get a phased plan with API references and
document pointers per step.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> registers a friendly alias.)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). One sentence describing what each wire does on the DUT. - DUT context — set with
lager box dut: the box’s purpose, MCU, subsystems, and references to schematics and datasheets.

