Skip to main content
Glama

Agentic HIL

PyPI version CI License

Connect your AI to reality.

Let your agent develop, test, and improve firmware autonomously. In the real world. Agentic HIL makes this possible as a hard gate: it enforces strict safety boundaries and verifies the results on real hardware.

https://github.com/user-attachments/assets/8d39ba93-beeb-484e-b9e9-d9ce79538523

Watch the agent set up a fresh firmware project, write the firmware, and make the board say Hello World after installation and one restart. The recording shows real hardware feedback through the gate. The agent saves a test plan and runs it with both a correct and a deliberately wrong expectation. You get the plan, a report, and evidence that the test can pass and fail. The run ends with the lease released, the safe state confirmed, and nothing quarantined.

Get started

Install Agentic HIL for your user with one command. No admin rights required.

Linux / macOS (any shell):

curl -LsSf https://agentic-hil.github.io/install.sh | sh

Windows, in PowerShell:

irm https://agentic-hil.github.io/install.ps1 | iex

The installer registers the skill and MCP server for every supported agent CLI it finds on your PATH. It keeps the installation outside your repositories. Restart your agent once, then ask your first hardware question. Your agent sets up the project's bench through MCP.

If no claude, codex, or opencode CLI is found, the installer prints the next step. Install your agent CLI, then run agentic-hil agent-install --agent <claude-code|codex|opencode> to register it.

The installer asks the package manager where its user bin directory is and adds that directory to your shell startup files or Windows user Path when needed. Open a new shell to use the command. Pass --no-path (-NoPath in PowerShell) to manage that change yourself; the installer prints the line to add.

A fresh installation gets agentic-hil[can] from PyPI. Use --version <x.y.z> to pin a release. Rerunning the installer repairs an existing installation: editable checkouts reporting a .devN version are kept, and uv tools installed from a path, URL, or git reference are refreshed from that recorded source. To inspect and verify the installer before running it, follow the checksummed route in installation: download the script and its checksum from the same release, check the file, then run that file.

For a guided first run, try the STM32 starter. It has the firmware, test plans, and a planted defect ready for a three-step walkthrough on a Nucleo-F446RE.

Claude Code can also install the skill from the plugin marketplace: /plugin marketplace add agentic-hil/agentic-hil, then /plugin install agentic-hil@agentic-hil. The install command above still provides and registers the MCP server, with a verified absolute executable path outside your repository.

See installation for cmd.exe, registering one agent, using your own package manager, setting up an attached bench, optional components, and upgrades. The same installer command can repair an installation when agentic-hil upgrade fails. Troubleshooting covers startup problems.

In a clone of this repository, try a first check without a board:

agentic-hil check-plan examples/nucleo-f446re_demo/testconfig.yaml

It answers All 1 test plan(s) load through the reactor's loader. and exits 0, without loading a bench configuration or touching hardware.

Related MCP server: Chiplab

Let your agent close the loop

You set the goal. Your agent writes and builds the firmware. Agentic HIL puts it on the board, exercises the device, and checks its responses against the test criteria. When a test fails, the agent gets concrete results it can use to diagnose the problem, change the code, and try again.

Agentic HIL supplies the hardware execution and feedback that make this development loop possible. Much of the flashing, testing, and checking you would do at the bench becomes part of the agent's workflow. You review the code alongside a record of what ran, what passed, and what failed, and focus your attention on requirements, design decisions, and test coverage.

Agentic Hardware-in-the-Loop (Agentic HIL) connects coding agents to the bench through MCP tools and CI suites through a pytest plugin. Setup is available for Claude Code, Codex, and OpenCode.

Each hardware action returns a structured result with its outcome, diagnostics, and report and log paths. Your agent gets feedback it can act on, and you can trace the result back to the recorded run.

Bring your bench into the loop

Agentic HIL connects to your probe through its backend: ST-Link through OpenOCD or the STM32CubeProgrammer CLI, and CMSIS-DAP probes through pyOCD. It also flashes and resets ESP32 targets through esptool and their USB-UART bridge, without opening a debug session. Hardware support follows the probe and backend.

Send commands and read responses over serial ports and CAN buses using PCAN, SocketCAN, or a custom bridge. Several runs can share a CAN bus through the broker.

Agentic HIL runs on Linux, macOS, and Windows with Python 3.10 or newer, with CI coverage across all three platforms. The Nucleo-F446RE example takes you through a complete run on the board used to demonstrate the loop. See installation for backend and platform details.

Put the firmware to the test

Write down what the device should do in a reviewable YAML test plan. The test reactor validates the plan before touching hardware, then flashes, resets, and exercises the device in the order you specify. Checks compare actual responses with exact values, patterns, or numeric ranges. A check passes when the device meets that expectation.

Plans name logical devices, and the bench configuration connects them to real hardware. Use the same plan at your desk and in CI. A failed step stops the run; sessions are cleaned up, and configured recovery actions and their outcomes are recorded with the test results. Write your first hardware test.

Set boundaries that hold

You decide which devices and actions your agent may use. Agentic HIL rejects undeclared devices before opening a driver. It enforces permissions, validates requests, applies timeouts, and records what happened. The CLI, MCP tools, pytest plugin, and test reactor all pass through the same gate.

The authoritative configuration lives outside the workspace, beyond the agent's own file tools. Review the permissions it grants. Use agentic-hil revoke <key> or agentic-hil grant <key> from your own shell to change individual grants. Over MCP, an agent can only narrow its authority. Flashing is refused while either allow_raw_debugger_commands or allow_mass_erase is enabled.

Device leases protect runs from interference across the machine, and a SHA-256 audit chain makes the hardware record tamper-evident. A failed run keeps its failed verdict while configured recovery works to restore the bench and records the outcome. A broken audit trail holds the bench until operator recovery, because another hardware test cannot rebuild missing evidence.

Read the safety model for the overview and the security design for the full reasoning.

Try it on a real board

Start with the Nucleo-F446RE demo. Connect the board, build the firmware, and set up Agentic HIL from the example's directory:

cd examples/nucleo-f446re_demo
cmake --preset Debug && cmake --build --preset Debug   # → build/Debug/nucleo-f446re_demo.elf
agentic-hil setup --agent claude-code                  # or: codex / opencode
agentic-hil doctor

doctor checks the configuration against the attached bench and reports missing tools or hardware before you flash. If you connected the board after setup, agentic-hil adopt-hardware fills in the probe identity, backend executable, and COM device left unset. Use --dry-run to see the proposed changes first. On a host with OpenOCD and no STM32CubeProgrammer, the host's USB inventory can identify an attached ST-Link. Use --probe-id <serial> to select one when several probes are attached.

Run the example's hardware test plan:

agentic-hil test-reactor --test-config testconfig.yaml

The plan flashes the firmware, opens the serial port, resets the board, and checks the boot output for Hello World. A missing or wrong boot banner fails the test and returns the device output for diagnosis. The run closes the sessions it opened, including when a step fails.

Your agent can drive the same steps through MCP tools. Run pytest tests/ from the example directory to put the boot check in a regression suite. The example guide covers all three paths, and hardware testing shows how to write plans for your own device.

Go deeper

Your next step

Read

Install, upgrade, or add CAN, pyOCD, or esptool support

docs/installation.md

Define the bench and its permissions

docs/configuration.md

Drive hardware through MCP

docs/mcp-tools.md

Connect a specific MCP host

docs/mcp-hosts.md

Write hardware tests with YAML or pytest

docs/testing.md

Understand how safety boundaries and recovery work

docs/safety-model.md and docs/security-design.md

Find platform and response-time commitments

docs/support.md

Diagnose a failed run

TROUBLESHOOTING.md

Set up your agent for this project

AI_AGENT_QUICKSTART.md and AGENTS.md

Use agentic-hil for the package installation, CLI command, repository URL, and MCP server name. Python imports, pytest plugin names, fixtures, and Python examples use agentic_hil.

Development

To work on Agentic HIL itself:

python -m pip install -e '.[dev]'
ruff check src tests evals tools
pytest
python -m build
twine check dist/*

Releases publish to PyPI through GitHub trusted publishing in .github/workflows/workflow.yml. See CONTRIBUTING.md to contribute.

Security

Policy bypasses are treated as vulnerabilities; see SECURITY.md.

Support

Linux, macOS, and Windows have equal support. Hardware support follows the probe and backend: ST-Link through OpenOCD or STM32CubeProgrammer, CMSIS-DAP through pyOCD, and ESP32 USB-UART bridges through esptool.

Issues receive a response within 24 hours on workdays, and security reports within seven days. See the support policy for the full scope and commitments.

Ask questions in Discussions Q&A, share a run in Show and tell, or submit your first run report, whether it passed or failed.

License

Apache-2.0. See LICENSE.

Available Tools

44 tools
artifact_uploadA
Idempotent

Store a firmware image in artifacts.upload_directory and return its artifact_id for flash_firmware or debug_start_session; no board needed. Give image_path, or filename with data_base64, else invalid_argument. Needs allow_upload, else permission_denied. The id is the sha256 of the bytes plus the lowercased extension: same bytes and extension, same id. Unsafe destination: unsafe_configured_path.

Inputs: filename, image_path, data_base64.

bench_run_startA

Declare a run holding the devices a sequence like flash, reset, read needs until bench_run_stop or server exit, no timeout; without one the board is free between calls. All or nothing: a refused start holds none. Other devices fail undeclared_device; a second start, run_already_active; a standing incident, resource_quarantined. A single call, or flash_firmware with capture, needs no run.

Inputs: devices (required), label, wait_s.

bench_run_statusA
Read-only

Report whether this server has a run open (run_active), what it declared (declared_devices, run_label) and which devices it holds (held_devices); read it when unsure whether you still hold the bench. In memory only: what another process holds shows in hardware_lease_status.

Inputs: no named parameters.

bench_run_stopA
Idempotent

End the bench_run_start run and release its devices (released_devices). With no run open it answers run_was_active: false. A COM, CAN or debug session still open keeps its own device: open_leases, still_held_devices. With an incident open it runs the recovery recovery.auto_recover allows (by default reset into halt, then a probe re-read), reported in recovery.

Inputs: no named parameters.

can_buses_listA
Read-only

List every can_buses entry in buses, keyed by bus_id, the name can_session_start, can_send and can_read take. Each shows session_active, listen_only with its listen_only_enforcement, fd, max_frame_data_bytes and max_buffer_frames; a bus with shares adds active_participants. Needs no session and opens no adapter. Use this instead of ip link or candump.

Inputs: no named parameters.

can_readA
Read-only

Read the CAN frames your can_session_start session received into frames, counted by frames_read. Use it instead of candump; to wait for a reply, pass until_id rather than polling. Without a session: session_not_active. Returned frames are consumed; an empty read is still ok. Adapter faults: can_read_failed; after can_adapter_invalid_response, can_session_stop and start again.

Inputs: bus_id (required), until_id, max_frames, participant, +1 more.

can_sendA
Destructive

Send one CAN frame (CAN FD on an fd: true bus) on the can_session_start session, else session_not_active. Needs the bus allow_write, else permission_denied; a listen_only bus refuses with can_listen_only_mode. A repeat sends again. ok: the adapter accepted it, not that a node ACKed it. can_send_failed sets cleanup_required: it may have gone out. Use this instead of cansend.

Inputs: bus_id (required), frame_id (required), rtr, data_hex, +2 more.

can_session_startA
Destructive

Open a session on a configured CAN bus for can_send and can_read, until can_session_stop or server exit. Returns session; a repeat call answers already_active: true. Fails can_bus_not_configured, device_busy or resource_busy (bus held), can_adapter_timeout (bridge timeout_s, default 10 s), and on a listen_only bus can_listen_only_unsupported or can_listen_only_unconfirmed.

Inputs: bus_id (required), participant, clear_rx_queue.

can_session_stopA
Idempotent

Close the can_session_start session on bus_id when done with the bus; its lease is released. Its adapter closes unless other participants share the bus. A declared run still holds the bus. can_send and can_read then answer session_not_active. With no session open, was_active is false. If the close fails or a bridge is silent for 1 s, it returns can_adapter_close_failed and keeps the session.

Inputs: bus_id (required), participant.

classify_last_errorA
Read-only

Explain the last hardware failure: error_type names it, likely_causes says what to check, report_path and log_path hold the evidence. Unlike get_last_report, it keeps that failure through later successes. source_tool is the failed tool, or reset_target if a flash's recovery reset failed too. Some refusals, such as allow_flash off, record nothing. Needs no board; no failure yet: report_not_found.

Inputs: no named parameters.

com_ports_listA
Read-only

List com_ports entries in ports by port_id, which com_session_start takes (not a device path), with session_active. Opens no port. available_com_ports holds host serial ports, or permission_denied unless a configured port may be read, serial_backend_not_available without pyserial, com_port_discovery_failed on an OS error; the call stays ok. Use this instead of picocom or /dev/tty*.

Inputs: no named parameters.

com_readA
Read-only

Read what the board sent on a COM port session from com_session_start (else session_not_active), instead of screen, minicom or picocom. With until, one call waits for a pattern instead of polling. Each byte is returned once, as text and hex. If until is not seen in time, the answer is still ok, with until_matched false and the bytes so far.

Inputs: port_id (required), until, max_bytes, wait_timeout_s.

com_session_startA
Destructive

Open the serial port a com_ports entry names and hold it, with its machine-wide lock, until com_session_stop; a reader buffers what the board sends for com_read. DTR and RTS are driven as configured on open, which can reset a board. device_busy, resource_busy or com_port_busy: another server, process or program has the port. permission_denied: neither reading nor writing is allowed.

Inputs: port_id (required), clear_buffer.

com_session_stopA
Idempotent

Close the com_session_start session on port_id: stop its reader, close the port, release its lock. Unread bytes are dropped; the session log at log_path keeps them. Without a session it returns ok with was_active false. If the reader does not end within max(1 s, timeout_s + 0.5 s) of the close, it returns com_port_close_failed and keeps the session registered; call again to retry.

Inputs: port_id (required).

com_writeA
Destructive

Send bytes over the session com_session_start opened on port_id (else session_not_active); needs the port's allow_write (else permission_denied). At most max_write_bytes encoded bytes, 4096 by default. bytes_written counts the bytes sent; a short write returns serial_write_incomplete. Example: com_session_start port_id "uart0", com_write text "hello\r\n", com_read until "\n", com_session_stop.

Inputs: port_id (required), hex, text.

debug_clear_breakpointsA
Idempotent

Removes every breakpoint GDB holds in the debug_start_session session (else session_not_active), then checks none is left. It neither resumes nor halts the core. It answers cleared (the count) and backend_reconciled true; a second call clears 0. Unconfirmed: ok false, breakpoint_reconciliation_failed; a retry is safe. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: no named parameters.

debug_continueA

Resumes the core in the debug_start_session session until it stops. Needs allow_debug_execution, else permission_denied. Returns stop_reason, stop (frame): breakpoint_hit is ok; unexpected_breakpoint and target_exception are not. An exception or debugger_error stop is not resumed. No session: session_not_active. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: timeout_s.

debug_dump_symbol_ihexA
Destructive

Read an allowed symbol from target memory and write it as Intel HEX to output_path; returns address, size_bytes and output. Value inline: debug_symbol_value. OpenOCD needs debug_start_session (else session_not_active); pyOCD and STM32CubeProgrammer, the ELF last flashed via flash_firmware (else symbol_source_not_available). Over debug.max_dump_size_bytes: permission_denied.

Inputs: symbol (required), output_path (required).

debugger_infoA
Read-only

Check the debugger backend is installed: runs only --version, at most 10 s; contacts no probe or board. Replaces openocd. Returns backend, executable, version, config_status. Next: debugger_probes_list (probe ids), probe_target (board). Failures: debugger_not_found (missing), timeout; not_supported unless exactly one debugger is configured; permission_denied without allow_probe (config version 1).

Inputs: no named parameters.

debugger_probes_listA
Read-only

List the probe ids of the in-circuit debuggers or programmers on this host; connects to no board. Replaces st-info. Returns probes, each with a probe_id to set as the debugger entry's probe_id. pyOCD and STM32CubeProgrammer ask their CLI; OpenOCD reads the USB serial inventory, complete false (adapters it cannot read there: not_supported). Failure: probe_discovery_failed.

Inputs: no named parameters.

debug_get_session_statusA
Read-only

Reports if the debug_start_session session is open and its status: halted, running, error or cleanup_required. Records new stops, but never halts or resumes the core; debug_halt halts, debug_get_stop_reason reads the last stop. Abnormal stop: ok true, target_ok false, target_error_type. No session: ok, active false, status stopped. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: no named parameters.

debug_get_stop_reasonA
Read-only

Why the core last stopped: stop_reason (breakpoint_hit, halted, exception), stop (frame). Records a newly arrived stop; never halts or resumes the core. Abnormal stop: ok true, target_ok false, target_error_type. None yet: stop_reason_not_available. Without debug_start_session: session_not_active. Session: debug_get_session_status. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: no named parameters.

debug_haltA

Halts the core; the session stays open. It needs debug_start_session (else session_not_active) on OpenOCD with exactly one debugger configured, else not_supported. debug_continue resumes. Returns stop_reason halted or a stopped core's recorded stop. If an acknowledged interrupt's stop times out, ok and halt_confirmed are false, target_state unknown, bench quarantined; a confirmed halt can lift it.

Inputs: timeout_s.

debug_list_breakpointsA
Read-only

Lists the breakpoints debug_set_breakpoint added in the debug_start_session session, from the session's own record without asking GDB: breakpoints (id, backend_id, location). Never halts or resumes the core. No session: ok, active false, breakpoints empty. debug_clear_breakpoints removes them and checks GDB. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: no named parameters.

debug_set_breakpointA

Adds a breakpoint in the debug_start_session session (else session_not_active) without resuming the core. Each call adds one and returns its breakpoint id; debug_list_breakpoints lists them. A location without a grant answers permission_denied. An unconfirmed insert answers cleanup_required; call debug_clear_breakpoints. OpenOCD only, exactly one debugger configured; else not_supported.

Inputs: location (required).

debug_start_sessionA
Destructive

Opens a GDB session on an ELF for debug_continue and debug_halt. OpenOCD backend only; others answer not_supported. Needs GDB (debug.gdb_executable or PATH), the debugger entry's scripts and allow_raw_debugger_commands off. Returns the core halted: session (status, stop_reason), log_path. A second start: session_already_active. debug_get_session_status inspects it; debug_stop_session ends it.

Inputs: mode, timeout_s, image_path, artifact_id.

debug_stop_sessionA
Idempotent

Ends the debug_start_session session; debug_halt keeps it open. Confirms the core halted, disables resume on detach, ends GDB and the debug server, drops breakpoints, frees flash_firmware and reset_target. OpenOCD backend only; others answer not_supported. Success: safe_state_confirmed true. No session: ok, active false. Unproven: ok false, cleanup_required, hardware_state unknown, quarantined.

Inputs: timeout_s.

debug_symbol_infoA
Read-only

Find an allowed symbol's hex address, size_bytes and resolved_from in the ELF. Reads no target memory; for bytes use debug_symbol_value, for Intel HEX debug_dump_symbol_ihex. OpenOCD needs debug_start_session (else session_not_active). pyOCD and STM32CubeProgrammer use the ELF this server last flashed via flash_firmware (else symbol_source_not_available; symbol_source_changed if changed since).

Inputs: symbol (required).

debug_symbol_valueA
Read-only

Reads a symbol from target memory, like gdb print. debug_symbol_info gives its address, debug_dump_symbol_ihex a file. Returns hex, plus value_unsigned and value_signed at 1, 2, 4 or 8 bytes. OpenOCD needs debug_start_session (else session_not_active); pyOCD and STM32CubeProgrammer, the ELF flash_firmware last wrote (else symbol_source_not_available). Over max_dump_size_bytes: permission_denied.

Inputs: symbol (required).

flash_firmwareA
Destructive

Write firmware to the board via the in-circuit debugger or programmer, not st-flash; every call writes it again. Needs allow_flash, else permission_denied. resource_busy: debug_stop_session first; device_busy: held elsewhere. The debugger entry's timeout_s (seconds, 60 unless set) caps each debugger command, else timeout. No bench_run_start needed; capture with reset_after_flash adds boot output.

Inputs: capture, image_path, artifact_id, reset_after_flash.

get_last_reportA
Read-only

Return the newest stored hardware report, pass or fail, under report. For the last failure diagnosed, even after successes, use classify_last_error. Needs no board; reading changes nothing. After a failure it can be the recovery's reset_target or probe_target (report.tool). ok stays true for a failed report: judge report.ok, report.audit_ok, report.cleanup_required. None yet: report_not_found.

Inputs: no named parameters.

hardware_lease_statusA
Read-only

Read who holds this bench, from any process (bench_held, held_devices), and any open incident: blocked, cleanup_reasons, auto_recoverable, quarantine_guidance, next_step. Only incident_stands: true needs hardware_recover; otherwise the next hardware call settles it or stands it down. standing_incidents are other projects' incidents, not yours to clear. Drives no device.

Inputs: no named parameters.

hardware_recoverA
Idempotent

Clear the standing quarantine that blocks hardware calls. Call it when hardware_lease_status shows incident_stands, rather than deleting state files. It needs allow_recover and touches no hardware. A no-contact reason clears with no argument. Any other reason answers recovery_requires_physical_check: ask the operator, pass their answer verbatim as operator_statement, never invent one.

Inputs: operator_statement, accept_config_change.

probe_targetA
Idempotent

Connect the in-circuit debugger or programmer to the board and confirm it answers (target_detected true), with no reset and no flash; reset_target resets. Replaces openocd. Refused with resource_busy while a debug session is open. Failures: adapter_not_found (no probe), target_not_detected (board silent), debugger_not_found (backend missing), timeout (one command over debugger.timeout_s).

Inputs: no named parameters.

project_config_adopt_hardwareA
Idempotent

Fill the configuration keys that still hold placeholders from the attached probe. Call it once a board is attached, so nobody retypes its serial. It may also rename a COM device to its stable name and correct a stale identity_source. It writes only when apply is true, never flashes or erases. A read that leaves the board state unknown may get it reset into halt by recovery (resource_quarantined).

Inputs: apply, probe_id, com_port_id, debugger_id.

project_config_createA
Destructive

Generate this workspace's configuration from attached hardware instead of writing one by hand: every permission true except allow_raw_debugger_commands and allow_mass_erase, which it writes false. Never ask for those two to be turned on. Regenerating is the operator's call, not a way to narrow or re-open.

Inputs: no named parameters.

project_config_describeA
Read-only

List the keys project_config_set may change: writable_keys with current_value and value_schema, locked_keys naming in unlocked_by the permission that opens each. Read it before project_config_set instead of guessing; it needs no permission. writes_blocked_by_open_run is true while this server holds a run or session. Bad YAML answers config_invalid, an unreadable file config_unreadable.

Inputs: no named parameters.

project_config_reload_descriptionA
Read-only

Re-read target, debuggers, com_ports and can_buses from this workspace's configuration into the running server, never permissions or debug. Call it after project_config_set, project_config_adopt_hardware or a hand edit, rather than a restart. New devices get every permission false; changed grants need a restart (restart_required_for). description_changes lists what moved.

Inputs: no named parameters.

project_config_setA
Destructive

Write values you choose to named keys of the configuration file. Call it after project_config_describe lists the keys, rather than editing the configuration file. Device keys need allow_config_description_write, permission keys allow_config_permissions_write, else permission_denied. Permissions only narrow: closing allow_config_permissions_write freezes them all at once (permissions_frozen).

Inputs: changes (required).

reset_targetA

Reset the board through the in-circuit debugger or programmer: the firmware restarts, flash is kept. Replaces st-util. Needs allow_reset (else permission_denied). Refused with resource_busy while a debug session is open: debug_stop_session first. To check the board without a reset use probe_target. Failures: reset_failed (reset not confirmed), timeout (one command over debugger.timeout_s).

Inputs: mode.

server_upgradeA
Idempotent

Upgrade this installation to the newest release with the uv, pipx or pip that installed it. Use it when the operator asks; it takes no arguments and needs allow_upgrade. Each manager run may take 600 s. running_version stays old until this server restarts. On Windows, ask the operator to run agentic-hil upgrade (upgrade_cli_only_on_host). On failure the operator runs any reinstall_command.

Inputs: no named parameters.

test_reactor_runA
Destructive

Run a test plan file (agentic-hil://reference/test-plan) on the board. For calls made one by one, use bench_run_start, whose open run refuses this with run_already_active. permission_denied and device_busy refuse at once, before any step. A failing step gets the recovery recovery.auto_recover allows, reported in recovery. With detach, poll test_reactor_status; test_reactor_stop ends it.

Inputs: detach, test_config_path.

test_reactor_statusA
Read-only

Follow a detached test_reactor_run by its handle; for a bench_run_start run, use bench_run_status. state goes starting, running, then finished or stopped, or worker_gone if its process died; stop_requested_at dates a test_reactor_stop. Once ended, run_ok is the verdict and canonical_report_path its own report; report_path is a mirror the next run overwrites. Fails run_state_invalid.

Inputs: run.

test_reactor_stopA
Idempotent

Ask a test plan run to stop by writing a request it reads between steps. It finishes the step it is in (a delay or device wait ends early), closes its devices and writes its report; one still starting ends before any step. Answers at once stop_requested: true, also on a repeat; an ended run answers stop_requested: false. Fails run_state_invalid, or run_worker_gone (its process died).

Inputs: run (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 44 tools

    Disambiguation4/5

    The set has several superficially similar status/report tools (debug_get_session_status, debug_get_stop_reason, get_last_report, classify_last_error, bench_run_status, test_reactor_status, hardware_lease_status), but descriptions cross-reference each other explicitly and assign distinct purposes, so an agent can tell them apart. The run-vs-run distinction (bench_run_start vs test_reactor_run) is also carefully delineated. Only minor boundary friction remains among the many 'status' tools.

    Naming Consistency4/5

    Names are uniformly snake_case with a clear verb_noun pattern and domain prefixes (debug_*, com_*, can_*, bench_run_*, project_config_*). A few names lack a domain prefix (get_last_report, classify_last_error, artifact_upload, server_upgrade) and project_config_reload_description is an awkward phrasing, but overall the convention is predictable.

    Tool Count2/5

    44 tools is well beyond the 25+ heavy threshold. The domain is genuinely broad (debug, flash, serial, CAN, config, recovery, bench orchestration), but the surface is bloated with many fine-grained session/status/breakpoint tools that could be consolidated. This is a lot of surface for an agent to navigate reliably.

    Completeness5/5

    Coverage is remarkably thorough: each subsystem has full lifecycle tools (session start/stop, breakpoint set/list/clear, read/write), plus flash, reset, symbol inspection, bench-run orchestration, config describe/set/adopt/create, error classification, and quarantine recovery. No obvious dead ends for the stated hardware-in-the-loop purpose.

    Maintenance

    ActivityActive
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Stateful MCP server for driving debug probes (J-Link) to flash, debug, and inspect embedded targets. Enables AI agents to perform flash, memory, breakpoint, and ELF/SVD-aware operations conversationally.
      41
      49 PyPI
      10
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      MCP server for simulating firmware on virtual microcontroller instances, allowing AI agents to upload, run, and read UART output from supported boards such as STM32 and Nordic.
      18
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      MCP server for AI-assisted MCU and embedded firmware debugging. It connects to real hardware via debug probes, inspects CPU/memory/peripherals, manages Keil builds, and provides structured evidence for fault diagnosis.
      19
      36 PyPI
      9
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that lets AI coding agents drive the full STM32 development loop—code generation, build, flash, debug, serial monitoring, and fault diagnosis—end to end via CubeIDE, CubeMX, CubeProgrammer, OpenOCD, and GDB.
      1
      MIT