Skip to content

feat(mcp): browser OAuth2 login on first run (works with no prior xurl setup)#80

Merged
santiagomed merged 1 commit into
mainfrom
fix/mcp-browser-login
Jun 29, 2026
Merged

feat(mcp): browser OAuth2 login on first run (works with no prior xurl setup)#80
santiagomed merged 1 commit into
mainfrom
fix/mcp-browser-login

Conversation

@santiagomed

Copy link
Copy Markdown
Collaborator

What

Make xurl mcp self-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 — using CLIENT_ID/CLIENT_SECRET from 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/mcp exposes no OAuth discovery anyway. So the bridge must own the login. Doing it at first run lets npx … mcp authenticate end-to-end with just the user's app credentials in env.

Notes

  • Login output stays on stderr; the stdout JSON-RPC channel is untouched.
  • The handshake is held during login, so set a generous startup_timeout_sec (docs/config examples updated to 300).
  • First-run browser login needs a browser on the host and the X app's redirect URI (http://localhost:8080/callback) registered. Headless hosts authenticate out-of-band first with xurl auth oauth2 --headless.
  • oauth2Flow is 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.

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`.
@santiagomed santiagomed merged commit e719d94 into main Jun 29, 2026
2 checks passed
@santiagomed santiagomed deleted the fix/mcp-browser-login branch June 29, 2026 22:36
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