charmbracelet/crush · error
mcp '%s' does not use OAuth authentication
Error message
mcp '%s' does not use OAuth authentication
What it means
AuthenticateMCP only supports MCP servers of type HTTP that have OAuth enabled. If the configured server lacks m.OAuth or is not config.MCPHttp, the function returns this error without starting the browser auth flow.
Source
Thrown at internal/agent/tools/mcp/init.go:365
slog.Debug("Skipping disabled MCP", "name", name)
return nil
}
return initClient(ctx, cfg, name, m, currentGen(name), cfg.Resolver())
}
// AuthenticateMCP initiates the OAuth flow for an MCP server that is in
// StateNeedsAuth. It creates the OAuth handler (which starts a local
// callback server), connects to the server (which triggers the browser
// auth flow on 401), and transitions to StateConnected on success.
func AuthenticateMCP(ctx context.Context, cfg *config.ConfigStore, name string) error {
m, exists := cfg.Config().MCP[name]
if !exists {
return fmt.Errorf("mcp '%s' not found in configuration", name)
}
if !m.OAuth || m.Type != config.MCPHttp {
return fmt.Errorf("mcp '%s' does not use OAuth authentication", name)
}
updateState(name, StateStarting, nil, nil, Counts{}, withPending(m))
// This is the user-initiated flow, so permit the interactive browser
// authorization the handler otherwise withholds during startup.
ctx = mcpoauth.WithInteractive(ctx)
// The OAuth handler persists the token automatically as it is
// exchanged, so a successful connection has already saved it.
_, err := connectAndRegister(ctx, cfg, name, m, currentGen(name), cfg.Resolver(), channelEnabled(cfg.Overrides().EnabledChannels, name))
if err != nil {
return err
}
return nil
}
// PendingAuthServer describes an MCP server awaiting OAuth.View on GitHub (pinned to 7944b8e522)
Solutions
- Set the OAuth option on the HTTP MCP server entry in config.
- Switch the server definition to type http if OAuth is intended.
- For stdio/API-key servers, provide credentials via env/config instead of OAuth.
- Use the correct command for non-OAuth servers instead of MCPAuthenticate.
Example fix
// before
mcp github {
type http
url "https://api.github.com/mcp"
}
// after
mcp github {
type http
url "https://api.github.com/mcp"
oauth true
} Defensive patterns
Strategy: validation
Validate before calling
srv, ok := cfg.Config().MCP[name]
if !ok || !srv.OAuth || srv.Type != config.MCPHttp {
return fmt.Errorf("server %q must be an HTTP MCP server with OAuth enabled", name)
} Try / catch
if err := mcp.AuthenticateMCP(ctx, cfg, name); err != nil {
if strings.Contains(err.Error(), "does not use OAuth") {
// fall back to env-var/API-key credentials for this server
}
return err
} Prevention
- Set oauth true on HTTP MCP server entries that need browser auth.
- Use env/config credentials for stdio and API-key servers instead of OAuth.
- Document each MCP server's auth mechanism next to its config entry.
- Validate server type before invoking OAuth flows.
When it happens
Trigger: Calling AuthenticateMCP on an MCP server defined as stdio/sse type, or an HTTP server configured without the OAuth flag set to true in its mcp entry.
Common situations: Trying to run browser OAuth for a local stdio MCP server; forgetting to set the oauth option on an HTTP server; using authenticate on a server that uses static API-key headers instead.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- mcp '%s' not found in configuration
- mcp '%s' already has an authentication in progress
- failed to get MCP pending auth: %w
- interactive OAuth authorization required
- failed to start OAuth callback listener: all candidate ports
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/a7a5a16bcf306b36.
Report an issue: GitHub.