feat(mcp): browser OAuth2 login on first run (works with no prior xurl setup)#80
Merged
Conversation
When the bridge has no cached token it now runs the interactive browser login (using CLIENT_ID/CLIENT_SECRET from its environment) and holds the handshake until it completes, instead of failing fast. This lets the npx-launched bridge authenticate with no prior xurl install or setup, then caches and auto-refreshes the token. Login output stays on stderr so the stdout JSON-RPC channel is unaffected; set a generous startup_timeout_sec on the server. Headless hosts authenticate out-of-band first with `xurl auth oauth2 --headless`.
tcaldwell-x
approved these changes
Jun 29, 2026
tcaldwell-x
approved these changes
Jun 29, 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.
What
Make
xurl mcpself-authenticate so it works for users with no prior xurl install or setup (the npx route). When the bridge has no cached token it now runs the interactive browser OAuth2 login — usingCLIENT_ID/CLIENT_SECRETfrom its environment — and holds the MCP handshake until the login completes, then caches and auto-refreshes the token. Previously it failed fast.Why
Grok (and MCP clients generally) only drive OAuth for HTTP MCP servers with OAuth discovery; a stdio bridge can't surface a "needs auth" prompt, and
api.x.com/mcpexposes no OAuth discovery anyway. So the bridge must own the login. Doing it at first run letsnpx … mcpauthenticate end-to-end with just the user's app credentials inenv.Notes
startup_timeout_sec(docs/config examples updated to 300).http://localhost:8080/callback) registered. Headless hosts authenticate out-of-band first withxurl auth oauth2 --headless.oauth2Flowis injected into the bridge so the browser login is stubbed in tests; bootstrap tests cover token-present, login-success, and login-failure paths.gofmt,go vet,go test -race ./...all green.