Agentic HIL
PYPI · AGENTIC-HIL
Develop firmware on the real board behind a debug probe: flash, reset, UART and CAN, policy-gated.
Available components
Last scanned (17 hours ago)
Scores higher than 98% of PyPI servers
Category IoT and Hardware
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security99
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs setuptools.build_meta at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 1 of 12 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to agentic-hil/agentic-hil). View diagnostics → Pass
- Clear OSI-approved license (Apache-2.0).Pass
- Actively maintained (last published 0 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability80
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 8642 tokens (~151/item across 57 items; 48 tools + 9 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 50 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities60
- Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28. See how to fix → Fail
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 +15
- Malware scan: unverified → pass ▲ security
- 3 Nov 26 −15
- Malware scan: pass → unverified ▼ security
- Package version: 0.25.0 → 0.26.0 functional
- 29 Oct 26 +1
- Stability: 0.97 → pass security
- 28 Oct 26 −1
- Stability: pass → 0.97 functional
- 27 Oct 26 +15
- Malware scan: unverified → pass ▲ security
- 26 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- Package version: 0.24.0 → 0.25.0 functional
- 22 Oct 26 +1
- Stability: 0.97 → pass security
- 20 Oct 26 −1
- Stability: pass → 0.93 functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Analysed pypi/agentic-hil@0.26.0
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | agentic-hil/agentic-hil |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/agentic-hil/agentic-hil/.github/workflows/workflow.yml@refs/tags/v0.26.0 |
| Rekor log index | 3675708983 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:ab333a0bf6413cbe081281a491b76cca195d65e2b9a1afe53457cc144d8a9ee4 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | setuptools.build_meta |
Background: Why install scripts are a supply-chain risk →
Dependencies 12 packages
| Packages resolved | 12 |
|---|---|
| Stale | 1 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
artifact_upload ~228
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.
| Name | Type | Req | Description |
|---|---|---|---|
| data_base64 | string | – | The image as padded standard base64, whitespace ignored, else invalid_argument. Decoded, at most artifacts.max_upload_size_mb MiB (default 64), else artifact_too_large. |
| filename | string | – | Bare name for data_base64, no path (like app.elf); its lowercased extension picks the format check and ends the artifact_id. A path: invalid_argument. |
| image_path | string | – | Local file to store, inside the workspace and artifacts.allowed_roots (build if unset), with an allowed extension (.elf, .hex, .bin). Missing: artifact_not_found; invalid: artifact_validation_failed. |
No output schema declared.
No examples provided.
bench_run_start ~205
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.
| Name | Type | Req | Description |
|---|---|---|---|
| devices | array | yes | The devices the run holds, one selector each, all resolved before any is locked. Success returns them as `declared_devices`, with `run_label`. |
| label | string | – | Optional, no default: free text returned as `run_label` and shown as the holder's label to anyone refused `device_busy`. |
| wait_s | number | – | Seconds to wait for a device another holder has, 0 to 900. Default 0: a held device fails `device_busy` at once. |
No output schema declared.
No examples provided.
bench_run_status ~70
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
bench_run_stop ~97
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`.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
can_buses_list ~104
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
can_read ~322
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.
| Name | Type | Req | Description |
|---|---|---|---|
| bus_id | string | yes | A `can_buses` entry (can_buses_list), else `can_bus_not_configured`. |
| max_frames | integer | – | Most frames to return, 1 to the bus `max_buffer_frames` (1024 unless configured), else `invalid_argument`. Default `max_buffer_frames`. |
| participant | string | – | Required on a bus with `shares`. It reads only frames its filter accepts, never its own sends. Each frame read spends its budget; `can_participant_frame_budget_exhausted` ends its run. |
| until_id | – | – | Integer id (0 to 0x1FFFFFFF) to wait for, or a list of 1 to 8. Returns the frames read through the first match. Only the numeric id is compared, not the extended flag. |
| wait_timeout_s | number | – | Seconds to wait for frames. Without until_id: default 0 (answer at once with what is queued), at most the bus `timeout_s` (default 10 s) and 60 s. With until_id: default 10 s, at most 60 s. |
No output schema declared.
No examples provided.
can_send ~400
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.
| Name | Type | Req | Description |
|---|---|---|---|
| bus_id | string | yes | A `can_buses` entry (can_buses_list), else `can_bus_not_configured`. The adapter gets the bus `timeout_s` (default 10 s) to take the frame; replies come from can_read. |
| data_hex | string | – | Hex byte pairs, whitespace ignored; default empty. At most `max_frame_data_bytes`; classic over 8 bytes: `can_classic_frame_too_large`; FD only 0-8,12,16,20,24,32,48,64: `can_fd_frame_length_invalid`. |
| extended | boolean | – | Default false: 11-bit standard id. True: 29-bit extended id. |
| frame_id | – | yes | Arbitration id: an integer, a decimal string or a 0x hex string. 0 to 0x7FF, or 0 to 0x1FFFFFFF when extended, else `invalid_argument`. The result echoes the sent `frame`. |
| participant | string | – | Required with `shares`; needs its own `allow_write`. frame_id must pass its filter (`can_participant_filter_violation`). Sends spend its budget; `can_participant_frame_budget_exhausted` ends its run. |
| rtr | boolean | – | Default false: a data frame. True sends a remote frame; an `fd: true` bus refuses it with `can_fd_remote_frame_unsupported`. |
No output schema declared.
No examples provided.
can_session_start ~272
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`.
| Name | Type | Req | Description |
|---|---|---|---|
| bus_id | string | yes | A `can_buses` entry (can_buses_list). peak needs PCAN-Basic, socketcan an up interface, both via python-can (`agentic-hil[can]`, else `can_backend_not_available`); process runs a bridge `executable`. |
| clear_rx_queue | boolean | – | Default true: discard frames already queued, also on a repeat call, counted in `frames_drained`. Bounded: a queue that keeps filling fails `can_queue_clear_limit`. Ignored for a participant. |
| participant | string | – | Required on a bus with `shares`; any other name, or any name on a bus without `shares`, fails `can_participant_not_configured`. A broker owns the adapter; each participant gets its own filtered queue. |
No output schema declared.
No examples provided.
can_session_stop ~208
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.
| Name | Type | Req | Description |
|---|---|---|---|
| bus_id | string | yes | A `can_buses` entry from can_buses_list, else `can_bus_not_configured`. Example: can_session_start(bus_id="bench"), can_read(bus_id="bench", max_frames=10), can_session_stop(bus_id="bench"). |
| participant | string | – | Required on a bus with `shares`: only this participant detaches, the others stay. A name with no open session, or any name on a bus without `shares`, answers `was_active: false` and closes nothing. |
No output schema declared.
No examples provided.
classify_last_error ~95
Explain the last hardware failure. Unlike get_last_report, the failure survives later successes. Returns error_type (its code), likely_causes (what to check), report_path and log_path (evidence). source_tool is the failed tool, or reset_target if a flash's recovery reset failed too. Flash refusals by allow_flash or allow_mass_erase record nothing. Needs no board; no failure yet: report_not_found.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
com_ports_list ~107
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 ports, or `permission_denied` on version 1 unless a configured port may be read, `serial_backend_not_available` without pyserial, `com_port_discovery_failed` on OS errors; the call stays ok. Use this instead of picocom or /dev/tty*.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
com_read ~272
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.
| Name | Type | Req | Description |
|---|---|---|---|
| max_bytes | integer | – | Most bytes to return; default the port's max_buffer_bytes (65536 unless configured). The rest stays buffered, see buffer_remaining_bytes. With until, a wait also ends once max_bytes are buffered. |
| port_id | string | yes | The com_ports entry name (see com_ports_list), not a device path; an unknown name gives com_port_not_configured. Under config version 1, permission_denied unless allow_read is true. |
| until | – | – | Text, or up to 8 texts, matched literally as bytes in the port's encoding, not as a regex. Returns the feedback through the first match; the rest stays buffered. |
| wait_timeout_s | number | – | Seconds to wait. Without until the default is 0 and a wait ends at the first bytes to arrive; with until the default is 10 s. Waits are capped at 60 s. |
No output schema declared.
No examples provided.
com_session_start ~189
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.
| Name | Type | Req | Description |
|---|---|---|---|
| clear_buffer | boolean | – | Default true: discard bytes received so far, also on a repeat start for the same port_id, which keeps a live session (already_active) and replaces a failed one. False keeps them for com_read. |
| port_id | string | yes | Name of a com_ports entry (com_ports_list shows them), not a device path. Unknown names fail with com_port_not_configured; a device that will not open, with com_port_open_failed. |
No output schema declared.
No examples provided.
com_session_stop ~139
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.
| Name | Type | Req | Description |
|---|---|---|---|
| port_id | string | yes | Name of a com_ports entry in the project configuration (com_ports_list shows them), not a device path; an unknown name fails with com_port_not_configured. |
No output schema declared.
No examples provided.
com_write ~225
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.
| Name | Type | Req | Description |
|---|---|---|---|
| hex | string | – | Bytes as hexadecimal byte pairs, whitespace ignored, for example "0d 0a". Give hex or text, not both; hex suits binary payloads. |
| port_id | string | yes | Name of a com_ports entry in the project configuration (com_ports_list shows them), not a device path; an unknown name fails with com_port_not_configured. |
| text | string | – | Characters to send, encoded with the port's configured encoding (utf-8 by default) and sent as is: no line ending is added, so include \r\n yourself. Give text or hex, not both. |
No output schema declared.
No examples provided.
debug_clear_breakpoints ~94
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. GDB server only, exactly one debugger configured; else not_supported.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
debug_continue ~148
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. GDB server only, exactly one debugger configured; else not_supported.
| Name | Type | Req | Description |
|---|---|---|---|
| timeout_s | number | – | Seconds to wait for a stop. Default and ceiling: the debugger entry's timeout_s (60 unless set); under 0.1 counts as 0.1 first. Expiry: interrupt, its stop, up to 5 s each; timeout, halt_confirmed. |
No output schema declared.
No examples provided.
debug_dump_symbol_ihex ~194
Read a 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 use an open session, else the ELF flash_firmware last wrote (else symbol_source_not_available). Over debug.max_dump_size_bytes: permission_denied.
| Name | Type | Req | Description |
|---|---|---|---|
| output_path | string | yes | Workspace path ending .hex or .ihex, no '..' segment, under artifacts.allowed_roots if validation.require_allowed_root (default true), else output_validation_failed. Folders created, a file replaced. |
| symbol | string | yes | C identifier, optionally ::-qualified, e.g. boot_counter. Allowed if in debug.allowed_symbols or debug.allow_all_symbols is true (default false), else permission_denied. Not in ELF: symbol_not_found. |
No output schema declared.
No examples provided.
debug_get_session_status ~99
Reports if the debug_start_session session is open and its status: halted, running, error or cleanup_required. Records new stops; 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. GDB server only, exactly one debugger configured; else not_supported.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
debug_get_stop_reason ~98
Reads why the core last stopped: stop_reason (breakpoint_hit, halted, exception), stop (frame). Records a new 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. GDB server only, exactly one debugger configured; else not_supported.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
debug_halt ~149
Halts the core; the session stays open. Needs debug_start_session (else session_not_active) on a GDB server, exactly one debugger configured, else not_supported. 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, quarantined; a confirmed halt lifts it unless the session is in error.
| Name | Type | Req | Description |
|---|---|---|---|
| timeout_s | number | – | Seconds each for the interrupt and stop. The default and ceiling is 10, or the debugger's timeout_s if lower; under 0.1 counts as 0.1 first. Expiry answers timeout. A stopped core gets no interrupt. |
No output schema declared.
No examples provided.
debug_list_breakpoints ~92
Lists the breakpoints from the debug_start_session session's own record without asking GDB: breakpoints (id, backend_id, location), status, and cleanup_required, quarantined and hardware_state when cleanup is unconfirmed. Never halts or resumes the core. No session: ok, active false. debug_clear_breakpoints removes them. GDB server only, exactly one debugger configured; else not_supported.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
debug_set_breakpoint ~146
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. GDB server only, exactly one debugger configured; else not_supported.
| Name | Type | Req | Description |
|---|---|---|---|
| location | – | yes | "main", {"symbol": "main"}, {"function": "main"}: C identifier, needs debug.allowed_symbols or debug.allow_all_symbols. {"file": "a.c", "line": 9}: line from 1, no '..', needs debug.allow_all_symbols. |
No output schema declared.
No examples provided.
debug_start_session ~284
Opens a GDB session on an ELF for debug_continue and debug_halt. OpenOCD, pyOCD or ST-LINK_gdbserver; else not_supported. Needs GDB (debug.gdb_executable or PATH), the debugger's executable 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.
| Name | Type | Req | Description |
|---|---|---|---|
| artifact_id | string | – | Id of an ELF stored with artifact_upload. Give this or image_path, not both. |
| image_path | string | – | Path to a .elf file, relative to the workspace or absolute, inside the workspace and (by default) artifacts.allowed_roots. Give this or artifact_id, not both. |
| mode | string | – | attach (default): halts the core, no reset. reset_halt: resets, halts; needs allow_reset. load: resets, flashes the ELF, resets, halts; needs allow_reset and allow_flash, not allow_mass_erase. |
| timeout_s | number | – | Seconds. Default and ceiling: the debugger entry's timeout_s (60 unless set); 0.1 at least. Bounds the debug server's start and each GDB step (10 s at most). Expiry: timeout. |
No output schema declared.
No examples provided.
debug_stop_session ~162
Ends the debug_start_session session; debug_halt keeps it open. Confirms core halted, disables resume on detach, ends GDB and debug server, drops breakpoints, frees flash_firmware and reset_target. OpenOCD, pyOCD or ST-LINK_gdbserver only; else not_supported. Success: safe_state_confirmed true. No session: ok, active false. Unproven: ok false, cleanup_required, hardware_state unknown, quarantined.
| Name | Type | Req | Description |
|---|---|---|---|
| timeout_s | number | – | Seconds per teardown step. Default and ceiling: 5, or the debugger's timeout_s if lower; 0.1 at least. Fails: halt_not_confirmed, breakpoints_not_removed, detach_resume_not_confirmed, cleanup_failed. |
No output schema declared.
No examples provided.
debug_symbol_info ~145
Find a 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 an open session, else the ELF flash_firmware last wrote (else symbol_source_not_available; symbol_source_changed if changed since).
| Name | Type | Req | Description |
|---|---|---|---|
| symbol | string | yes | C identifier, optionally ::-qualified, e.g. boot_counter. Allowed if in debug.allowed_symbols or debug.allow_all_symbols is true (default false), else permission_denied. Not in ELF: symbol_not_found. |
No output schema declared.
No examples provided.
debug_symbol_value ~155
Reads a symbol from target memory, like gdb print. Address: debug_symbol_info; file: debug_dump_symbol_ihex. Returns hex plus value_unsigned and value_signed at 1/2/4/8 bytes. OpenOCD needs debug_start_session (else session_not_active); pyOCD and STM32CubeProgrammer use an open session, else flash_firmware's last ELF (else symbol_source_not_available). Over max_dump_size_bytes: permission_denied.
| Name | Type | Req | Description |
|---|---|---|---|
| symbol | string | yes | C identifier, optionally ::-qualified, e.g. boot_counter. Allowed if in debug.allowed_symbols or debug.allow_all_symbols is true (default false), else permission_denied. Not in ELF: symbol_not_found. |
No output schema declared.
No examples provided.
debugger_info ~95
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).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
debugger_probes_list ~98
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
flash_firmware ~288
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.
| Name | Type | Req | Description |
|---|---|---|---|
| artifact_id | string | – | An artifact_id from artifact_upload, not with image_path; needs allow_upload, else permission_denied. Refused: artifact_not_found, artifact_validation_failed, artifact_too_large (max_upload_size_mb). |
| capture | object | – | Read a COM port across the flash: opened before it, ended by a match, max_bytes or the wait. Needs reset_after_flash. A read failing after a good flash is ok false, image written. |
| image_path | string | – | A .elf, .hex or .bin inside the workspace and artifacts.allowed_roots (build if unset). A .bin needs flash_address on every backend. pyOCD does not verify (verify false). |
| reset_after_flash | boolean | – | Reset the board after flashing; needs allow_reset, else permission_denied. Default false: not reset. If a failed flash leaves an incident, recovery.auto_recover may try a reset into halt. |
No output schema declared.
No examples provided.
get_last_report ~92
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
hardware_lease_status ~103
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
hardware_recover ~169
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.
| Name | Type | Req | Description |
|---|---|---|---|
| accept_config_change | boolean | – | Default false. True only after the operator has reviewed both digests a config_changed refusal reports: accepts the configuration change since the incident; recorded in the ledger. |
| operator_statement | string | – | The operator's own answer, asked in chat, passed verbatim; recorded in the ledger as theirs. Never invent one. No statement clears an audit_broken reason: only its operator_command does. |
No output schema declared.
No examples provided.
power_supply_cycle ~150
Power-cycle the board on one supply channel: output off, wait `off_s`, output on, each state read back. Needs `allow_output`. The stored set points are held to the effective limits and the protection is armed at them first. A type that cannot read its output state is refused before contact (`not_supported`). Every call cycles the board again.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | integer | – | Output channel, numbered from 1. Required on a supply with more than one channel. |
| off_s | number | yes | Seconds the output stays off, 0.5 to 30. |
| supply_id | string | yes | A `power_supplies` entry of the authoritative configuration, else `unknown_device`. |
No output schema declared.
No examples provided.
power_supply_output ~141
Switch one supply channel's output on or off and read the state back. Needs `allow_output`. Before switching on, the stored set points are held to the effective limits and the protection is armed at them. A type that cannot read its output state is refused before contact (`not_supported`). Switching to the state already held changes nothing.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | integer | – | Output channel, numbered from 1. Required on a supply with more than one channel. |
| on | boolean | yes | true switches the output on, false switches it off. |
| supply_id | string | yes | A `power_supplies` entry of the authoritative configuration, else `unknown_device`. |
No output schema declared.
No examples provided.
power_supply_set ~196
Set the voltage, the current or both on one supply channel. Needs `allow_set`. Refused before contact when the configuration sets no limit for the channel, or a value is above its effective limit (`power_supply_limit_exceeded`). Arms the supply's protection at the limits first, writes, and reads every value back exactly (`power_supply_readback_mismatch`). Does not switch the output.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | integer | – | Output channel, numbered from 1. Required on a supply with more than one channel. |
| current_a | number | – | Current set point in A, a multiple of the type's resolution and at most the effective limit. Never rounded. |
| supply_id | string | yes | A `power_supplies` entry of the authoritative configuration, else `unknown_device`. |
| voltage_v | number | – | Voltage set point in V, a multiple of the type's resolution and at most the effective limit. Never rounded. |
No output schema declared.
No examples provided.
power_supply_status ~134
Read a configured bench power supply: per channel its set points, measured voltage and current, output state, protection and effective limits, each exact or null where the type cannot read it. Writes nothing and needs no grant. `missing_limits` and `writes_refused_reason` say why writes on a channel would be refused. A unit other than the configured one fails `power_supply_identity_mismatch`.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | integer | – | Output channel, numbered from 1. Without it every channel is read. |
| supply_id | string | yes | A `power_supplies` entry of the authoritative configuration, else `unknown_device`. |
No output schema declared.
No examples provided.
probe_target ~92
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).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
project_config_adopt_hardware ~276
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).
| Name | Type | Req | Description |
|---|---|---|---|
| apply | boolean | – | Default false writes nothing. true writes carried via project_config_set (allow_config_description_write, else permission_denied), then call project_config_reload_description; none: applied false. |
| com_port_id | string | – | com_ports entry for the discovered device; default: the one naming it, else the only one, else a new dut_uart, created with every permission false. Several, none named: unavailable. |
| debugger_id | string | – | Configured debuggers entry that receives the values; needed when there are several (else invalid_argument). Not configured: unknown_device. An entry naming another probe: hardware_mismatch. |
| probe_id | string | – | Serial of the attached probe to read, each read step taking up to 10 s; defaults to the configured probe_id. With neither, several attached probes answer ambiguous_hardware. Selects, never adds one. |
No output schema declared.
No examples provided.
project_config_create ~72
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
project_config_describe ~87
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
project_config_reload_description ~85
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
project_config_set ~123
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).
| Name | Type | Req | Description |
|---|---|---|---|
| changes | array | yes | One or more {key, value} pairs, each key at most once, validated together: an unknown or repeated key or a value its value_schema refuses answers invalid_argument and nothing is written. |
No output schema declared.
No examples provided.
reset_target ~140
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).
| Name | Type | Req | Description |
|---|---|---|---|
| mode | string | – | Default 'run' (core executes); 'halt' stops the core at reset; 'init' also runs the reset-init script (clocks, wait states, watchdog), OpenOCD-only, else not_supported. |
No output schema declared.
No examples provided.
server_upgrade ~91
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
test_reactor_run ~221
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.
| Name | Type | Req | Description |
|---|---|---|---|
| detach | boolean | – | Default false: answers at the plan's end with `ok`, `steps`. True: once a worker holds the devices (30 s max), not at the plan's end: `run`, `state` or the verdict; else `run_worker_unresponsive`. |
| test_config_path | string | – | Path inside workspace_root, relative to it; default `.agentic-hil/testconfig.yaml`. Missing: `test_config_not_found`; unreadable: `test_config_unreadable`; outside or malformed: `test_config_invalid`. |
No output schema declared.
No examples provided.
test_reactor_status ~163
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`.
| Name | Type | Req | Description |
|---|---|---|---|
| run | string | – | A handle from test_reactor_run's `run`: `run-` and 16 hex digits, else `invalid_argument`; unknown: `run_not_found`. Leave it out to list this bench's runs: `runs`, `active_runs`. |
No output schema declared.
No examples provided.
test_reactor_stop ~144
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).
| Name | Type | Req | Description |
|---|---|---|---|
| run | string | yes | A handle from test_reactor_run's `run`: `run-` and 16 hex digits, else `invalid_argument`; one this bench never issued fails `run_not_found`. |
No output schema declared.
No examples provided.
How do I install the Agentic HIL MCP server?
Agentic HIL runs locally as a PyPI package, launched with uvx agentic-hil. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · agentic-hil
claude mcp add agentic-hil-agentic-hil -- uvx agentic-hil
What is the Agentic HIL MCP server?
Agentic HIL is an MCP server listed in the public MCP registry as io.github.agentic-hil/agentic-hil. Develop firmware on the real board behind a debug probe: flash, reset, UART and CAN, policy-gated. This page covers its PyPI package (agentic-hil).
Is the Agentic HIL MCP server safe to use?
Agentic HIL scores 95 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 4 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Agentic HIL MCP server expose?
Agentic HIL exposes 48 tools: debugger_info, debugger_probes_list, probe_target, artifact_upload, flash_firmware, and 43 more. Their descriptions and schemas cost roughly 7,659 tokens of context every time the server is loaded.
Is the Agentic HIL MCP server still maintained?
Agentic HIL is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Agentic HIL MCP server under?
Agentic HIL declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.