feat(mcp): admin overview — all users' tokens + OAuth clients, with revoke - #34
Merged
Conversation
…evoke
Add an admin-only MCP Admin page (System → MCP Admin) giving a fleet-wide
view of MCP credentials: every user's active API tokens (annotated with the
owner) and all registered OAuth clients, with revoke/delete on any of them.
Removing an OAuth client also purges its codes and refresh tokens. Secrets
are never exposed — only metadata.
Backend:
- store: ListAllAPITokens (join users for username), AdminRevokeAPIToken,
ListOAuthClients, DeleteOAuthClient (cascades codes + refresh tokens).
- api: /api/mcp-admin/{tokens,oauth-clients} handlers, gated by the
"__admin" section (sectionForPath: mcp-admin → __admin).
- tests: store unit tests; HTTP functional test; pentests asserting the
admin gate holds (non-admin → 403, no side effects), unauthenticated →
401, self-service revoke stays owner-scoped (IDOR), and the list never
leaks token secrets/hashes.
Frontend:
- MCPAdmin page, api client methods + AdminMCPToken/AdminOAuthClient types,
admin-only nav entry, route, rebuilt web/dist.
Docs: docs/mcp.md admin section + CHANGELOG entry.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an admin-only “MCP Admin” overview to manage MCP credentials fleet-wide, complementing the existing per-user “MCP Access” token management and making shared instances easier to administer safely.
Changes:
- Adds new admin UI page to list/revoke all users’ MCP API tokens and list/delete dynamically registered OAuth clients.
- Introduces new admin API endpoints + store methods for listing/revoking tokens and listing/deleting OAuth clients (with cascading purge of codes/refresh tokens).
- Expands access control mapping so
/api/mcp-admin/*routes are gated by the__adminsection; adds unit/HTTP/pen-test coverage and docs/changelog updates.
Reviewed changes
Copilot reviewed 15 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/pages/MCPAdmin.tsx | New admin UI page for fleet-wide MCP token + OAuth client overview with revoke/delete actions. |
| web/src/lib/types.ts | Adds admin-specific response types for MCP tokens and OAuth clients. |
| web/src/lib/api.ts | Adds frontend API helpers for /api/mcp-admin/* endpoints. |
| web/src/layout/Shell.tsx | Adds “MCP Admin” navigation item (admin-only) and icon import. |
| web/src/App.tsx | Registers the /mcp-admin route. |
| web/dist/index.html | Rebuilt frontend bundle references. |
| web/dist/assets/index-DlPBIcda.css | Rebuilt compiled CSS output. |
| web/dist/assets/CodeEditor-R6mzRIeK.js | Rebuilt compiled JS output. |
| internal/store/oauth.go | Adds store methods to list OAuth clients and delete a client while purging dependent auth state in one transaction. |
| internal/store/mcp_admin_test.go | Store-level tests for admin token listing/revocation and OAuth client list/delete cascade behavior. |
| internal/store/api_tokens.go | Adds ListAllAPITokens (with username join) and AdminRevokeAPIToken (non-owner-scoped). |
| internal/api/server.go | Mounts new /api/mcp-admin/* routes. |
| internal/api/mcp_admin_pentest_test.go | Adversarial tests for admin gating, unauthenticated behavior, IDOR protection, and secret/hash non-leakage. |
| internal/api/mcp_admin_handlers.go | Implements admin handlers for listing/revoking tokens and listing/deleting OAuth clients. |
| internal/api/mcp_admin_handlers_test.go | HTTP functional test covering admin list/revoke and client list/delete flows. |
| internal/api/access_middleware.go | Maps mcp-admin segment to __admin section for permissions middleware. |
| docs/mcp.md | Documents the new MCP Admin overview page and behavior. |
| CHANGELOG.md | Adds an Unreleased entry describing the MCP Admin overview feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+17
to
+19
| // /api/mcp-admin/… which sectionForPath maps to "__admin", so the permissions | ||
| // middleware rejects non-admins with 403 before any handler runs. Secrets are | ||
| // never exposed here — only token hashes/metadata and public OAuth client rows. |
- store: ListAllAPITokens no longer SELECTs/scans token_hash — the admin overview is metadata-only, so the digest never reaches process memory and can't leak via a log line or panic. - comment: the handler header said the overview exposes "token hashes"; it does not (and a pentest asserts no hash leak). Reworded to "metadata (no secret, not even the stored hash)".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MCP Admin overview — make MCP team-ready
The MCP feature (#31) gave each user a self-service MCP Access page for their own tokens. On a shared instance an administrator had no way to see or cut off MCP access across the fleet. This adds that.
What's new
A new admin-only page System → MCP Admin with a fleet-wide view:
Secrets are never exposed here — only metadata (no raw token, no stored hash).
Backend
ListAllAPITokens(joinsusersfor the username),AdminRevokeAPIToken(not owner-scoped),ListOAuthClients,DeleteOAuthClient(cascades codes + refresh tokens in one tx)./api/mcp-admin/tokens(GET, DELETE{id}) and/api/mcp-admin/oauth-clients(GET, DELETE{id}), mounted in the authenticated group and gated by the__adminsection (sectionForPath:mcp-admin→__admin), so the existing permissions middleware rejects non-admins before any handler runs.Security & tests
This manages other users' credentials, so it gets adversarial coverage per the repo's
feature-testsdiscipline:mcp_admin_pentest_test.go):go test -short ./...,go vet,gofmt, andtsc --noEmitall green;web/distrebuilt.Docs
docs/mcp.mdadmin-overview section +CHANGELOG.mdentry.🤖 Generated with Claude Code