mcp-proxy: drive per-connection login on a 401 (generic, all agents) - #557
Open
sunishsheth2009 wants to merge 4 commits into
Open
mcp-proxy: drive per-connection login on a 401 (generic, all agents)#557sunishsheth2009 wants to merge 4 commits into
sunishsheth2009 wants to merge 4 commits into
Conversation
This was referenced Sep 10, 2026
Give every coding agent a working login flow for connection-backed AI Gateway mcp-services endpoints, done in the stdio proxy every agent already spawns — no new library (cf. mcp-remote) and no per-agent OAuth app. When AI Gateway has no per-user connection credential it answers with HTTP 401 (RFC 9728). The proxy's httpx auth hook already sees every response, so on a 401 for a connection-backed URL it runs the Databricks CLI U2M login with an RFC 8707 resource indicator (`databricks auth login --resource <mcp-url>`, using the CLI's own registered redirect — no --client-id), then retries with a fresh token. A resource-aware /oidc drives the connection's SaaS login before minting the token, so the retry succeeds — transparently to the agent, which just sees the request authenticate rather than a failed tools/list. A later credential revoke re-triggers the login on the next 401. New module mcp_connection_login holds connection_from_url + run_connection_login; mcp_proxy._build_token_auth gains the login-on-401 retry. Unit-tested. Depends on the CLI --resource flag (databricks/cli#6621) and /oidc resource handling (login). Co-authored-by: Isaac <no-reply@databricks.com>
sunishsheth2009
force-pushed
the
mcp-connection-login-proxy
branch
from
September 10, 2026 23:44
42235ff to
79ee16c
Compare
Fixes the two defects that made the proxy hang "connecting…" on a 401 instead of behaving like a generic OAuth MCP bridge (mcp-remote): 1. Non-blocking: the browser login ran via a synchronous subprocess inside the sync httpx auth_flow, which the async client executes on the event-loop thread — freezing the transport (stdio pumps included) for the whole login. Add async_auth_flow that offloads run_connection_login to a worker thread (anyio.to_thread.run_sync), so the loop stays responsive and cancellable while the user completes the browser flow. sync auth_flow kept for parity; both share the decision + login logic. 2. Visible URL: run_connection_login captured the CLI's output, hiding the authorize URL. Route the CLI's stdout+stderr to the proxy's stderr (fd 2, the agent's MCP log) — never fd 1 (the JSON-RPC wire) — and let the CLI open the browser, so the login is discoverable exactly like mcp-remote's. Co-authored-by: Isaac <no-reply@databricks.com>
Makes the generic proxy behave like a generic OAuth MCP bridge (mcp-remote): the connection login happens while the agent shows "connecting…", and the browser opens on its own — instead of racing the agent's tools/list timeout or burying the URL. - Connect-time login: before opening the bridge, serve() probes the connection (_connection_login_required: a lightweight initialize + tools/list to AI Gateway); on a 401 it drives run_connection_login *then*, so the agent's session comes up already authenticated. The on-401 retry in the auth hook stays as a mid-session fallback (credential revoked while connected). PAT profiles skip it (no connection OAuth). - Browser auto-open: the login inherits the environment (incl. $BROWSER), so databricks-cli opens the browser on the user's machine; the authorize URL is the printed fallback. Co-authored-by: Isaac <no-reply@databricks.com>
… the probe Simplify to what a generic OAuth MCP bridge (mcp-remote) does: authenticate at connect, then serve. Before opening the bridge, serve() runs a blocking `databricks auth login --resource <mcp-url>` for connection-backed services — the databricks-cli equivalent of mcp-remote's in-process OAuth, where --resource also routes /oidc through the connection sign-in (/mcp-service-login). The agent blocks on "connecting…" while it runs (browser opens via $BROWSER, or the URL is printed), then the session comes up authenticated, so AI Gateway is never asked to elicit a login. Idempotent: once signed in it returns immediately. Removes the redundant startup probe (Claude already fires initialize+tools/list; the proxy shouldn't duplicate that) and the on-401 retry inside the auth hook (the connect-time login makes it unnecessary). _build_token_auth is back to a plain per-request bearer read of the session that login established. Co-authored-by: Isaac <no-reply@databricks.com>
sunishsheth2009
force-pushed
the
mcp-connection-login-proxy
branch
2 times, most recently
from
September 11, 2026 04:01
9dec3fa to
35c1a1d
Compare
sunishsheth2009
marked this pull request as ready for review
September 11, 2026 04:05
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.
What
Give every coding agent (codex, cursor, gemini, claude, …) a working login flow for connection-backed AI Gateway
mcp-servicesendpoints (e.g.system.ai.github) — implemented in theug mcp-proxystdio bridge every agent already spawns. No new library (this is what a generic OAuth MCP bridge likemcp-remotedoes, done in ucode with the Databricks CLI), and no per-agent OAuth app.How
A connection-backed
mcp-servicesendpoint needs a per-user connection credential before its tools can be used. The proxy drives that login at connect time, before it opens the stdio↔HTTP bridge:serve()detects a connection-backed URL and runs a blockingdatabricks auth login --resource <mcp-url>. The RFC 8707resourceindicator makes a resource-aware/oidcroute the browser through the connection's own SaaS login (/mcp-service-login) before minting the token. It uses the CLI's own default client + registered loopback redirect — no--client-id, no auth-side redirect change.This is the
mcp-remotepattern: the CLI opens the browser natively (macOS/Windows/Linux-desktop) and, when it can't (a headless/remote box), prints the authorize URL to stderr so the user can open it manually. The proxy never writes to stdout (the MCP JSON-RPC wire).Why this shape (supersedes the earlier bridges in this PR's history)
Earlier iterations tried a proxy that faked a
sign_intool / rewrotetools/list, a login-on-401 httpx auth-hook retry, and a launch-time check — each either more complex or subtly wrong (the auth hook ran a blocking subprocess inside the event loop; launch-time fired a login per connection at every launch). Driving the login once at connect, and letting the agent block on "connecting…" while it runs, is the minimal generic realization and matches howmcp-remotebehaves.Dependencies
--resource: Allow OAuth U2M logins to send RFC 8707 resource indicators cli#6621. Until released,databricks auth loginignores--resource./oidcresource-indicator handling (login §2) +/mcp-service-loginreturn_to (§3) — the universe side of this flow. AI Gateway §1 (the 401) is already on staging.Scope
Tests
test_mcp_connection_login— connection-FQN parsing, and the CLI login runner with the subprocess mocked (sends--resource/--hostand no--client-id; routes output to stderr; reports nonzero-exit, timeout, and missing-binary).test_mcp_proxy— connect-time login ordering (login → bridge), non-connection URLs skip it, a login failure exits before the bridge, and--use-patskips it.uv run pytest tests/test_mcp*.pygreen; ruff + ty clean.This pull request and its description were written by Isaac.