siyuan-note/siyuan · warning

mcp oauth authorization required

Error message

mcp oauth authorization required

What it means

errOAuthAuthorizationRequired is a sentinel error signaling that the remote MCP server responded with an OAuth challenge and the client needs the user to complete interactive authorization before the connection can succeed. Callers detect it with errors.Is to treat it as a control-flow signal (abort this connect attempt quietly, prompt for authorization, or mark credentials rejected) rather than a hard failure.

Solutions

  1. Trigger the interactive OAuth authorization flow for this server (reconnect with interactive mode so the browser authorization can run)
  2. If stored credentials are rejected, clear/re-authorize the server's OAuth credentials (markOAuthCredentialRejected path) and authorize again
  3. Check that the server's authorization/redirect endpoints are reachable from the browser

Example fix

// caller pattern
if errors.Is(err, errOAuthAuthorizationRequired) {
    // prompt the user to authorize, then retry the connection
    return nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before connecting: check whether the server needs OAuth and whether a token exists
if !hasAuthorizationHeader(server.Headers) && serverRequiresOAuth(server.URL) && !hasStoredToken(server.ID) {
    // plan an interactive authorization step
}

Try / catch

err := connectOneServer(ctx, server, false)
switch {
case errors.Is(err, errOAuthAuthorizationRequired):
    // run interactive OAuth authorization, then retry the connect
    retryWithAuthorization(server)
case err != nil && setOAuthRetryStateForError(ctx, server.ID, err.Error()):
    markOAuthCredentialRejected(server.ID, server.URL)
}

Prevention

When it happens

Trigger: During connectOneServer the HTTP transport's OAuth handler receives a 401/403 with a WWW-Authenticate Bearer challenge and no valid cached token; the handler returns this sentinel so the connect loop can pause for interactive authorization.

Common situations: First connection to an OAuth-protected MCP server with no stored token; a stored access token expired or was revoked; the server rotated its authorization requirements; running non-interactively so the browser-based flow cannot complete.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/9aad2bc8a65be829. Report an issue: GitHub.

Appendix: source

Thrown at kernel/mcp/client/oauth.go:47

	"net/url"
	"slices"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/modelcontextprotocol/go-sdk/auth"
	"github.com/modelcontextprotocol/go-sdk/oauthex"
	"github.com/siyuan-note/httpclient"
	"github.com/siyuan-note/logging"
	"github.com/siyuan-note/siyuan/kernel/conf"
	"github.com/siyuan-note/siyuan/kernel/util"
	"golang.org/x/oauth2"
)

const oauthAuthorizationTimeout = 5 * time.Minute

var errOAuthAuthorizationRequired = errors.New("mcp oauth authorization required")

type oauthCallbackResult struct {
	Code  string
	State string
	Error string
}

type oauthFlow struct {
	State   string
	Issuer  string
	Result  chan oauthCallbackResult
	Expires time.Time
}

var oauthFlows = struct {
	sync.Mutex
	items map[string]*oauthFlow
}{items: map[string]*oauthFlow{}}

View on GitHub (pinned to 9f775e8a12)