Skip to content

docs(design): m-mcp-exact-tool-surface Lane B — embeddable session-owned protocol surface (#498) - #582

Merged
sunholo-voight-kampff merged 1 commit into
devfrom
sprint/m-mcp-exact-tool-surface-lane-b
Aug 4, 2026
Merged

docs(design): m-mcp-exact-tool-surface Lane B — embeddable session-owned protocol surface (#498)#582
sunholo-voight-kampff merged 1 commit into
devfrom
sprint/m-mcp-exact-tool-surface-lane-b

Conversation

@sunholo-voight-kampff

Copy link
Copy Markdown
Collaborator

Design doc for Lane B of #498, filed by the Ailang World mission and recorded as its sole clause-6 external blocker (w-mcp-projection is BLOCKED on it). Docs-only — no code changes.

What it designs

A narrow public github.com/sunholo-data/ailang/serveapi package exporting AILANG's existing MCP-HTTP and A2A serving machinery behind host-owned callbacks, covering all seven of #498's requested behaviours: caller-owned mux, principal/session resolved before discovery and invocation, caller-supplied exact descriptors, invocation returned with the same resolved session, MCP tools and A2A skills projected from one descriptor set, no built-in tool unless the caller supplies it, and upstream MCP/A2A conformance + SSE framing preserved.

AILANG stays the protocol owner; the host keeps session, capability and state. No World persistence, store, or scheduler comes upstream. The standalone CLI's defaults are unchanged structurallycmd/ailang stays on apiserver.New/Server.Start rather than depending on callback defaults.

The premise that shrank the work

The MCP Go SDK already hands AILANG a per-request server-selection callback, and internal/apiserver/mcp.go:303 calls it while discarding the request:

mcp.NewStreamableHTTPHandler(
    func(r *http.Request) *mcp.Server { return ms.mcpServer },   // r ignored
    &mcp.StreamableHTTPOptions{Stateless: true})

So requirements 2–3 are supported by the dependency already in use — this is a wiring and authority problem, not a transport problem.

Quorum

Designer codex:gpt-5.6-sol. Reviewers gpt5-6-sol + gemini-3-1-pro, both present in both rounds (no N−1 degrade). Metered $0.1910.

  • R1 BLOCKED ×2 → revision.
  • R2 BLOCKED ×2narrow-refinement carve-out: both remaining objections carried a concrete reviewer-authored proposed_fix and neither disputed the design direction, so the reviewers' verbatim fixes were applied and recorded in the doc's Quorum Verification Log. Not a force-pass; no contested direction overridden.

Two reviewer claims were measured rather than forwarded (the controller runs the check instead of buying another round):

  1. "Per-request SDK servers break SSE." Refuted on this path — in Stateless mode the SDK answers GET/DELETE with 405 Allow: POST, so there is no long-lived stream to correlate, and getServer(req) is called per POST. But the reviewer surfaced a genuine adjacent landmine, now closed: Stateless: true is a frozen requirement, stateful/resumable MCP is an explicit non-goal with the empty-registry failure mode written out, a Conflict Surface row forces any future stateful change to revisit the decision, and acceptance asserts GET⇒405.
  2. "A2A timeout mapping was never verified against the existing wire format." Correct that it was unverified. Measured: a2a.go:304 is w.WriteHeader(http.StatusOK) // JSON-RPC always returns 200. and all existing task errors are JSON-RPC codes — so the design's mandate preserves the surface (V27). -32603 is new to the file, recorded with a known-positive control so the zero is a measurement (V28).

Bounded waits and bounded concurrency

R2's other catch was sharp: a deadline bounds the wait, not the resource. A context-ignoring callback still leaks a goroutine per request. Applied verbatim: Config.MaxConcurrentCallbacks, a capacity token held until the goroutine actually exits, a frozen overload envelope on exhaustion, and the plain statement that in-process Go callbacks cannot be forcibly terminated — so the guarantee is narrowed to bounded latency and bounded callback starts, never enforced completion. The test is discriminating in both directions.

Notes

  • 28-row Verification Log; 10-row Conflict Surface incl. make check-boundaries and make check-file-sizes (server.go is 764/800 — the design adds nothing to it).
  • Doc declares **Planner-Lane**: opus-required; derive-planner-lane.sh returns opus declared:opus-required, exercising the iteration-136 lane end-to-end on a brand-new doc.
  • Estimated ~17h across 2–3 days, 3 milestones.

🤖 Generated with Claude Code

…ned protocol surface (#498)

Lane B of #498, filed by the Ailang World mission and its sole clause-6 external
blocker. Adds a narrow public `serveapi` package exporting AILANG's MCP-HTTP and
A2A handlers behind host-owned callbacks: caller-owned mux, principal/session
resolved BEFORE discovery and invocation, caller-supplied exact descriptors, MCP
tools and A2A skills projected from ONE set, and no built-in tool unless the
caller supplies it. AILANG stays the protocol owner; the host owns session,
capability and state. Standalone CLI defaults are structurally unchanged
(cmd/ailang stays on apiserver.New/Server.Start).

Central premise, controller-verified: the MCP Go SDK already hands AILANG a
per-request `getServer(*http.Request)` callback, which mcp.go:303 currently calls
while discarding the request. Requirements 2-3 therefore need no new transport
work.

Quorum: designer codex:gpt-5.6-sol; reviewers gpt5-6-sol + gemini-3-1-pro, both
present in both rounds (no N-1 degrade). R1 BLOCKED x2 -> revision. R2 BLOCKED x2
-> narrow-refinement carve-out (both objections carried concrete reviewer-authored
fixes and neither disputed the design direction); reviewers' verbatim fixes
applied and recorded in the doc's Quorum Verification Log. Metered $0.1910.

Two reviewer claims were MEASURED by the controller rather than forwarded:
- SSE breakage from per-request servers: REFUTED on this path. Stateless mode
  answers GET/DELETE with 405 Allow: POST, so no cross-request stream exists.
  The real adjacent landmine it surfaced is closed: Stateless:true is frozen,
  stateful/resumable MCP is an explicit non-goal, and acceptance asserts GET=>405.
- A2A timeout wire format: a2a.go:304 already writes HTTP 200 with a JSON-RPC
  envelope, so the design's mandate preserves the surface rather than corrupting
  it (V27); -32603 is new to the file, with a known-positive control (V28).

Co-Authored-By: codex <gpt-5.6-sol>
@sonarqubecloud

sonarqubecloud Bot commented Aug 4, 2026

Copy link
Copy Markdown

@sunholo-voight-kampff
sunholo-voight-kampff merged commit 2629ad8 into dev Aug 4, 2026
20 checks passed
@sunholo-voight-kampff
sunholo-voight-kampff deleted the sprint/m-mcp-exact-tool-surface-lane-b branch August 4, 2026 02:17
sunholo-voight-kampff pushed a commit that referenced this pull request Aug 4, 2026
…uorum-cleared

STATUS stamp for iteration 137, iter-134 rotated to the archive (invariant
asserted: 1731 -> 1731, 3 stamps, queue rows control-checked post-edit), log
entry 142, and the Lane B queue row retagged DOC LANDED + QUORUM-CLEARED with
"route to sprint-planner" as its next step.

Iteration 137 landed PR #582 (squash 2629ad8, dev CI green SHA-addressed:
20 checks, 0 non-success, plus per-workflow confirm) and closed iteration 136's
owed evaluator gap (sonnet PASS 84/100 r1, zero blocking, 5/5 mutations caught,
follow-ups filed as #581).

Notable: the STATUS rotation itself failed destructively on first attempt
because zsh arrays are 1-indexed -- ${S[2]} selected iteration 135 as "oldest"
and ${S[0]} was empty. The iter-127 line-count assertion caught it, both files
were restored from git and re-verified, and the rotation was redone without any
array indexing. Same zsh family as the ${PIPESTATUS[0]} lesson already recorded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant