Proxy MCP OAuth callbacks through command center#70
Open
mlund01 wants to merge 1 commit into
Open
Conversation
Adds a second CallbackSource implementation (WsbridgeCallbackSource) that routes the IdP redirect through the command center a squadron is connected to, rather than binding a local loopback port. Motivation: - Squadrons running on remote hosts can't receive a browser redirect on 127.0.0.1. - Some IdPs (Slack, enterprise SSO) reject plain-HTTP loopback redirects or require a pre-registered HTTPS callback URL. Command center already terminates TLS, so it's the natural place to host a stable callback. Routing is by OAuth `state` value (always cryptographically random and per-flow), which means the redirect URI is fixed per command center deployment and doesn't rotate on every login — fixing the existing "re-register DCR on every port change" workaround in flow.go. Config changes: - command_center.url → command_center.host. Host is just the scheme + domain (plus an optional path prefix if command center is mapped behind one). Squadron derives WebSocketURL (http(s) → ws(s), /ws appended) and OAuthRedirectURI (scheme preserved, /oauth/callback appended) from it. - Legacy `url` field is rejected with a clear migration error. New surfaces: - mcp/oauth/callback_wsbridge.go — WsbridgeCallbackSource. - mcp/oauth/flow.go — CallbackSource gained SetState(state); generated earlier in RunLoginFlow so the bridge source can register its listener before the IdP handshake. - wsbridge/client.go — public SendRequest, OAuth listener plumbing. - wsbridge/handlers.go — handlers for OAuthCallbackDelivery and StartMCPLogin. StartMCPLoginHook is a package-level indirection so cmd/engage can wire the oauth package without an import cycle. - cmd/oauth_hook.go — installs the StartMCPLoginHook, bridging commander-initiated logins to RunLoginFlow. The standalone `squadron mcp login` CLI still uses the loopback source because the CLI process has no live WS bridge. UI-initiated logins from command center use the proxy path. TEMP: go.mod has a local replace pointing at ../squadron-wire for the new protocol message types. Revert + bump once squadron-wire tags a new version (see sibling PR).
This was referenced Apr 18, 2026
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.
Summary
WsbridgeCallbackSourceroutes MCP OAuth callbacks through command center instead of a local loopback port, so remote squadrons and HTTPS-only IdPs can complete OAuth.command_center.url→command_center.host: a single base URL drives both the WS connection (wss://host/ws) and the OAuth redirect URI (https://host/oauth/callback). Legacyurlfield rejected with a migration error.statevalue, which lets the redirect URI stay fixed per command center deployment — also fixes the current "re-register DCR on every ephemeral port" workaround.squadron mcp loginstill uses loopback (CLI has no live bridge); the command center UI gets a "Connect" button per MCP server that callsPOST /api/instances/{id}/mcp/{name}/oauth/start.Paired with:
TEMP notice
go.modhas a localreplacefor squadron-wire until the sibling PR merges and a tag is cut. Will be removed + bumped before merge.Test plan
go test ./config/... ./wsbridge/... ./mcp/oauth/...green./squadron engage --foregroundcomes up clean,GET /oauth/callback?state=Xresponds with the expected error pagesquadron mcp loginstill works for local standalone use