Skip to content

Latest commit

 

History

History
302 lines (202 loc) · 7.91 KB

File metadata and controls

302 lines (202 loc) · 7.91 KB

Authentication Guide

gitlab-mcp supports multiple authentication methods. Token behavior depends on whether remote authorization is enabled.

Token Resolution

Default Mode (REMOTE_AUTHORIZATION=false)

Static PAT (GITLAB_PERSONAL_ACCESS_TOKEN)
  └─> OAuth 2.0 PKCE
      └─> External token script
          └─> Token file

Remote Authorization Mode (REMOTE_AUTHORIZATION=true, HTTP)

Per-request auth only (required)

In remote authorization mode, each request must include Authorization: Bearer <token> or Private-Token: <token>, or Job-Token: <token>. If ENABLE_DYNAMIC_API_URL=true, each request must also include X-GitLab-API-URL.

Cookie-based auth (GITLAB_AUTH_COOKIE_PATH) is applied independently through a cookie jar and is not part of the token chain.


1. Personal Access Token (PAT)

The simplest method. Create a token at GitLab > Settings > Access Tokens with the api scope.

GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx

This token is the default request token in stdio and HTTP modes when REMOTE_AUTHORIZATION=false. When REMOTE_AUTHORIZATION=true, request headers are required and PAT fallback is disabled.


2. OAuth 2.0 PKCE

Browser-based OAuth flow for interactive use. The server launches a local callback server and opens the browser for authorization.

Setup

  1. Register an OAuth application in GitLab (Settings > Applications or admin area):

    • Redirect URI: http://127.0.0.1:8765/callback
    • Scopes: api
    • Confidential: No (for PKCE public clients)
    • Note the Application ID
  2. Configure environment variables:

GITLAB_USE_OAUTH=true
GITLAB_OAUTH_CLIENT_ID=your-application-id
GITLAB_OAUTH_REDIRECT_URI=http://127.0.0.1:8765/callback
GITLAB_OAUTH_SCOPES=api

If GITLAB_OAUTH_SCOPES is omitted, gitlab-mcp defaults to api, or read_api when GITLAB_READ_ONLY_MODE=true.

Optional Settings

# For confidential applications
GITLAB_OAUTH_CLIENT_SECRET=your-client-secret

# Custom GitLab URL (derived from GITLAB_API_URL if not set)
GITLAB_OAUTH_GITLAB_URL=https://gitlab.example.com

# Token storage location (default: ~/.gitlab-mcp-oauth-token.json)
GITLAB_OAUTH_TOKEN_PATH=~/.gitlab-mcp-oauth-token.json

# Disable auto-opening the browser
GITLAB_OAUTH_AUTO_OPEN_BROWSER=false

How It Works

  1. On first request, the server checks for a stored token at GITLAB_OAUTH_TOKEN_PATH
  2. If no valid token exists, it generates a PKCE challenge and opens the browser
  3. The user authorizes the application in GitLab
  4. GitLab redirects back to the local callback server with an authorization code
  5. The server exchanges the code for an access token (with PKCE verifier)
  6. The token is persisted to disk (chmod 600) for future sessions
  7. On subsequent requests, the stored token is reused until it expires
  8. Expired tokens are automatically refreshed using the refresh token

Notes

  • The callback server listens for up to 3 minutes before timing out
  • Token files are stored with 0600 permissions
  • If refresh fails, the server falls back to interactive authorization

3. External Token Script

Execute a shell command to obtain a token dynamically. Useful for integration with secret managers, vault systems, or custom token providers.

GITLAB_TOKEN_SCRIPT=/path/to/get-token.sh
GITLAB_TOKEN_SCRIPT_TIMEOUT_MS=10000   # 500ms–120s (default: 10s)
GITLAB_TOKEN_CACHE_SECONDS=300         # 0–86400s (default: 5min)

Script Output Format

The script must output one of:

  1. Raw token string (plain text on stdout):

    glpat-xxxxxxxxxxxxxxxxxxxx
    
  2. JSON object with any of these keys:

    { "access_token": "glpat-xxxxxxxxxxxxxxxxxxxx" }
    { "token": "glpat-xxxxxxxxxxxxxxxxxxxx" }
    { "private_token": "glpat-xxxxxxxxxxxxxxxxxxxx" }

Example Script

#!/usr/bin/env bash
set -euo pipefail

# Example: read from environment or secret manager
if [[ -n "${GITLAB_OAUTH_ACCESS_TOKEN:-}" ]]; then
  printf '{"access_token":"%s"}\n' "${GITLAB_OAUTH_ACCESS_TOKEN}"
  exit 0
fi

echo "Token not available" >&2
exit 1

The resolved token is cached for GITLAB_TOKEN_CACHE_SECONDS to avoid repeated script executions.


4. Token File

Read a token from a file on disk. The file should contain a raw token string or JSON (same format as the token script output).

GITLAB_TOKEN_FILE=~/.gitlab-token

Security

By default, the server enforces strict file permissions — the token file must be readable only by the owner (chmod 600). If the file has group or other permissions, the server rejects it.

To override this check:

GITLAB_ALLOW_INSECURE_TOKEN_FILE=true

The token is cached for GITLAB_TOKEN_CACHE_SECONDS (default: 300s).


5. Cookie-Based Auth

Use browser cookies from a Netscape-format cookie file. This is useful when working with GitLab instances that use SSO or other browser-based authentication.

GITLAB_AUTH_COOKIE_PATH=~/.gitlab-cookies.txt

How It Works

  1. The server reads cookies from the file in Netscape cookie format
  2. A cookie jar is created and attached to all API requests via fetch-cookie
  3. Before the first API call to each GitLab instance, a warmup request is sent to establish the session
  4. If the cookie file changes on disk, it is automatically reloaded

Warmup Path

The warmup request hits a lightweight endpoint to establish the session:

GITLAB_COOKIE_WARMUP_PATH=/user   # default

Cookie File Format

Standard Netscape cookie format (tab-separated):

# Netscape HTTP Cookie File
.gitlab.example.com	TRUE	/	TRUE	0	_gitlab_session	abc123...

Lines starting with #HttpOnly_ are parsed as HttpOnly cookies.


6. Remote Authorization (HTTP Mode)

In HTTP transport mode, this enables strict per-request credentials. This is the recommended approach for shared/multi-user deployments.

REMOTE_AUTHORIZATION=true

REMOTE_AUTHORIZATION=true enforces per-request credentials. If a request does not include a token header, the request is rejected.

Client Headers

The server accepts tokens via:

  • Authorization: Bearer <token> — Standard bearer token
  • Private-Token: <token> — GitLab private token header
  • Job-Token: <token> — GitLab CI job token header

Dynamic API URL

When serving multiple GitLab instances, enable dynamic API URL per request:

REMOTE_AUTHORIZATION=true
ENABLE_DYNAMIC_API_URL=true

Clients can then send:

X-GitLab-API-URL: https://other-gitlab.example.com/api/v4

Authentication Flow (HTTP Mode)

  1. Client sends a request with auth headers
  2. The server extracts the token and required API URL (when dynamic API URLs are enabled) from headers
  3. Auth context is stored in AsyncLocalStorage for the duration of the request
  4. All GitLab API calls within that request use the per-session credentials
  5. Requests missing required headers are rejected before tool execution

Cloudflare Bypass

If your GitLab instance is behind Cloudflare, enable browser-like headers:

GITLAB_CLOUDFLARE_BYPASS=true

This adds:

  • A Chrome-like User-Agent header
  • Accept-Language: en-US,en;q=0.9
  • Cache-Control: no-cache
  • Pragma: no-cache

You can also set a custom User-Agent:

GITLAB_USER_AGENT="MyApp/1.0"

TLS & Proxy Configuration

Custom CA Certificate

For self-signed or internal CA certificates:

GITLAB_CA_CERT_PATH=/path/to/ca-bundle.pem

HTTP Proxy

HTTP_PROXY=http://proxy.example.com:8080
HTTPS_PROXY=http://proxy.example.com:8080

Insecure TLS (Not Recommended)

To disable TLS certificate verification, you must explicitly acknowledge the risk:

NODE_TLS_REJECT_UNAUTHORIZED=0
GITLAB_ALLOW_INSECURE_TLS=true

Both settings are required — setting only NODE_TLS_REJECT_UNAUTHORIZED=0 without the acknowledgment flag will cause a startup error.