feat(mcp): MCP tool + maintain CLI for contributor-issue-draft generation - #7019
Conversation
… maintain CLI The POST /v1/repos/:owner/:repo/contributor-issue-drafts/generate route was web-dashboard-only: no MCP tool and no CLI could reach it. Add loopover_generate_contributor_issue_drafts to src/mcp/server.ts (requireRepoManageAccess-gated) and a `maintain generate-issue-drafts` CLI subcommand. Both preserve the route's create-safety EXACTLY: dry-run by default, and the write path is entered only when the caller passes BOTH create:true and dryRun:false, so neither surface can silently open issues. The MCP tool re-applies the route's explicit_create_requires_dry_run_false guard and returns only the counts + posture, never the per-draft title/body text. Closes JSONbored#6757
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7019 +/- ##
=======================================
Coverage 93.72% 93.73%
=======================================
Files 690 690
Lines 68560 68571 +11
Branches 18743 18745 +2
=======================================
+ Hits 64261 64273 +12
Misses 3302 3302
+ Partials 997 996 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-17 18:25:29 UTC
Review summary Nits — 5 non-blocking
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.
|
What
POST /v1/repos/:owner/:repo/contributor-issue-drafts/generatewas web-dashboard-only — no MCP tool and no CLI could reach it. This adds both mirrors the issue asks for:loopover_generate_contributor_issue_draftsinsrc/mcp/server.ts,requireRepoManageAccess-gated.maintain generate-issue-drafts [--create] [--limit N] --repo owner/repoCLI inpackages/loopover-mcp/bin/loopover-mcp.js.Create-safety, preserved identically on both surfaces
The whole risk here is silently opening issues, so both mirrors reproduce the route's guard exactly:
dryRun/create/limitschema mirrors the route'scontributorIssueDraftGenerateSchemabyte-for-byte (same defaults, same 1–20 bound). The CLI sends{create:false, dryRun:true}for a bare invocation.createalone never writes. The MCP handler re-applies the route'sexplicit_create_requires_dry_run_falseguard: a caller must pass bothcreate:trueanddryRun:false. The CLI's--createmaps to exactly that{create:true, dryRun:false}shape — the only shape the route accepts for a real write.{create:true, dryRun:false}), and the write path requires repo write access.proposed/created/skipped*), never the per-drafttitle/body— the same public-safe scrubgetAgentAuditFeeduses. The CLI's plain-text path sanitizes the generated draft titles for the terminal (fix(mcp): ANSI/control-char terminal sanitization is applied to exactly one output path, not the others that also print third-party text #6261).requireRepoManageAccessis checked first, before the guard or the service.Testing
test/unit/mcp-generate-contributor-issue-drafts.test.ts(new, 5 cases): dry-run preview returns counts and omitsdrafts[];create:truewithoutdryRun:falseis rejected (explicit_create_requires_dry_run_false); a static MCP-token caller is denied withoutMCP_ACTUATION_REPO_ALLOWLIST; an operator session is admitted and attributed; and the tool'sstructuredContentequals a direct service call for identical input (surface parity).test/unit/mcp-cli-maintain.test.ts(2 cases): a bare command forwards{create:false, dryRun:true}and strips an ANSI escape from a draft title;--create --limit 3forwards{create:true, dryRun:false, limit:3}and renders the created issue link.Patch coverage measured, not assumed: every changed line and branch in
src/mcp/server.tsis covered — 0 uncovered statements, 0 uncovered branches (packages/loopover-mcp/bin/**is outsidevitest.config.ts's coverage scope, so the CLI is exercised for correctness rather than the gate).Green locally at this base (
ad8536e):typecheck,build --workspace @loopover/engine,build:mcp,test:mcp-pack,command-reference:check,docs:drift-check,manifest:drift-check, and the full blast radius of 40 test files (311 tests) touching the changed symbols.Resubmit of #6976 (auto-closed on a mechanical base-branch conflict; CI was 16/16 green). Rebased onto current main with the conflict resolved.
Closes #6757