You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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)
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.
Context
packages/loopover-engine/src/miner/local-write-tools.tsdefines 9 purebuildXSpecfunctions 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 aroundsrc/mcp/server.ts:2381-2430, each following the exact patternasync (input) => this.toolResult(this.localWriteSpec(buildXSpec(input)))).packages/loopover-mcp/bin/loopover-mcp.js(local stdio CLI): the same 8 tools, registered viaregisterStdioTool(...)around lines 2037-2103, plus matching entries inSTDIO_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 bypackages/loopover-miner/lib/claim-conflict-resolver.js:120to build thegh 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 fromsrc/mcp/local-write-tools.ts.Requirements
src/mcp/server.ts, add a new zod input shapeclosePrShapefollowing the exact pattern of the neighboringapplyLabelsShape(repoFullName: z.string().min(3).max(SCENARIO_MAX_REPO_FULL_NAME_CHARS),number: z.number().int().positive()) plus an optionalcomment: z.string().max(WRITE_TOOL_BODY_MAX).optional().loopover_close_prvia the existingregister(...)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), usinginputSchema: closePrShape,outputSchema: localWriteActionOutputSchema, and handlerasync (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).loopover_close_pr: "agent"to theMCP_TOOL_CATEGORIESmap (src/mcp/server.ts, alongside the other 8 write-tools at ~line 1766-1773) so it carries the same_meta.categorythe others do.buildClosePrSpecfrom./local-write-toolsinsrc/mcp/server.tsalongside the other 8 imports (~line 148-157).packages/loopover-mcp/bin/loopover-mcp.js: importbuildClosePrSpecfrom@loopover/enginealongside the existing 8 write-tool imports (~lines 10-18), add aclosePrShapeconstant next toapplyLabelsShape/postEligibilityCommentShape(~lines 353-361) with the same bounds as the server-side shape, add aSTDIO_TOOL_DESCRIPTORSentry (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 aregisterStdioTool("loopover_close_pr", ...)block usinglocalWriteSpecResult(buildClosePrSpec(input)), placed with the other 8 write-tool registrations (~lines 2035-2103).commandMUST exactly match whatbuildClosePrSpecalready produces (no reimplementation):gh pr close <number> --repo '<repoFullName>', optionally followed by&& gh pr comment <number> --repo '<repoFullName>' --body '<comment>'whencommentis supplied — this is enforced by the existing engine-level test, not something the MCP-layer PR needs to re-derive.Deliverables
loopover_close_prtool registered insrc/mcp/server.ts(shape, category entry, registration, import)loopover_close_prtool registered inpackages/loopover-mcp/bin/loopover-mcp.js(shape, descriptor entry,registerStdioToolblock, import)test/unit/mcp-write-tools.test.ts(server-side) asserting the tool returns the correctaction/command/boundary, following the existingloopover_apply_labels/loopover_post_eligibility_commentcases in the same filetest/unit/mcp-cli-write-tools.test.ts) for the local stdio registration, following the existing sibling cases in that fileTest Coverage Requirements
This touches
src/mcp/server.tsandpackages/loopover-mcp/bin/loopover-mcp.js, both undersrc/**/packages/**— the repo's 99%+ Codecov patch gate applies in full. Every new branch (with/withoutcomment) must be covered by the new test cases listed above; do not add the tool without a passing test asserting its exactcommandstring.Expected Outcome
An MCP client (remote or the local stdio CLI) can call
loopover_close_prexactly the way it already callsloopover_open_pr/loopover_apply_labels/etc., and gets back a LOCAL-execution spec it runs with its ownghcredentials — 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 bysrc/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 ofbuildClosePrSpec)