Skip to content

contract(stdio): migrate the stdio MCP server's 102 tools to @loopover/contract — typed handlers, no hand-mirrored shapes #9537

Description

@JSONbored

Context

Part of #9515; the stdio third of what #9518 originally covered, split out so each migration is a single reviewable PR.

packages/loopover-mcp/bin/loopover-mcp.ts registers 102 tools, of which (after #9517's pilot) only a handful declare an outputSchema. Its ~85 shape constants (:371-1104) hand-mirror the remote server's — several say so in their own comments (:376, :381, :407, …) — and the registration helper erases all typing (:1740-1742, three anys), so every handler takes (input: any). STDIO_TOOL_DESCRIPTORS (:1108-1668) is a third hand-maintained list of name/category/description for all 102.

Two divergences #9517 found and modelled as unions, which converge here: loopover_get_repo_context and loopover_get_pr_reviewability return different payloads from this server than from the remote one (this server proxies the REST route; the remote builds its own object). Resolving them is wire-visible and belongs in this issue's batches, not the keystone's.

Requirements

  1. Migrate all 102 tools to register from @loopover/contract, by category, reusing the entries contract(remote): migrate the remote MCP server's tools to @loopover/contract — typed handlers, real output schemas #9518 lands for tools that exist on both servers rather than adding a second definition.
  2. Typed handlers. The registration helper stops erasing types; handlers derive their input type via z.infer. No (input: any) remains — enforce with a lint/grep gate.
  3. Real output schemas on every tool, replacing unschematized structuredContent.
  4. Delete STDIO_TOOL_DESCRIPTORS. Name, category, and description come from the registry; the tools CLI command and _meta.category read it.
  5. Converge the two divergent payloads with the remote server, so one tool name means one shape. Whichever side changes, the change is wire-visible and gets called out explicitly in the PR body.
  6. buildPlanDag/validatePlanDag (:173-215, hand-duplicated from src/services/plan-dag.ts) move to one shared home and the duplicate is deleted.
  7. No wire regression otherwise: names, descriptions, and input shapes preserved or widened, asserted by a tools/list snapshot per batch. Full branch-counted coverage.

Non-goals

Deliverables

  • All 102 tools registered from the contract, handlers typed, any gate in CI
  • Real output schemas throughout
  • STDIO_TOOL_DESCRIPTORS deleted
  • get_repo_context / get_pr_reviewability payloads converged with the remote server
  • Plan-DAG duplication eliminated
  • Per-batch tools/list snapshots

Expected outcome

grep -rn "mirror of the remote" packages/loopover-mcp returns nothing, no zod shape describing the same contract exists twice in the repo, and a caller gets the same shape from a tool name regardless of which server answered.

References

Part of #9515. Blocked by #9517 and #9518 (shared entries land there first). Split from #9518, alongside the miner server migration. Unblocks #9521.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions