{"record":{"id":"be92bf3a77e08d73","repo":"charmbracelet/crush","slug":"failed-to-create-oauth-handler-for-mcp-q-w","errorCode":null,"errorMessage":"failed to create OAuth handler for mcp %q: %w","messagePattern":"failed to create OAuth handler for mcp %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/mcp/init.go","lineNumber":1109,"sourceCode":"\t\t\t\tclientID, err := resolver.ResolveValue(m.OAuthClientID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"oauth_client_id: %w\", err)\n\t\t\t\t}\n\t\t\t\tclientSecret, err := resolver.ResolveValue(m.OAuthClientSecret)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"oauth_client_secret: %w\", err)\n\t\t\t\t}\n\t\t\t\tpreregistered = &oauth.OAuthClient{\n\t\t\t\t\tClientID:     strings.TrimSpace(clientID),\n\t\t\t\t\tClientSecret: strings.TrimSpace(clientSecret),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Normalize trailing slash for PRM discovery compatibility.\n\t\t\tnormalizedURL := strings.TrimSuffix(url, \"/\")\n\t\t\toauthHandler, oauthErr := mcpoauth.NewHandler(name, normalizedURL, m.OAuthToken, preregistered, tokenSaver, mcpoauth.IsInteractive(ctx), m.OAuthCallbackPort)\n\t\t\tif oauthErr != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to create OAuth handler for mcp %q: %w\", name, oauthErr)\n\t\t\t}\n\t\t\tauthURLs.Set(name, oauthHandler)\n\t\t\treturn &mcp.StreamableClientTransport{\n\t\t\t\tEndpoint:     url,\n\t\t\t\tOAuthHandler: oauthHandler,\n\t\t\t}, oauthHandler, nil\n\t\t}\n\n\t\theaders, err := m.ResolvedHeaders(resolver)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tclient := &http.Client{\n\t\t\tTransport: &headerRoundTripper{\n\t\t\t\theaders: headers,\n\t\t\t},\n\t\t}\n\t\treturn &mcp.StreamableClientTransport{","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/mcp/init.go#L1091-L1127","documentation":"After resolving URL and credentials, createTransport constructs the OAuth handler via mcpoauth.NewHandler (handling PRM discovery, token storage, registration). Any failure from that constructor is wrapped as 'failed to create OAuth handler for mcp %q'. The URL is trailing-slash-normalized beforehand for PRM discovery compatibility.","triggerScenarios":"mcpoauth.NewHandler returning an error: invalid OAuth token cache file, malformed server metadata/PRM discovery configuration, invalid callback port, or internal client registration failures.","commonSituations":"Unwritable token persistence location (HOME not set in CI); OAuth callback port already in use or out of allowed range; MCP server's well-known OAuth metadata unreachable or malformed; stale cached client registration after server-side changes.","solutions":["Read the wrapped cause for the underlying NewHandler failure","Verify the MCP server's /.well-known/oauth-protected-resource metadata is reachable","Check the OAuth callback port is free (or unset to use the default) and writable token cache dir","Clear cached OAuth state/token files for this server and retry the auth flow"],"exampleFix":"// before: port fixed and already in use\nmcp api type http url 'https://api.example.com/mcp' oauth oauth_callback_port 8080\n// after: let the handler pick a free port\nmcp api type http url 'https://api.example.com/mcp' oauth","handlingStrategy":"fallback","validationCode":"resp, err := http.Get(strings.TrimSuffix(serverURL, \"/\") + \"/.well-known/oauth-protected-resource\")\nif err != nil || resp.StatusCode != 200 {\n    return errors.New(\"OAuth metadata discovery unavailable; check server URL and connectivity\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := mcpoauth.NewHandler(name, url, token, nil, saver, interactive, port); err != nil {\n    // clear cached token state and retry once, else surface the wrapped error\n}","preventionTips":["Verify the server exposes valid /.well-known OAuth metadata before enabling oauth","Choose a free callback port or omit the port option","Ensure the token cache directory is writable (set HOME in CI)","Clear stale OAuth caches after server-side registration changes"],"tags":["mcp","oauth","http","initialization"],"backgroundTag":"oauth-handler-init-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}