Agent transports — MCP (ign mcp serve) and LSP (ign lsp)
v1.1 exposes the whole command surface over protocols. Both modes own stdout completely — the streaming exceptions above apply doubly, since inside a protocol stream a single stray byte is protocol death. Both are thin lenses: the command surface they mirror is the CLI's own, so a new CLI verb becomes an MCP tool or an LSP capability through derivation, never a second hand-written catalog.
ign mcp serve — the MCP transport
Register with any stdio MCP client:
claude mcp add ign -- ign mcp serve # Claude Code
# generic client: command `ign`, args ["mcp", "serve"]
- The tool catalog derives from
Cli::command()— every CLI verb surfaces as a tool automatically (83 at v1.1) with global args folded into each schema (--json/--compactforced on,--yesreplaced by theconfirmfield, profile ambient). A CI parity test walks the live clap tree, so the catalog structurally cannot drift from the CLI. - The frozen envelope rides verbatim as tool-result content — the
two documented prose exceptions (
ign api call's gateway-verbatim data, MCP's own refusal prose below) are dated above and in the Contract exceptions section. - Guarded writes translate
--yesto aconfirmtool-call field. This applies to every--yes-guarded verb, includingworkspace push(confirm: trueis the MCP-native confirmation for the splice).confirmis deliberately OPTIONAL in every guarded schema — a required field would invite agents to auto-fill it, defeating the human-in-the-loop gate. Omitting it returns the same refusal envelope (blast radius and all) as the tool result; unknown keys fail closed with-32602. Deliberately unguarded verbs (rig downand the others) carry noconfirmproperty at all on either surface — that asymmetry is by design, not a gap. pingnever starves: tool calls are served concurrently while one blocks on the gateway.protocolVersionnegotiates2025-06-18(echo-if-equal).- Raw-stdout verbs refuse at the bridge:
ign rig logsandign logs --followprint through in-dispatch sinks, so the MCP bridge refuses them before they can corrupt the stream — the refusal names the terminal form.
ign lsp — live gateway truth for editors
A stdio LSP server (sync dispatch loop) serving three completion families (tag paths, named queries, providers), TTL-stamped hover, and diagnostics from a TTL-cached gateway snapshot:
- Never a blocking network call inside an LSP request — handlers are pure functions over one snapshot Arc; the request path cannot hang the editor.
- A dead gateway degrades honestly: diagnostics publish EMPTY (no cached oracle, no verdict) instead of spamming errors; the background refresher re-resolves per cycle so recovery appears next cycle.
- Composition, not replacement: Python
ignition-lspkeeps statics ownership (definition, codeAction, workspace symbols); nvim's native multi-client merge composes the two servers. The nvim/zed clients live in ignition-ide-plugins (ignition_liveregistersign lspbeside the statics client whenignis on PATH; virtual buffers re-attach across restarts for both clients).
Agent skills — the playbook layer
The ignition-ops skills teach agents
the contract rules this README codifies (envelope streams, exit
taxonomy, guarded-write semantics, loss gates) without reading 1,600
lines first: ign-contract, ign-gateway, ign-tags,
ign-workspace, ign-rigs. Install with npx skills add TheThoughtagen/ignition-cli (any harness the skills CLI supports) or
as a Claude Code plugin: /plugin marketplace add TheThoughtagen/ignition-cli → /plugin install ignition-ops@ignition-cli.