github/github-mcp-server · error

failed to get GitHub client: %w

Error message

failed to get GitHub client: %w

What it means

The get_secret_scanning_alert tool failed to construct a go-github client before any API call. With BaseDeps (stdio) GetClient cannot fail; with RequestDeps (pkg/github/dependencies.go:308) it fails when the request context carries no token info ('no token info in context') or when the REST/upload URLs cannot be derived from the configured API hosts. Seeing this error means the request-scoped auth/host wiring is broken, not GitHub itself.

Source

Thrown at pkg/github/secret_scanning.go:67

		},
		[]scopes.Scope{scopes.SecurityEvents},
		func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
			owner, err := RequiredParam[string](args, "owner")
			if err != nil {
				return utils.NewToolResultError(err.Error()), nil, nil
			}
			repo, err := RequiredParam[string](args, "repo")
			if err != nil {
				return utils.NewToolResultError(err.Error()), nil, nil
			}
			alertNumber, err := RequiredInt(args, "alertNumber")
			if err != nil {
				return utils.NewToolResultError(err.Error()), nil, nil
			}

			client, err := deps.GetClient(ctx)
			if err != nil {
				return nil, nil, fmt.Errorf("failed to get GitHub client: %w", err)
			}

			alert, resp, err := client.SecretScanning.GetAlert(ctx, owner, repo, int64(alertNumber))
			if err != nil {
				return ghErrors.NewGitHubAPIErrorResponse(ctx,
					fmt.Sprintf("failed to get alert with number '%d'", alertNumber),
					resp,
					err,
				), nil, nil
			}
			defer func() { _ = resp.Body.Close() }()

			if resp.StatusCode != http.StatusOK {
				body, err := io.ReadAll(resp.Body)
				if err != nil {
					return nil, nil, fmt.Errorf("failed to read response body: %w", err)
				}
				return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get alert", resp, body), nil, nil

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Ensure a token reaches every request: set GITHUB_PERSONAL_ACCESS_TOKEN for stdio, or pass Authorization per request in remote mode
  2. Check GITHUB_HOST / GITHUB_ENTERPRISE_URL / GITHUB_API_URL spellings and formats (scheme + host)
  3. If embedding the server, use BaseDeps with a pre-built client when per-request tokens are not available
Defensive patterns

Strategy: validation

Validate before calling

// stdio: fail fast at startup, not per tool call
if os.Getenv("GITHUB_PERSONAL_ACCESS_TOKEN") == "" && os.Getenv("GITHUB_TOKEN") == "" {
    log.Fatal("no GitHub token configured; set GITHUB_PERSONAL_ACCESS_TOKEN")
}
// remote: middleware guaranteeing token info before tools run
_, ok := ghcontext.GetTokenInfo(ctx)
if !ok {
    http.Error(w, "missing GitHub token", http.StatusUnauthorized)
    return
}

Type guard

func isMissingTokenErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "no token info in context")
}

Try / catch

client, err := deps.GetClient(ctx)
if err != nil {
    if isMissingTokenErr(err) {
        return nil, nil, utils.NewToolResultError("authentication required: provide a GitHub token for this request")
    }
    return nil, nil, fmt.Errorf("failed to get GitHub client: %w", err)
}

Prevention

When it happens

Trigger: Remote/hosted deployments where the MCP request has no token (missing Authorization header, unauthenticated transport); GITHUB_HOST / GITHUB_ENTERPRISE_URL values that make apiHosts.BaseRESTURL() or UploadURL() fail; client construction error from go-github.NewClient.

Common situations: Serving HTTP mode while the token was only provided for stdio; env var typos (GH_HOST vs GITHUB_HOST); OAuth flow not completed before tool calls; Docker image started without the token env var.

Related errors


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