Authentication
How Auth Works
Loading diagram...
Smart Auth Detection
Mux now uses a two-phase connection strategy that avoids false auth triggers:
- Phase 1: Try without auth — Connects to the server without an OAuth provider. If it succeeds, no auth is needed (e.g., servers using API key headers).
- Phase 2: Probe OAuth discovery — If the server returns 401, Mux probes
/.well-known/oauth-authorization-serveron the server's origin. Only if the server has a valid OAuth discovery endpoint (withauthorization_endpoint) does Mux trigger the browser auth flow. - Fail fast — If the server returns 401 but has no OAuth discovery, Mux immediately fails with a clear error message instead of waiting 120s for a callback that will never come.
This means:
- Servers with API key headers (Datadog, etc.) → connect instantly, no OAuth popup
- Internal services without OAuth → fail fast with actionable error
- OAuth-enabled servers (GitLab, Sitecore, etc.) → normal auth flow as before
Auth Types Supported
| Type | Config | Behavior |
|---|---|---|
| None | No env/headers/auth | Direct connection, no credentials |
| Env tokens | env: { "TOKEN": "${VAR}" } | Injected from shell environment at startup |
| Static headers | headers: { "X-API-Key": "${KEY}" } | Injected into every HTTP request |
| OAuth (browser) | Server returns 401 + has OAuth discovery | Mux opens browser → you authorize → token cached |
Browser-Based OAuth (HTTP Servers)
Most HTTP MCP servers (GitLab, Jira, Slack, ServiceNow, Datadog, Sitecore) use the MCP protocol's built-in OAuth. When Mux connects and gets a 401:
- Mux probes the server's
/.well-known/oauth-authorization-serverendpoint - If OAuth metadata is found, Mux opens your browser with the authorization URL
- You click "Authorize" in the browser
- Browser redirects back to
localhost:48912/callback - Mux exchanges the auth code for tokens and caches them
This is the same flow as Kiro IDE/CLI — no extra configuration needed. First call triggers auth, subsequent calls use the cached token. If the token expires, it auto-refreshes using the refresh token.
Early Auth Completion
Mux now detects externally-completed authorization immediately:
- Token file polling — While waiting for the OAuth callback, Mux monitors
~/.mux/tokens.jsonfor modifications. If the file changes (e.g., from a redirect flow that writes directly), it resolves immediately without waiting for the callback. - Countdown timer — During the auth wait, a countdown is displayed to stderr so you can see how much time remains:
[MUX] ⏳ Waiting for "sitecore" authorization... 95s remaining - Instant resolution — As soon as auth completes (via callback OR token detection), the timer clears and connection proceeds.
[!TIP] Pre-authorize all HTTP servers after setup:
mux-cli auth --all
Token Persistence
Tokens are stored encrypted in ~/.mux/tokens.json using AES-256-GCM. The file is never plain text.
Security layers:
- AES-256-GCM encryption at rest (tokens + client registrations)
- Key derived from machine identity via PBKDF2 (100k iterations)
- File permissions
0600(owner read/write only) - Directory permissions
0700on~/.mux/ - OAuth callback server bound to
127.0.0.1only (not network-accessible)
What cat ~/.mux/tokens.json shows:
{"v":1,"enc":"WgWcn6RPi5TO60lD...","iv":"abc123...","tag":"xyz789..."}
Token lifecycle:
- Cached token valid → used immediately (no browser popup)
- Token expiring within 60s → refreshed automatically via refresh_token
- Refresh token expired → one-time browser OAuth flow, new tokens cached
- Server disabled/re-enabled → tokens survive (that's the whole point)