Skip to content

MCP: add loopover_close_pr write-tool to match its 8 registered siblings #6615

Description

@JSONbored

Context

packages/loopover-engine/src/miner/local-write-tools.ts defines 9 pure buildXSpec functions that construct LOCAL-execution action specs for the miner write-tools boundary (loopover never performs the write itself): buildOpenPrSpec, buildClosePrSpec, buildFileIssueSpec, buildApplyLabelsSpec, buildPostEligibilityCommentSpec, buildCreateBranchSpec, buildDeleteBranchSpec, buildTestGenSpec, buildFollowUpIssueSpec.

8 of the 9 are registered as MCP tools in BOTH surfaces:

  • src/mcp/server.ts (remote MCP server): loopover_open_pr, loopover_file_issue, loopover_apply_labels, loopover_post_eligibility_comment, loopover_create_branch, loopover_delete_branch, loopover_generate_tests, loopover_file_follow_up_issue (registered around src/mcp/server.ts:2381-2430, each following the exact pattern async (input) => this.toolResult(this.localWriteSpec(buildXSpec(input)))).
  • packages/loopover-mcp/bin/loopover-mcp.js (local stdio CLI): the same 8 tools, registered via registerStdioTool(...) around lines 2037-2103, plus matching entries in STDIO_TOOL_DESCRIPTORS (~lines 1035-1077).

buildClosePrSpec (packages/loopover-engine/src/miner/local-write-tools.ts:53-64) is the ONLY one of the 9 with no MCP tool anywhere. It is fully implemented, fully tested (test/unit/local-write-tools.test.ts:41-50), and already consumed internally by packages/loopover-miner/lib/claim-conflict-resolver.js:120 to build the gh pr close <n> --repo <repo> [&& gh pr comment ...] command when a miner loses a claim-conflict adjudication — but no MCP client (remote or local) can currently call this builder directly.

buildClosePrSpec's signature: buildClosePrSpec(input: { repoFullName: string; number: number; comment?: string | undefined }): LocalWriteActionSpec, re-exported unchanged from src/mcp/local-write-tools.ts.

Requirements

  • In src/mcp/server.ts, add a new zod input shape closePrShape following the exact pattern of the neighboring applyLabelsShape (repoFullName: z.string().min(3).max(SCENARIO_MAX_REPO_FULL_NAME_CHARS), number: z.number().int().positive()) plus an optional comment: z.string().max(WRITE_TOOL_BODY_MAX).optional().
  • Register loopover_close_pr via the existing register(...) wrapper, in the same "feat(agent): miner write-tools (open_pr/file_issue/...) — local-executed #780 miner write-tools" block as the other 8 (src/mcp/server.ts:2380-2430), using inputSchema: closePrShape, outputSchema: localWriteActionOutputSchema, and handler async (input) => this.toolResult(this.localWriteSpec(buildClosePrSpec(input))) — do not add any auth/DB access; none of the sibling write-tools require it (they are pure spec builders).
  • Add loopover_close_pr: "agent" to the MCP_TOOL_CATEGORIES map (src/mcp/server.ts, alongside the other 8 write-tools at ~line 1766-1773) so it carries the same _meta.category the others do.
  • Import buildClosePrSpec from ./local-write-tools in src/mcp/server.ts alongside the other 8 imports (~line 148-157).
  • Mirror the tool in packages/loopover-mcp/bin/loopover-mcp.js: import buildClosePrSpec from @loopover/engine alongside the existing 8 write-tool imports (~lines 10-18), add a closePrShape constant next to applyLabelsShape/postEligibilityCommentShape (~lines 353-361) with the same bounds as the server-side shape, add a STDIO_TOOL_DESCRIPTORS entry (category "agent", description mirroring the other write-tools' "Build a LOCAL-execution spec to... (run it with your own gh creds; loopover never performs the write)." phrasing), and a registerStdioTool("loopover_close_pr", ...) block using localWriteSpecResult(buildClosePrSpec(input)), placed with the other 8 write-tool registrations (~lines 2035-2103).
  • The generated command MUST exactly match what buildClosePrSpec already produces (no reimplementation): gh pr close <number> --repo '<repoFullName>', optionally followed by && gh pr comment <number> --repo '<repoFullName>' --body '<comment>' when comment is supplied — this is enforced by the existing engine-level test, not something the MCP-layer PR needs to re-derive.

Deliverables

  • loopover_close_pr tool registered in src/mcp/server.ts (shape, category entry, registration, import)
  • loopover_close_pr tool registered in packages/loopover-mcp/bin/loopover-mcp.js (shape, descriptor entry, registerStdioTool block, import)
  • New test case(s) added to test/unit/mcp-write-tools.test.ts (server-side) asserting the tool returns the correct action/command/boundary, following the existing loopover_apply_labels/loopover_post_eligibility_comment cases in the same file
  • New test case(s) added to the CLI's write-tools test coverage (test/unit/mcp-cli-write-tools.test.ts) for the local stdio registration, following the existing sibling cases in that file

Test Coverage Requirements

This touches src/mcp/server.ts and packages/loopover-mcp/bin/loopover-mcp.js, both under src/**/packages/** — the repo's 99%+ Codecov patch gate applies in full. Every new branch (with/without comment) must be covered by the new test cases listed above; do not add the tool without a passing test asserting its exact command string.

Expected Outcome

An MCP client (remote or the local stdio CLI) can call loopover_close_pr exactly the way it already calls loopover_open_pr/loopover_apply_labels/etc., and gets back a LOCAL-execution spec it runs with its own gh credentials — no new write path, no new auth, just parity with the other 8 already-registered write-tools that already share this exact builder module.

Links & Resources

  • packages/loopover-engine/src/miner/local-write-tools.ts:53-64 (buildClosePrSpec)
  • src/mcp/local-write-tools.ts (thin re-export used by src/mcp/server.ts)
  • src/mcp/server.ts:2380-2430 (sibling registrations to copy)
  • packages/loopover-mcp/bin/loopover-mcp.js:2028-2103 (sibling CLI registrations to copy)
  • test/unit/local-write-tools.test.ts:41-50 (existing builder-level test, already passing)
  • packages/loopover-miner/lib/claim-conflict-resolver.js:120 (existing internal consumer of buildClosePrSpec)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions