Skip to content

feat(mcp): add remote + stdio tool surfaces for loopover_get_repo_focus_manifest - #7918

Closed
xfodev wants to merge 2 commits into
JSONbored:mainfrom
xfodev:feat/get-repo-focus-manifest-two-surfaces-7808
Closed

feat(mcp): add remote + stdio tool surfaces for loopover_get_repo_focus_manifest#7918
xfodev wants to merge 2 commits into
JSONbored:mainfrom
xfodev:feat/get-repo-focus-manifest-two-surfaces-7808

Conversation

@xfodev

@xfodev xfodev commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the two missing MCP surfaces for loopover_get_repo_focus_manifest (a repo's own persisted focus manifest + compiled policy): a remote MCP tool in src/mcp/server.ts and a local stdio MCP tool in packages/loopover-mcp/bin. Mirrors the two-surface loopover_get_maintainer_noise shape but replicates the underlying GET /v1/repos/:owner/:repo/focus-manifest route's own auth — requireRepoAccess (the read-level maintainer/owner/operator + session-repo-access mirror), not the stricter requireRepoApprovalQueueAccess (which adds a live-write check the GET route does not perform).

Read-only, per the issue's scope boundary: no tool for the refresh(POST)/PUT write routes, no new REST route, no new human CLI verb.

What changed

  • src/mcp/server.ts: register loopover_get_repo_focus_manifest (input ownerRepoShape, focusManifestOutputSchema returning { repoFullName, manifest, policy }), add its MCP_TOOL_CATEGORIES entry ("maintainer"), and a getRepoFocusManifest handler calling loadRepoFocusManifest + compileFocusManifestPolicy exactly as the GET route does, behind requireRepoAccess.
  • packages/loopover-mcp/bin/loopover-mcp.ts: register the local stdio tool proxying GET ${repoBase}/focus-manifest via apiGet.

Testing / coverage

  • test/unit/mcp-output-schemas.test.ts: authorized success (seeded manifest → { repoFullName, manifest.present, policy }) and the forbidden branch (static mcp identity outside the read allowlist → cannot access this repository); added the tool to TOOLS_WITH_OUTPUT_SCHEMA. Both run in-process against LoopoverMcp(env).createServer(), so every changed line/branch in src/mcp/server.ts is Codecov-covered.
  • test/unit/mcp-cli-repo-focus-manifest.test.ts: in-process stdio invocation (via loopover_plan_repo_issues has no REST route, CLI command, or local stdio MCP tool #7764's isProcessEntrypoint guard + InMemoryTransport) so the bin tool's apiGet-proxy body gets real Codecov-measured coverage — a subprocess spawn can't be v8-instrumented.
  • test/unit/mcp-tool-rename-aliases.test.ts: tool-count invariant → 83. This also reconciles a pin drift — feat(mcp): add remote + stdio tool surfaces for loopover_get_activation_preview #7887 registered loopover_get_activation_preview's stdio tool without bumping this pin (live count had reached 82), documented inline in the same convention as the earlier #6942 note.

Incidental regression fix (required for CI)

This PR's packages/loopover-mcp/** change pulls the whole mcp-cli-*.test.ts suite into CI's scoped test selection, which surfaced a pre-existing failure: test/unit/mcp-cli-activation-preview.test.ts (added by #7887) hangs to its hook timeout on main. #7764 later gated the bin's top-level await server.connect(...) behind isProcessEntrypoint() (realpath(argv[1]) === realpath(this module)); that test set argv[1] to the bare string "loopover-mcp", so realpathSync throws → the guard is false → the server never connects → client.connect hangs. #7887 merged just before #7764, so its own CI never ran against the guard. Fixed by pointing argv[1] at the bin's resolved path (test-only change).

No REST/OpenAPI change (the focus-manifest route already exists), no migrations, no wrangler changes.

Closes #7808

…us_manifest

Register loopover_get_repo_focus_manifest as a remote MCP tool (src/mcp/server.ts)
and a local stdio MCP tool (packages/loopover-mcp/bin), mirroring the two-surface
loopover_get_maintainer_noise shape but replicating the GET
/v1/repos/:owner/:repo/focus-manifest route's own auth: requireRepoAccess (the
read-level maintainer/owner/operator + session-repo-access mirror), not the
stricter requireRepoApprovalQueueAccess. Read-only: no refresh/PUT tool, no new
REST route, no new human CLI verb.

Closes JSONbored#7808
@xfodev
xfodev requested a review from JSONbored as a code owner July 21, 2026 17:39
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

…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.
@xfodev
xfodev force-pushed the feat/get-repo-focus-manifest-two-surfaces-7808 branch from 62479a6 to 07adbff Compare July 21, 2026 17:44
@loopover-orb loopover-orb Bot closed this Jul 21, 2026
@loopover-orb

loopover-orb Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

This repository reviews pull requests one-shot: the PR must be correct as originally opened. Pushing an additional commit closes it automatically instead of restarting review — open a fresh pull request with every fix included.

@loopover-orb loopover-orb Bot added review-evasion Gittensor contributor context gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. labels Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 45.45455% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.85%. Comparing base (b3e1bc3) to head (07adbff).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/mcp/server.ts 25.00% 6 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #7918       +/-   ##
===========================================
+ Coverage   58.78%   80.85%   +22.06%     
===========================================
  Files         730       90      -640     
  Lines       74842    24387    -50455     
  Branches    22839     4691    -18148     
===========================================
- Hits        43999    19719    -24280     
+ Misses      27180     4427    -22753     
+ Partials     3663      241     -3422     
Flag Coverage Δ
shard-1 22.75% <27.27%> (?)
shard-2 21.80% <45.45%> (-25.09%) ⬇️

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 13.60% <100.00%> (+0.30%) ⬆️
src/mcp/server.ts 57.27% <25.00%> (+9.47%) ⬆️

... and 640 files with indirect coverage changes

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. review-evasion Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loopover_get_repo_focus_manifest (read-only) has a REST route but no remote MCP tool or local stdio MCP tool

1 participant