charmbracelet/crush · error
failed to authenticate MCP: %w
Error message
failed to authenticate MCP: %w
What it means
This error is returned by Client.MCPAuthenticate when the HTTP POST to /workspaces/{id}/mcp/auth fails before a response is available. It wraps the underlying transport error (connection failure, DNS resolution, timeout, or context cancellation) with %w, so the root cause is preserved via errors.Unwrap/Is. It means the authentication request never completed successfully at the network layer.
Source
Thrown at internal/client/proto.go:378
}
var resp proto.MCPAuthResponse
if err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {
return "", fmt.Errorf("failed to decode MCP auth URL: %w", err)
}
return resp.AuthURL, nil
}
// MCPAuthenticate runs the OAuth flow for a named MCP server. The server's
// local browser is suppressed; the caller is responsible for surfacing the
// authorization URL (via polling [Client.MCPPendingAuth] / state events)
// and opening it on the user's machine. The call blocks until the flow
// completes, fails, or ctx is cancelled.
func (c *Client) MCPAuthenticate(ctx context.Context, id, name string) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/auth", id), nil,
jsonBody(proto.MCPNameRequest{Name: name}),
http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return fmt.Errorf("failed to authenticate MCP: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
var e proto.Error
if err := json.NewDecoder(rsp.Body).Decode(&e); err == nil && e.Message != "" {
return fmt.Errorf("failed to authenticate MCP: %s", e.Message)
}
return fmt.Errorf("failed to authenticate MCP: status code %d", rsp.StatusCode)
}
return nil
}
// MCPRefreshPrompts refreshes prompts for a named MCP client.
func (c *Client) MCPRefreshPrompts(ctx context.Context, id, name string) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/refresh-prompts", id), nil,
jsonBody(struct {
Name string `json:"name"`
}{Name: name}),View on GitHub (pinned to 7944b8e522)
Solutions
- Inspect the wrapped error with errors.Unwrap (or %v of the returned error) to identify the root cause
- Verify the MCP server/API endpoint is running and reachable at the configured base URL
- Confirm the workspace id and MCP name are correct and the network/proxy allows the request
- Retry with a fresh context and adequate timeout if the cause was a cancelled or expired ctx
Example fix
// before
err := client.MCPAuthenticate(ctx, "ws-123", "filesystem") // ctx already near deadline
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := client.MCPAuthenticate(ctx, "ws-123", "filesystem"); err != nil {
log.Printf("mcp auth failed: %v", err) // wrapped cause is visible
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight connectivity check before calling the API
func serverReachable(ctx context.Context, baseURL string) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, http.MethodHead, baseURL, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("server unreachable: %w", err)
}
resp.Body.Close()
return nil
} Type guard
// Narrow the wrapped transport cause
func isTransportErr(err error) bool {
var netErr net.Error
var urlErr *url.Error
return errors.As(err, &netErr) || errors.As(err, &urlErr) || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled)
} Try / catch
// Go has no try/catch; use retry with error unwrapping
if err := client.MCPAuthenticate(ctx, id, name); err != nil {
if errors.Is(err, context.Canceled) {
return err // do not retry caller cancellation
}
if isTransportErr(err) {
err = retryWithBackoff(3, func() error { return client.MCPAuthenticate(ctx, id, name) })
}
return err
} Prevention
- Pass a context with an explicit timeout rather than a background context
- Health-check the server base URL at startup before issuing MCP calls
- Verify host/port/TLS configuration against the deployed server version
- Handle network transitions (VPN/Wi-Fi) by re-running connectivity checks before retries
When it happens
Trigger: Calling MCPAuthenticate(ctx, id, name) when the server is unreachable, the base URL is misconfigured, the network is down, TLS fails, or the passed ctx is cancelled before the request completes.
Common situations: Dev environment with the API server not running; wrong host/port in client configuration; corporate proxy or VPN blocking the request; long-running auth triggering context deadline exceeded; expired session behind an auth proxy returning connection resets.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- failed to refresh MCP prompts: %w
- failed to get MCP auth URL: %w
- failed to download from URL: %w
- failed to create request: %w
- failed to fetch URL: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/02e8f1c5ca4d2acf.
Report an issue: GitHub.