Skip to content

fix: extend pending_verification bootstrap path to cover per_user_oauth clients - #3873

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
05-29-feat_add_per_user_oauth_mcp_support_for_config.json
Aug 8, 2026
Merged

fix: extend pending_verification bootstrap path to cover per_user_oauth clients#3873
Pratham-Mishra04 merged 1 commit into
devfrom
05-29-feat_add_per_user_oauth_mcp_support_for_config.json

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Extends the pending_verification bootstrap flow to cover per_user_oauth clients in addition to shared oauth clients. Previously, only shared OAuth clients declared in config.json were parked in pending_verification awaiting admin authorization. Per-user OAuth clients loaded from config were not handled the same way, meaning they could end up in an inconsistent state before an admin completed the verification step.

Changes

  • Unified the pending_verification gate in AddClient to apply to both oauth and per_user_oauth auth types when PendingOAuthConfig is set, replacing the previous shared-OAuth-only check.
  • The initiate-verification endpoint now accepts both oauth and per_user_oauth auth types instead of rejecting the latter.
  • The complete-oauth callback handler now permits both OAuth-based auth types to complete through the endpoint, with downstream branching handling the per-user vs. shared distinction.
  • When loading MCP config from config.json, OAuth-based clients (oauth or per_user_oauth) that have no inline oauth_config block and no existing oauth_config_id now have an empty OAuth2Config synthesized so they consistently land in pending_verification and the initiate-verification endpoint can run discovery and dynamic client registration at admin-click time.
  • UI updated to show auth-type-aware labels and descriptions: per_user_oauth clients in pending_verification show a "Verify" button and a description clarifying that the admin test login is a one-time setup step and each user will authenticate individually afterward. The success toast message is similarly differentiated.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Declare a per_user_oauth MCP client in config.json with a connection_string but no oauth_config block.
  2. Start the server and confirm the client appears in pending_verification state.
  3. As an admin, open the client sheet and confirm the "Verify" button and per-user description are shown.
  4. Click "Verify" and complete the browser OAuth flow.
  5. Confirm the client transitions out of pending_verification and tools are discovered.
  6. Confirm that subsequent user requests trigger individual per-user authentication rather than reusing the admin token.
  7. Repeat steps 1–6 for a shared oauth client to confirm existing behavior is unchanged.
go test ./core/mcp/... ./transports/bifrost-http/...

cd ui
pnpm i
pnpm build

Breaking changes

  • Yes
  • No

Security considerations

The admin verification flow for per_user_oauth uses the upstream token only as a temporary credential to validate the OAuth configuration and discover tools, then revokes it. The token is not persisted or reused for end-user requests. No end-user credentials are stored as a result of the admin verification step.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added shared and per-user OAuth verification for MCP clients.
    • Added completion links, next-step guidance, and tailored labels during per-user OAuth setup.
    • OAuth clients without saved configuration now enter a guided pending-verification flow.
    • Per-user OAuth clients now display dedicated verification and success messaging.
  • Bug Fixes

    • Prevented connection attempts while OAuth authorization is pending.
    • Improved recovery after OAuth verification completes.
    • Prevented configuration files from overwriting server-managed OAuth settings.
    • Preserved protected connection settings during configuration updates.
    • Prevented unauthorized changes to protected MCP client settings.

Walkthrough

This PR extends OAuth pending-verification handling to shared and per_user_oauth clients. It updates client management, configuration bootstrap, HTTP verification and completion handlers, reconciliation tests, and MCP registry UI.

Changes

Per-user OAuth pending verification

Layer / File(s) Summary
Client manager pending-verification branch
core/mcp/clientmanager.go
Shared and per-user OAuth clients with PendingOAuthConfig enter PendingVerification, retain their connection URL, and skip normal setup.
Config bootstrap synthesis and reconciliation
transports/bifrost-http/lib/config.go, transports/bifrost-http/lib/config_test.go
Config loading clears server-managed OAuth IDs and creates pending OAuth configuration when required. Tests cover immutable fields, OAuth drift, pending configuration, and per-user headers.
OAuth verification and completion flow
transports/bifrost-http/handlers/mcp.go
Verification initiation and completion accept both OAuth types. Config-bootstrap completion clears pending state and reports clearing failures.
MCP registry verification UI
ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx, ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
Labels, guidance, success messages, popup behavior, and authorizer state vary by OAuth type.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConfigBootstrap
  participant ClientManager
  participant MCPRegistry
  participant HTTPHandlers

  ConfigBootstrap->>ClientManager: load OAuth client with pending configuration
  ClientManager->>ClientManager: set PendingVerification state
  MCPRegistry->>HTTPHandlers: initiate verification
  HTTPHandlers-->>MCPRegistry: return authorization and completion URLs
  MCPRegistry->>HTTPHandlers: complete OAuth verification
  HTTPHandlers->>ClientManager: update verified connection
  HTTPHandlers->>ConfigBootstrap: clear pending OAuth configuration
Loading

Possibly related PRs

Suggested reviewers: akshaydeo, danpiths, roroghost17

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes extending the pending verification flow to per-user OAuth clients.
Description check ✅ Passed The description covers the purpose, changes, affected areas, testing steps, breaking changes, and security considerations.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 05-29-feat_add_per_user_oauth_mcp_support_for_config.json

Comment @coderabbitai help to get the list of available commands.

Pratham-Mishra04 commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

The cleanup error path should be fixed before merging.

  • A database cleanup failure is hidden behind a successful response.
  • The retained marker sends the verified client back to pending_verification after restart.
  • The normal successful path otherwise clears the marker at the correct point.

transports/bifrost-http/handlers/mcp.go

Important Files Changed

Filename Overview
transports/bifrost-http/handlers/mcp.go Extends OAuth bootstrap completion to per-user clients, but a failed marker cleanup is still reported as success.
transports/bifrost-http/lib/config.go Normalizes OAuth clients loaded from config and synthesizes pending bootstrap state.
core/mcp/clientmanager.go Extends the pending-verification gate to per-user OAuth clients.
ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx Adds per-user OAuth verification labels and success messaging.

Reviews (6): Last reviewed commit: "feat: add per user oauth mcp support for..." | Re-trigger Greptile

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from ff11dc3 to 4d85b9c Compare July 1, 2026 10:15
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from 2e6de8c to 41d8011 Compare July 1, 2026 10:15
@coderabbitai
coderabbitai Bot requested a review from roroghost17 July 1, 2026 10:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
core/mcp/clientmanager.go (1)

358-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add table-driven coverage for the new per_user_oauth branch.

The pending-verification gate now branches on two auth types, but no test changes are visible for this behavior change. Since core/mcp/clientmanager_test.go exists in this package, consider adding a case asserting per_user_oauth clients with PendingOAuthConfig set land in MCPConnectionStatePendingVerification, alongside the existing oauth case.

As per path instructions, "review agent loops for bounded depth, deterministic tool execution behavior" and general Go guideline to apply "table-driven coverage for behavior changes."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/mcp/clientmanager.go` around lines 358 - 359, Add table-driven test
coverage in clientmanager_test for the pending-verification branch in
ClientManager behavior. Extend the existing auth-state tests to include a
per_user_oauth case with PendingOAuthConfig set and assert it resolves to
MCPConnectionStatePendingVerification, alongside the existing oauth coverage.
Use the same test setup/helpers already used for the oauth branch so the new
case exercises the config.PendingOAuthConfig gate and the AuthType check in the
client manager logic.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@transports/bifrost-http/lib/config.go`:
- Around line 1620-1631: The OAuth bootstrap fallback in the config loader is
unreachable from the config-file path because the schema currently requires
oauth_config_id for oauth and per_user_oauth. Update the MCP schema validation
to allow the bootstrap-pending shape, or move the PendingOAuthConfig synthesis
in config.go behind a non-config.json source path so the runtime gate and
initiate-verification flow can actually reach it.

---

Nitpick comments:
In `@core/mcp/clientmanager.go`:
- Around line 358-359: Add table-driven test coverage in clientmanager_test for
the pending-verification branch in ClientManager behavior. Extend the existing
auth-state tests to include a per_user_oauth case with PendingOAuthConfig set
and assert it resolves to MCPConnectionStatePendingVerification, alongside the
existing oauth coverage. Use the same test setup/helpers already used for the
oauth branch so the new case exercises the config.PendingOAuthConfig gate and
the AuthType check in the client manager logic.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b70191eb-7cca-4fd2-8560-0df58a74ac26

📥 Commits

Reviewing files that changed from the base of the PR and between 41d8011 and 4d85b9c.

📒 Files selected for processing (4)
  • core/mcp/clientmanager.go
  • transports/bifrost-http/handlers/mcp.go
  • transports/bifrost-http/lib/config.go
  • ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx

Comment thread transports/bifrost-http/lib/config.go Outdated
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from 4d85b9c to fd86d73 Compare July 2, 2026 05:29
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from 41d8011 to dc2f30a Compare July 2, 2026 05:29
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from fd86d73 to c26897d Compare July 2, 2026 13:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from dc2f30a to ae90a7d Compare July 2, 2026 13:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from c26897d to 77e5f5f Compare July 3, 2026 06:17
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from ae90a7d to 32cf960 Compare July 3, 2026 06:17
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from 77e5f5f to a5d0538 Compare July 21, 2026 09:16
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from 32cf960 to 8e33d96 Compare July 21, 2026 09:16
Comment thread transports/bifrost-http/handlers/mcp.go
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx`:
- Around line 226-242: Serialize concurrent bootstrap flows in the client
verification action so only one bootstrap can run at a time, preventing shared
oauthConfigId, mcpClientId, and "oauth_popup" state from being overwritten.
Update the relevant bootstrap/verification handler around the popup
initialization to disable or reject other bootstrap actions until the active
flow completes, then restore availability on success or failure. Add an E2E test
covering two initiation requests resolving out of order.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b194710c-5aa4-49f9-b82a-74c0ae7cb9f3

📥 Commits

Reviewing files that changed from the base of the PR and between fd4d929 and b9a6764.

📒 Files selected for processing (6)
  • core/mcp/clientmanager.go
  • transports/bifrost-http/handlers/mcp.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/lib/config_test.go
  • ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx
  • ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx
  • transports/bifrost-http/lib/config.go
  • core/mcp/clientmanager.go
  • transports/bifrost-http/handlers/mcp.go
  • transports/bifrost-http/lib/config_test.go

Comment on lines +226 to +242
const isPerUserOauth = client.config.auth_type === "per_user_oauth";
// Open a blank popup synchronously, before the initiateVerification
// await, so the click's transient user-activation is captured here
// rather than consumed by the network round-trip — otherwise the
// browser can block OAuth2Authorizer's later window.open entirely.
// OAuth2Authorizer navigates this handle once authorize_url is known.
const width = 600;
const height = 700;
const left = window.screen.width / 2 - width / 2;
const top = window.screen.height / 2 - height / 2;
const popup = window.open("", "oauth_popup", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
// Not needed for per_user_oauth: that flow shows a confirm step first
// and opens its own popup synchronously from that step's own button
// click, so pre-opening one here would just leak an unused window.
let popup: Window | null = null;
if (!isPerUserOauth) {
const width = 600;
const height = 700;
const left = window.screen.width / 2 - width / 2;
const top = window.screen.height / 2 - height / 2;
popup = window.open("", "oauth_popup", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- target file outline ---'
ast-grep outline ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
printf '%s\n' '--- relevant target sections ---'
sed -n '160,275p' ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
printf '%s\n' '--- all relevant symbols and popup usage ---'
rg -n -C 4 'bootstrapAuthorize|authorizingClients|oauth_popup|initialPopup|OAuth2Authorizer|initiateVerification' ui
printf '%s\n' '--- candidate OAuth2Authorizer files ---'
fd -i 'OAuth2Authorizer|oauth.*author' ui

Repository: maximhq/bifrost

Length of output: 31198


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- row action guards and handler wiring ---'
sed -n '1,145p' ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
sed -n '620,665p' ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
printf '%s\n' '--- OAuth2Authorizer implementation ---'
sed -n '1,330p' ui/app/workspace/mcp-registry/views/oauth2Authorizer.tsx
printf '%s\n' '--- API mutation definition ---'
sed -n '245,275p' ui/lib/store/apis/mcpApi.ts

Repository: maximhq/bifrost

Length of output: 18207


Serialize concurrent bootstrap flows or key state and popups per client.

Different rows can start verification at the same time. Both shared OAuth flows use the "oauth_popup" target, and bootstrapAuthorize stores only one flow. An out-of-order response can replace the active oauthConfigId and mcpClientId, leaving the other flow stranded.

Disable all bootstrap actions while one flow is active, or store flow state per client_id and use a unique popup name for each flow. Add an E2E test for two initiation requests that resolve out of order.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx` around lines 226 -
242, Serialize concurrent bootstrap flows in the client verification action so
only one bootstrap can run at a time, preventing shared oauthConfigId,
mcpClientId, and "oauth_popup" state from being overwritten. Update the relevant
bootstrap/verification handler around the popup initialization to disable or
reject other bootstrap actions until the active flow completes, then restore
availability on success or failure. Add an E2E test covering two initiation
requests resolving out of order.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from b9a6764 to 9129d60 Compare August 8, 2026 08:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_ui_support_for_pending_auth_mcps branch from fd4d929 to 561a8a5 Compare August 8, 2026 08:43

Pratham-Mishra04 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

Merge activity

  • Aug 8, 8:47 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Aug 8, 8:53 AM UTC: Graphite rebased this pull request as part of a merge.
  • Aug 8, 8:53 AM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from 05-29-feat_ui_support_for_pending_auth_mcps to graphite-base/3873 August 8, 2026 08:49
@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from graphite-base/3873 to dev August 8, 2026 08:51
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch from 9129d60 to a866cd8 Compare August 8, 2026 08:52
@Pratham-Mishra04
Pratham-Mishra04 merged commit 095e2e4 into dev Aug 8, 2026
14 of 15 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 05-29-feat_add_per_user_oauth_mcp_support_for_config.json branch August 8, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants