ka2a documentation
Read-only MCP diagnostics
This guide describes ka2a at revision a34b8bc9d319502002f104d28f90d18c325a5d26. Source: docs/mcp.md. Source links require repository access. The App examples on the product page use reviewed revision a7c8ac4a85f5.
Contents
ka2a mcp lets an agent client inspect one endpoint's recorded state. Model Context
Protocol (MCP) carries the tool calls. MCP Apps adds an interactive view inside a
compatible client. Clients without App support receive text and JSON results.
The server reads an existing state directory. It works while ka2a run owns the endpoint
and after the node stops. It needs no broker credentials and never contacts Kafka.
The tools cannot send or change work.
Connect a client
Build or locate the
ka2abinary. For a source build with the App, run these commands from the repository root:make web make buildThis creates
bin/ka2a.make webneeds Node 22.12 or later and npm. The binary needs no Node at runtime. Without generated assets, all six tools work but advertise no App.Choose an existing endpoint state directory. The MCP process must run as a user who can read it. To create a demo endpoint first, follow Try it. The server refuses a missing, unsafe or incompatible store before the MCP session starts.
Add the server to your MCP client. Replace both paths with absolute paths on the host that will run the process:
{ "mcpServers": { "ka2a": { "command": "/absolute/path/to/ka2a", "args": ["mcp", "--state-dir", "/absolute/path/to/endpoint-state"] } } }The configuration location depends on the client. It launches the command as a subprocess and exchanges MCP messages through standard input and output (stdio). You can use
KA2A_STATE_DIRinstead of--state-dir.Call
node_statuswith{}. In an App-capable client, use the section navigation to inspect operations and other records. Otherwise, call the tools below directly.
There is no custom web listener or login page. Metrics and health probes keep their existing guarded endpoints. See the configuration reference for all startup flags.
Tools
| Tool | Arguments | Result |
|---|---|---|
node_status | {} | A ka2a.snapshot/1 with endpoint identity, quarantine, storage and counts. Its record lists are empty. |
list_operations | Optional limit (default 50, maximum 200), nonnegative cursor (default 0) and exchange states. | A ka2a.snapshot/1 with sent operations, newest first. operations.next_cursor is 0 at the end. |
get_operation | Required positive integer seq from an operation row. | A ka2a.operation/1 with send, exchange, response and task observations. |
inspect_endpoint | Required section, with optional page and state filters described below. | A snapshot page for outbox, dispatch, rejections, incidents or partitions. |
get_recovery_rehearsal | {} | The sanitized simulation report selected at server startup. |
get_implementation_replay | {} | The model/implementation observation artifact selected at server startup. |
For example, call list_operations with:
{"limit": 10, "cursor": 0}
Then call get_operation with a seq from the result:
{"seq": 42}
A pseudonym such as op~... is display data, not a lookup key. Pseudonyms stay consistent
within one server session and change when the server restarts. The tools have no option
to reveal raw message identifiers.
Read the source before interpreting a result
Endpoint and operation results identify the store observation with source.statement and captured_at.
Recovery reports use simulated_at and their notice. Replay artifacts identify sources, revision and scope, without a capture timestamp.
- An owner lock means a process held the lock at capture time. It is not a health check.
- Without an owner, the data is historical: the last state committed to the store.
- Broker connectivity stays unknown unless you enable the separate live-status read below.
- A broker acknowledgement does not establish remote recording. A protocol response does not establish that the application task completed.
- Each page is a new snapshot. Concurrent writes can change counts between calls.
- Free bytes inside SQLite are unused database pages, not free disk capacity.
The tools omit bodies, typed response results, task snapshots and key material. Stored text remains untrusted data. Tool metadata declares read-only, idempotent and closed-world hints. These describe the implementation and do not grant client permissions.
Endpoint status App
All six tools use one self-contained App. Its navigation, refresh, state filters and next/previous controls call fixed read-only tools through the host. Capture time, source limits and unknown observations stay visible.
The host must advertise the io.modelcontextprotocol/ui extension and support the
text/html;profile=mcp-app MIME type. The server then adds a UI resource reference to the
tool metadata. Its only App resource is ui://ka2a/node-status.html, at most 2 MiB.
Text and JSON results remain available to every client.
The App makes no external API or resource requests. Its content security policy forbids external connections, assets, frames and forms. Stored text remains inert. Cancelled or superseded requests cannot replace a newer view.
Release binaries contain the App. Go-only source builds and make verify need no Node.
The App build guide covers browser tests and screenshot regeneration.
Those tests use a local host built with the official SDK. They do not qualify every
third-party MCP client.
The App replaces the former serve-ui and run --ui-listen interface. There is no separate
web UI, login token or cookie session.
Operation journeys and endpoint inspection
Select a row from list_operations, or call get_operation, to inspect one journey.
Local admission, broker acknowledgement and the protocol response keep separate timestamps
and meanings. The App labels remote recording “Not directly observed” because the local store has no separate remote receipt.
The SDK and CLI can infer remote recording from a correlated response.
The view shows publication attempts, reasons and the observed task state. Its arrows describe protocol stages. They do not reconstruct an event history or fill gaps in evidence.
inspect_endpoint accepts these arguments:
| Argument | Values |
|---|---|
section | outbox, dispatch, rejections, incidents or partitions. |
limit | Optional integer from 1 to 200. |
cursor | Optional page cursor. Partitions have no cursor. |
states | Optional array for outbox and dispatch. Default filters show unresolved publication and started or held dispatch. |
Each row can reveal all retained fields in the observation result. Configuration, counts
and outbox totals come from the same read. list_operations also accepts an exchange
states filter.
Optional live status
For the running node's broker, credential and catalog observations, start the node with
run --control. Add --live-status to the MCP command:
ka2a mcp --state-dir /absolute/state --live-status
MCP reads GET /status on the endpoint's private local socket. It does not contact a broker.
A missing socket leaves connectivity unknown. This process observation is separate from
the store transaction. --budget-bytes selects the observed storage budget, and the App
labels its source.
Inspect a retained snapshot
To read a previously exported snapshot instead of a current store:
ka2a mcp --snapshot /absolute/snapshot.json
The file must contain pseudonymized identifiers. It keeps its original capture time and contains only the recorded pages. The server never reads a current store for this source. Operation lookup searches only the recorded operations page.
Retained files show source.retained_file: true. Their page limits stay visible.
Custom limits, filters and further cursors are refused. The App disables those controls.
Retained recovery rehearsals
A recovery rehearsal is a saved simulation report. The simulator runs real store transitions on a private copy. The MCP tool reads the report without running or applying recovery.
Run the simulator, save its JSON output, then select that file when starting the MCP server. Replace the paths and dispatch number with your own values:
ka2a recovery simulate --state-dir /absolute/state \
--release-dispatch 3 --reason operator_checked --output json > /absolute/rehearsal.json
ka2a mcp --state-dir /absolute/state --recovery-report /absolute/rehearsal.json
Call get_recovery_rehearsal with {}. The App shows before/after states, refused actions
and invariant checks: the store rules that the simulation checked. The operator supplies
the report, and the viewer does not independently verify it. An apply receipt is not a rehearsal.
The reader accepts at most 256 KiB, 100 actions, 200 changed records and 32 invariants. It refuses malformed or duplicate JSON fields and unsupported states. The view omits source paths, source identifiers and free-text details. Operation targets use session pseudonyms. Keep the original local report for exact refusal details. Its SHA-256 digest appears in the App.
Model and implementation replay
A replay compares expected model states with recorded implementation observations. The development harness exports observations from the real checkpoint coordinator and SQLite store. Run this command from the source checkout, then select the artifact at MCP startup:
KA2A_REPLAY_EXPORT=/absolute/replay.json \
go test ./internal/modelbridge -run '^TestExportModelImplementationReplay$' -count=1
ka2a mcp --state-dir /absolute/state --replay-report /absolute/replay.json
Call get_implementation_replay with {}. One cursor moves through both sets of values.
The App highlights the first mismatch. The display includes selected observation points
and labels test broker and handler counters. The harness also checks the complete replay
mapping. A negative-control test confirms that a broken coordinator produces a mismatch.
The model-implementation-replay/1 artifact records:
- model, trace and mapping paths with SHA-256 digests.
- the implementation revision, or
unknown, and whether the working tree was modified. - exact integers as
#bigintstrings. - the trace scope and exclusions.
The reader accepts at most 256 KiB, 200 steps and 64 comparisons per step. The normalized MCP replay result is at most 512 KiB, including its text fallback. The reader refuses inconsistent comparison flags and first-divergence claims.
Agreement covers the recorded trace and mapping. It does not prove general implementation correctness or liveness. The production binary never runs Quint or the replay harness.
Boundaries and request limits
The tools never take ownership, migrate, admit, retry, release, abandon, import, export or purge work. Tool arguments cannot supply paths. Startup flags select retained files.
| Limit | Value |
|---|---|
| Request frame | At most 64 KiB. |
| Unanswered calls in the SDK session | At most 16. |
| Tool deadline | Five seconds. |
| Tool result | At most 1 MiB, including structured content and the JSON text fallback. The JSON-RPC envelope is outside this bound. |
| Drain after end of input | Up to five seconds for accepted calls. |
An excessive result asks the client to narrow the page. Unknown arguments and out-of-range
values fail. Storage and lookup failures retain their observation error codes, such as
state_missing, unsafe_storage, not_found or expired.
Standard output carries only protocol messages, including with --output json.
Diagnostics go to standard error. A stop signal ends the command even if the client stopped
reading output.
Read-only SQLite inspection can create an empty write-ahead log (WAL) and its shared-memory index beside a closed store. It does not change durable records or the epoch.