RFD 0066 — Agent integration: the Argon MCP server
- State: discussion
- Depends on: RFD 0014 (§19 runtime serving — the connection/serve split this parallels: a transport-agnostic dispatch core under a thin transport layer), RFD 0033 (the ad-hoc query and mutation surface — the type-checked-or-refused body this exposes as
argon_ad_hoc_query), RFD 0036 (heterogeneous and specialized stores — theConnection::Remotefederation path the remote profile rides), RFD 0046 (derivation serving surfaces — the structuredProofTree/explainmodel this consumes, and the why-not boundary it marks open), RFD 0052 (deployment topologies and the connection abstraction — the embedded vs. standalone split this server’s two profiles inherit) - Prior art: the Model Context Protocol (MCP) and the official Rust SDK (
rmcp) — the tool/resource/prompt vocabulary and the stdio transport this server speaks; the Language Server Protocol (ox lsp) as the editor-frontend precedent — a second frontend over the same compiler internals, shipped with the toolchain, editor-agnostic; CQRS read-model framing (RFD 0020 D10) for why the runtime read surface is a shared asset a third frontend may serve without owning the engine.
Question
Argon’s compiler and runtime expose no live integration surface for a coding agent. ox gen --target ts-skill emits a static, per-ontology SKILL.md + SDK reference for writing TypeScript against a generated SDK — explicitly a code-generation artifact, not a runtime client. ox lsp gives an editor-agent the check loop, and nothing more. The live compiler+runtime agent lane is empty: an agent cannot reach the runtime’s structured provenance, bitemporal as_of, first-class n-ary relations, forks, or standpoints, and cannot close the authoring loop (edit → check → why → build → reload → query → explain) against a running knowledge base.
What is the right integration surface for a coding agent, and where does it sit relative to the existing frontends? Specifically: does it ride the existing transport-agnostic dispatch core (sibling to oxc-serve’s HTTP layer) or duplicate runtime logic; what does it expose and what does it withhold; and how does it keep source, artifact, and the served module coherent so an agent never reasons over a stale or wrongly-typed knowledge base?
Context
- The dispatch core is already transport-agnostic.
oxc-connection’sRuntimeServiceis the state holderoxc-servewraps; thedispatch_*_coreentry points andexplain_fork_fact_proofare framing-neutral.oxc-serveis a thin axum/v1layer over them (RFD 0014). A coding-agent surface is a third frontend over the same core — sibling to HTTP, not a new runtime. RuntimeServicecarries the coherence machinery the bareConnectiondoes not. It holdsreload_if_changed/spawn_watch_task(hot-swap the active module on artifact change; loud-refuse an invalidating schema change against a live ABox, never silently re-type), theOperabilityLimitsgovernor, per-scope mutation locks, cursor pagination over query rows, and the fork lifecycle. The bare embeddedConnection(the Tide / RFD 0052 embedder path) has no reload — building on it would reintroduce source/artifact incoherence and duplicate reload logic.- The governor already enforces the loud-gate philosophy at runtime.
OperabilityLimitsenforces a request timeout, a reasoner budget checked at every fixpoint round boundary (so CPU-bound work terminates), and a row cap that refuses loudly rather than truncating.AdmissionControl(multi-tenant concurrency fairness) is a separate, orthogonal concern — inert for a single stdio client. - Cursor pagination over query rows already exists (
DispatchRequest.page, R-M17/#259); only theConnection::queryconvenience omits it. Riding the fullDispatchRequestthroughRuntimeServicegets paging for free. - The coherence primitives already exist.
oxc-oxbin::content_hash(SHA-256 over canonical CBOR, §18.6), the loadedmodule_hash, and the lockfile hashes are the substrate for a precise staleness model — none of it needs to be invented. - Structured provenance already exists for data facts.
explain_factreturns a structuredProofTree; a clean non-derivation is reported asderived:false,root:None. The check-violationwhyis, by contrast, currently prose (render_violation_why). Real why-not provenance does not exist (RFD 0046 marks it open). - The diagnostic catalog is single-source and already teaches.
ox explain OE####emits extended explanations fromgrammar.d; the same catalog feeds CLI and LSP. The loud-gate codes (OE13xx, OE1317) are the actionable surface an agent most needs guidance on.
Decision
Specify oxc-mcp / ox mcp: an MCP (Model Context Protocol) server that exposes the authoring loop (check/build/why) and the runtime (bitemporal query, structured provenance, forks, standpoints) to agents, as a third frontend over the existing dispatch core — sibling to oxc-serve’s HTTP layer, parallel to ox lsp.
D1 — Runtime-provenance-led, one closed loop
The headline value is the runtime: structured ProofTree provenance (explain_fact), bitemporal as_of, first-class n-ary relations, forks, standpoints — none of which a coding agent can otherwise reach. The authoring loop (check/why/build) is the on-ramp, not the headline — ox lsp already gives an editor-agent the check loop. The product is the closed loop: edit source → check → why → build → reload → query → explain_fact → iterate. The design is organized around making that loop coherent and legible, not around re-exposing the editor’s check surface.
D2 — The runtime backend is RuntimeService, not the bare Connection; the server is a third frontend
oxc-mcp’s tool handlers are to RuntimeService what oxc-serve’s HTTP handlers are: thin framing over dispatch_*_core + explain_fork_fact_proof, minus axum, plus the authoring tools. The backend is RuntimeService precisely because it carries reload_if_changed/spawn_watch_task, the governor, per-scope mutation locks, cursor pagination, and the fork lifecycle. The bare Connection has no reload — using it would reintroduce source/artifact incoherence and duplicate reload logic. One McpError(ConnectionError) newtype (to satisfy the orphan rule), symmetric to serve’s ApiError.
D3 — Two profiles, one tool surface
- Local =
RuntimeService(in-memory storage, watchingtarget/<pkg>.oxbin) +oxc-workspace— the full authoring and runtime surface, coherent by construction; what a coding agent uses. - Remote = a
/v1HTTP client against a deployedox runtime serve(theConnection::Remoteimpl, RFD 0052 D2) — runtime read/introspect only (you do not author against a deployed knowledge base), gaining admission + crash isolation from the separate process.
These are profiles, not maturity levels — the tool surface is one surface; a profile determines which tools are live. The agent learns which surface is available via argon_status.
D4 — The coherence invariant (the spine)
Source, artifact, and served module are kept coherent by construction, never guessed:
argon_buildwrites the.oxbin, then explicitly callsreload_if_changedbefore returning (deterministic — it does not rely on the watch debounce); the watch task is a backstop.- Every runtime result is stamped with the serving
module_hash. argon_statusexposes{loaded_module_hash, on_disk_oxbin_hash, source_dirty, fork, as_of, limits, capabilities}so staleness is observable, never inferred.- An invalidating schema swap against a live ABox refuses loudly — structured
schema_incompatible/needs_rebuild— never a crash, never a silent re-type.
The primitives (content_hash, module_hash, lockfile hashes) already exist; D4 composes them into a stated invariant.
(As-built: the dirty check is a content-hash of the build inputs — a blake3
digest over every *.ar under the project PLUS ox.toml / ox.lock (the
prelude / dependency surface that changes the artifact without touching an .ar),
compared to the digest captured at the last build. It is unsound-safe: an
unreadable input fails TOWARD dirty, never silently clean. The first cut’s mtime
proxy was racy and blind to ox.toml/lockfile edits — replaced. argon_build
verifies active_module_hash == built_hash after reload rather than trusting
reload_if_changed silently. A dirty runtime tool auto-builds (DirtyPolicy),
or refuses with a structured DIRTY_WORKSPACE / NO_ARTIFACT result naming the
next step.)
D5 — Governor: reuse, do not rebuild
The MCP server configures the existing OperabilityLimits (a tighter row cap to protect agent context) and adds per-call cancellation. It does not import AdmissionControl — multi-tenant concurrency fairness is inert and unneeded for a single stdio client. The row cap refuses loudly over the limit (the loud-gate philosophy applied to result size); it never truncates.
D6 — Pagination: ride the full DispatchRequest
Cursor pagination over query rows already exists (DispatchRequest.page, R-M17/#259); only the Connection::query convenience omits it. Riding RuntimeService + the full DispatchRequest gets paging for free. Over-cap unpaged reads refuse loudly — never truncate.
D7 — Error model: domain outcomes are successful results
Domain outcomes — check found violations, an ad-hoc body is ill-typed, a query is empty, a fact is not derived — are successful tool results (isError:false) carrying structured payloads. McpError is reserved for “couldn’t run.” Surfaced payloads carry stable, machine-readable fields: stale_artifact, needs_build, limit_exceeded, capability_required, diagnostic_codes, retryable.
(As-built: the split is exactly this — McpError is a newtype over
oxc_connection::ConnectionError (orphan rule), mapping the core’s status / code
/ message / details onto rmcp’s ErrorData; everything else returns
Ok(CallToolResult) with a structured payload (needs_build, stale_artifact,
diagnostic_codes, limit_exceeded, truncated, …). A row-cap overflow
(ARGON_RUNTIME_RESULT_TOO_LARGE), a derive of an underivable head
(ARGON_RUNTIME_DERIVE_FAILED), an ad-hoc type error, and a check delta-guard
rejection (ARGON_RUNTIME_CHECK_VIOLATION) are all domain outcomes, not errors.
capability_required / retryable are reserved for the gated fork / Remote
surfaces.)
D8 — ProofTree folding
A recursive derivation branches exponentially, so explain_fact returns a bounded projection — the root plus the first N inference levels, each unexpanded subtree carrying a stable node-id — plus an expand_proof(node_id) tool for depth on demand. Never naive full serialization.
D9 — Teaching lives in the diagnostic catalog, not in the server
Enrich the loud-gate codes (OE13xx, OE1317) with actionable, fix-class remediation in the single-source catalog (grammar.d) → CLI (ox explain), LSP, and MCP all benefit; the argon_check payload inlines them. The loud-gate sequence (an agent will not infer it from tool descriptions alone) is encoded in the server instructions field and in the argon_authoring_loop / argon_diagnose_absence prompts.
D10 — Write model: ephemeral fork first-class, promotion built correctly
The ephemeral fork (create → mutate test facts → query/derive/explain → auto-abort, never promotes) is read-shaped, safe, and first-class — the hypothetical-reasoning / rule-testing primitive. Promote-to-main is built correctly, not omitted: fork_diff summarizes in domain terms; promotion is capability-gated per-call with an unmistakable state indicator, carrying conflict behavior + provenance. The fork machinery already exists in RuntimeService.
D11 — why unification
explain_fact already returns a structured ProofTree for data facts; the check-violation why is currently prose (render_violation_why). Unify the check-violation why to the same structured trace shape (violated rule/constraint id, involved declarations, premise facts, spans) plus a prose rendering — one provenance model, two entry points. This is a real build item in oxc-runtime’s check-explanation path, not an MCP veneer.
D12 — Negative provenance: an honest boundary
“Why did X not derive / why is this query empty” is where ontology authors live, and real why-not provenance does not exist (RFD 0046 marks it open/out-of-scope; explain returns a clean derived:false, root:None). Do not fake it. explain_fact reports derived:false distinctly (a membership answer, not an error); argon_diagnose_absence guides the decomposition with existing tools (confirm the rule is evaluable, derive each body predicate, explain each expected premise, check as_of/standpoint). Genuine why-not is the top runtime frontier (a reasoner feature, RFD 0046), outside this RFD’s remit.
D13 — Packaging
oxc-mcp is a crate (an rmcp server; a Backend trait with Local/Remote impls; an actor/mailbox serializing the non-Sync state with per-call cancellation; the coherence layer). ox mcp is a subcommand in oxc-driver mirroring ox lsp, shipped with the toolchain via oxup, editor-agnostic. A Claude Code plugin bundle (a manifest registering ox mcp + the prompts as a skill) is the reference distribution. The rmcp (official Rust MCP SDK) API must be verified at implementation time.
Tool, resource, and prompt surface
Names are snake_case, no dots (MCP-tool-name convention). This section is
reconciled to the as-built oxc-mcp surface (the embedded stdio profile);
where the implementation refined the original enumeration the delta is stated
inline. The decisions D1–D13 stand; only the surface census moves.
Authoring (loud gate):
argon_check— the full check pipeline over SOURCE; structured diagnostics ({code, severity, message, range, fix?}). Runs even when no artifact is loaded (the repair on-ramp); binds the samefull_package_diagnosticsthe LSP runs. (Fix-class remediation is whatever the single-source catalog carries per D9 — the payload inlines the catalog codes, it does not author its own.)argon_build— compile to.oxbinbehind the loud gate, atomically write, reload, and verifyactive_module_hash == built_hash; returns{ok, moduleHash, wroteOxbin, gateFailures, message}. A gate failure is a domain outcome, not an error.argon_status— the staleness probe: loaded vs on-disk module hash,sourceDirty,artifactLoaded, the paths.argon_test— test-mode build; reports whether the test-bearing artifact compiled (the loud test gate).
Runtime read (full Truth4 envelope):
argon_query— a declared query; bitemporalas_of; cursor-paged; returns the FULL four-valued (Truth4) envelope (per-row truth, hidden K3 counts). Federation is driven by the query’s declaredacross [...]clause — there is no per-callacrossoverride (it is not on the lifted dispatch core, so exposing one would be a false affordance).argon_ad_hoc_query— an RFD 0033 body (source string), type-checked against the loaded module or refused; fullTruth4.argon_derive— materialize a derived extent; fullTruth4envelope, optional per-tuple proof tags.argon_scenario_run— materialize the whole derived model once and project every head in the FULLTruth4envelope ({projection, factsDerived, facts:[{head, tuple, truth4, hidden}], hidden}). A scenario materializes only definite-Isfacts (foreign connectors hard-refused;across/ enumerate heads held separately; defeat planes 2-valued), so each fact carriestruth4:"Is"andhiddenis all-zero — the tag makes “all-Is by construction” legible rather than leaving the agent unable to tell it from an envelope-stripped read.projectK3:truerenders the bare{head, tuple}. (As-built rename of the RFD’sargon_snapshot: the tool runs the scenario’s full derivation, not a paged store dump — the name now says what it does. Deliberately a tool, not a standing resource, as the RFD intended. The full-Truth4 envelope is single-sourced in the MCP renderer over the shared corederived_snapshot_value— the/v1/snapshotflat shape is unchanged.)argon_explain_fact— the full structural AND/ORProofTreefor one fact (live read-point only);maxDepthfolds the tree. A not-derived fact returnsderived:falseplus awhyNotnegative-provenance tree — an honest membership answer (D12), not a synthesized why-not.argon_expand_proof— re-reconstruct a fact’s proof at a largermaxDepthto drill past afoldedmarker (D8). (As-built: folding is by depth, not by per-node id —maxDepthis the stable handle; same reconstruction asexplain_fact.)argon_checks_current— evaluate the module’s checks against current state (optionally one by name); returns the violation set +clean.argon_why— glass-box runtime check violations: evaluate the scope’s checks and return the firings. (As-built: the D11 unification — a single structured check-violation provenance shape inoxc-runtime, prose + structured trace — is NOT what shipped here.argon_whyreturns the structured firing set the runtime already produces; the deeper D11 build item inoxc-runtimeis a follow-on, see “Gated / follow-on”.)
Write (full check-guard pipeline):
argon_mutate— a declared mutation; returns the receipt, minted entities, and the RFD 0046 D2 derived delta ({added, removed}per head, whenincludeDerivedDeltais set) + observe-channel diagnostics. A check delta-guard rejection (ARGON_RUNTIME_CHECK_VIOLATION) is a structured domain refusal — atomic, nothing persisted — not an error.argon_ad_hoc_mutate— an RFD 0033 mutate body (source string), type-checked then executed and persisted through the SAME RFD 0025 check delta-guard pipeline as a declared mutation.argon_batch— an ordered array of declared mutations executed ALL-OR-NOTHING in ONE per-scope critical section (step N sees steps 0..N), persisted in one transaction. A mid-batch check-guard violation rolls back the WHOLE batch — nothing persisted — surfaced as a structured domain refusal carrying the failing step’s 0-basedbatchStep. RidesRuntimeService::run_batch(lifted by #1205), with the step projection single-sourced inoxc_connection::render_batchso the/v1/batchand MCP surfaces cannot drift.
Compute (pull-plane evaluation):
argon_compute— evaluate a declared compute fn over the scope’s committed state (optional bitemporalas_of); returns{value, emissions, moduleHash}. A top-level payloadless enum constant renders{tag}(RFD 0027 D5). RidesRuntimeService::run_compute(lifted by #1205), with the value projection single-sourced inoxc_connection::render_compute(the same/v1compute render, byte-for-byte).
Discovery / introspection:
argon_schema_lookup— look up a concept / relation / query / mutation / check by qualified path or short name, or the whole schema index, from the loaded module (scoped — never an unfiltered whole-TBox dump). (As-built: this folds in the RFD’s separateargon_list_queries+argon_describe_query— one name-or-index lookup over the schema covers list-all and describe-one.)argon_epistemics— the per-construct epistemic profile: decidability tiers + standpoint lattice from the loaded artifact,constructfilters to one name. (As-built addition: the tool-shaped read over the tier/standpoint surfaces the RFD only exposed as resources.)
The complete as-built tool census is eighteen: argon_check, argon_build,
argon_status, argon_query, argon_derive, argon_mutate, argon_batch,
argon_compute, argon_ad_hoc_query, argon_ad_hoc_mutate,
argon_explain_fact, argon_expand_proof, argon_why, argon_checks_current,
argon_scenario_run, argon_test, argon_epistemics, argon_schema_lookup.
Resources (stable, addressable; routed through the ArgonRuntimeHandle trait,
not a local file read, so a future Remote impl serves them identically):
argon://diagnostics/catalog— the wholeOE####catalog (every code, severity, description, long-form explanation, reserved flag); the agent’s authority on what a code MEANS, sourced from the sameOxcDiagnosticCodethe compiler emits.argon://diagnostics/{code}— a template: one code’s entry.argon://schema/index— the loaded module’s schema index. (As-built: a single scoped index resource, not the RFD’sargon://schema/{path}per-path template — per-construct lookup is theargon_schema_lookuptool’s job; the resource is the index.)argon://standpoints— the standpoint lattice (artifactstandpoint-latticesection, §D.7).argon://tiers— the decidability tier table (artifacttier-tablesection, §D.8).argon://module— the active artifact’s load status + module hash. (As-built rename of the RFD’sargon://module“manifest + hashes”.)
Five resources + one template. As the RFD intended: not current-diagnostics
(that is argon_check output), not the derived snapshot (that is
argon_scenario_run).
Prompts (investigation playbooks; each written so the agent drives the full epistemic state, not the K3 projection, and respects the loud-gate build loop):
argon_investigate_fact— is this fact derived, and why / why-not? Drivesargon_status→argon_explain_fact→argon_expand_proof, reading every row’struth4.argon_diagnose_absence— the counter-abduction loop: a query is empty / a fact is missing; inspect thehiddenCan/Bothcounts first, then derive, explain a representative missing tuple, and propose the smallest base-fact change as a type-checkedargon_ad_hoc_mutatefor a human to confirm.argon_audit_mutation— what would this write change (the D2 derived delta) and does it cross any check? Drivesargon_mutatewithincludeDerivedDeltaandargon_whyon a refusal.
(As-built delta: three prompts — the RFD named argon_authoring_loop +
argon_diagnose_absence. argon_authoring_loop is subsumed by the server
instructions field, which states the loud-gate sequence verbatim; the three
shipped prompts are the runtime-investigation playbooks D1 leads with —
fact-provenance, absence-diagnosis, write-audit.)
Gated / follow-on (NOT in the as-built surface)
- Remote (
/v1client) profile + streamable-HTTP transport. The backend is theArgonRuntimeHandletrait precisely so aRemoteimpl slots in without reworking a handler, but it is NOT built — it is gated on the open coordination-model decision (how an agent’s scope/principal binds to a remote deployment, an Open question below). The as-built ships the embeddedstdioprofile only; D3’s two-profile design stands, one profile is live. - Fork lifecycle (
argon_fork_create/_mutate/_query/_derive/_explain/_diff/_abort/_promote, D10). Forks are NOT on the transport-neutralRuntimeServicesurface the #1205 dispatch lift exposed — fork orchestration lives on the embeddedoxc_connection::Connectionand as serve-private/v1handlers (exactly as query dispatch did before #1205). Wiring forks here would mean reimplementing that orchestration; instead it is a follow-on needing a fork-orchestration lift (analogous to #1205) plus the coordination-model decision. D10’s write model stands as design; the live surface is the declared/ad-hocargon_mutatewrite path. - Structured check-violation
whyinoxc-runtime(D11).argon_whyships glass-boxing the runtime’s existing firing set; the deeper D11 build item — one unified structured trace shape (prose + structured) shared byexplain_factand the check-violation why — is a realoxc-runtimeitem, still to land. - Claude Code plugin bundle (D13).
ox mcpships with the toolchain; the reference plugin manifest registeringox mcp+ the prompts as a skill is a follow-on distribution artifact.
Concurrency and isolation
(As-built reconciliation: the #1205 dispatch lift made RuntimeService
Clone + Send + Sync, so the planned actor/mailbox is unnecessary — the
backend holds the service directly and the rmcp handler tasks call the lifted
run_query / run_mutation / run_compute / run_batch orchestration against
it; the service is internally synchronized. Read-only runtime ops never hold the
ServiceState lock across the CPU-bound reasoner: they take a brief guard only to
deep_clone the scope store, drop it, and reason against the clone — the
snapshot-then-reason discipline the serve foreign-read path uses. Only the ad-hoc
mutate path holds the write guard, serialized per scope. The single-stdio-client
profile means there is no second agent session to race the backend; the
project-root lockfile / co-resident-LSP-watch interaction folds into the
still-open watch question below. Panic isolation at the handler boundary remains
the intent for the eventual Remote/HTTP profile.)
Rationale
- A third frontend, not a new runtime. The dispatch core is already transport-agnostic (RFD 0014); the only honest place for an agent surface is beside the HTTP layer, over the same
dispatch_*_core. Anything else duplicates runtime logic and invites drift. RuntimeService, because coherence is the hard part. The reason to rideRuntimeServicerather than the bareConnectionis exactly D4: reload, the governor, mutation locks, paging, forks. Building on the embedder path would mean re-implementing reload — and the first re-implementation that drifts is a silent stale-KB bug, the worst failure mode for an agent that trusts what it queries.- The runtime is the value the agent cannot otherwise reach. An editor-agent already has the check loop via LSP. What it does not have is structured provenance, bitemporal reads, n-ary relations, forks, and standpoints. Leading with the runtime (D1) is what makes this surface worth building rather than a re-skin of
ox lsp. - Honesty over a faked feature. Why-not provenance is where authors live, and it does not exist (D12). The disciplined move is to report
derived:falseprecisely and guide the decomposition with the tools that do exist — not to synthesize a plausible-looking explanation the substrate cannot back. Genuine why-not is named as the top runtime frontier, not quietly skipped. - Reuse the loud-gate everywhere. The governor, the catalog, the
ProofTreemodel, the fork machinery, paging — all exist. The server configures and frames them (D5, D6, D8, D9, D10); the only genuinely new build items are the framing layer, the coherence stamping (D4), and the structured check-violation why (D11).
Alternatives considered
- Build on the bare embedded
Connection(the Tide / RFD 0052 path). Rejected: it has no reload, so the server would either re-implementreload_if_changed(duplicate logic, the drift risk above) or serve a stale module.RuntimeServicealready owns coherence. - Author-against-remote (a uniform read+write surface across both profiles). Rejected: you do not author against a deployed knowledge base. The remote profile is read/introspect only (D3); authoring is inherently local where source, build, and reload are co-located.
- Maturity levels (a v1 read-only surface, write later) rather than profiles. Rejected: the full surface above is committed scope. Local vs. remote is a capability distinction (what is live where), not a phasing of ambition; the fork write model (D10) is part of the design, not a deferred tier.
- Fake why-not provenance (synthesize a “why empty” explanation). Rejected on honesty grounds (D12): the substrate cannot back it (RFD 0046 open). A confident wrong explanation is worse than a precise
derived:falseplus a guided decomposition. - Naive full
ProofTreeserialization. Rejected: a recursive derivation branches exponentially and would blow the agent’s context. Bounded projection + lazyexpand_proof(D8) is the only viable shape. - Teach the loud-gate inside the server (tool descriptions, hardcoded prose). Rejected: teaching belongs in the single-source catalog (D9) so CLI, LSP, and MCP share it; duplicating it in the server is a second source that drifts.
Consequences
- The agent lane is filled by a frontend, not a fork of the runtime.
oxc-mcpcouples toRuntimeService+dispatch_*_coreexactly asoxc-servedoes; the runtime stays one runtime. - A new committed build item lands in
oxc-runtime: the structured check-violation why (D11) unifies the two provenance entry points — it is not MCP-only. - The diagnostic catalog gains fix-class remediation on the loud-gate codes (D9), improving
ox explainand LSP, not only MCP. ox mcpships with the toolchain viaoxup, editor-agnostic, with a Claude Code plugin bundle as the reference distribution.- Why-not provenance is named as the top runtime frontier (D12), scoped out of this RFD and to RFD 0046 — a legible boundary, not a silent gap.
- This RFD is a design record. State
discussion: it fixes the design rationale, not the implementation. The embeddedstdioprofile (increments 1–5, the read/write/introspect surface above) is built —oxc-mcp/ox mcpship the eighteen-tool surface, five resources + one template, and three prompts reconciled above; the Remote profile, the live fork lifecycle (increments 6–7), the D11 structured check-violationwhy, and the Claude Code plugin bundle are the gated follow-ons. The build order below is the committed delivery shape; the surface section is reconciled to what is live.
Build order (delivery increments — the full surface above is committed scope, not a v1 subset)
oxc-mcpskeleton +Backend(Local =RuntimeService+ workspace) + actor +McpError+argon_status/ coherence stamping.- Authoring tools + catalog fix-class enrichment + inlined remediation + server instructions/prompts.
- Runtime read tools with paging + governor config + cancellation.
explain_fact+ProofTreefolding +expand_proof; structured check-violation why inoxc-runtime.- Discovery tools + schema/catalog resource templates.
- Fork model (ephemeral + capability-gated promote with diff-summary).
- Remote backend profile +
ox mcpsubcommand + Claude Code plugin bundle.
Open questions
- The exact
rmcpAPI. The official Rust MCP SDK surface (server construction, tool/resource/prompt registration, the stdio transport, cancellation) must be verified against the SDK at implementation time; the decisions above are framing-level and SDK-version-independent. - The capability mechanism for
argon_fork_promote. Per-call capability gating (D10) needs a concrete carrier — an explicit confirmation argument, a session capability grant, or a config-time enable — settled when increment 6 lands. - The row-cap default for the agent profile (D5). “Tighter than serve’s, to protect agent context” needs a measured default against real agent context budgets.
- Where the project-root lockfile lives and how it interacts with
ox lsp’s own watch. Two frontends (LSP + MCP) may watch the sametarget/<pkg>.oxbin; the lockfile (concurrency / isolation §) must not deadlock a co-resident editor session.
This design was hardened by a multi-model adversarial review — decorrelated critique across heterogeneous providers — which shaped the decisions above (notably the RuntimeService-not-Connection backend, the coherence invariant, and the honest why-not boundary).