Skip to content

mcp(discovery): server.json + .well-known surfaces, MCP registry publish, and the stdio gateway front door #9526

Description

@JSONbored

Context

Part of #9515 — the last mile: make the standardized servers discoverable, published, and unified behind one client entry. metagraphed's discovery layer is the model, including one hard lesson:

  • server.json (MCP registry manifest, streamable-http remote) published by an OIDC mcp-publisher workflow;
  • /.well-known/mcp/server-card.json computed at request time — an earlier committed version caused a merge conflict on every concurrent tool PR;
  • /.well-known/agent-tools/{index,openai,anthropic}.json as pure projections of listToolDefinitions();
  • the lesson: its version-sync workflow rotted silently for months because it watched a file path that no longer existed — the anti-rot guard is part of this issue's spec (and mcp: validate:mcp contract validator — Ajv output enforcement, per-tool smoke gate, version tri-lock across all three servers #9520 asserts it).

LoopOver today has none of this: no server.json, no .well-known MCP surfaces, serverInfo.version hardcoded "0.1.0" (src/mcp/server.ts:2169), and two-to-three separate client configs for what should feel like one product (loopover-mcp init-client for ORB stdio, a hand-written second entry for loopover-miner-mcp, and no client story at all for the remote /mcp).

Requirements

  1. Discovery surfaces on the Worker and self-host app, all computed at request time from the contract registry (contract(remote): migrate the remote MCP server's tools to @loopover/contract — typed handlers, real output schemas #9518) — never committed artifacts: /.well-known/mcp.json → server card (tools via listToolDefinitions(), capabilities, version, deterministic generated_at, weak ETag/304); /.well-known/agent-tools/index.json + openai.json + anthropic.json via the contract: create @loopover/contract — the single zod source for tool/API schemas, with a six-tool pilot #9517 spec builders, with the executor block pointing at /mcp + tools/call. Self-host serves the same routes scoped to its own availability-filtered tool set. Routes registered through the api: one route-registration seam — runtime zod validation + spec emission, with a route↔spec ratchet to zero unspecced routes #9519 seam (specced like everything else).
  2. server.json + registry publish: manifest at repo root (io.github.JSONbored/loopover, remotes: [{type: "streamable-http", url: "https://api.loopover.ai/mcp"}] plus the npm stdio package entry), validated field-by-field in CI against the tri-lock (mcp: validate:mcp contract validator — Ajv output enforcement, per-tool smoke gate, version tri-lock across all three servers #9520); a workflow_dispatch, main-only publish workflow using GitHub OIDC and a SHA-pinned mcp-publisher. Anti-rot guard: the workflow fails loudly if any path it watches is absent from HEAD; the version source is @loopover/mcp's package.json via the existing release automation — no new hand-bumped constants (serverInfo.version and src/services/mcp-compatibility.ts both derive from it).
  3. Gateway mode for the stdio bin (decision recorded here): when a loopover-mcp login session exists, the stdio server mounts the remote server's tools — fetch tools/list from the authenticated /mcp, re-register each remote-only tool as a passthrough proxy (schemas come across the wire; nothing duplicated), refresh on listChanged. Name collisions cannot occur by construction: post-contract(remote): migrate the remote MCP server's tools to @loopover/contract — typed handlers, real output schemas #9518 a tool name is either locality local-git (served locally) or remote (proxied) in the one contract registry — assert this invariant in validate:mcp. Offline/unauthenticated ⇒ local tools only plus one structured advisory resource, never an error. Opt-out flag --no-remote for byte-identical current behavior. init-client output and generated docs updated accordingly.
  4. AMS bin decision (recorded here): loopover-miner-mcp stays a separate stdio serverEpic: hosted AMS chat platform — sign up, connect GitHub, converse with your miner #9184's hard constraint is that local UX must not regress, and a dual-role operator's two-entry config is already documented and pin-tested. Revisit folding miner tools into the gateway only after the gateway has shipped and real dual-role usage data exists (reopen here with that data).
  5. Client-config surfaces regenerate (per contract: generate every derived surface — typed stdio client, CLI from one spec table, tool-reference docs, miner dedup, UI z.infer types #9521's generators): README config blocks, mcp-clients.mdx, init-client --print outputs — all derived, drift-checked, covering the three connection modes (stdio gateway, remote streamable-http direct, miner stdio).
  6. Telemetry (Epic: MCP contract standardization — one zod contract, three runtimes, one front door (ORB + AMS, self-host + hosted) #9515 group 9) distinguishes proxied vs local execution via a transport property so gateway adoption is measurable.
  7. Full branch-counted coverage (gateway proxy paths, offline fallback, ETag/304, availability filtering); fix-what-you-find applies.

Non-goals

Deliverables

  • Request-time server card + agent-tools trio on Worker and self-host
  • server.json + OIDC publish workflow with the anti-rot path guard and tri-lock validation
  • Stdio gateway mode (session-gated mount, offline-safe, --no-remote), locality invariant asserted in validate:mcp
  • AMS-separate decision recorded; regenerated client-config docs for all three modes
  • Transport-tagged telemetry

Expected outcome

https://api.loopover.ai/.well-known/mcp.json and the MCP registry describe the live server truthfully on every deploy with no hand-bumped versions and no committable drift; a contributor configures exactly one stdio server and transparently sees every local + remote tool their session entitles them to; and the #9183/#9184 chat platforms consume their tool catalogs from the same .well-known projections — one contract, three runtimes, one front door, done.

References

Part of #9515. Blocked by #9518 and #9520. Advances #9183 / #9184 (catalog endpoints) and #4877 Phase B (self-serve/discovery). Pattern source: metagraphed server.json / publish-mcp-registry.yml / worker-computed server card — plus its version-sync rot as the cautionary spec here.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.orbGittensory Orb related - maintainer self-hosting analytics.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions