labgrid-mcp
Drive real embedded hardware from Claude, AI editors, and any MCP client.
labgrid is the open-source framework embedded teams use to share lab hardware: boards ("places") with remotely switchable power, serial consoles, USB muxes, and flashing tools. labgrid-mcp is a Model Context Protocol server that plugs any labgrid lab into the MCP ecosystem, so agents and dev tools can work with the lab directly:
"Acquire the rk3399 board, flash last night's image, power-cycle it, and tell me whether it reaches a login prompt. Paste the console log if it doesn't."
Not only for chat: any MCP client, scripted or human-driven, gets a policy-gated remote-control surface over labgrid's mature driver ecosystem, with the reservations and ownership arbitration ad-hoc device servers don't have.
Features
- Full device lifecycle: discover, reserve, acquire, release; keepalive-backed so holds never expire mid-task
- Hardware control: power on/off/cycle, digital I/O, SD/USB mux switching
- Interactive serial console: open, read, send, close; ring-buffered
- SSH to the device: run commands, transfer files, tunnels in both directions
- Flashing (opt-in): DFU, fastboot, bootstrap loaders, image writing, all as background jobs with status/log polling
- Lab housekeeping: tags, aliases, comments, place management, change monitoring
- Safety gating: read-only mode and per-category allowlists; the irreversible families (flash, place deletion) are off by default
47 tools, 5 browseable labgrid:// resources, honest
readOnly/destructive annotations on every tool.
Try it in 5 minutes (no hardware needed)
Requires uv (its bundled uvx does the rest,
including provisioning Python):
uvx labgrid-mcp demo
This boots a complete fake lab on your machine: a real labgrid
coordinator and exporter, one demo board with a fake power switch and a fake
serial console. It prints a paste-ready .mcp.json snippet. Then ask
Claude:
- "List places, then acquire demo-place"
- "Power demo-place on and read its power state"
- "Open the console on demo-place and read its output"
Ctrl-C tears everything down.
Connect your lab
Needs a gRPC-era coordinator (labgrid ≥ 24; tested against 26.x). Add to
.mcp.json (Claude Code) or Claude Desktop's config:
{
"mcpServers": {
"labgrid": {
"command": "uvx",
"args": ["labgrid-mcp"],
"env": {
"LG_COORDINATOR": "127.0.0.1:20408"
}
}
}
}
(Running from a clone instead? Use "command": "uv",
"args": ["run", "--directory", "/path/to/labgrid-mcp", "labgrid-mcp"].)
Identity works exactly like labgrid-client: set LG_HOSTNAME /
LG_USERNAME, or omit them to use your real hostname/user.
Configuration
| Env var | Default | Effect |
|---|---|---|
LG_COORDINATOR |
127.0.0.1:20408 |
Coordinator address |
LG_HOSTNAME / LG_USERNAME |
real host/user | Identity, as in labgrid-client |
LABGRID_MCP_READONLY |
off | 1 = only read-only tools are registered: the Read group plus wait_for_change and forward_list |
LABGRID_MCP_ALLOW |
unset | Comma list of categories to register; flash and place_delete must be listed explicitly; they're off even by default |
LABGRID_MCP_SSH_KEYFILE |
unset | Private key for the SSH tools; unset, they error clearly at call time |
LABGRID_MCP_ACQUIRE_TIMEOUT |
120 |
Max seconds acquire_place waits for allocation |
Safety in one paragraph: flashing and place deletion can do irreversible
damage, so each needs its own explicit LABGRID_MCP_ALLOW entry. SSH tools
are arbitrary command execution on the acquired board, the same trust class
as a console session; LABGRID_MCP_READONLY=1 drops them along with every
other gated tool (forward_list stays, since it only lists in-memory tunnel
state). And a labgrid caveat worth knowing: the coordinator enforces no
ownership guard on place metadata: this server refuses to edit an acquired
place without force=True, but nothing can protect a place nobody holds
(and an empty tag value in set_place_tags deletes that key, which is
labgrid's own semantics). Details: docs/DESIGN.md §4 and §11.12.
Tools
All 47 tools by group
| Group | Tools |
|---|---|
| Read | coordinator_info, list_places, show_place, who, list_resources, list_reservations |
| Acquisition / reservation | acquire_place, release_place, allow_place, release_from, reserve, cancel_reservation, reservation_wait |
| Drivers | get_power_state, set_power, get_io, set_io, get_sd_mux, set_sd_mux, set_usb_mux |
| Console | console_open, console_read, console_send, console_close |
| SSH / forward | ssh_run, put_file, get_file, forward_open, forward_remote_open, forward_close, forward_list |
| Flash (opt-in) | flash_dfu, flash_fastboot, flash_script, bootstrap, write_image, flash_status, flash_logs |
| Place metadata | add_place, add_place_alias, delete_place_alias, set_place_tags, set_place_comment, add_place_match |
| Place deletion (opt-in) | delete_place, delete_place_match |
| Change monitoring | wait_for_change |
Resources: labgrid://places, labgrid://places/{name},
labgrid://resources, labgrid://reservations, labgrid://sessions.
Per-tool arguments and behaviors are documented in each tool's own
description (visible in your MCP client) and in
docs/DESIGN.md §5/§11.
Limitations
- No video/audio/screen capture or USB instruments (need gstreamer + physical USB; no sane MCP surface)
- No live event stream;
wait_for_changelong-polling instead - Old crossbar coordinators (labgrid < 24) can't connect
- Authentication is network-level (VPN/tunnel), exactly labgrid's own model
- The real flash/mux driver step needs a real board: the job machinery is fully CI-tested against fakes, the silicon-touching step is not
Development
The integration suite runs the whole stack, including the demo, against
real coordinator/exporter processes with fake hardware, in CI on every PR,
plus a weekly canary against labgrid master:
git clone <this-repo> labgrid-mcp && cd labgrid-mcp
uv sync
uv run pytest # unit
uv run pytest -m integration
Architecture, decision log, and a verified reference of labgrid's
internals: docs/DESIGN.md.
License
Apache-2.0. Copyright 2026 Onur Celep.
labgrid itself is LGPL-2.1-or-later and is used as a regular, unmodified dependency.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file labgrid_mcp-0.1.1.tar.gz.
File metadata
- Download URL: labgrid_mcp-0.1.1.tar.gz
- Upload date:
- Size: 292.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db8c37d37f3eeea9314a4a87ab1568520efdced69fa24a16b21e154998e5d9d1
|
|
| MD5 |
b04fb77415c0dadd7c1ea7bf1bfa6c64
|
|
| BLAKE2b-256 |
2bf810a43f770a21865b5848b00beaaf3939dc68c690034ffcdce410e7e6b036
|
Provenance
The following attestation bundles were made for labgrid_mcp-0.1.1.tar.gz:
Publisher:
publish-pypi.yml on onurcelep/labgrid-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
labgrid_mcp-0.1.1.tar.gz -
Subject digest:
db8c37d37f3eeea9314a4a87ab1568520efdced69fa24a16b21e154998e5d9d1 - Sigstore transparency entry: 2340958381
- Sigstore integration time:
-
Permalink:
onurcelep/labgrid-mcp@4eea3951e1e95623b91c2cdc1d318eb998d4361d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/onurcelep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4eea3951e1e95623b91c2cdc1d318eb998d4361d -
Trigger Event:
push
-
Statement type:
File details
Details for the file labgrid_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: labgrid_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 85.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00dff8a3c472faaa2a2e2abdf37269f702d78f775f1ecff4d4a93ea886cd57fe
|
|
| MD5 |
1ff69b55b40e3b63fd7d59076ce02a15
|
|
| BLAKE2b-256 |
887d0391d72adb06aaef2c3f15f974530505deb713ee9976b69a18181e17a4fa
|
Provenance
The following attestation bundles were made for labgrid_mcp-0.1.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on onurcelep/labgrid-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
labgrid_mcp-0.1.1-py3-none-any.whl -
Subject digest:
00dff8a3c472faaa2a2e2abdf37269f702d78f775f1ecff4d4a93ea886cd57fe - Sigstore transparency entry: 2340958384
- Sigstore integration time:
-
Permalink:
onurcelep/labgrid-mcp@4eea3951e1e95623b91c2cdc1d318eb998d4361d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/onurcelep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4eea3951e1e95623b91c2cdc1d318eb998d4361d -
Trigger Event:
push
-
Statement type: