Skip to main content
Every Lager Box runs an MCP (Model Context Protocol) server that lets an AI agent understand the bench, understand the device under test (DUT), and plan hardware-in-the-loop tests. It runs on-box and is reachable over the box’s local IP. The MCP server is read-only: it describes the bench and DUT but never drives hardware or runs code. The agent executes tests over a separate channel — the lager CLI.
MCP-compatible AI agent
    |  MCP (streamable-http via box IP)     ← discovery + planning (read-only)
    v
Lager MCP Server (on-box, port 8100)
    |  reads /etc/lager bench config (nets, DUT context, instruments)
    v
Bench / DUT metadata

AI agent  ──  lager python path/to/test.py --box <box-ip>  ──▶  Hardware
              (execution happens over the CLI, not MCP)

Connecting an agent

Point any MCP-compatible client at the box:
{
  "mcpServers": {
    "lager": {
      "url": "http://<box-ip>:8100/mcp"
    }
  }
}
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

ResourceWhat it gives the agent
lager://dut/overview.mdRead this first. A narrative briefing: what the box tests, the DUT MCU/peripherals, subsystems, and which documents to fetch.
lager://dut/contextThe full DUT context as structured JSON.
lager://bench/identityBox ID, hostname, version, and a per-DUT summary (purpose, MCU).
lager://bench/netlistEvery net with type, roles, instrument, and metadata.
lager://bench/interfacesProtocol interfaces (SPI, I2C, UART) and their nets.
lager://guide/overviewWhat Lager is and what a “net” is.
lager://guide/workflowThe recommended orient → discover → plan → write → run loop.
lager://guide/rtt-defmtThe 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-referenceCompact lager.Net API cheat sheet by net type.
lager://guide/docsLinks to the full hosted docs (docs.lagerdata.com) and the llms.txt page index for anything not covered on-box.

Tools

ToolPurpose
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.
PromptWhat 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.
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> registers a friendly alias.)
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). 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.
See Authoring DUT Context for the full guide.