feat: MCP OAuth plugin for automatic browser-based authentication#627
feat: MCP OAuth plugin for automatic browser-based authentication#627yanekyuk merged 9 commits intoindexnetwork:devfrom
Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 15 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
📝 WalkthroughWalkthroughThis pull request introduces an end-to-end MCP OAuth plugin for Index Network, enabling Claude Code to authenticate via browser-based OAuth. Changes include frontend login routes, backend MCP handler updates with OAuth token validation, Better Auth configuration switching from Changes
Sequence Diagram(s)sequenceDiagram
actor Claude as Claude Code
participant Frontend as Frontend<br/>(Login Page)
participant Backend as Backend<br/>(MCP Handler)
participant Auth as Better Auth<br/>(OAuth Server)
participant DB as Database
Claude->>Backend: GET /mcp (no Bearer token)
Backend->>Backend: resolveUserId(undefined)
Backend-->>Claude: 401 + WWW-Authenticate header
Claude->>Backend: Discover OAuth via .well-known
Backend-->>Claude: OAuth server metadata
Claude->>Frontend: Redirect to /login
Frontend->>Frontend: Check getSession()
Frontend-->>Claude: No session found
Frontend->>Claude: Show AuthModal
Claude->>Auth: POST /sign-in (magic link or OAuth)
Auth->>DB: Create/verify user
Auth->>Auth: Issue session
Auth-->>Frontend: Redirect with session
Frontend->>Auth: GET /authorize (with session)
Auth->>DB: Create oauth_consent record
Auth-->>Frontend: Redirect back to callback
Frontend->>Frontend: Extract opaque Bearer token
Claude->>Backend: GET /mcp (with Bearer token)
Backend->>Backend: resolveUserId(opaque token)
Backend->>Auth: GET /api/auth/mcp/get-session
Auth->>DB: Lookup oauth_access_token
Auth-->>Backend: Return userId
Backend->>DB: Process MCP request
Backend-->>Claude: 200 + MCP response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
protocol/src/lib/betterauth/betterauth.ts (1)
12-14: Consider centralizingAPP_URLusage across the codebase.The
APP_URLexport is a good addition. However, per context snippets,integration.controller.ts(line 64) andconversation.service.ts(line 220) define the same resolution logic locally. Consider importing this export frombetterauth.tsin those files to maintain a single source of truth.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@protocol/src/lib/betterauth/betterauth.ts` around lines 12 - 14, Several files duplicate the APP_URL resolution; import and use the single exported APP_URL from betterauth.ts instead of re-implementing the logic. In integration.controller.ts and conversation.service.ts remove the local process.env.FRONTEND_URL || process.env.APP_URL || 'https://index.network' logic, add an import for APP_URL from the betterauth module, and replace the local variable usages with the imported APP_URL symbol so the codebase has a single source of truth.frontend/src/app/login/page.tsx (1)
24-25: Consider validatingVITE_PROTOCOL_URLbefore redirect.If
VITE_PROTOCOL_URLis undefined or empty, the redirect URL becomes/api/auth/mcp/authorize...which may not resolve correctly depending on the deployment. This could silently fail or redirect to an unintended location.🔧 Optional validation
if (data?.session) { // Session exists → forward to the MCP authorize endpoint with the original OAuth params const protocolUrl = import.meta.env.VITE_PROTOCOL_URL ?? ""; + if (!protocolUrl) { + console.error("VITE_PROTOCOL_URL is not configured"); + setSessionChecked(true); + return; + } window.location.href = `${protocolUrl}/api/auth/mcp/authorize${window.location.search}`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/app/login/page.tsx` around lines 24 - 25, The redirect uses import.meta.env.VITE_PROTOCOL_URL (bound to protocolUrl) without validation, so an empty or undefined value yields an unintended path; update the logic before setting window.location.href to validate protocolUrl (e.g., check non-empty string, valid URL or fallback) and construct the target by using a safe base (protocolUrl if valid, otherwise a configured default or relative safe path) when assigning window.location.href in the component that performs the redirect.docs/superpowers/specs/2026-04-03-mcp-oauth-plugin-design.md (1)
12-27: Add language identifier to fenced code block.The flow diagram code block should specify a language (or use
textfor plain text) to satisfy markdown linting rules.📝 Fix markdown lint warning
-``` +```text User installs plugin → Claude Code reads plugin/.mcp.json🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/superpowers/specs/2026-04-03-mcp-oauth-plugin-design.md` around lines 12 - 27, The fenced code block showing the OAuth flow is missing a language identifier; update the opening backticks (```) for that flow diagram to include a language like "text" (i.e. change ``` to ```text) so the markdown linter is satisfied—look for the triple-backtick block containing the steps ("User installs plugin … MCP tools available ✓") and add the language identifier there.protocol/src/schemas/database.schema.ts (1)
493-498: Consider adding exported types for OAuth tables.Other tables in this file export both select and insert types (e.g.,
User/NewUser,Intent/NewIntent). The new OAuth tables don't have corresponding type exports, which could be useful for type safety in the auth adapter.📝 Add type exports for consistency
// Add after line 498: export type OAuthApplication = typeof oauthApplications.$inferSelect; export type NewOAuthApplication = typeof oauthApplications.$inferInsert; export type OAuthAccessToken = typeof oauthAccessTokens.$inferSelect; export type NewOAuthAccessToken = typeof oauthAccessTokens.$inferInsert; export type OAuthConsent = typeof oauthConsents.$inferSelect; export type NewOAuthConsent = typeof oauthConsents.$inferInsert;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@protocol/src/schemas/database.schema.ts` around lines 493 - 498, The OAuth tables (oauthApplications, oauthAccessTokens, oauthConsents) are missing exported select/insert types; add exported type aliases for each table like ExportType = typeof <table>.$inferSelect and NewExportType = typeof <table>.$inferInsert to match the pattern used for other tables (e.g., opportunities, personalIndexes); specifically add exported types for oauthApplications, oauthAccessTokens, and oauthConsents (both select and insert) so the auth adapter can use them for typing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/superpowers/specs/2026-04-03-mcp-oauth-plugin-design.md`:
- Around line 40-42: Update the WWW-Authenticate example in the docs to match
the implementation in mcp.handler.ts: change the code fence to include a
language identifier (```http) and replace the header so it uses
resource_metadata pointing to "/.well-known/oauth-protected-resource" (matching
the oauth-protected-resource used in mcp.handler.ts) instead of
oauth-authorization-server, and remove the realm parameter so the example
exactly mirrors the handler's output.
---
Nitpick comments:
In `@docs/superpowers/specs/2026-04-03-mcp-oauth-plugin-design.md`:
- Around line 12-27: The fenced code block showing the OAuth flow is missing a
language identifier; update the opening backticks (```) for that flow diagram to
include a language like "text" (i.e. change ``` to ```text) so the markdown
linter is satisfied—look for the triple-backtick block containing the steps
("User installs plugin … MCP tools available ✓") and add the language identifier
there.
In `@frontend/src/app/login/page.tsx`:
- Around line 24-25: The redirect uses import.meta.env.VITE_PROTOCOL_URL (bound
to protocolUrl) without validation, so an empty or undefined value yields an
unintended path; update the logic before setting window.location.href to
validate protocolUrl (e.g., check non-empty string, valid URL or fallback) and
construct the target by using a safe base (protocolUrl if valid, otherwise a
configured default or relative safe path) when assigning window.location.href in
the component that performs the redirect.
In `@protocol/src/lib/betterauth/betterauth.ts`:
- Around line 12-14: Several files duplicate the APP_URL resolution; import and
use the single exported APP_URL from betterauth.ts instead of re-implementing
the logic. In integration.controller.ts and conversation.service.ts remove the
local process.env.FRONTEND_URL || process.env.APP_URL || 'https://index.network'
logic, add an import for APP_URL from the betterauth module, and replace the
local variable usages with the imported APP_URL symbol so the codebase has a
single source of truth.
In `@protocol/src/schemas/database.schema.ts`:
- Around line 493-498: The OAuth tables (oauthApplications, oauthAccessTokens,
oauthConsents) are missing exported select/insert types; add exported type
aliases for each table like ExportType = typeof <table>.$inferSelect and
NewExportType = typeof <table>.$inferInsert to match the pattern used for other
tables (e.g., opportunities, personalIndexes); specifically add exported types
for oauthApplications, oauthAccessTokens, and oauthConsents (both select and
insert) so the auth adapter can use them for typing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 867111ed-a2fb-478a-a832-35285d0ee4e6
⛔ Files ignored due to path filters (1)
protocol/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (15)
.claude/handoff.mddocs/superpowers/specs/2026-04-03-mcp-oauth-plugin-design.mdfrontend/src/app/login/page.tsxfrontend/src/components/AuthModal.tsxfrontend/src/routes.tsxplugin/.mcp.jsonprotocol/drizzle/0033_add_mcp_oauth_tables.sqlprotocol/drizzle/meta/0033_snapshot.jsonprotocol/drizzle/meta/_journal.jsonprotocol/package.jsonprotocol/src/adapters/auth.adapter.tsprotocol/src/controllers/mcp.handler.tsprotocol/src/lib/betterauth/betterauth.tsprotocol/src/main.tsprotocol/src/schemas/database.schema.ts
💤 Files with no reviewable changes (2)
- protocol/package.json
- .claude/handoff.md
… login error handling
94e25b8 to
4d8a165
Compare
Summary
mcpplugin (replaces@better-auth/oauth-provider) to handle full MCP OAuth 2.0 PKCE flow nativelyWWW-Authenticate: Bearer resource_metadata=...header to MCP 401 responses so Claude Code auto-discovers the OAuth server/loginfrontend page as an OAuth bridge: redirects authenticated users back to the authorize endpoint, shows login modal for unauthenticated usersplugin/.mcp.jsonso installing the plugin registers the MCP server automatically with no manual token configoauth_application,oauth_access_token,oauth_consent) and migration0033_add_mcp_oauth_tables@better-auth/oauth-providerdependencyFlow
Test Plan
/mcpunauthenticated — verifyWWW-Authenticateheader is present in 401Summary by CodeRabbit
New Features
Documentation
Chores