github/github-mcp-server · error
GitHub App authentication and OAuth login (--oauth-client-id
Error message
GitHub App authentication and OAuth login (--oauth-client-id) are mutually exclusive: set only one
What it means
Thrown by the list_starred_repositories tool handler when deps.GetClient(ctx) fails before Activity.ListStarned can run. With per-request dependencies (RequestDeps in remote/server deployments) the client is built per call from token info in the context plus configured API hosts, so the wrapped cause is 'no token info in context', 'failed to get base REST URL'/'failed to get upload URL', or 'failed to create REST client'. With stdio BaseDeps the client is prebuilt and this error cannot occur.
Source
Thrown at cmd/github-mcp-server/main.go:69
// Fall back to the build-time baked-in client (official releases) when none is
// configured explicitly. The baked-in app is registered on github.com, so it is
// only applied to the default host; GHES/ghe.com users must bring their own
// --oauth-client-id. Recognizing the host via NormalizeHost means an explicit
// GITHUB_HOST=github.com (or api.github.com) still counts as the default and keeps
// zero-config login working. The secret tracks the id, so an explicitly provided
// id with no secret never picks up the baked-in secret.
if oauthClientID == "" && !appAuthRequested && oauth.NormalizeHost(viper.GetString("host")) == "https://github.com" {
oauthClientID = buildinfo.OAuthClientID
oauthClientSecret = buildinfo.OAuthClientSecret
}
if token == "" && !appAuthRequested && oauthClientID == "" {
return errors.New("authentication required: set GITHUB_PERSONAL_ACCESS_TOKEN, configure GitHub App auth, or pass --oauth-client-id to log in via OAuth")
}
if appAuthRequested && token != "" {
return errors.New("GitHub App authentication and GITHUB_PERSONAL_ACCESS_TOKEN are mutually exclusive: set only one")
}
if appAuthRequested && oauthClientID != "" {
return errors.New("GitHub App authentication and OAuth login (--oauth-client-id) are mutually exclusive: set only one")
}
// If you're wondering why we're not using viper.GetStringSlice("toolsets"),
// it's because viper doesn't handle comma-separated values correctly for env
// vars when using GetStringSlice.
// https://github.com/spf13/viper/issues/380
//
// Additionally, viper.UnmarshalKey returns an empty slice even when the flag
// is not set, but we need nil to indicate "use defaults". So we check IsSet first.
var enabledToolsets []string
if viper.IsSet("toolsets") {
if err := viper.UnmarshalKey("toolsets", &enabledToolsets); err != nil {
return fmt.Errorf("failed to unmarshal toolsets: %w", err)
}
}
// else: enabledToolsets stays nil, meaning "use defaults"
// Parse tools (similar to toolsets)View on GitHub (pinned to 0ea1f775a7)
Solutions
- Inspect the wrapped cause after the colon to tell auth ('no token info in context') from host config ('failed to get base REST URL')
- Supply a valid GitHub token for the server process or incoming request
- Correct the API host env vars to absolute URLs and restart
- Verify with a cheap authenticated call such as get_me before paging through starred repositories
Example fix
// before: remote deployment drops the caller's token // list_starred_repositories -> "failed to get GitHub client: no token info in context" // after: gateway forwards Authorization to the server proxy_set_header Authorization $http_authorization;
Defensive patterns
Strategy: try-catch
Validate before calling
func preflightGitHubClient() error {
if os.Getenv("GITHUB_PERSONAL_ACCESS_TOKEN") == "" {
return fmt.Errorf("missing token: list_starred_repositories cannot build a client")
}
return nil
} Type guard
func isGitHubClientError(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to get GitHub client")
} Try / catch
repos, _, err := callListStarredRepositories(ctx, username)
if err != nil {
if isGitHubClientError(err) {
// auth/host config problem: surface to operator, stop paging
return fmt.Errorf("fix server auth or API host config: %w", err)
}
return err
} Prevention
- Ensure the gateway forwards Authorization to the remote server
- Verify the token env var in the same shell/user that runs the server
- Smoke-test with get_me before paginating starred repositories
- Route 'failed to get GitHub client' to ops alerts, not user-facing retries
When it happens
Trigger: Calling list_starred_repositories (with or without username) when the request context has no token info, when GITHUB_API_HOSTS / GITHUB_BASE_URL / GITHUB_UPLOAD_URL are malformed so URL resolution errors, or when go-github's WithEnterpriseURLs rejects a non-absolute enterprise URL.
Common situations: Missing GITHUB_PERSONAL_ACCESS_TOKEN in the deployment env; gateway stripping the Authorization header; enterprise API host misconfiguration; env vars set on a different user than the one running the server process.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- GitHub App installation ID is required (GITHUB_APP_INSTALLAT
- GitHub App REST base URL is required
- owner not specified
- owner is required
- failed to get GitHub client: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/872377cd8a0bf6ad.
Report an issue: GitHub.