Skip to content

Server crashes on startup when /user endpoint returns 403 (scope insufficient) — all tools become unusable #703

Description

@j34ni

Bug Description

The GitLab MCP server fails to serve ANY tools at startup if the authenticated PAT lacks the User: Read scope required by the /user endpoint. This is a warmup initialization bug — the /user call is treated as fatal, blocking all functional tools (list_projects, list_issues, etc.) even though those tools use completely different API endpoints and have their own scopes.

Steps to Reproduce

  1. Create a fine-grained PAT on a GitLab self-hosted or gitlab.com instance
  2. Grant the token scopes like Project: Read, Merge Request: Read
  3. Do NOT grant User: Read scope
  4. Configure the MCP server with GITLAB_API_URL and GITLAB_PERSONAL_ACCESS_TOKEN
  5. Start the MCP server

Result: Server fails on startup with 403 error from /user endpoint. ALL tools return 403/401 errors.

Expected Behavior

The server should start normally. The warmup call to /user should be non-fatal (just log a debug warning), and all tools that have proper scopes should function normally.

Root Cause

In build/index.js around line 965-974:

const response = await fetch(`${getEffectiveApiUrl()}/user`, {
    ...getFetchConfig(),
    redirect: "follow",
});
initialSessionRequestMade = response.ok || response.status === 401;

The warmup code treats any response other than 200/401 as an unhandled failure. A 403 (insufficient scope) is not caught and bubbles up as a fatal error that kills the entire MCP server.

Environment

  • GitLab instance: gitlab.sigma2.no (self-hosted)
  • Token type: Fine-grained PAT with Project: Read scope but NOT User: Read
  • Package: @zereight/mcp-gitlab (latest)

Suggested Fix

Either:

  1. Catch 403 in the warmup and treat it as non-fatal (log debug, continue)
  2. Only warmup on tools that actually need /user (lazy warmup)
  3. Remove the startup /user call entirely if it's not strictly required

Note: The code at line 970 already handles 401 gracefully (response.ok || response.status === 401). The same should apply to 403, since it may indicate a scope mismatch rather than an auth failure.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions