Skip to content

feat(ai): add MCP transport pool#562

Merged
rickylabs merged 2 commits into
mainfrom
feat/463-ai-mcp-pool
Jul 7, 2026
Merged

feat(ai): add MCP transport pool#562
rickylabs merged 2 commits into
mainfrom
feat/463-ai-mcp-pool

Conversation

@rickylabs

Copy link
Copy Markdown
Owner

Summary

Adds the upstream @netscript/ai/mcp pooling primitive for beta.6: multi-server MCP transport reuse keyed by server id, prefixed tool names, pooled dispatch, and data-only ui:// resource extraction for downstream render seams.

Scope

Slices

  • S1 MCP pool + ui:// extraction — 39f50c2

Definition of Done

  • Multi-server pool keyed by server id over existing transports.
  • Keep-alive reuse across turns without per-turn teardown.
  • Tool-name prefixing prevents cross-server collisions.
  • Data-only ui:// resource/src extraction is exposed from @netscript/ai/mcp.
  • plugins/ai can consume the core pool without re-implementing pooling.
  • gate:jsr doc-lint and publish dry-run pass without --allow-slow-types.

Validation

  • deno task check — PASS, exit 0; wrapper ran deno check --quiet --unstable-kv <files>, filesSelected=2133, batches=18, failedBatches=0, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-check.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-lint.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-fmt.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-doc-lint.ts --root packages/ai --pretty — PASS, exit 0; totalErrors=0; ./mcp.ts total=0.
  • deno publish --dry-run --allow-dirty from packages/ai — PASS, exit 0; no --allow-slow-types; warnings only for existing unanalyzable dynamic imports in tanstack-connector.ts.
  • deno test --allow-all packages/ai/tests/ — PASS, exit 0; 78 passed, 0 failed.
  • deno test --allow-all packages/ai/tests/mcp_test.ts — PASS, exit 0; 11 passed, 0 failed.

Harness

  • Run dir: .llm/runs/beta6-nondash--supervisor/
  • Phase: impl
  • Generator: Tier-D WSL Codex; separate IMPL-EVAL required before merge.

Drift / Debt

  • No material implementation drift.
  • Note: direct deno task check --unstable-kv is not a supported wrapper invocation because the task already passes --unstable-kv internally; the supported deno task check gate passed and reported the underlying unstable-kv command.

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [VERDICT: READY_FOR_IMPL_EVAL]

Landed FAI-7 MCP pooling primitive + ui:// resource extraction in @netscript/ai/mcp.

Slice

  • Commit: 39f50c2 (feat(ai): prove mcp pooling and ui resource extraction)
  • Scope: McpTransportPool over existing stdio/Streamable-HTTP transports; server-id keying; warm reuse across calls; prefixed tool names; pooled dispatch; extracted McpUiResource objects with uri + src for downstream render seams.
  • Files: packages/ai/mcp.ts, packages/ai/src/mcp/application/pool.ts, packages/ai/tests/mcp_test.ts

Gate Evidence

  • deno task check — PASS, exit 0; underlying wrapper command deno check --quiet --unstable-kv <files>; filesSelected=2133, batches=18, failedBatches=0, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-check.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-lint.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-fmt.ts --root packages/ai --ext ts,tsx --pretty — PASS, exit 0; filesSelected=75, batches=1, findings=0.
  • deno run --allow-read --allow-run .llm/tools/run-deno-doc-lint.ts --root packages/ai --pretty — PASS, exit 0; totalErrors=0; ./mcp.ts total=0.
  • deno publish --dry-run --allow-dirty from packages/ai — PASS, exit 0; no --allow-slow-types; pre-existing dynamic-import warnings in src/mcp/adapters/tanstack-connector.ts.
  • deno test --allow-all packages/ai/tests/ — PASS, exit 0; 78 passed, 0 failed.

Notes

  • No deno.lock diff.
  • No new as type casts in the touched implementation/test files.
  • Direct deno task check --unstable-kv is not supported by the wrapper task because the task itself already supplies --unstable-kv; the supported root check passed and reported the unstable-kv underlying command.

Next

  • Separate OpenHands IMPL-EVAL required; generator does not self-certify.

@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: A1 SLICE REVIEW] [Tier-A supervisor sign-off — PASS]

Substantive review of slice 39f50c2b (@netscript/ai/mcp pooling primitive). This is the Tier-A
supervisor review that precedes IMPL-EVAL; the generator (Tier-D Codex) correctly did not
self-certify.

Verified against acceptance

  • Keyed multi-server poolMap<serverId, transport>; duplicate server id and duplicate
    prefixed tool name both throw AiError. The pool implements McpTransportPort, so it is a drop-in
    transport (good composition).
  • Keep-alive across turnslistTools/callTool never tear down warm transports; test proves
    connectCount === 1 across repeated listTools+callTool.
  • Tool-name prefixing${serverId}__${remoteName} (separator configurable); route map plus
    #routeFromName fallback resolves a prefixed name back to (transport, remoteName).
  • ui:// extraction (data-only) — recursive walk of parsed content, dedup by uri, yields
    {uri, src, mimeType?, text?, blob?, serverId?, toolName?, toolCallId?}; standalone
    extractMcpUiResources export for the render seam.
  • Core, not a rewrite — pools over existing createMcpTransport / StdioMcpTransport /
    StreamableHttpMcpTransport; no transport logic reimplemented. No as casts; proper type guards.

Gate evidence accepted (wrapper-backed)

check / scoped check+lint+fmt / doc-lint (./mcp.ts total=0) / publish --dry-run (no
--allow-slow-types) all PASS; 78 + 11 tests green; no deno.lock diff; no new casts.

Carry-forward note for IMPL-EVAL (non-blocking)

ui:// extraction parses McpToolResult.content as a JSON string. IMPL-EVAL should confirm that
matches what the real stdio/Streamable-HTTP transports actually place in .content — if a live
transport returns already-structured (non-string) content, extraction would be a silent no-op in
production. Verify against the transport contract, not just the in-memory RecordingTransport test
double.

A1 PASS → proceeding to IMPL-EVAL (separate OpenHands qwen-3.7-max session). Merge remains behind a
PASS verdict; #463 is the upstream AI-stack primitive (#257/#379 land after).

@rickylabs

Copy link
Copy Markdown
Owner Author

@openhands-agent model=openrouter/qwen/qwen3.7-max output=pr-comment iterations=1500

use harness

IMPL-EVAL — FAI-7 MCP pooling primitive + ui:// extraction (issue #463, PR #562)

You are the IMPL-EVAL evaluator (separate session from the Tier-D generator) for one slice of the
beta6-nondash--supervisor harness run. Branch: feat/463-ai-mcp-pool. Read-only validation. The
generator already ran gates green and the Tier-A supervisor gave A1 sign-off; your job is to
independently confirm — or refute — that this is real, and to run the one cross-check A1 flagged.

Execute the cheapest decisive checks FIRST, form a verdict, POST it, then spend remaining budget on
the deep check.
Do NOT enumerate a plan without executing it.

SKILL

Run artifacts (read from the RUN branch, not this PR branch)

git fetch origin chore/beta6-nondash-supervisor-run
git show origin/chore/beta6-nondash-supervisor-run:.llm/runs/beta6-nondash--supervisor/plan.md   # row AI-463

Same path for worklog.md (see the #463 dispatch entry). Context, not the deliverable — read fast.

DECISIVE CHECKS — run in THIS ORDER, post verdict after check 4

  1. Surface + core placement (cheap grep/read). packages/ai/mcp.ts exports
    createMcpTransportPool, createMcpTransportPoolFromTransports, extractMcpUiResources,
    McpTransportPool, McpUiResource, McpPooledToolResult. Pool lives at
    packages/ai/src/mcp/application/pool.ts (core), pools OVER existing transports
    (createMcpTransport), does NOT reimplement stdio/HTTP transport logic. Confirm plugins/ai does
    not re-hand-roll pooling.
  2. Acceptance behaviors (read pool.ts + tests/mcp_test.ts). (a) keyed by server id, duplicate
    id throws; (b) keep-alive — listTools/callTool reuse warm transports (test asserts
    connectCount === 1); (c) tool-name prefixing ${serverId}__${remoteName} with collision guard;
    (d) ui:// extraction yields data-only {uri, src, ...}. Each behavior must have a real assertion,
    not a stubbed pass.
  3. Tests + gates (decisive). deno test --allow-all packages/ai/tests/ green (~78) and
    packages/ai/tests/mcp_test.ts (~11); run-deno-doc-lint.ts --root packages/ai totalErrors=0 with
    ./mcp.ts clean; deno publish --dry-run from packages/ai exit 0 WITHOUT --allow-slow-types.
  4. Lock + casts (decisive). git diff c9a703bf..HEAD -- deno.lock empty; scan the diff for as
    casts beyond the repo's 2 accepted. → FORM VERDICT AND POST THE PR COMMENT NOW.
  5. (Only if budget remains) The A1 carry-forward check — production ui:// shape.
    withUiResources in pool.ts parses McpToolResult.content as a JSON string. Confirm the
    real StdioMcpTransport / StreamableHttpMcpTransport actually place a JSON string in
    .content (inspect src/mcp/adapters/*-transport.ts + the McpToolResult contract in
    src/ports/mcp-transport.ts). If a live transport returns already-structured (non-string) content,
    ui:// extraction is a silent prod no-op → that is a FAIL_FIX (record the exact mismatch). If
    the contract genuinely fixes content to a JSON string, record it as confirmed and keep the PASS.

Rules

  • Read-only. NEVER mutate deno.lockgit checkout -- deno.lock before any commit. TRUE base
    c9a703bf.
  • Write your verdict to .llm/runs/beta6-nondash--supervisor/evaluate-463.md (per-slice filename),
    commit it to THIS PR branch, and post the PR comment. End both with the OPENHANDS_VERDICT: line
    (undecorated, first token of its line): PASS / FAIL_FIX / FAIL_RESCOPE / FAIL_DEBT.

OUTPUT CONTRACT (mandatory — verdict first)

  1. Post the verdict PR comment IMMEDIATELY after you form the verdict — BEFORE any
    optional deep-dive, extra verification, or long context dump. Iteration budgets
    exhaust; a verdict comment deferred to the end of the run is frequently lost.
  2. That PR comment MUST start with the formal header line, exactly:
    [PHASE: ] [VERDICT: ]
    where is your eval phase (e.g. IMPL-EVAL, PLAN-EVAL) and is one
    of PASS, FAIL_FIX, FAIL_RESCOPE, FAIL_DEBT, FAIL_PLAN.
  3. ALWAYS end BOTH the verdict PR comment AND your summary file with one final
    machine-readable line of the exact form:
    OPENHANDS_VERDICT:
    using a literal token from: PASS, FAIL_FIX, FAIL_RESCOPE, FAIL_DEBT, FAIL_PLAN,
    NONE. Use NONE only when no verdict could be reached.

@rickylabs

rickylabs commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

OpenHands Agent — Completed

OPENHANDS_VERDICT: PASS

Model: openrouter/qwen/qwen3.7-max
Provider: OPENROUTER
Job status: success
Verdict source: summary-file
Verdict comment: #562 (comment)
Summary source: agent
Housekeeping: ack=success trace=success commit-artifacts=success replies=skipped draft-pr=skipped
Trace: .llm/tmp/run/openhands/pr-562/run-28851696949-1 (in the Actions artifact)
Artifact: openhands-agent-28851696949-1

IMPL-EVAL Summary — Issue #463 (PR #562)

Summary

Independent IMPL-EVAL validation completed for the MCP transport pool primitive. All four decisive checks passed. The implementation is real, gates are green, lock file untouched, no type casts introduced.

Changes

  • Added .llm/runs/beta6-nondash--supervisor/evaluate-463.md (evaluation artifact)
  • Posted verdict PR comment to feat(ai): add MCP transport pool #562
  • Committed and pushed to feat/463-ai-mcp-pool branch

Validation

Check 1: Surface + Core Placement ✅

  • packages/ai/mcp.ts exports all 6 required pool symbols
  • Pool at packages/ai/src/mcp/application/pool.ts (CORE, archetype-1)
  • Zero pool references in plugins/ai/ — no re-hand-rolling

Check 2: Acceptance Behaviors ✅

  • Duplicate server id throws AiError
  • Keep-alive: connectCount === 1 across multiple listTools/callTool calls
  • Tool-name prefixing ${serverId}__${remoteName} with collision guard
  • ui:// extraction yields data-only {uri, src, ...} with real assertions

Check 3: Tests + Gates ✅ (DECISIVE)

  • Tests: 78 passed, 0 failed (11 MCP tests)
  • Doc lint: totalErrors=0, ./mcp.ts clean
  • Publish: deno publish --dry-run exit 0 WITHOUT --allow-slow-types

Check 4: Lock + Casts ✅ (DECISIVE)

  • deno.lock diff empty (zero changes from base c9a703b)
  • Zero type casts in implementation

Check 5: A1 Carry-Forward ✅

  • McpToolResult.content contract: readonly content: string
  • tanstack-connector.ts applies stringifyContent() to guarantee string output
  • No silent prod no-op — extraction path is production-safe

Responses to Review Comments

None — this is a fresh IMPL-EVAL session.

Remaining Risks

Verdict

All decisive checks passed. Implementation is real, gates are green, lock untouched, no casts.

OPENHANDS_VERDICT: PASS

Run: https://github.com/rickylabs/netscript/actions/runs/28851696949

rickylabs added a commit that referenced this pull request Jul 7, 2026
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: PASS]

IMPL-EVAL Independent Validation — PR #562 (Issue #463)

Check 1: Surface + Core Placement ✅

  • packages/ai/mcp.ts exports all 6 required symbols: createMcpTransportPool, createMcpTransportPoolFromTransports, extractMcpUiResources, McpTransportPool, McpUiResource, McpPooledToolResult
  • Pool implementation at packages/ai/src/mcp/application/pool.ts (CORE, archetype-1)
  • plugins/ai has zero references to pool/Pool — no re-hand-rolling violation

Check 2: Acceptance Behaviors ✅

  • (a) Keyed by server id, duplicate id throws AiError (constructor)
  • (b) Keep-alive: test asserts connectCount === 1 across multiple listTools/callTool calls
  • (c) Tool-name prefixing ${serverId}__${remoteName} with collision guard in #collectTools + #prefixTool
  • (d) ui:// extraction yields data-only {uri, src, ...} — test validates exact shape with real assertions

Check 3: Tests + Gates ✅ (DECISIVE)

  • deno test --allow-all packages/ai/tests/: 78 passed, 0 failed (11 MCP tests)
  • run-deno-doc-lint.ts --root packages/ai: totalErrors=0, ./mcp.ts clean
  • deno publish --dry-run from packages/ai: exit 0, "Success Dry run complete" — NO --allow-slow-types used

Check 4: Lock + Casts ✅ (DECISIVE)

  • git diff c9a703bf..HEAD -- deno.lock: empty (zero changes from base)
  • Scan for as casts: only match is test name string "as plain resource" — zero type casts in implementation

Evidence

All gates run fresh in this eval session. Lock file untouched. No as casts beyond the repo's accepted baseline.

OPENHANDS_VERDICT: PASS

Independent validation of MCP transport pool implementation.

Co-authored-by: openhands <openhands@all-hands.dev>
@rickylabs
rickylabs marked this pull request as ready for review July 7, 2026 08:33
@rickylabs
rickylabs merged commit 12161ac into main Jul 7, 2026
8 checks passed
@rickylabs
rickylabs deleted the feat/463-ai-mcp-pool branch July 7, 2026 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[AI-stack FAI-7] MCP pooling primitive + ui:// resource extraction

2 participants