feat(mcp): register loopover_propose_action as a local stdio MCP tool - #7894
feat(mcp): register loopover_propose_action as a local stdio MCP tool#7894tryeverything24 wants to merge 1 commit into
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7894 +/- ##
==========================================
- Coverage 88.85% 80.67% -8.18%
==========================================
Files 88 89 +1
Lines 21214 23365 +2151
Branches 3675 4508 +833
==========================================
Hits 18849 18849
- Misses 2187 4338 +2151
Partials 178 178
Flags with carried forward coverage won't be shown. Click here to find out more.
|
Closes JSONbored#7753 Mirrors the exact registerStdioTool pattern PR JSONbored#6382 used for the 5 maintain-surface siblings (loopover_list_pending_actions et al): the handler calls the same bare POST .../agent/pending-actions endpoint `maintain propose` already calls, through the same apiPost client, and its description comes from the same stdioToolDescription centralized lookup. JSONbored#6744 added the route + CLI mirror without a stdio registration, so it fell outside JSONbored#6152's batch despite being the same family. The route's response always carries a fully-populated `action` (id/actionClass/status set unconditionally, per src/api/routes.ts's POST handler) -- only `created` genuinely varies, so that's the only branch the handler formats defensively. New dedicated suite (mcp-cli-propose-action-tool.test.ts) covers registration, the proxy contract, both the "Staged"/"Already staged" branches, an API-failure path, and pre-flight schema rejection -- following mcp-cli-maintain- tools.test.ts's shape. Bumped the pinned stdio tool count 80 -> 81 in mcp-tool-rename-aliases.test.ts (rebased past JSONbored#7877's own 79 -> 80 bump).
dd7f7ea to
998dd34
Compare
|
Caution 🛑 LoopOver review result - reject/close recommendedReview updated: 2026-07-21 16:38:07 UTC
Review summary Blockers
Nits — 5 non-blocking
Why this is blocked
📋 Copy for AI agents — paste into your coding agentCI checks failing
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
LoopOver is closing this pull request on the maintainer's behalf (CI is failing (codecov/patch); AI reviewers agree on a likely critical defect: codecov/patch reports 0.00% coverage of the diff despite test/unit/mcp-cli-propose-action-tool.test.ts being added with 8 tests targeting this exact code — this mismatch should be understood before merging, since it may indicate the new registerStdioTool block or proposeActionShape isn't actually being exercised by CI's coverage instrumentation.). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed. |
Summary
loopover_propose_actionwas registered as a remote MCP tool (src/mcp/server.ts:2582) and has a CLI mirror (maintain propose) — but had no local stdio registration inpackages/loopover-mcp/bin/loopover-mcp.ts, so a self-host operator using the local server (not the CLI or the remote MCP) had no way to call it directly. #6744 added the REST route + CLI mirror but never the stdio tool, so it fell outside #6152/PR #6382's own 5-tool batch for the same maintain-adjacent family (loopover_list_pending_actions,loopover_decide_pending_action,loopover_set_agent_paused,loopover_set_action_autonomy,loopover_get_gate_precision).Closes #7753
What changed
proposeActionShapeinput schema (mirrorssrc/mcp/server.ts's ownproposeActionShapefield-for-field;actionClassreuses the file's existingPROPOSE_ACTION_CLASSESconstant so this schema andmaintain propose's own validation can never disagree about what the route accepts).registerStdioTool("loopover_propose_action", ...)block placed directly after its five siblings, mirroring their exact shape:description: stdioToolDescription("loopover_propose_action"),inputSchema: proposeActionShape, handler returnstoolResult(...).maintain proposealready calls —apiPost(${toolRepoBase(owner, repo)}/agent/pending-actions, ...)— through the sameapiPostclient, so auth/timeouts/error-shaping come from there and there is no new/duplicated HTTP path.loopover_propose_actionentry toSTDIO_TOOL_DESCRIPTORS(categoryagent, matching the remote server'sMCP_TOOL_CATEGORIESentry for the same tool name) — the description is centralized there, not hardcoded inline, same as every sibling.action(id/actionClass/statusset unconditionally — confirmed by readingsrc/api/routes.ts's POST handler andcreatePendingAgentActionIfAbsent); onlycreatedgenuinely varies (false when an equivalent action is already staged), so that is the only branch the handler formats defensively — no speculative??fallbacks on fields the route guarantees.Tests
New
test/unit/mcp-cli-propose-action-tool.test.ts, followingmcp-cli-maintain-tools.test.ts's exact shape (the suite that covers #6152's five siblings): spins up the fixture API server + a real stdioStdioClientTransport/MCPClientagainst the built CLI, and asserts:loopover-mcp tools --json, with matching descriptions),POST /v1/repos/:owner/:repo/agent/pending-actionsendpointmaintain proposeuses, forwarding every optional field (reason/label/reviewBody/mergeMethod/closeComment),"Staged ..."whencreated: trueand"Already staged ..."whencreated: false(added a small additiveproposeActionCreatedoverride option to the sharedmcp-cli-harness.tsfixture, same pattern as the existingrepoDocRefreshoverride, to exercise thefalsebranch),actionClassand a non-positivepullNumber, before any network call.Also bumped the pinned stdio tool count in
test/unit/mcp-tool-rename-aliases.test.ts(rebased past #7877/loopover_get_outcome_calibration's own count bump: 80 → 81).Verification
npm run build --workspace @loopover/engine && npm run build:mcp— clean.npm run typecheck— 0 errors.npx vitest runon the new suite +mcp-cli-maintain-tools,mcp-cli-maintain,mcp-tool-rename-aliases,mcp-cli-tools,mcp-tool-categories,mcp-cli-tools-search— 71/71 pass.npm run test:mcp-pack,npm run docs:drift-check,npm run command-reference:check,npm run manifest:drift-check,npm run engine-parity:drift-check— all clean.git diff --checkagainstupstream/main— clean.upstream/mainimmediately before push (picked up feat(mcp): register loopover_get_outcome_calibration as a local stdio tool #7877'sloopover_get_outcome_calibrationstdio-tool addition, which landed in between and independently bumped the same pinned tool-count assertions — resolved by keeping both changelog lines and rebasing my bump to 80 → 81).Coverage note
packages/loopover-mcp/bin/loopover-mcp.tsis exercised exclusively via real subprocess spawn (this file's owntest/unit/support/mcp-cli-harness.ts), which the v8 coverage provider cannot instrument in-process —vitest.config.ts'scoverage.includestill lists this path deliberately (percodecov.yml's own comment,test/unit/codecov-policy.test.ts#4864 forbids a blanket exemption), so this is graded, not skipped. This is the same shape as PR #6382/#7758's own additions to this exact file, which reportedcodecov/patch: 100.00% of diff hit. The new code here is functionally exercised end-to-end through the real MCP protocol by the new suite above, matching the established convention for this file rather than an unverified "no patch surface" disclosure.