Skip to main content

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/--compact forced on, --yes replaced by the confirm field, 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 --yes to a confirm tool-call field. This applies to every --yes-guarded verb, including workspace push (confirm: true is the MCP-native confirmation for the splice). confirm is 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 down and the others) carry no confirm property at all on either surface — that asymmetry is by design, not a gap.
  • ping never starves: tool calls are served concurrently while one blocks on the gateway. protocolVersion negotiates 2025-06-18 (echo-if-equal).
  • Raw-stdout verbs refuse at the bridge: ign rig logs and ign logs --follow print 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-lsp keeps 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_live registers ign lsp beside the statics client when ign is 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.