Context
GET /v1/repos/:owner/:repo/focus-manifest (src/api/routes.ts:2691) returns a repo's own persisted focus manifest plus its compiled policy (loadRepoFocusManifest → compileFocusManifestPolicy), gated by requireAppRole(["maintainer", "owner", "operator"]) plus a session-repo-access check when the caller is a session identity. This is a distinct capability from the already-tooled loopover_validate_config / POST /v1/validate/focus-manifest (which validates an ad-hoc manifest string the caller supplies, computed in-process with no repo lookup) — this route reads the repo's own stored manifest. It has no remote MCP tool and no local stdio MCP tool.
⚠️ Scope boundary — read-only, GET only. POST /v1/repos/:owner/:repo/focus-manifest/refresh (src/api/routes.ts:2705) and PUT /v1/repos/:owner/:repo/focus-manifest (src/api/routes.ts:2713) are separate, requireRepoWriteAccess-gated write routes on the same resource. Out of scope for this issue — do not add MCP/CLI mirrors for either of them here; a PR that adds a write-capable tool instead of (or in addition to) the read-only one does NOT satisfy this issue.
Requirements
⚠️ Required pattern — mirror loopover_get_maintainer_noise's two-surface shape (src/mcp/server.ts:1923-1930, stdio registration packages/loopover-mcp/bin/loopover-mcp.ts:1459-1467) for the registration mechanics, but replicate this route's own auth precisely — requireAppRole(["maintainer", "owner", "operator"]) plus the session-repo-access check — do not substitute requireRepoMaintainer or any other gate. No separate human CLI verb exists for maintainer-noise either — do not add one here.
- Register
loopover_get_repo_focus_manifest as a remote MCP tool in src/mcp/server.ts, input ownerRepoShape, calling loadRepoFocusManifest + compileFocusManifestPolicy exactly as the GET route does, returning the identical { repoFullName, manifest, policy } shape. Enforce the same role/session gate the REST route uses (see the scope-boundary callout above for the exact gate to replicate — check how the remote-MCP layer's existing requireRepoAccess/requireRepoApprovalQueueAccess-style helpers already express an app-role check, if one already does, before adding a new one).
- Add
loopover_get_repo_focus_manifest to MCP_TOOL_CATEGORIES as "maintainer".
- Register
loopover_get_repo_focus_manifest as a local stdio MCP tool in packages/loopover-mcp/bin/loopover-mcp.ts, calling GET ${repoBase}/focus-manifest via apiGet.
- Do not register any tool for the
refresh (POST) or PUT routes.
- Do not add a new human-typable CLI verb.
- Do not change
loadRepoFocusManifest, compileFocusManifestPolicy, the REST route, or its auth gate.
Deliverables
Test Coverage Requirements
src/mcp/server.ts and packages/loopover-mcp are both under the 99%+ Codecov patch gate — cover both the authorized and forbidden branches (mirroring the REST route's own auth test coverage). Verify packages/loopover-mcp's own coverage.include scoping first.
Expected Outcome
A repo's own persisted focus manifest and compiled policy are readable via remote MCP and local stdio MCP, with the exact same auth boundary the REST route already enforces — the write-side refresh/PUT routes remain REST-only, deliberately, pending a separate decision about exposing a write-capable tool.
Links & Resources
src/api/routes.ts:2691 (existing GET REST route, requireAppRole-gated); src/api/routes.ts:2705 and :2713 (the out-of-scope write routes on the same resource)
src/mcp/server.ts:1923-1930, packages/loopover-mcp/bin/loopover-mcp.ts:1459-1467 (the loopover_get_maintainer_noise two-surface registration pattern to mirror mechanically — note its auth gate itself differs, see Requirements)
src/mcp/server.ts:1798-1890 (MCP_TOOL_CATEGORIES map)
loopover_validate_config / POST /v1/validate/focus-manifest (the existing, distinct ad-hoc-string validator — not the same capability as this issue)
Context
GET /v1/repos/:owner/:repo/focus-manifest(src/api/routes.ts:2691) returns a repo's own persisted focus manifest plus its compiled policy (loadRepoFocusManifest→compileFocusManifestPolicy), gated byrequireAppRole(["maintainer", "owner", "operator"])plus a session-repo-access check when the caller is a session identity. This is a distinct capability from the already-tooledloopover_validate_config/POST /v1/validate/focus-manifest(which validates an ad-hoc manifest string the caller supplies, computed in-process with no repo lookup) — this route reads the repo's own stored manifest. It has no remote MCP tool and no local stdio MCP tool.Requirements
loopover_get_repo_focus_manifestas a remote MCP tool insrc/mcp/server.ts, inputownerRepoShape, callingloadRepoFocusManifest+compileFocusManifestPolicyexactly as the GET route does, returning the identical{ repoFullName, manifest, policy }shape. Enforce the same role/session gate the REST route uses (see the scope-boundary callout above for the exact gate to replicate — check how the remote-MCP layer's existingrequireRepoAccess/requireRepoApprovalQueueAccess-style helpers already express an app-role check, if one already does, before adding a new one).loopover_get_repo_focus_manifesttoMCP_TOOL_CATEGORIESas"maintainer".loopover_get_repo_focus_manifestas a local stdio MCP tool inpackages/loopover-mcp/bin/loopover-mcp.ts, callingGET ${repoBase}/focus-manifestviaapiGet.refresh(POST) orPUTroutes.loadRepoFocusManifest,compileFocusManifestPolicy, the REST route, or its auth gate.Deliverables
loopover_get_repo_focus_manifestregistered as a remote MCP tool insrc/mcp/server.ts, category"maintainer", inputownerRepoShape, with the same role/session auth the GET REST route enforces.loopover_get_repo_focus_manifestregistered as a local stdio MCP tool inpackages/loopover-mcp/bin/loopover-mcp.ts.refresh/PUTwrite routes, no new REST route, and no new human CLI verb.Test Coverage Requirements
src/mcp/server.tsandpackages/loopover-mcpare both under the 99%+ Codecov patch gate — cover both the authorized and forbidden branches (mirroring the REST route's own auth test coverage). Verifypackages/loopover-mcp's owncoverage.includescoping first.Expected Outcome
A repo's own persisted focus manifest and compiled policy are readable via remote MCP and local stdio MCP, with the exact same auth boundary the REST route already enforces — the write-side
refresh/PUTroutes remain REST-only, deliberately, pending a separate decision about exposing a write-capable tool.Links & Resources
src/api/routes.ts:2691(existing GET REST route,requireAppRole-gated);src/api/routes.ts:2705and:2713(the out-of-scope write routes on the same resource)src/mcp/server.ts:1923-1930,packages/loopover-mcp/bin/loopover-mcp.ts:1459-1467(theloopover_get_maintainer_noisetwo-surface registration pattern to mirror mechanically — note its auth gate itself differs, see Requirements)src/mcp/server.ts:1798-1890(MCP_TOOL_CATEGORIESmap)loopover_validate_config/POST /v1/validate/focus-manifest(the existing, distinct ad-hoc-string validator — not the same capability as this issue)