Back to Browse

Gitlab MCP Server

Developer ToolsModerate7.6MCP RegistryLocal
Free

Server data from the Official MCP Registry

GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more.

About

GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more.

Security Report

7.6
Moderate7.6Low Risk

This is a large, feature-rich GitLab MCP server that supports PAT, OAuth2, and remote authorization, with a clear purpose matching its requested network and filesystem access for GitLab API operations and downloads. The visible code shows deliberate security measures (constant-time secret comparison, redaction, token-bound download URLs, masking), though the truncated sources prevent a full audit of tool handlers, dependencies, and the download/file-write paths. Permissions such as network_http, env_vars, and file_write are expected for this category, and no malicious patterns were identified in the visible code. Package verification found 1 issue.

1 file analyzed · 4 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

HTTP Network Access

Connects to external APIs or services over the internet.

File System Read

Reads files on your machine. Normal for tools that analyze or process local data.

File System Write

Writes or modifies files on your machine. Check that this is expected for the tool.

env_vars

Check that this permission is expected for this type of plugin.

process_spawn

Check that this permission is expected for this type of plugin.

database

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

GitLab personal access token for local stdio use. A non-empty value overrides GITLAB_PERSONAL_ACCESS_TOKEN_FILE. One of this token, GITLAB_PERSONAL_ACCESS_TOKEN_FILE, GITLAB_JOB_TOKEN, GITLAB_AUTH_COOKIE_PATH, or GITLAB_USE_OAUTH=true must be set. Create a token with the GitLab scopes the tools need, such as api or read_api.Required

Environment variable: GITLAB_PERSONAL_ACCESS_TOKEN

Path to a file that contains the personal access token. Read once at startup and trimmed. Ignored when GITLAB_PERSONAL_ACCESS_TOKEN or --token is non-empty. A missing, unreadable, or empty file stops startup. Does not replace job token, OAuth, cookie, or remote authorization.Optional

Environment variable: GITLAB_PERSONAL_ACCESS_TOKEN_FILE

Optional GitLab CI job token to use instead of a personal access token when running inside GitLab CI.Required

Environment variable: GITLAB_JOB_TOKEN

Optional path to a GitLab authentication cookie file for cookie-based authentication.Optional

Environment variable: GITLAB_AUTH_COOKIE_PATH

Set to true to start with GitLab OAuth instead of a personal access token, job token, or cookie file.Optional

Environment variable: GITLAB_USE_OAUTH

GitLab OAuth application ID. When GITLAB_USE_OAUTH=true, set this or GITLAB_OAUTH_TOKEN_SCRIPT.Optional

Environment variable: GITLAB_OAUTH_CLIENT_ID

Command that prints an OAuth access token. When GITLAB_USE_OAUTH=true, set this or GITLAB_OAUTH_CLIENT_ID.Optional

Environment variable: GITLAB_OAUTH_TOKEN_SCRIPT

GitLab API base URL. Use https://gitlab.com/api/v4 for GitLab.com or your self-managed GitLab API URL.Optional

Environment variable: GITLAB_API_URL

Optional comma-separated list of GitLab project IDs that this server is allowed to access.Optional

Environment variable: GITLAB_ALLOWED_PROJECT_IDS

Tool exposure. Allowed values are readonly, modify, and full. Unset uses full. readonly keeps read-only tools. modify blocks delete and teardown tools.Optional

Environment variable: GITLAB_PERMISSION_MODE

Optional comma-separated list of toolsets to enable, such as projects, issues, merge_requests, pipelines, releases, users, groups, wiki, or search.Optional

Environment variable: GITLAB_TOOLSETS

Optional comma-separated list of individual tool names to add on top of enabled toolsets.Optional

Environment variable: GITLAB_TOOLS

Optional regular expression used to hide matching tools from the server.Optional

Environment variable: GITLAB_DENIED_TOOLS_REGEX

Optional comma-separated list of tool names that require explicit approval before execution.Optional

Environment variable: GITLAB_TOOL_POLICY_APPROVE

Optional comma-separated list of tool names to hide from tools/list.Optional

Environment variable: GITLAB_TOOL_POLICY_HIDDEN

Set to 0 only when you intentionally need to connect to a GitLab instance with invalid or self-signed TLS certificates.Optional

Environment variable: NODE_TLS_REJECT_UNAUTHORIZED

Optional path to a custom CA certificate file for self-managed GitLab instances.Optional

Environment variable: GITLAB_CA_CERT_PATH

Set to true to mask text tool results and returned errors using built-in or configured rules.Optional

Environment variable: GITLAB_MASKING_ENABLED

Optional path to a response-masking JSON configuration file.Optional

Environment variable: GITLAB_MASKING_CONFIG

Optional protected server-owned JSON file containing managed masking policies.Optional

Environment variable: GITLAB_MASKING_POLICY_FILE

Directory used to resolve response-masking configuration paths.Optional

Environment variable: GITLAB_MASKING_WORKSPACE_DIR

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-zereight-gitlab-mcp": {
      "env": {
        "GITLAB_TOOLS": "your-gitlab-tools-here",
        "GITLAB_API_URL": "your-gitlab-api-url-here",
        "GITLAB_TOOLSETS": "your-gitlab-toolsets-here",
        "GITLAB_JOB_TOKEN": "your-gitlab-job-token-here",
        "GITLAB_USE_OAUTH": "your-gitlab-use-oauth-here",
        "GITLAB_CA_CERT_PATH": "your-gitlab-ca-cert-path-here",
        "GITLAB_MASKING_CONFIG": "your-gitlab-masking-config-here",
        "GITLAB_MASKING_ENABLED": "your-gitlab-masking-enabled-here",
        "GITLAB_OAUTH_CLIENT_ID": "your-gitlab-oauth-client-id-here",
        "GITLAB_PERMISSION_MODE": "your-gitlab-permission-mode-here",
        "GITLAB_AUTH_COOKIE_PATH": "your-gitlab-auth-cookie-path-here",
        "GITLAB_DENIED_TOOLS_REGEX": "your-gitlab-denied-tools-regex-here",
        "GITLAB_OAUTH_TOKEN_SCRIPT": "your-gitlab-oauth-token-script-here",
        "GITLAB_TOOL_POLICY_HIDDEN": "your-gitlab-tool-policy-hidden-here",
        "GITLAB_ALLOWED_PROJECT_IDS": "your-gitlab-allowed-project-ids-here",
        "GITLAB_MASKING_POLICY_FILE": "your-gitlab-masking-policy-file-here",
        "GITLAB_TOOL_POLICY_APPROVE": "your-gitlab-tool-policy-approve-here",
        "GITLAB_MASKING_WORKSPACE_DIR": "your-gitlab-masking-workspace-dir-here",
        "GITLAB_PERSONAL_ACCESS_TOKEN": "your-gitlab-personal-access-token-here",
        "NODE_TLS_REJECT_UNAUTHORIZED": "your-node-tls-reject-unauthorized-here",
        "GITLAB_PERSONAL_ACCESS_TOKEN_FILE": "your-gitlab-personal-access-token-file-here"
      },
      "args": [
        "-y",
        "@zereight/mcp-gitlab"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

GitLab MCP Server

GitHub stars npm downloads npm GitHub License Install in VS Code Install in Cursor Ask DeepWiki MCP Toplist mcpindex

English | 한국어 | 简体中文 | Português (Brasil)

📖 Documentation → Setup guides, environment variables, and the full tool reference live on the hosted docs site.

Install @zereight/mcp-gitlab with the recommended local personal-access-token setup. These commands use the same arguments as the Claude Code and Codex guides.

Install the zereight-mcp-gitlab binary first with npm install -g @zereight/mcp-gitlab, or Homebrew brew tap zereight/gitlab-mcp https://github.com/zereight/gitlab-mcp and brew install zereight/gitlab-mcp/zereight-mcp-gitlab.

Read the token without echo, then export it. The shell history keeps the variable name.

read -rs GITLAB_PERSONAL_ACCESS_TOKEN && export GITLAB_PERSONAL_ACCESS_TOKEN
ClientInstall
Claude Codeclaude mcp add gitlab --transport stdio --scope local --env GITLAB_PERSONAL_ACCESS_TOKEN="$GITLAB_PERSONAL_ACCESS_TOKEN" --env GITLAB_API_URL=https://gitlab.com/api/v4 -- zereight-mcp-gitlab
Codexcodex mcp add gitlab --env GITLAB_PERSONAL_ACCESS_TOKEN="$GITLAB_PERSONAL_ACCESS_TOKEN" --env GITLAB_API_URL=https://gitlab.com/api/v4 -- zereight-mcp-gitlab
CursorCursor setup guide
VS CodeVS Code setup guide
JSON clientsJSON-based MCP clients setup guide

Star History Chart

@zereight/mcp-gitlab

Agent-workflow-optimized GitLab MCP — manage projects, merge requests, issues, pipelines, wiki, releases, tags, milestones, and more through stdio, SSE, and Streamable HTTP.

Supports PAT, OAuth, read-only mode, dynamic API URLs, and remote authorization for VS Code, Claude, Cursor, Copilot, and other MCP clients.

Why use this GitLab MCP?

  • 276 tools: 274 in toolsets + execute_graphql + discover_tools — start with a small toolset; activate more at runtime without CQRS-style grouping
  • MR 2-step review — list_merge_request_changed_files → batched get_merge_request_file_diff
  • Agent Skill built in — workflow guidance in skills/gitlab-mcp/
  • Flexible auth — Personal Access Token, local OAuth2 browser flow, MCP OAuth proxy, and per-request remote authorization
  • Multiple transports — stdio for local clients, SSE for legacy clients, and Streamable HTTP for modern remote deployments
  • Client-friendly setup — examples for Claude Code, Codex, Antigravity, OpenCode, Copilot, Cline, Roo Code, Cursor, Kilo Code, and Amp Code
  • Self-hosted ready — works with custom GitLab instances, proxy settings, and dynamic API URL routing
  • JMESPath result filtering — optional jmespath on tool calls (see tools/list) shrinks JSON results without changing GitLab API requests; when response masking is enabled, JMESPath runs on masked data.

How we compare

@zereight/mcp-gitlabGitLab MCP A (community CQRS-style)GitLab official MCP server
Best forAI agent workflowsEnterprise multi-instance / grouped toolsBuilt into GitLab, no separate install
Tool model276 tools: 274 in toolsets + execute_graphql + discover_tools~50–60 grouped browse_* / manage_* toolsToolsets chosen with an HTTP header
MR review2-step batched diffVariesget_merge_request with diffs
Node.js>=18.17Often >=24Node.js 20+ for stdio via mcp-remote
LicenseMITVariesPart of GitLab

Full comparison with GitLab MCP A →

GitLab also ships an official MCP server.

  • Free, Premium, and Ultimate. Moved from Premium to Free in GitLab 19.2. Generally available in GitLab 19.5.
  • On GitLab.com, a top-level group Owner allows access to the MCP server. On GitLab Self-Managed and GitLab Dedicated, an administrator controls the instance setting. Default rules are on the official page.
  • Remote clients use HTTP https://<gitlab.example.com>/api/v4/mcp with OAuth 2.0 dynamic client registration.
  • stdio goes through mcp-remote and needs Node.js 20 or later.
  • Toolsets use the X-Gitlab-Enabled-Mcp-Server-Toolsets header. An optional X-Gitlab-Mcp-Server-Tool-Name-Prefix header keeps the first 32 characters of a tool-name prefix.

Quick start: choose either Personal Access Token or OAuth2 setup below, install @zereight/mcp-gitlab, and use zereight-mcp-gitlab in your MCP client configuration.

Client Setup Guides

Usage

Setup Overview

Authentication Methods

The server supports four authentication methods:

For local/desktop use (most common):

  1. Personal Access Token (GITLAB_PERSONAL_ACCESS_TOKEN or GITLAB_PERSONAL_ACCESS_TOKEN_FILE) — simplest setup
  2. OAuth2 — Local Browser (GITLAB_USE_OAUTH) — recommended for better security

For server/remote deployments:

  1. OAuth2 — MCP Proxy (GITLAB_MCP_OAUTH) — for remote MCP clients such as Claude.ai
  2. Remote Authorization (REMOTE_AUTHORIZATION) — multi-user deployments where each caller provides their own token
Quick setup paths

For the simplest local setup, start with a Personal Access Token. For browser-based local auth, use OAuth2. For remote or multi-user deployments, continue to the MCP OAuth and Remote Authorization sections later in this README.

Install the server once:

brew tap zereight/gitlab-mcp https://github.com/zereight/gitlab-mcp
brew install zereight/gitlab-mcp/zereight-mcp-gitlab

Or with npm:

npm install -g @zereight/mcp-gitlab

Or with Nix, by adding this flake to your own:

# flake.nix
inputs.gitlab-mcp.url = "github:zereight/gitlab-mcp";

# wherever you configure your MCP client:
command = lib.getExe inputs.gitlab-mcp.packages.${system}.default;

The store path is pinned by your lock file; update it with nix flake update gitlab-mcp.

The examples use zereight-mcp-gitlab, a less collision-prone alias for the legacy mcp-gitlab binary. If your MCP client cannot find it, use the absolute path from which zereight-mcp-gitlab.

No global install? Pin npx to the previous stable release (the version these docs recommend), for example npx -y @zereight/mcp-gitlab@2.3.0. If you always want the newest release, use npx -y @zereight/mcp-gitlab@latest instead. The server prints a notice to stderr on startup when a newer version is available (disable with GITLAB_DISABLE_VERSION_CHECK=true).

Using CLI Arguments (for clients with env var issues)

Some MCP clients (like GitHub Copilot CLI) have issues with environment variables. Use CLI arguments instead:

{
  "mcpServers": {
    "gitlab": {
      "command": "zereight-mcp-gitlab",
      "args": ["--token=YOUR_GITLAB_TOKEN", "--api-url=https://gitlab.com/api/v4"],
      "tools": ["*"]
    }
  }
}

Available CLI arguments:

  • --token - GitLab Personal Access Token (replaces GITLAB_PERSONAL_ACCESS_TOKEN)
  • --api-url - GitLab API URL (replaces GITLAB_API_URL)
  • --read-only=true - Deprecated (removed in next major (v3.0.0)); use --permission-mode=readonly instead (replaces GITLAB_READ_ONLY_MODE)
  • --permission-mode - Permission level: readonly, modify (no delete or teardown tools), or full (replaces GITLAB_PERMISSION_MODE, default full)
  • --toolsets=all - Enable named toolsets except the explicit-only api toolset (replaces GITLAB_TOOLSETS; unset uses the lean core default). gitlab_api_request needs --toolsets=api
  • --tools=list_issues - Add individual tools (replaces GITLAB_TOOLS)
  • --use-wiki=true - Deprecated (removed in next major (v3.0.0)); use --toolsets=core,wiki instead (replaces USE_GITLAB_WIKI)
  • --use-milestone=true - Deprecated (removed in next major (v3.0.0)); use --toolsets=core,milestones instead (replaces USE_MILESTONE)
  • --use-pipeline=true - Deprecated (removed in next major (v3.0.0)); use --toolsets=core,pipelines and append validate_ci_lint,validate_project_ci_lint to the existing --tools list (or set --tools=validate_ci_lint,validate_project_ci_lint when that list is unset) (replaces USE_PIPELINE)
  • --disable-version-check=true - Disable the startup new-version notice (replaces GITLAB_DISABLE_VERSION_CHECK)
  • --masking-enabled=true - Enable text-response masking (replaces GITLAB_MASKING_ENABLED)
  • --masking-config - Path to a masking configuration file (replaces GITLAB_MASKING_CONFIG)
  • --masking-policy-file - Path to a protected managed-policy file (replaces GITLAB_MASKING_POLICY_FILE)
  • --masking-workspace-dir - Directory used to resolve masking files (replaces GITLAB_MASKING_WORKSPACE_DIR)
  • --download-dir - Directory download_attachment saves files under (replaces GITLAB_DOWNLOAD_DIR; default .gitlab-mcp-downloads)
  • --compact-results=true - Truncate oversized MCP tool replies and attach a CLI command for the full payload (replaces GITLAB_MCP_COMPACT_RESULTS; default off)
  • --compact-result-chars - Character threshold for compacting (replaces GITLAB_MCP_COMPACT_RESULT_CHARS; default 4000)
  • --compact-tools - Comma-separated tool names to compact when oversized, without turning global compact on (replaces GITLAB_MCP_COMPACT_TOOLS)
  • --tool-profile - full (default) or slim. slim drops draft notes, emoji reactions, labels, CI catalog tools, and create_group from the initial list. Ignored when GITLAB_TOOLSETS is set (replaces GITLAB_TOOL_PROFILE)

If you already set GITLAB_TOOLSETS or --toolsets, append wiki, milestones, or pipelines to that list instead of replacing it. If you already set GITLAB_TOOLS or --tools, append validate_ci_lint and validate_project_ci_lint to that list instead of replacing it. An explicit list replaces the default core toolset; it does not merge.

CLI arguments take precedence over environment variables.

zereight-mcp-gitlab auth is a subcommand (not an MCP server flag). It runs GitLab device flow and exits. See CLI Arguments.

The same binary is also a gh-style GitLab CLI (tool <name> or curated forms such as mr list). No MCP registration is needed — set a PAT, or run auth and set GITLAB_USE_OAUTH=true: see CLI without MCP. Use it for the full payload in a terminal. MCP replies stay in the chat unless you set GITLAB_MCP_COMPACT_RESULTS=true (or --compact-results), which replaces oversized tool replies with a preview and a CLI command. Human CLI is never compacted. Same permission mode, toolsets, denied-tools regex, and tool-policy filters. Destructive tools and GITLAB_TOOL_POLICY_APPROVE tools need --yes. See Human CLI.

Fine-grained tool filtering: use GITLAB_PERMISSION_MODE=modify to allow create/update while blocking every delete tool and the destructive teardown tools (cancel_pipeline, cancel_pipeline_job, stop_environment, stop_stale_environments, unprotect_branch, unprotect_tag) — including destructive mutations (deletion and teardown verbs) through execute_graphql and push_files delete/move actions — or GITLAB_PERMISSION_MODE=readonly for read-only access. You can also enable toolset groups with GITLAB_TOOLSETS=<group,…>, allow-list individual tools with GITLAB_TOOLS=<tool,…> (e.g. read-only groups plus a few specific write tools), and deny-list by pattern with GITLAB_DENIED_TOOLS_REGEX. The legacy USE_GITLAB_WIKI / USE_MILESTONE / USE_PIPELINE flags are deprecated (removed in next major (v3.0.0)). Use GITLAB_TOOLSETS=core,wiki, core,milestones, or core,pipelines (USE_PIPELINE also needs validate_ci_lint,validate_project_ci_lint appended to an existing GITLAB_TOOLS list instead of replacing it). If you already set GITLAB_TOOLSETS, append the toolset to your existing list instead of replacing it. If GITLAB_TOOLS is unset, set GITLAB_TOOLS=validate_ci_lint,validate_project_ci_lint. If it is already set, append validate_ci_lint,validate_project_ci_lint instead of replacing that list. See Tools Reference and Environment Variables.

[!CAUTION] gitlab_api_request (toolset api) bypasses GITLAB_ALLOWED_GROUPS and other group restrictions, project allowlists, tool-level restrictions (GITLAB_TOOLS, GITLAB_DENIED_TOOLS_REGEX on other tools), and individual tool safety checks. The full token permission scope is exposed. Prompt injection can drive this tool. Operators who rely on these restrictions must NOT enable it. Enable it only by listing api in GITLAB_TOOLSETS (GITLAB_TOOLSETS=all, discover_tools, GITLAB_TOOLS, legacy USE_* flags, and GITLAB_TOOL_PROFILE do not). GITLAB_ALLOWED_PROJECT_IDS is checked only for /projects/:id paths. Endpoints such as /search, /users, /groups/:id, and /runners are not constrained. GITLAB_PROJECT_ID and OAuth group allowlists are not enforced.

  • sse

Pass the variable name only. The Docker client copies the exported GITLAB_PERSONAL_ACCESS_TOKEN into the container.

docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e GITLAB_PERSONAL_ACCESS_TOKEN \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e GITLAB_TOOLSETS=core,wiki,milestones,pipelines \
  -e SSE=true \
  -e SSE_AUTH_TOKEN=your_mcp_sse_token \
  -p 3333:3002 \
  zereight050/gitlab-mcp
{
  "mcpServers": {
    "gitlab": {
      "type": "sse",
      "url": "http://localhost:3333/sse",
      "headers": {
        "Authorization": "Bearer your_mcp_sse_token"
      }
    }
  }
}
  • streamable-http
docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e REMOTE_AUTHORIZATION=true \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e GITLAB_TOOLSETS=core,wiki,milestones,pipelines \
  -e STREAMABLE_HTTP=true \
  -p 3333:3002 \
  zereight050/gitlab-mcp
{
  "mcpServers": {
    "gitlab": {
      "type": "streamable-http",
      "url": "http://localhost:3333/mcp",
      "headers": {
        "Authorization": "Bearer glpat-..."
      }
    }
  }
}
Using MCP OAuth Proxy (GITLAB_MCP_OAUTH)

For server/remote deployments only. This mode requires the MCP server to be deployed with a publicly accessible HTTPS URL. For local/desktop use, see GITLAB_USE_OAUTH above.

For remote MCP clients that support the MCP OAuth specification (e.g. Claude.ai). The server acts as a full OAuth 2.0 authorization server — unauthenticated requests receive a 401 + WWW-Authenticate response, which triggers the OAuth browser flow automatically on the client side.

Remote MCP clients such as OpenCode, MCPJam, and Claude.ai can send their own callback URL during authorization. If you cannot register every client callback URL in GitLab, enable GITLAB_OAUTH_CALLBACK_PROXY=true. With callback proxy mode, GitLab only needs one registered redirect URI: {MCP_SERVER_URL}/callback.

GITLAB_OAUTH_REDIRECT_URI is for local OAuth (GITLAB_USE_OAUTH) only. It does not override remote MCP OAuth client callback URLs and should not be used to fix remote Unregistered redirect_uri errors.

This variable exists because the local OAuth flow starts a browser on the same machine as the MCP server and listens for the callback on a local HTTP server, for example http://127.0.0.1:8888/callback.

Remote MCP OAuth is different. In GITLAB_MCP_OAUTH=true mode, the MCP client provides its own callback URL during /authorize. GITLAB_OAUTH_REDIRECT_URI does not replace that client-provided URL.

ModeEnable withCallback variableGitLab redirect URI
Local OAuthGITLAB_USE_OAUTH=trueGITLAB_OAUTH_REDIRECT_URIhttp://127.0.0.1:8888/callback or your local callback
Remote MCP OAuthGITLAB_MCP_OAUTH=trueGITLAB_OAUTH_CALLBACK_PROXY=true{MCP_SERVER_URL}/callback

Use GITLAB_OAUTH_REDIRECT_URI only when the MCP server itself owns the local browser callback. Use GITLAB_OAUTH_CALLBACK_PROXY=true when a remote MCP client owns the callback URL.

How it works: You deploy this MCP server somewhere with a public HTTPS URL. MCP clients connect to {MCP_SERVER_URL}/mcp. The server handles the OAuth 2.0 flow, exchanging credentials with GitLab on behalf of the client.

Prerequisites:

  1. A publicly accessible HTTPS server URL (MCP_SERVER_URL) — use ngrok for local testing
  2. A pre-registered GitLab OAuth application with api (or read_api) scopes — Go to Admin area → Applications, set Redirect URI to {MCP_SERVER_URL}/callback
Environment VariableRequiredDescription
GITLAB_MCP_OAUTH✅Set to true to enable
GITLAB_API_URL✅GitLab API base URL
GITLAB_OAUTH_APP_ID✅GitLab OAuth Application ID
MCP_SERVER_URL✅Public HTTPS URL of this MCP server
STREAMABLE_HTTP✅Must be true
GITLAB_OAUTH_CALLBACK_PROXYoptionalSet to true to use the MCP server's fixed /callback URL
GITLAB_OAUTH_ALLOWED_REDIRECT_URISoptionalClient callback URLs that callback proxy mode will redirect to (default: Claude, ChatGPT, Cursor and loopback callbacks; defaults,<url> to add one)
GITLAB_OAUTH_SCOPESoptionalComma-separated scopes (default: api,read_api,read_user)
GITLAB_OAUTH_ALLOWED_GROUPSoptionalComma-separated group full paths — only members (and subgroup members) may use the server (replaces deprecated GITLAB_ALLOWED_GROUPS)

When STREAMABLE_HTTP=true, server-side GitLab credentials (GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_JOB_TOKEN, GITLAB_AUTH_COOKIE_PATH, or GITLAB_USE_OAUTH) require REMOTE_AUTHORIZATION=true, GITLAB_MCP_OAUTH=true, or STREAMABLE_HTTP_AUTH_TOKEN.

Troubleshooting Unregistered redirect_uri

Check the redirect_uri in the browser URL. If it points to a client callback such as http://127.0.0.1:xxxxx/.../callback, enable:

GITLAB_OAUTH_CALLBACK_PROXY=true

Do not fix remote MCP OAuth by changing GITLAB_OAUTH_REDIRECT_URI. That variable is for local OAuth (GITLAB_USE_OAUTH) only.

docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e GITLAB_MCP_OAUTH=true \
  -e GITLAB_OAUTH_CALLBACK_PROXY=true \
  -e STREAMABLE_HTTP=true \
  -e MCP_SERVER_URL=https://your-server.example.com \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_OAUTH_APP_ID=your_app_id \
  -p 3000:3002 \
  zereight050/gitlab-mcp

MCP client configuration:

{
  "mcpServers": {
    "gitlab": {
      "type": "http",
      "url": "https://your-server.example.com/mcp"
    }
  }
}
Using Remote Authorization (REMOTE_AUTHORIZATION)

For server/remote deployments only. Each HTTP caller provides their own GitLab token directly in request headers — no OAuth flow involved.

For multi-user or multi-tenant deployments where each caller provides their own GitLab token in the HTTP request header. No OAuth flow — the MCP server forwards the token to GitLab on behalf of the caller.

Header priority: Private-Token > JOB-TOKEN > Authorization: Bearer

Environment VariableRequiredDescription
REMOTE_AUTHORIZATION✅Set to true to enable
STREAMABLE_HTTP✅Must be true
ENABLE_DYNAMIC_API_URLoptionalAllow per-request GitLab URL via X-GitLab-API-URL header
GITLAB_ALLOWED_HOSTSoptionalComma-separated allowed X-GitLab-API-URL hosts; GITLAB_API_URL hosts are always allowed. Also trusted as download redirect targets (release assets, job artifacts, uploaded attachments); list private-network hosts here
GITLAB_ALLOW_UNAUTHENTICATED_TOOL_DISCOVERYoptionalAllow unauthenticated initialize, notifications/initialized, tools/list, and server/discover only (tool calls still require auth)
MCP_SERVER_URL / MCP_ALLOWED_HOSTS / MCP_ALLOWED_ORIGINSoptionalAllowed public /mcp host/origin values for DNS rebinding protection
MCP_TRUST_PROXYoptionalTrust Forwarded / X-Forwarded-* headers behind a reverse proxy (download URLs, Express req.ip, /mcp IP rate limits, OAuth rate limits)

GITLAB_ALLOW_UNAUTHENTICATED_TOOL_DISCOVERY=true is intended for MCP gateways or admin UIs that need to inspect tool metadata before a user provides a GitLab token. Leave it disabled unless the tool list is safe to expose in your deployment.

When MCP_SERVER_URL is not set, remote download URLs fall back to the local server address. Set MCP_TRUST_PROXY=true only if the server is reachable through a trusted reverse proxy and direct client access to the MCP server is blocked. This enables Express trust proxy for Streamable HTTP and SSE, derives public download URLs from Forwarded / X-Forwarded-Proto / X-Forwarded-Host / X-Forwarded-Prefix, and keeps OAuth endpoint rate limiting working when proxies send X-Forwarded-For with a client port (for example 1.2.3.4:5678). Existing OAuth+proxy deployments must set this explicitly after the flag was introduced.

Example request headers:

Private-Token: glpat-xxxxxxxxxxxxxxxxxxxx

or using a Bearer token:

Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx

⚠️ REMOTE_AUTHORIZATION is not compatible with SSE transport. STREAMABLE_HTTP=true is required.

Environment Variables

Use the dedicated reference for the full environment variable list:

Most users only need one of these starting sets:

  • Local PAT: GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_API_URL
  • Local OAuth: GITLAB_USE_OAUTH=true, GITLAB_OAUTH_CLIENT_ID, GITLAB_OAUTH_REDIRECT_URI, GITLAB_API_URL
  • Remote multi-user HTTP: STREAMABLE_HTTP=true, REMOTE_AUTHORIZATION=true (or GITLAB_MCP_OAUTH=true), MCP_TRUST_PROXY=true (behind a reverse proxy), MAX_REQUESTS_PER_MINUTE=300, MCP_SERVER_URL or MCP_ALLOWED_HOSTS, HOST, PORT
  • Multiple side-by-side deployments: set a distinct MCP_SERVER_NAME per instance (e.g. gitlab-selfhosted-readonly) so clients, logs, and telemetry can tell them apart
  • Multi-pod HPA (stateless): above + OAUTH_STATELESS_MODE=true, OAUTH_STATELESS_SECRET (same across all pods). See Stateless Mode.

Commonly referenced variables:

  • GITLAB_API_URL
  • GITLAB_PERSONAL_ACCESS_TOKEN
  • GITLAB_USE_OAUTH
  • REMOTE_AUTHORIZATION
  • MCP_TRUST_PROXY
  • MAX_REQUESTS_PER_MINUTE
  • MAX_SESSIONS
  • MCP_ALLOWED_HOSTS
  • MCP_ALLOWED_ORIGINS
  • GITLAB_MCP_OAUTH
  • GITLAB_OAUTH_CALLBACK_PROXY
  • GITLAB_OAUTH_ALLOWED_REDIRECT_URIS
  • OAUTH_REGISTER_RATE_LIMIT_PER_HOUR
  • OAUTH_STATELESS_MODE
  • OAUTH_STATELESS_SECRET

The reference document also covers:

  • auth and OAuth variables
  • MCP OAuth proxy variables
  • project and tool filtering variables
  • dynamic tool discovery via discover_tools (on-demand toolset activation)
  • transport and session variables
  • proxy and TLS variables

For callback proxy mode details, see GitLab MCP OAuth Callback Proxy.

SSE session limits

GET /sse is subject to the same remote-transport controls as Streamable HTTP:

  • Capacity: at most MAX_SESSIONS concurrent SSE sessions (default 1000); further connections get 503.
  • Creation rate limit: new connections are limited to MAX_REQUESTS_PER_MINUTE per client IP (default 60); excess connections get 429.
  • Idle timeout: a session that receives no POST /messages request for SESSION_TIMEOUT_SECONDS (default 1 hour) is closed, so an idle client must reconnect instead of holding a capacity slot. Unlike Streamable HTTP, holding the SSE stream open does not count as activity.
  • /health returns 503 with status: "degraded" while the instance is at capacity.

Tune these with MAX_SESSIONS, MAX_REQUESTS_PER_MINUTE, and SESSION_TIMEOUT_SECONDS.

Remote Authorization Setup (Multi-User Support)

When using REMOTE_AUTHORIZATION=true, the MCP server can support multiple users, each with their own GitLab token passed via HTTP headers. This is useful for:

  • Shared MCP server instances where each user needs their own GitLab access
  • IDE integrations that can inject user-specific tokens into MCP requests

Setup Example:

# Start server with remote authorization
docker run -d \
  -e HOST=0.0.0.0 \
  -e STREAMABLE_HTTP=true \
  -e REMOTE_AUTHORIZATION=true \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e SESSION_TIMEOUT_SECONDS=3600 \
  -p 3333:3002 \
  zereight050/gitlab-mcp

Client Configuration:

Your IDE or MCP client must send one of these headers with each request:

Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx

or

Private-Token: glpat-xxxxxxxxxxxxxxxxxxxx

The token is stored per session (identified by mcp-session-id header) and reused for subsequent requests in the same session.

Remote Authorization Client Configuration Example with Cursor
{
  "mcpServers": {
    "GitLab": {
      "url": "http(s)://<your_mcp_gitlab_server>/mcp",
      "headers": {
        "Authorization": "Bearer glpat-..."
      }
    }
  }
}

Important Notes:

  • Remote authorization only works with Streamable HTTP transport
  • Each session is isolated - tokens from one session cannot access another session's data Tokens are automatically cleaned up when sessions close
  • Session timeout: Auth tokens expire after SESSION_TIMEOUT_SECONDS (default 1 hour) of inactivity. After timeout, the client must send auth headers again. The transport session remains active.
  • Each request resets the timeout timer for that session
  • Rate limiting: /mcp requests are limited to MAX_REQUESTS_PER_MINUTE per client IP, and per MCP session when using OAuth or remote authorization (default 60). See environment-variables.md.
  • Capacity limit: Server accepts up to MAX_SESSIONS concurrent sessions (default 1000)

MCP OAuth Setup (Claude.ai Native OAuth)

When using GITLAB_MCP_OAUTH=true, the server acts as an OAuth proxy to your GitLab instance. Claude.ai (and any MCP-spec-compliant client) handles the entire browser authentication flow automatically — no manual Personal Access Token management needed.

Prerequisites:

A pre-registered GitLab OAuth application is required. GitLab restricts dynamically registered (unverified) applications to the mcp scope, which is insufficient for API calls (need api or read_api).

  1. Go to your GitLab instance → Admin Area > Applications (instance-wide) or User Settings > Applications (personal)
  2. Create a new application with:
    • Confidential: unchecked
    • Scopes: api, read_api, read_user (or whichever scopes you intend to request via GITLAB_OAUTH_SCOPES)
  3. Save and copy the Application ID — this is your GITLAB_OAUTH_APP_ID

How it works:

  1. User adds your MCP server URL in Claude.ai
  2. Claude.ai discovers OAuth endpoints via /.well-known/oauth-authorization-server
  3. Claude.ai registers itself via Dynamic Client Registration (POST /register) — handled locally by the MCP server (each client gets a virtual client ID)
  4. Claude.ai redirects the user's browser to GitLab's login page using the pre-registered OAuth application
  5. User authenticates; GitLab redirects back to https://claude.ai/api/mcp/auth_callback
  6. Claude.ai sends Authorization: Bearer <token> on every MCP request
  7. Server validates the token with GitLab and stores it per session

Server setup:

docker run -d \
  -e STREAMABLE_HTTP=true \
  -e GITLAB_MCP_OAUTH=true \
  -e GITLAB_OAUTH_APP_ID="your-gitlab-oauth-app-client-id" \
  -e GITLAB_API_URL="https://gitlab.example.com/api/v4" \
  -e MCP_SERVER_URL="https://your-mcp-server.example.com" \
  -p 3002:3002 \
  zereight050/gitlab-mcp

For local development (HTTP allowed):

MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=true \
STREAMABLE_HTTP=true \
GITLAB_MCP_OAUTH=true \
GITLAB_OAUTH_APP_ID=your-gitlab-oauth-app-client-id \
MCP_SERVER_URL=http://localhost:3002 \
GITLAB_API_URL=https://gitlab.com/api/v4 \
node build/index.js

Claude.ai configuration:

{
  "mcpServers": {
    "GitLab": {
      "url": "https://your-mcp-server.example.com/mcp"
    }
  }
}

No headers field is needed — Claude.ai obtains the token via OAuth automatically.

Environment variables:

VariableRequiredDescription
GITLAB_MCP_OAUTHYesSet to true to enable
GITLAB_OAUTH_APP_IDYesClient ID of the pre-registered GitLab OAuth application
MCP_SERVER_URLYesPublic HTTPS URL of your MCP server; also allowed for /mcp Host/Origin checks
GITLAB_API_URLYesYour GitLab instance API URL (e.g. https://gitlab.com/api/v4)
STREAMABLE_HTTPYesMust be true (SSE is not supported)
GITLAB_OAUTH_SCOPESNoComma-separated GitLab scopes to request (e.g. api,read_user). Defaults to api (or read_api when the effective permission mode is readonly). The pre-registered application must be configured with at least these scopes.
OAUTH_REGISTER_RATE_LIMIT_PER_HOURNoPer-IP rolling limit for Dynamic Client Registration (POST /register). Default 20/hour; range 1–1000. Raise when clients (e.g. multiple IDE windows) hit registration throttling. Not a GitLab API limit.
MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URLNoSet true for local HTTP dev only

Important Notes:

Documentation truncated — see the full README on GitHub.

Reviews

No reviews yet

Be the first to review this server!