github/github-mcp-server · error · utils.ErrUnsupportedAuthorizationHeader

bad request: unsupported Authorization header

Error message

bad request: unsupported Authorization header

What it means

The 400 written when the Authorization header uses the non-standard 'GitHub-Bearer ' scheme, which ParseAuthorizationHeader explicitly refuses with ErrUnsupportedAuthorizationHeader ('bad request: unsupported Authorization header'). The sentinel is reserved for this scheme - the server intentionally does not decrypt GitHub-Bearer payloads; all other unrecognized formats land in the badly-formatted bucket instead.

Source

Thrown at pkg/http/middleware/token.go:34

			ctx := r.Context()

			// Check if token info already exists in context, if it does, skip extraction.
			// In remote setup, we may have already extracted token info earlier.
			if _, ok := ghcontext.GetTokenInfo(ctx); ok {
				// Token info already exists in context, skip extraction
				next.ServeHTTP(w, r)
				return
			}

			tokenType, token, err := utils.ParseAuthorizationHeader(r)
			if err != nil {
				// For missing Authorization header, return 401 with WWW-Authenticate header per MCP spec
				if errors.Is(err, utils.ErrMissingAuthorizationHeader) {
					sendAuthChallenge(w, r, oauthCfg)
					return
				}
				// For other auth errors (bad format, unsupported), return 400
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}

			ctx = ghcontext.WithTokenInfo(ctx, &ghcontext.TokenInfo{
				Token:     token,
				TokenType: tokenType,
			})
			r = r.WithContext(ctx)

			next.ServeHTTP(w, r)
		})
	}
}

// sendAuthChallenge sends a 401 Unauthorized response with WWW-Authenticate header
// containing the OAuth protected resource metadata URL as per RFC 6750 and MCP spec.
func sendAuthChallenge(w http.ResponseWriter, r *http.Request, oauthCfg *oauth.Config) {
	resourcePath := oauth.ResolveResourcePath(r, oauthCfg)

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Use the standard 'Authorization: Bearer <token>' form ('bearer' lowercase is also accepted)
  2. Remove or fix any proxy that rewrites the scheme name
  3. Confirm the HTTP client sets the header verbatim without scheme translation

Example fix

# before
Authorization: GitHub-Bearer AbCdEf...

# after
Authorization: Bearer ghp_AbCdEf...
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(authHeader, "GitHub-Bearer ") {
	return errors.New("unsupported scheme: use 'Authorization: Bearer <token>'")
}
req.Header.Set("Authorization", "Bearer "+token)

Type guard

func isUnsupportedAuthHeader(err error) bool {
	return errors.Is(err, utils.ErrUnsupportedAuthorizationHeader)
}

Try / catch

if _, _, err := utils.ParseAuthorizationHeader(req); err != nil {
	if errors.Is(err, utils.ErrUnsupportedAuthorizationHeader) {
		// specifically the GitHub-Bearer scheme: tell the client to switch to plain Bearer
	}
}

Prevention

When it happens

Trigger: Sending 'Authorization: GitHub-Bearer <blob>' - e.g. replaying a header captured from GitHub's own first-party clients, or a client library/proxy defaulting to that scheme name.

Common situations: Copy-pasting auth schemes from other GitHub tooling; internal proxies rewriting the Authorization scheme; security tools replaying captured headers.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/0623b4416f04d39f. Report an issue: GitHub.