{"record":{"id":"d0ff3ab146d8c5e2","repo":"siyuan-note/siyuan","slug":"server-returned-s-without-an-oauth-bearer-challen","errorCode":null,"errorMessage":"server returned %s without an OAuth Bearer challenge","messagePattern":"server returned (.+?) without an OAuth Bearer challenge","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/oauth.go","lineNumber":192,"sourceCode":"func credentialToken(credential oauthCredential) *oauth2.Token {\n\treturn &oauth2.Token{\n\t\tAccessToken:  credential.AccessToken,\n\t\tTokenType:    credential.TokenType,\n\t\tRefreshToken: credential.RefreshToken,\n\t\tExpiry:       credential.Expiry,\n\t}\n}\n\nfunc (h *mcpOAuthHandler) Authorize(ctx context.Context, req *http.Request, resp *http.Response) (retErr error) {\n\tdefer resp.Body.Close()\n\tdefer io.Copy(io.Discard, io.LimitReader(resp.Body, 1<<20))\n\n\tchallenges, err := oauthex.ParseWWWAuthenticate(resp.Header.Values(\"WWW-Authenticate\"))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parse OAuth challenge: %w\", err)\n\t}\n\tif !hasBearerChallenge(challenges) {\n\t\treturn fmt.Errorf(\"server returned %s without an OAuth Bearer challenge\", resp.Status)\n\t}\n\tchallengeError := bearerChallengeParam(challenges, \"error\")\n\tif resp.StatusCode == http.StatusForbidden && challengeError != \"insufficient_scope\" {\n\t\treturn fmt.Errorf(\"server returned %s\", resp.Status)\n\t}\n\tinteractive := h.interactive.Load()\n\tif interactive {\n\t\tdefer func() {\n\t\t\tif retErr != nil && !errors.Is(retErr, context.Canceled) {\n\t\t\t\tsetMCPRuntimeStateForContext(ctx, h.server.ID, \"authorization_required\", 0, retErr.Error(), \"\")\n\t\t\t}\n\t\t}()\n\t}\n\n\tprm, err := discoverProtectedResource(ctx, challenges, req.URL.String(), h.client)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/client/oauth.go#L174-L210","documentation":"After parsing the WWW-Authenticate challenges, Authorize requires at least one OAuth Bearer challenge to drive the authorization flow. If the response's challenges contain no Bearer scheme, it fails with 'server returned %s without an OAuth Bearer challenge', where %s is the HTTP status line. This guards against servers that return 401/403 without usable OAuth metadata.","triggerScenarios":"An HTTP MCP server responds with 401/403 during Connect but its WWW-Authenticate headers lack a Bearer challenge (e.g. only Basic, or no challenge at all), so the OAuth handler cannot determine scope/authorization endpoints.","commonSituations":"Server uses non-OAuth auth (Basic auth, API key) while the client expected OAuth; misconfigured reverse proxy stripping the WWW-Authenticate header; server returning a plain 401 HTML error page from a gateway instead of the MCP OAuth flow.","solutions":["Verify the endpoint actually speaks MCP with OAuth; if it uses API keys instead, configure the key in the server's Headers so the OAuth handler is skipped","Check that a reverse proxy is not stripping WWW-Authenticate headers and fix its configuration","Confirm the server URL points at the MCP endpoint, not a generic login page","If you control the server, make it emit a Bearer WWW-Authenticate challenge on 401"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := handler.Authorize(ctx, req, resp)\nif err != nil && strings.Contains(err.Error(), \"without an OAuth Bearer challenge\") {\n    // server does not offer OAuth; fall back to static header auth\n    configureStaticHeaders(server)\n}","preventionTips":["Confirm the MCP server implements the OAuth authorization flow before relying on it","Use static Authorization headers for servers that use API keys instead of OAuth","Ensure reverse proxies do not strip WWW-Authenticate responses","Point the server URL at the real MCP endpoint, not a gateway login page"],"tags":["mcp","oauth","http-headers","authentication"],"backgroundTag":"unexpected-response-shape","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}