Skip to content

MCP: add a REST route + CLI mirror for loopover_get_eligibility_plan #6621

Description

@JSONbored

Context

loopover_get_eligibility_plan (src/mcp/server.ts:2358-2367) derives a structured eligibility plan (is the branch/PR eligible now, public-safe blockers, cleanup paths) from a ScorePreviewResult via deriveEligibilityPlan (src/services/eligibility-plan.ts:109). Its handler (getEligibilityPlan, src/mcp/server.ts:3956-3972) fetches the exact same repo/snapshot/contributor-evidence data as previewScore/loopover_preview_local_pr_score, builds the same ScorePreviewResult via buildScorePreview(...), then applies deriveEligibilityPlan(preview) before returning.

This is structurally identical to how loopover_explain_score_breakdown is built: its handler also fetches the same repo/snapshot/evidence data, calls buildScorePreview(...), and then applies a second pure derivation (explainScoreBreakdown(preview)) on top. loopover_explain_score_breakdown has a full REST + CLI mirror pair:

  • POST /v1/scoring/explain-breakdown (src/api/routes.ts:2108-2124) — same input schema (scorePreviewSchema) as POST /v1/scoring/preview, same repo/snapshot/evidence fetch, then explainScoreBreakdown(preview) instead of makeScorePreviewRecord(...).
  • registerStdioTool("loopover_explain_score_breakdown", ...) in packages/loopover-mcp/bin/loopover-mcp.js:1512-1557, which assembles a scoring-preview request body from local branch/diff metadata and calls apiPost("/v1/scoring/explain-breakdown", body).

loopover_get_eligibility_plan has neither: there is no /v1/scoring/eligibility-plan (or equivalent) REST route, and no CLI mirror in packages/loopover-mcp/bin/loopover-mcp.js at all — grepping the CLI source for "eligibility" turns up only the unrelated loopover_post_eligibility_comment write-tool. A contributor using the local CLI currently cannot get an eligibility-plan verdict at all, despite already being able to fetch both the raw score preview (loopover_preview_local_pr_score/v1/scoring/preview) and its breakdown explanation (loopover_explain_score_breakdown/v1/scoring/explain-breakdown) through the CLI today.

Requirements

  • Add POST /v1/scoring/eligibility-plan to src/api/routes.ts, placed immediately after /v1/scoring/explain-breakdown (src/api/routes.ts:2108-2124) and structured identically to it: parse the body with the same scorePreviewSchema, call requireContributorAccess when contributorLogin is supplied (matching /v1/scoring/preview's own conditional check — loopover_get_eligibility_plan's own MCP handler only gates on contributorLogin being present, same as previewScore, not explainScoreBreakdown's unconditional-required version), fetch repo/snapshot/evidence/contributorIssues the same way, build scoreInput/preview via buildScorePreview(...), then return c.json(deriveEligibilityPlan(preview)). Reuse deriveEligibilityPlan from src/services/eligibility-plan.ts as-is; do not reimplement it in the route.
  • In packages/loopover-mcp/bin/loopover-mcp.js, add a registerStdioTool("loopover_get_eligibility_plan", ...) block immediately after the existing loopover_explain_score_breakdown block (packages/loopover-mcp/bin/loopover-mcp.js:1512-1558), reusing the exact same localScoreShape input schema and the exact same local-branch-metadata-to-request-body assembly logic loopover_explain_score_breakdown's handler already contains (workspace resolution, collectLocalDiff, buildBranchAnalysisPayload, estimated source lines) — the only difference should be the final call: apiPost("/v1/scoring/eligibility-plan", body) instead of apiPost("/v1/scoring/explain-breakdown", body). Do not duplicate that assembly logic by copy-pasting a second, drifting copy — factor the shared body-building into a helper both stdio tools call, OR (if a helper extraction is out of scope for this issue) copy the block verbatim and note in the PR description that a follow-up should de-duplicate it.
  • Add a matching STDIO_TOOL_DESCRIPTORS entry (category "discovery", matching loopover_get_eligibility_plan: "discovery" in the server's own MCP_TOOL_CATEGORIES).

Deliverables

  • POST /v1/scoring/eligibility-plan route added to src/api/routes.ts
  • loopover_get_eligibility_plan stdio tool registered in packages/loopover-mcp/bin/loopover-mcp.js, with a STDIO_TOOL_DESCRIPTORS entry
  • New route-level test(s) covering an eligible plan, an ineligible plan with blockers, and the contributorLogin-optional path, following the existing /v1/scoring/explain-breakdown route tests
  • New CLI-level test(s) covering the stdio tool's request-body assembly and apiPost call, following test/unit/mcp-cli-plan-scorer-tools.test.ts's existing coverage of loopover_explain_score_breakdown

Test Coverage Requirements

This touches src/api/routes.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 (eligible/ineligible plans, contributorLogin present/absent) must be covered by new tests.

Expected Outcome

A contributor using the local loopover-mcp CLI can get an eligibility-plan verdict (eligible now / blockers / cleanup paths) the same way they can already get a raw score preview or a score breakdown explanation — closing the one tool in that trio that currently has no REST route or CLI mirror.

Links & Resources

  • src/mcp/server.ts:2358-2367 (existing MCP tool) and :3956-3972 (getEligibilityPlan handler, the exact logic to mirror server-side in the new route)
  • src/services/eligibility-plan.ts:109 (deriveEligibilityPlan, reuse as-is)
  • src/api/routes.ts:2086-2124 (/v1/scoring/preview and /v1/scoring/explain-breakdown, the two routes to model the new one on)
  • packages/loopover-mcp/bin/loopover-mcp.js:1503-1558 (loopover_explain_score_breakdown stdio tool, the CLI-mirror pattern — and its body-assembly logic — to copy)
  • test/unit/mcp-cli-plan-scorer-tools.test.ts (existing CLI-mirror test precedent)
  • test/unit/mcp-eligibility-plan.test.ts (existing server-side test to extend/mirror at the route level)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions