ug mcp add: register connection-backed MCP services as direct HTTP for OAuth-client-capable agents - #555
Closed
sunishsheth2009 wants to merge 1 commit into
Closed
Conversation
…r OAuth-client-capable agents Connection-backed AI Gateway MCP services (…/ai-gateway/mcp-services/…) need a per-user connection login before their tools can be called. Registered as the stdio proxy, an agent only ever sees "connected" (the proxy injects a workspace token) and the login can't be triggered from /mcp. Registered as a direct-HTTP server, the agent does the OAuth itself: /mcp shows "needs authentication" → Authenticate → /oidc → /mcp-service-login → login → connected. /oidc has no dynamic client registration, so the agent must present a pre-registered public client. Only Claude Code's `mcp add` supports pinning one (--client-id); its published claude-code app has the loopback /callback redirect Claude uses. Other agents' `mcp add` accept only a static bearer, not an OAuth client — codex (--bearer-token-env-var), gemini (--header), cursor (config) — so despite their published apps (codex-cli, cursor-desktop, …) they can't drive this flow and stay on the stdio proxy. ug mcp add now registers these services as direct HTTP with the agent's OAuth client (AGENT_OAUTH_CLIENT — today just claude → claude-code) when that client is registered on the workspace, probed via a back-channel token-endpoint check (401 invalid_client = absent, cached per workspace+client). Everything else keeps the stdio proxy: non-connection MCPs, the skills registry, PAT auth, agents with no mapped OAuth client, and workspaces where the client isn't published. Co-authored-by: Isaac <no-reply@databricks.com>
Collaborator
Author
|
Closing: superseded by the simpler setup-time login approach. The Claude-only direct-HTTP path can't cover codex/gemini/etc.; instead ucode will run |
Collaborator
Author
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 Claude Code and Cursor their native connection-login experience for connection-backed AI Gateway
mcp-servicesendpoints (e.g.system.ai.github): the agent itself is the OAuth client and drives the/oidc→/mcp-service-loginlogin, so/mcpshows a real "Authenticate" (Claude) / login (Cursor) prompt instead of a token silently injected by the proxy. This is a much better UX than the generic stdio-proxy path for the agents that can do it.It is probe-driven with a safe fallback: only used when the agent's OAuth app is actually published on the workspace; otherwise (and for every other agent) it falls back to the generic
ug mcp-proxystdio path (#557).How
/oidchas no dynamic client registration, so the agent must present a pre-registered public client whose loopback/callbackredirect is registered:claude mcp add --transport http --client-id claude-code(Claude drives MCP OAuth with the RFC 8707resourceindicator).url+auth: {CLIENT_ID: cursor-desktop}entry in~/.cursor/mcp.json(Cursor supports a pre-registered client; its fixedhttp://localhost:8787/callbackredirect matches by path, RFC 8252 §8.4).mcp_oauth.oauth_client_available(workspace, client_id)back-channel-probes/oidc/v1/token(401invalid_client= absent, else present) and caches the answer per workspace (weekly TTL).configure_client_mcp_serverregisters direct-HTTP only when: the URL is a connection-backedmcp-servicesendpoint, the agent has a mapped OAuth client (AGENT_OAUTH_CLIENT), that client is published, and it isn't a--use-pat/ skills-registry registration. Everything else keeps the stdio proxy.Relationship to the generic proxy (#557)
Complementary. #557 gives every agent a working login via the proxy (connect-time
databricks auth login --resource). This PR is a UX upgrade layered on top: where an agent can be the OAuth client and its app exists, we let it drive the login natively. Same server-side flow underneath (/oidc→/mcp-service-login), same §2/§3 dependency.Dependencies
Same server side as #557: AI Gateway §1 (
WWW-Authenticate401, already on staging) + login §2 (/oidcresource-indicator redirect) + webapp §3 (/mcp-service-loginreturn_to). No CLI dependency for the native path (the agent is the OAuth client, not the CLI).Scope / fallback
mcp-services+ Claude/Cursor + published app → native direct-HTTP.Tests
test_mcp_oauth(probe: present/absent/network-fail, cache TTL).test_mcp.TestConfigureClientMcpServer(Claude + Cursor each: direct-HTTP when the app is available, proxy fallback when not, proxy under--use-pat, proxy for non-connection URLs; an OAuth-less agent proxies and never probes).test_agent_cursor(theurl+authentry shape and merge).uv run pytestgreen (pre-existing unrelated failures intest_codex_smart_routing_v2/test_e2e_user_agentconfirmed onmain); ruff + ty clean.This pull request and its description were written by Isaac.