Skip to content

docs(proposal): RFC — federated MCP control plane with scientific admission - #30

Open
kotama7 wants to merge 4 commits into
mainfrom
docs/tool-registry-integration-rfc
Open

kotama7 wants to merge 4 commits into
mainfrom
docs/tool-registry-integration-rfc

Conversation

@kotama7

@kotama7 kotama7 commented Jun 8, 2026

Copy link
Copy Markdown
Owner

What

This remains a design-only RFC. It revises proposals/2026-06-broad-tool-registry-integration.md from a small hand-curated broker into a provider-neutral MCP federation control plane with an ARI scientific-admission layer.

No runtime, API, or skill implementation is included.

Decision

ARI will expose a stable five-tool surface:

  • discover
  • describe
  • invoke
  • get_status
  • get_result

Behind it, catalog collections are integrated by source/provider adapters:

CatalogSource -> Candidate catalog -> Scientific Admission
              -> CATALOG.lock -> ProviderAdapter -> EAR/cassettes

The manual extension unit is a catalog source or collection-level adapter, not an individual tool.

What the revised RFC adds

  • generated sources.yaml -> candidates -> admission -> CATALOG.lock lifecycle;
  • opaque immutable tool_ref identities and bounded/paginated descriptions;
  • generic stdio MCP and compact-collection adapter contracts;
  • ToolUniverse as an initial scientific provider, not ARI's canonical registry or trust boundary;
  • compatibility with future MCP collections without per-tool integration;
  • non-transitive trust and leaf-origin tracking across nested aggregators;
  • capability/equivalence/independence modeling for competing tools;
  • four admission levels: discovered, callable, reproducible, scientifically admitted;
  • normalized async/result/artifact envelopes;
  • ARI-owned EAR/cassette record-replay;
  • OpenROAD and Qiskit/IBM Quantum domain profiles;
  • staged A.0 -> C implementation and concrete exit criteria.

Why

A hand-maintained list cannot scale to ToolUniverse-sized or future MCP collections. Conversely, live registry discovery cannot safely imply execution or scientific validity.

The revised design separates:

  • broad automated discovery from narrow immutable execution;
  • generic MCP interoperability from scientific evidence and reproducibility;
  • technical name collisions from genuine independent-method comparison.

Implementation sequence

  1. A.0: fixed five-tool broker kernel, static source, generic stdio provider, one pinned fixture.
  2. A.1: generated federation catalog, normalized descriptors, lock/index, cycle handling.
  3. A.2: ToolUniverse Compact collection adapter and bulk-import demonstration.
  4. B.0: scientific admission, result envelope, EAR/cassette replay, environment isolation.
  5. B.1: conflict resolution plus sandboxed OpenROAD and Qiskit pilots.
  6. C: official Registry and additional collection sources, HTTP/OAuth/Tasks, optional core graduation.

Stages A/B preserve the existing zero-ari-core-change approach unless a domain pilot proves a concrete limitation.

Existing verified constraints retained

  • no ARI_PHASE reaches skill subprocesses;
  • reproduction must receive cassettes through the curate/publish/clone bundle;
  • the R-CCS fx700/A64FX stdio launch spike passed online and pre-warmed offline;
  • Stage A.0 must retain arch-correct uv, a clean managed interpreter, and malformed-stdout isolation;
  • discovery/schema output must respect ARI's 4,000-character tool-output cap;
  • submit-style calls must return a handle within the outer 300-second timeout.

Validation

  • git diff --check — passed.
  • Markdown code-fence balance — passed.
  • All 15 external primary-source links in the RFC returned HTTP 200.
  • Relevant launch, phase, timeout, and output-cap assumptions were re-verified against current origin/main.
  • Repository-wide docs checks are not used as a gate for this proposal: on the old PR branch they traverse generated docs/node_modules and report pre-existing archived-link/README drift unrelated to these two proposal files.

kotama7 and others added 2 commits June 8, 2026 23:52
Design-only proposal (no runtime/code change) for extending ARI beyond
ToolUniverse's biomedical-only scope via a single staged stdio broker skill
(ari-skill-tool-registry): breadth from the official MCP Registry, cross-science
domain-fit from mcp.science + the Argonne MCP-for-Science pattern, with ARI
supplying reproducibility (snapshot/cache/digest-pin into the EAR) since none of
the upstreams do.

Marked NOT build-ready: records two blockers re-verified against code —
ARI_PHASE does not exist (phase never reaches a skill subprocess), and the
reproduce sandbox runs an isolated reproduce.sh that cannot see the broker or
its cassettes — plus the real compute-node spike that gates any implementation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ero ari-core change)

Adversarial review (verified against code) confirmed the two blockers are a
single coupled hand-off mismatch, both resolvable with zero ari-core change:

- BLOCKER 1 (phase signal): drop it entirely. All four reproduce stages are
  `phase: paper` direct tool calls with no react block (workflow.yaml), so the
  broker never runs during reproduce and needs no phase awareness. Live-vs-replay
  is governed by phase-scoping + ARI_TOOL_REGISTRY_LIVE + the explicit
  invoke(mode=) arg. No ARI_PHASE, no core change.
- BLOCKER 2 (sandbox can't see cassettes): vendor frozen cassettes via the
  existing curate->publish->clone chain — an explicit ear/publish.yaml include
  rule lands tool_registry_cassettes/** + CATALOG.lock + a dependency-free
  .ari_lib/replay.sh in repro_sandbox/; reproduce.sh reads them as on-disk
  fixtures (fail-loud on miss), no skill/MCP/network. No core change.

Adds §4a; reframes §6 (NOT READY -> blockers resolved, real-env spike the only
gate); marks §7 step 2 done. Applies the review's 6 corrections (client.py:310/38
citations, future tense for net-new broker pieces, publish.yaml-absent ships
silently-without-cassettes not skip, no-jq replay shim, cow_node_id caveat).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kotama7

kotama7 commented Jun 8, 2026

Copy link
Copy Markdown
Owner Author

Update — both build blockers resolved in design (§4a, zero ari-core change)

Followed up on the two adversarial-review blockers. A verification pass against the actual code found they are a single coupled hand-off mismatch, and both are resolvable with zero ari-core change:

  • BLOCKER 1 (phase signal) → dropped entirely. All four reproduce stages (ors_seed_sandbox/ors_build_reproduce/ors_run_reproduce/ors_grade) are phase: paper direct tool calls with no react: block — so the broker never runs during reproduce and never needs to know the phase. Live-vs-replay is governed by workflow.yaml phase-scoping + the default-OFF ARI_TOOL_REGISTRY_LIVE flag + the explicit invoke(…, mode=) arg. No ARI_PHASE, no core change.
  • BLOCKER 2 (sandbox can't see cassettes) → vendor via the existing curate→publish→clone chain. An explicit ear/publish.yaml include rule lands tool_registry_cassettes/** + CATALOG.lock + a dependency-free .ari_lib/replay.sh into repro_sandbox/; the generated reproduce.sh reads them as on-disk fixtures (fail-loud on miss) — no skill, no MCP, no network. No core change.

The resolution itself was adversarially re-checked (verdict sound-with-fixes); its 6 corrections are applied — corrected client.py:310/38 citations, future tense for the net-new broker pieces, the precise publish.yaml-absent failure mode (curate does not skip — it falls back to _DEFAULT_PUBLISH_YAML and ships the bundle silently without cassettes), a no-jq replay shim (default apptainer image lacks jq), and the cow_node_id env-channel caveat.

Status moves from NOT build-readyblockers resolved; gated only on the real-env spike (§7.1). See new §4a. Remaining gate before a Stage A.0 code PR: the R-CCS compute-node spike (uvx launch / no-network cold-spawn / docker-under-SLURM).

… fx700/A64FX

Ran the §7.1 launch spike on a real R-CCS fx700 (A64FX, aarch64) compute node:
spawned a pinned `uvx mcp-science <server>` over stdio exactly as ari-core's
MCPClient launches skills, then completed initialize + list_tools. All four
cases passed — online AND offline (cache-only), for both the light `timer` and
the heavy `python-code-execution` (numpy/scipy/matplotlib) server.

The spike surfaced 3 arch/robustness provisions (each a real failure first),
now folded into Stage A.0 and §4 "Launch robustness":
  1. arch-correct uv — the shared ~/.local/bin/uv is x86 and Exec-format-errors
     on aarch64 even though `command -v uvx` resolves (shared /home).
  2. uv-managed aarch64 CPython — an active x86 VIRTUAL_ENV broke uv; force
     UV_PYTHON_PREFERENCE=only-managed with VIRTUAL_ENV cleared.
  3. broker stdout sanitizer — the mcp-science launcher prints a non-JSON
     "Running command: [...]" preamble to stdout that corrupts the MCP stream.

Secondary: fx700 has PyPI network (not air-gapped) yet the offline-cache path
is validated; no docker (singularity present); x86 login cache does not transfer
to aarch64. Status moves to: blockers resolved + spike cleared; ready for a
Stage A.0 PR. Full logs in workspace/checkpoints (gitignored).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kotama7

kotama7 commented Jun 8, 2026

Copy link
Copy Markdown
Owner Author

§7.1 spike run on real hardware (R-CCS fx700 / A64FX) → GATE CLEARED

Ran the launch spike on a real fx700 compute node (srun), spawning a pinned uvx mcp-science <server> over stdio exactly as ari-core's MCPClient launches skills, then initialize + list_tools.

Test Result
timer online ✅ ok, handshake 3.85s, tools ["wait"]
timer offline (cache-only) ✅ ok, 3.1s
python-code-execution online (numpy/scipy/matplotlib/plotly) ✅ ok, 5.66s
python-code-execution offline (cache-only) ✅ ok, 4.68s

Launch/stdio/offline is viable on ARI's demonstrated platform — but only after 3 provisions, each a real failure first (now folded into Stage A.0 + §4 "Launch robustness"):

  1. arch-correct uv — the shared ~/.local/bin/uv is x86_64 and Exec format errors on aarch64, even though command -v uvx resolves (shared /home). Classic "path resolves ≠ binary runs."
  2. uv-managed aarch64 CPython — an active x86 VIRTUAL_ENV broke uv; force UV_PYTHON_PREFERENCE=only-managed with VIRTUAL_ENV cleared.
  3. broker stdout sanitizer — the mcp-science launcher prints a non-JSON Running command: […] line to stdout that corrupts the MCP JSON-RPC stream (the server itself was fine). The broker must forward only JSON-RPC lines.

Secondary: fx700 has PyPI network (not air-gapped) yet the offline-from-cache path is independently validated (reproducibility posture holds); no docker, singularity present (confirms the no-docker assumption); an x86-login cache does not transfer to aarch64; heavy cold-spawn (~190 MiB wheels) stays within the 300 s tool timeout but pre-warm is recommended.

See new §7.2. Status → blockers resolved + spike cleared; ready for a Stage A.0 implementation PR.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Quality Report

  • Generated (UTC): 2026-08-01T16:30:10Z
  • Repo: /home/runner/work/ARI/ARI
  • Checkers: 1 run, 6 unavailable
  • Findings: 21 total; 0 net-new vs baseline

Checkers

checker status findings allowlisted Δ new note
check_complexity unavailable 0 0 0 no JSON for check_complexity in quality-artifacts
check_import_boundaries unavailable 0 0 0 no JSON for check_import_boundaries in quality-artifacts
check_public_api_contracts error 0 0 0 unparseable JSON (check_public_api_contracts.json): Expectin
check_viz_api_schema ok 21 21 0
check_prompts unavailable 0 0 0 no JSON for check_prompts in quality-artifacts
check_dead_code unavailable 0 0 0 no JSON for check_dead_code in quality-artifacts
check_directory_policy unavailable 0 0 0 no JSON for check_directory_policy in quality-artifacts

Areas

area LOC findings
ari-core/ari/agent 3319 0
ari-core/ari/cli 2599 0
ari-core/ari/clone 665 0
ari-core/ari/config 779 0
ari-core/ari/configs 69 0
ari-core/ari/evaluator 1300 0
ari-core/ari/llm 1246 0
ari-core/ari/mcp 495 0
ari-core/ari/memory 472 0
ari-core/ari/migrations 170 0
ari-core/ari/orchestrator 3157 0
ari-core/ari/pipeline 4180 0
ari-core/ari/prompts 420 0
ari-core/ari/protocols 410 0
ari-core/ari/public 148 0
ari-core/ari/publish 794 0
ari-core/ari/registry 511 0
ari-core/ari/schemas 20 0
ari-core/ari/viz 8532 21
ari-skill-benchmark/src 175 0
ari-skill-coding/src 644 0
ari-skill-evaluator/src 952 0
ari-skill-hpc/src 1004 0
ari-skill-idea/src 1916 0
ari-skill-memory/src 2876 0
ari-skill-orchestrator/src 1043 0
ari-skill-paper/src 4256 0
ari-skill-paper-re/src 5843 0
ari-skill-plot/src 802 0
ari-skill-replicate/src 1684 0
ari-skill-transform/src 3180 0
ari-skill-vlm/src 355 0
ari-skill-web/src 712 0

Dead code

  • Source: check_dead_code (status: unavailable)
  • Note: no JSON for check_dead_code in quality-artifacts
  • Baseline: scripts/quality/baselines/dead_code_baseline.json
  • Safe-to-delete surviving human review: 0
classification count
SAFE_DELETE_CANDIDATE 0
QUARANTINE_CANDIDATE 0
TEST_ONLY 0
DOCS_ONLY 0
DYNAMIC_REFERENCE_RISK 0
PUBLIC_CONTRACT 0
REVIEW_REQUIRED 0

@kotama7 kotama7 changed the title docs(proposal): RFC — broad external MCP tool-registry integration (design, NOT build-ready) docs(proposal): RFC — federated MCP control plane with scientific admission Aug 1, 2026
@kotama7

kotama7 commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Implementation of this RFC is now available in draft PR #66 from the separate skills branch. It covers the full P0–P6 component migration, scientific-admission contracts, ToolUniverse/OpenROAD/Qiskit profiles, final compatibility cleanup, and permanent documentation.

This branch has not been deployed

No deployments
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