# Configure Agentic HIL in MCP Hosts

Agentic Hardware-in-the-Loop (Agentic HIL) exposes the same local MCP stdio server and the same tool semantics in every host. Only the host configuration syntax changes.

Every block below was verified against the linked host documentation on
2026-08-19. Moving that date is a release chore, described under "The Host
Documentation Check" in [Release Strategy](release-strategy.md), because a date
nobody moves invites more trust than it can carry.

## Common Setup

Install the server once and initialize the firmware project from its repository root:

```bash
agentic-hil setup --agent claude-code   # or: codex / opencode
```

`setup` installs the skill, registers the host with a verified absolute
executable path, and creates the external policy. Install it first if the
command is missing: [AI_AGENT_QUICKSTART.md](https://github.com/agentic-hil/agentic-hil/blob/master/AI_AGENT_QUICKSTART.md) has the
complete install chain. The per-host blocks below are the reference for every
host, the three `setup` registers itself included.

`setup` composes two commands; either runs on its own:

```bash
agentic-hil agent-install --agent claude-code   # skill + user-level registration; once per user and agent
agentic-hil init --agent claude-code            # this project's policy + doctor; from the project root
```

`agent-install` writes only under the invoking user's home: user-wide, meaning
per user and per machine, not shared with another OS user on the host. It needs
no project and reads no configuration, so a second repository for this user
needs only `init`, and a configuration location this profile refuses cannot take
the registration down.

Every host configuration below represents this launch contract:

```text
Server name:       agentic-hil
Transport:         stdio
Command:           <verified absolute path to persistent agentic-hil>
Arguments:         mcp-stdio
Working directory: firmware project root
Environment:       optional AGENTIC_HIL_CONFIG absolute-path override
```

The official MCP Registry identity is `io.github.agentic-hil/agentic-hil`. That registry identity, the local server key `agentic-hil`, and the executable `agentic-hil` refer to the same server, but they are not interchangeable fields.

The MCP host needs a persistent, trusted `agentic-hil` executable and must store its reviewed absolute path, never a bare command resolved afresh from `PATH`. `agentic-hil setup` performs the path, ownership, link, and persistence checks for supported hosts. A stable user-owned pipx/uv-tool link is allowed only when its parent chain and fully resolved target are also owner- and mode-safe and outside the workspace, temporary directories, and caches; the stored command remains the absolute user-bin link path. For a manual host, locate the user-level tool directory with `uv tool dir --bin`, review the resulting console script and target, and substitute its absolute path in the examples below. Do not save an unversioned `uvx` invocation as a long-lived server command: it can resolve a different package version later and its cache is not an installation boundary.

`server.json` publishes `"runtimeHint": "uvx"` to the MCP Registry, and that is not a contradiction: the hint tells a registry client how to fetch and try the package, which is a trial run, not the persistent registration this page governs. After trying it that way, run `agentic-hil setup --agent <agent>` so the stored command is a verified executable. `agentic-hil doctor` prints the exact command registration will accept, or says why there is none yet.

## Generated by `agent-install` (recommended)

For these three agents you do **not** need to hand-write the blocks below. `agentic-hil agent-install --agent <agent>`, which `agentic-hil setup --agent <agent>` runs first, registers the server in that agent's **user-level** config, outside the firmware repo so the untrusted repo cannot control how the agent launches tools (the same trust boundary as the authoritative config), with no baked-in `cwd` and with the verified absolute persistent executable path:

- Claude Code → `~/.claude.json` user scope (secure direct merge)
- Codex → `~/.codex/config.toml` (`[mcp_servers.agentic-hil]`)
- opencode → `~/.config/opencode/opencode.json` (`mcp.agentic-hil`)

The host launches the verified executable with `mcp-stdio` from the firmware project root; the server discovers the project's config from that working directory. The per-host blocks below are the reference and the path for other hosts. A deliberate project-scoped `.mcp.json` from `agentic-hil mcp-config --output .mcp.json` also contains the machine-specific absolute executable and must remain uncommitted.

## Authoritative Project Config

Run `agentic-hil init` from the firmware project root. It creates one authoritative config outside the repository with every permission granted except the two flashing is interlocked against, binds its mandatory `workspace_root` to that absolute project path, and verifies the result with `doctor`. Rerunning it keeps a config that is already there; only `--force` rewrites one. The generated path is under `${XDG_CONFIG_HOME:-~/.config}/agentic-hil/projects/<project-id>/config.yaml` on POSIX or `%APPDATA%/agentic-hil/projects/<project-id>/config.yaml` on Windows.

The operator reviews that file and takes away the permissions this bench should not have: every one of them starts granted except `allow_raw_debugger_commands` and the irreversible `allow_mass_erase`, which start false because `flash_firmware` is refused on a probe while either is true. Telling the agent which ones to take away works as well as editing: over MCP `project_config_set` writes `false` into a permission and no other value. The MCP server discovers the file from the configured firmware-project working directory. If a different external location is needed, set its absolute path as `AGENTIC_HIL_CONFIG` in the host's user-level, managed, or parent-process environment; do not add a machine-specific value to `.vscode/mcp.json`, `.codex/config.toml`, `.mcp.json`, `opencode.json`, or another repository-controlled file. For unattended hardware benches, use a host/user-level registration that the agent cannot edit.

Optional POSIX override:

```bash
export AGENTIC_HIL_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/agentic-hil/projects/<project-id>/config.yaml"
```

Optional Windows PowerShell override:

```powershell
$env:AGENTIC_HIL_CONFIG = "$env:APPDATA\agentic-hil\projects\<project-id>\config.yaml"
```

`%APPDATA%` and `%LOCALAPPDATA%` are the discovered defaults, and nothing about their ACLs is inspected: the ownership walk that once did was removed in 0.8.0, because it could only defend against a different account on the same machine and never against your own processes. What is still refused with `unsafe_configured_path` is a path that is not the object it names: a symlinked component, a file where a directory belongs. To bind a project to another location (a redirected profile directory, a roaming share), the override is the supported answer rather than a workaround:

```powershell
$env:AGENTIC_HIL_CONFIG = "$env:USERPROFILE\.agentic-hil\projects\<project-id>\config.yaml"
```

Set `state_root` in that file to a directory under the same root. Set `AGENTIC_HIL_CONFIG` in the host's user-level or managed environment, never in a repository-controlled file. Where each file lives: `agentic-hil://reference/platform-paths`.

## Canonical Tool Names

Agentic HIL returns one canonical name for each tool in MCP `tools/list`, such as `probe_target`, `flash_firmware`, and `com_read`. Hosts may display a qualified form such as `agentic-hil_probe_target` or `mcp__agentic-hil__probe_target`. That prefix is a host-side namespace, not a second Agentic HIL API.

Documentation, prompts, tests, and cross-host workflows should use the canonical wire name `probe_target`. Do not add aliases or change behavior by host. Use a qualified rendering only where a host's own permission or tool-selection syntax requires it.

## Tool Annotations

Each entry in `tools/list` carries the MCP `annotations` object (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) as defined in schema revision 2025-06-18, the protocol version this server advertises. Hosts that use those fields to decide which calls need confirmation get an answer per tool instead of one blanket judgement by name.

What they say:

| Class | Tools |
|---|---|
| changes nothing (`readOnlyHint: true`) | `debugger_info`, `debugger_probes_list`, `debug_get_session_status`, `debug_list_breakpoints`, `debug_get_stop_reason`, `debug_symbol_info`, `debug_symbol_value`, `get_last_report`, `classify_last_error`, `com_ports_list`, `com_read`, `can_buses_list`, `can_read`, `bench_run_status`, `project_config_describe`, `project_config_reload_description`, `test_reactor_status` |
| changes something reversible (`destructiveHint: false`) | `probe_target`, `artifact_upload`, `reset_target`, `debug_stop_session`, `debug_set_breakpoint`, `debug_clear_breakpoints`, `debug_continue`, `debug_halt`, `com_session_stop`, `can_session_stop`, `bench_run_start`, `bench_run_stop`, `test_reactor_stop`, `hardware_recover`, `project_config_adopt_hardware`, `server_upgrade` |
| may destroy what it replaces (`destructiveHint: true`) | `flash_firmware`, `debug_start_session`, `debug_dump_symbol_ihex`, `com_session_start`, `com_write`, `can_session_start`, `can_send`, `test_reactor_run`, `project_config_create`, `project_config_set` |

Three of them are worth reading before configuring a host's permission rules. `probe_target` reads and is still not read-only, because an SWD attach halts the core. `project_config_reload_description` *is* read-only: it re-reads the authoritative file, writes nothing, and touches no hardware. A host that blocks it sends the operator back to reconnecting the server, which is what it exists to avoid. `server_upgrade` replaces the installed package and is still not destructive: it erases nothing this server holds, leaves the bench and the configuration untouched, and the release it replaces is still on the index. It is idempotent because it can only lift to the newest one, so a second call finds nothing to do.

`openWorldHint` is `false` on every tool but `server_upgrade`: a bench is the closed, named set of devices the authoritative configuration declares, plus that configuration and the workspace artifact store. `server_upgrade` is `true` because what it installs comes off a package index over the network, an entity outside this machine, which is the open world exactly as the schema means it.

These are hints. Agentic HIL decides nothing by them (what a call may do is decided by the permissions in the authoritative configuration and by the machine-wide device locks), and a host is free to prompt for anything regardless.

## VS Code and GitHub Copilot

Use this server shape in the operator-controlled VS Code user-profile MCP configuration:

```json
{
  "servers": {
    "agentic-hil": {
      "type": "stdio",
      "command": "/absolute/path/to/persistent/agentic-hil",
      "args": [
        "mcp-stdio"
      ],
      "cwd": "${workspaceFolder}"
    }
  }
}
```

Run **MCP: List Servers**, start `agentic-hil`, and approve the workspace server after reviewing it. VS Code uses `servers`, not `mcpServers`. Prefer its user-profile MCP configuration for the operator-controlled registration; the configured `cwd` enables automatic config discovery.

Sources: [VS Code MCP configuration reference](https://code.visualstudio.com/docs/agents/reference/mcp-configuration) and [GitHub Copilot MCP setup](https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp-in-your-ide/extend-copilot-chat-with-mcp).

## JetBrains AI Assistant in CLion

Open **Settings | Tools | AI Assistant | Model Context Protocol (MCP)**, add a stdio server, and paste:

```json
{
  "mcpServers": {
    "agentic-hil": {
      "command": "/absolute/path/to/persistent/agentic-hil",
      "args": [
        "mcp-stdio"
      ]
    }
  }
}
```

Set **Working directory** to the firmware repository root and then enable the server. JetBrains documents this as an IDE configuration flow, not as a portable repository file. An operator-set `AGENTIC_HIL_CONFIG` remains available as an optional override.

If CLion uses the GitHub Copilot plugin instead of JetBrains AI Assistant, open Copilot Chat, select **Configure your MCP server**, and use the plugin's `mcp.json` shape:

```json
{
  "servers": {
    "agentic-hil": {
      "command": "/absolute/path/to/persistent/agentic-hil",
      "args": [
        "mcp-stdio"
      ]
    }
  }
}
```

The AI Assistant and Copilot plugin use different JSON containers. Their server and tool semantics remain identical.

Sources: [JetBrains AI Assistant MCP setup](https://www.jetbrains.com/help/ai-assistant/configure-an-mcp-server.html) and [GitHub Copilot MCP setup for JetBrains IDEs](https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp-in-your-ide/extend-copilot-chat-with-mcp?tool=jetbrains).

## OpenAI Codex

Put this table in the operator-controlled `~/.codex/config.toml` and replace `cwd` with the absolute firmware repository root:

```toml
[mcp_servers.agentic-hil]
command = "/absolute/path/to/persistent/agentic-hil"
args = ["mcp-stdio"]
cwd = "/absolute/path/to/firmware-project"
enabled = true
```

The configured `cwd` enables automatic config discovery. Start Codex with `AGENTIC_HIL_CONFIG` inherited only when an absolute-path override is required. Project-scoped configuration is unnecessary for this registration.

Sources: [Codex MCP setup](https://learn.chatgpt.com/docs/extend/mcp) and [Codex configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference). Both moved off `developers.openai.com`, which answers them with a permanent redirect.

## Claude Code

Use this server shape in an operator-controlled Claude Code user registration:

```json
{
  "mcpServers": {
    "agentic-hil": {
      "type": "stdio",
      "command": "/absolute/path/to/persistent/agentic-hil",
      "args": [
        "mcp-stdio"
      ]
    }
  }
}
```

The equivalent CLI command, run from the firmware repository root, is:

```bash
claude mcp add --transport stdio --scope user agentic-hil -- "/absolute/path/to/persistent/agentic-hil" mcp-stdio
```

`agentic-hil mcp-config --output .mcp.json` writes this host family's machine-local `mcpServers` discovery format with the verified absolute executable: the `command` and `args` above, and no `type`, because Claude Code reads an entry without one as a stdio server and only a `url` entry has to declare its transport. The user-level entry `agent-install` writes does state `"type": "stdio"`, because an operator reads that file. Neither includes `AGENTIC_HIL_CONFIG`, and neither generates VS Code, Codex, or OpenCode configuration. Keep this machine-specific project file uncommitted; prefer `setup --agent claude` for the secure user-scoped registration and add an operator-set override only when needed.

Source: [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp).

## OpenCode

Add this server to the operator-controlled `~/.config/opencode/opencode.json` and replace `cwd` with the absolute firmware repository root:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "agentic-hil": {
      "type": "local",
      "command": [
        "/absolute/path/to/persistent/agentic-hil",
        "mcp-stdio"
      ],
      "cwd": "/absolute/path/to/firmware-project",
      "enabled": true
    }
  }
}
```

OpenCode uses `mcp`, `type: "local"`, and one command array. For an operator-controlled registration, use `~/.config/opencode/opencode.json`; its `cwd` enables automatic config discovery. If an override is needed, inherit `AGENTIC_HIL_CONFIG` from the parent environment rather than placing its machine-specific value in project configuration. Managed configuration is preferable on unattended benches because project configuration has higher precedence than normal global configuration.

Sources: [OpenCode MCP servers](https://opencode.ai/docs/mcp-servers/) and [OpenCode configuration locations](https://opencode.ai/docs/config/).

## Generic MCP Host

MCP standardizes the stdio transport, not a universal host configuration file. In the host's MCP settings, map the common launch contract to its local fields:

```text
Name:              agentic-hil
Transport:         stdio
Executable:        <verified absolute path to persistent agentic-hil>
Arguments:         mcp-stdio
Working directory: <absolute firmware repository root>
Environment:       optional AGENTIC_HIL_CONFIG=<absolute external config path>
```

Do not assume that `mcpServers`, `servers`, `mcp`, `env`, `cwd`, or `enabled` are portable keys. A Claude-compatible `.mcp.json` is a host convention, not part of the MCP specification.

Source: [MCP stdio transport specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#stdio).

## Verify the Connection

1. Confirm the host reports `agentic-hil` as connected.
2. Inspect the host's tool list or MCP `tools/list` result.
3. Confirm canonical tools such as `debugger_info`, `probe_target`, and `flash_firmware` are present.
4. Run `debugger_info` before a hardware action when setup is unclear.
5. Treat `permission_denied` as authoritative. Ask the operator to review the authoritative config; do not bypass it.

See [Troubleshooting](https://github.com/agentic-hil/agentic-hil/blob/master/TROUBLESHOOTING.md) for startup, configuration, `PATH`, and debugger errors.
