siyuan-note/siyuan · error
server returned
Error message
server returned %s
What it means
Authorize was invoked after the MCP server rejected a request, but the WWW-Authenticate response carried no OAuth Bearer challenge (or none could be parsed as one). The library only knows how to start an OAuth flow when the server advertises a Bearer challenge describing the resource/auth servers; anything else (Basic, Digest, none, or a plain error page) is opaque. This guards against guessing auth schemes the client cannot perform.
Solutions
- Verify the MCP server URL points at the actual OAuth-protected MCP endpoint, not a proxy or UI route
- Check with curl -i that the server returns WWW-Authenticate: Bearer ... on 401; fix server/proxy config to emit it
- If a proxy strips the header, configure it to pass through WWW-Authenticate
- If the server does not use OAuth at all, supply credentials via a supported non-OAuth auth method instead of calling Authorize
Example fix
// before: pointing at a proxy that swallows challenges
server := mcp.NewClientHandler("https://gw.example.com/mcp")
// after: point directly at the OAuth-protected resource
server := mcp.NewClientHandler("https://mcp.example.com/mcp") Defensive patterns
Strategy: validation
Validate before calling
resp, _ := http.Get(serverURL)
ch, err := oauthex.ParseWWWAuthenticate(resp.Header.Values("WWW-Authenticate"))
if err != nil || !hasBearerChallenge(ch) {
return errors.New("endpoint does not advertise OAuth Bearer challenge")
} Try / catch
err := h.Authorize(ctx, req, resp)
if err != nil && strings.Contains(err.Error(), "without an OAuth Bearer challenge") {
surfaceToUser("Server did not advertise OAuth; check URL/proxy WWW-Authenticate passthrough")
} Prevention
- Always curl -i the MCP endpoint to confirm a Bearer WWW-Authenticate challenge on 401 before wiring OAuth
- Configure reverse proxies to pass through WWW-Authenticate headers
- Keep the MCP server URL pointing at the OAuth-protected resource, not a gateway UI
When it happens
Trigger: Calling MCPClient.Authorize when resp.StatusCode is 401/403 but the response lacks a WWW-Authenticate header with scheme Bearer, e.g. a reverse proxy returns 401 with Basic challenge, or the endpoint returns an HTML error page with no challenge at all.
Common situations: MCP server URL points at a gateway/proxy that strips or rewrites WWW-Authenticate; wrong URL hits a non-OAuth endpoint; server is not actually an OAuth-protected resource; API gateway uses API keys instead of OAuth.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- discover OAuth authorization server
- OAuth protected resource metadata not found
- OAuth token endpoint returned
- refresh OAuth credentials
- register OAuth client
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/5c12500fd4090395.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/client/oauth.go:196
RefreshToken: credential.RefreshToken,
Expiry: credential.Expiry,
}
}
func (h *mcpOAuthHandler) Authorize(ctx context.Context, req *http.Request, resp *http.Response) (retErr error) {
defer resp.Body.Close()
defer io.Copy(io.Discard, io.LimitReader(resp.Body, 1<<20))
challenges, err := oauthex.ParseWWWAuthenticate(resp.Header.Values("WWW-Authenticate"))
if err != nil {
return fmt.Errorf("parse OAuth challenge: %w", err)
}
if !hasBearerChallenge(challenges) {
return fmt.Errorf("server returned %s without an OAuth Bearer challenge", resp.Status)
}
challengeError := bearerChallengeParam(challenges, "error")
if resp.StatusCode == http.StatusForbidden && challengeError != "insufficient_scope" {
return fmt.Errorf("server returned %s", resp.Status)
}
interactive := h.interactive.Load()
if interactive {
defer func() {
if retErr != nil && !errors.Is(retErr, context.Canceled) {
setMCPRuntimeStateForContext(ctx, h.server.ID, "authorization_required", 0, retErr.Error(), "")
}
}()
}
prm, err := discoverProtectedResource(ctx, challenges, req.URL.String(), h.client)
if err != nil {
return err
}
asm, err := auth.GetAuthServerMetadata(ctx, prm.AuthorizationServers[0], h.client)
if err != nil {
return fmt.Errorf("discover OAuth authorization server: %w", err)View on GitHub (pinned to 9f775e8a12)