Skip to content

feat(mcp): add remote + stdio tool surfaces for loopover_get_activation_preview - #7887

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
xfodev:feat/mcp-tool-activation-preview-7799
Jul 21, 2026
Merged

feat(mcp): add remote + stdio tool surfaces for loopover_get_activation_preview#7887
JSONbored merged 1 commit into
JSONbored:mainfrom
xfodev:feat/mcp-tool-activation-preview-7799

Conversation

@xfodev

@xfodev xfodev commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

GET /v1/repos/:owner/:repo/activation-preview (src/api/routes.ts, the deterministic maintainer-activation demo behind buildMaintainerActivationPreview, gated by the per-repo maintainer gate) had a REST route but no remote MCP tool and no local stdio MCP tool — unlike its loopover_get_maintainer_noise sibling, which has both. Mirrors that sibling exactly:

  • Remote MCP tool loopover_get_activation_preview in src/mcp/server.ts (category maintainer), ownerRepoShape input, assembling getRepository + resolveRepositorySettings + listPullRequestsbuildMaintainerActivationPreview identically to the route, behind the same maintainer gate.
  • Local stdio MCP tool in packages/loopover-mcp/bin/loopover-mcp.ts, proxying apiGet of the existing route.

No new REST route, no human CLI verb (the sibling has none); buildMaintainerActivationPreview, the route, its gate, and src/services/** are unchanged.

Tests

test/unit/mcp-cli-activation-preview.test.ts (new, in-process) drives the stdio tool via a real MCP client over an in-memory transport. mcp-output-schemas.test.ts gains the tool's output-schema entry plus a happy-path and a member-only-denied case, covering the remote registration in-process. Both new surfaces are 100% statement + branch covered; mcp-cli-completion-spec, mcp-tool-categories, and mcp-tool-rename-aliases (tool-count sync) pass.

UI Evidence

N/A — no UI/frontend changes (backend MCP tool registration only; no apps/** files touched).

Validation

  • Root tsc --noEmit clean (my files); new tool registrations 100% covered; category-sync, completion-spec, output-schema, and tool-count tests pass; rebased on latest main. No wallet/hotkey/trust-score/reward terms in tool output.

Closes #7799

…vation_preview

GET /v1/repos/:owner/:repo/activation-preview had a REST route but no remote MCP
tool and no local stdio MCP tool, unlike its maintainer-noise sibling which has
both. Register loopover_get_activation_preview as a remote MCP tool (category
maintainer, assembling the same getRepository + resolveRepositorySettings +
listPullRequests -> buildMaintainerActivationPreview the route uses, behind the
same maintainer gate) and as a local stdio tool proxying GET the existing route.
No REST route, CLI verb, service, or UI change.

Closes JSONbored#7799
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.31%. Comparing base (1454d22) to head (15319c0).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7887      +/-   ##
==========================================
- Coverage   91.40%   82.31%   -9.10%     
==========================================
  Files         730       90     -640     
  Lines       74763    24353   -50410     
  Branches    22815     4684   -18131     
==========================================
- Hits        68335    20045   -48290     
+ Misses       5385     4090    -1295     
+ Partials     1043      218     -825     
Flag Coverage Δ
shard-1 22.68% <45.45%> (-35.89%) ⬇️
shard-2 12.67% <18.18%> (-39.17%) ⬇️
shard-3 24.65% <72.72%> (-25.57%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/loopover-mcp/bin/loopover-mcp.ts 10.96% <100.00%> (+10.96%) ⬆️
src/mcp/server.ts 96.48% <100.00%> (+0.02%) ⬆️

... and 640 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 21, 2026
@loopover-orb

loopover-orb Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-21 16:32:00 UTC

6 files · 1 AI reviewer · no blockers · readiness 80/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR adds a remote MCP tool and stdio CLI mirror for the existing `/v1/repos/:owner/:repo/activation-preview` REST route, following the established `loopover_get_maintainer_noise` pattern almost line-for-line: same `Promise.all` assembly of `getRepository`/`resolveRepositorySettings`/`listPullRequests`, same category registration, same output-schema shape, and a stdio proxy that just does `apiGet`. Tests cover both the remote tool (happy path + member-only denial) and the stdio proxy via an in-memory MCP transport, and the tool-count assertions were bumped from 79 to 80 consistently across the rename-aliases test. The change is well-scoped and closes #7799 as described, with no route, service, or schema changes needed since it purely wires an existing deterministic builder into two new tool surfaces.

Nits — 5 non-blocking
  • src/mcp/server.ts:3149 — `getActivationPreview` calls `this.requireRepoApprovalQueueAccess(fullName)` while the sibling `getLabelAudit`/most other maintainer tools call `this.requireRepoAccess`; confirm `requireRepoApprovalQueueAccess` enforces the same maintainer-only gate as the REST route (rather than an approval-queue-specific scope) since the method name suggests a narrower purpose than "maintainer access".
  • packages/loopover-mcp/bin/loopover-mcp.ts:1484 — the new tool handler types `({ owner, repo }: any)`, matching the file's existing convention but still worth tightening to the shape from `ownerRepoShape` if the file is ever cleaned up.
  • test/unit/mcp-cli-activation-preview.test.ts — duplicates a fair amount of harness/env-save boilerplate already present in `mcp-cli-maintainer-noise.test.ts`; consider extracting a shared setup helper if a third such test is added.
  • Double-check `requireRepoApprovalQueueAccess` vs `requireRepoAccess` naming/semantics at src/mcp/server.ts:3149 before merge, since a mismatched gate would be a real access-control bug even though the added test only verifies the member-only-denied case for a private repo.
  • Consider adding one stdio-proxy test asserting the error/non-200 path from `apiGet`, mirroring what likely exists for `loopover_get_maintainer_noise`, to keep the two tools' coverage symmetric.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7799
Related work ⚠️ 1 scoped overlap Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 80 registered-repo PR(s), 46 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor xfodev; Gittensor profile; 80 PR(s), 0 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff registers loopover_get_activation_preview as a remote MCP tool in src/mcp/server.ts (category "maintainer", ownerRepoShape input, assembling getRepository/resolveRepositorySettings/listPullRequests into buildMaintainerActivationPreview) and as a local stdio tool in loopover-mcp.ts proxying GET .../activation-preview via apiGet, matching the maintainer_noise pattern with no new REST route

Review context
  • Author: xfodev
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: JavaScript, TypeScript
  • Official Gittensor activity: 80 PR(s), 0 issue(s).
  • Related work: Titles/paths share 7 meaningful terms. (PR #7894, PR #7893)
Contributor next steps
  • Start here: Review top overlaps.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask 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.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

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.

  • Re-run LoopOver review

@JSONbored
JSONbored merged commit e8e5d89 into JSONbored:main Jul 21, 2026
12 checks passed
RealDiligent added a commit to RealDiligent/gittensory that referenced this pull request Jul 21, 2026
Mirror the maintain-family registerStdioTool pattern (JSONbored#6382/JSONbored#7877) and reuse
the same REST endpoint the existing `maintain automation-state` CLI already
calls. Bump the stdio tool-count invariant to 83 (correcting the stale pin
left after JSONbored#7887).

Closes JSONbored#7752.

Co-authored-by: Cursor <cursoragent@cursor.com>
tryeverything24 added a commit to tryeverything24/loopover that referenced this pull request Jul 21, 2026
Closes JSONbored#7754

Mirrors the existing registerStdioTool siblings (loopover_get_gate_precision,
loopover_get_outcome_calibration, loopover_plan_repo_issues) exactly: same
input-schema convention, same stdioToolDescription lookup, same toolResult
formatting. The tool proxies to the same POST {repoBase}/repo-docs/refresh
endpoint the maintain refresh-docs CLI subcommand already calls, so there is
no duplicated HTTP logic.

Extends the existing array-driven test/unit/mcp-cli-maintain-tools.test.ts
(same pattern PR JSONbored#7877 used for its outcome-calibration sibling) rather than
adding a new dedicated test file, reusing the fixture server's existing
/repo-docs/refresh route.

Also corrects test/unit/mcp-tool-rename-aliases.test.ts's pinned tool count:
the live count was 83, not 82, because JSONbored#7799 (PR JSONbored#7887) registered
loopover_get_activation_preview without ever bumping this pin.
xfodev added a commit to xfodev/loopover that referenced this pull request Jul 21, 2026
…SONbored#7764's entrypoint guard

JSONbored#7764 gated the bin's top-level `await server.connect(new StdioServerTransport())` behind
isProcessEntrypoint() (realpath(argv[1]) === realpath(this module)). JSONbored#7887's activation-preview
test set argv[1] to the bare string "loopover-mcp", so realpathSync throws, the guard is false,
the top-level connect is skipped, its mocked in-memory transport is never wired to the server,
and client.connect hangs to the 10s hook timeout. JSONbored#7887 merged just before JSONbored#7764, so its CI never
saw the guard; main has been latently red on this test since. Point argv[1] at the bin's own
resolved path so the guard is satisfied on import. Surfaced here because this PR's bin change pulls
the mcp-cli-*.test.ts suite into scoped selection.
@github-actions github-actions Bot mentioned this pull request Jul 21, 2026
12 tasks
xfodev added a commit to xfodev/loopover that referenced this pull request Jul 21, 2026
…SONbored#7764's entrypoint guard

JSONbored#7764 gated the bin's top-level `await server.connect(new StdioServerTransport())` behind
isProcessEntrypoint() (realpath(argv[1]) === realpath(this module)). JSONbored#7887's activation-preview
test set argv[1] to the bare string "loopover-mcp", so realpathSync throws, the guard is false,
the top-level connect is skipped, its mocked in-memory transport is never wired to the server,
and client.connect hangs to the 10s hook timeout. JSONbored#7887 merged just before JSONbored#7764, so its CI never
saw the guard; main has been latently red on this test since. Point argv[1] at the bin's own
resolved path so the guard is satisfied on import. Surfaced here because this PR's bin change pulls
the mcp-cli-*.test.ts suite into scoped selection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loopover_get_activation_preview has a REST route but no remote MCP tool or local stdio MCP tool

2 participants