Skip to main content
Glama

GitLab MCP Server

GitHub stars npm downloads npm GitHub License Ask DeepWiki MCP Toplist mcpindex

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

📖 Documentation → · llms.txt · llms-full.txt

Default: 40 tools (38 core + discover_tools + help). 288 tools exist in total (285 in toolsets + execute_graphql + discover_tools + help). Start lean; call discover_tools to activate more for this session.

Token budget: MCP clients send the whole tools/list to the model at session start. Keep the default (~40 tools, ~12k schema tokens). Call discover_tools to activate a category for this session (session-only; with OAUTH_STATELESS_MODE=true persist a named GITLAB_TOOLSETS list), or use Skill + CLI and skip MCP schemas. Do not set GITLAB_TOOLSETS=all — it loads ~all tools and costs ~73k schema tokens. See tools/list size and comparison.

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. Official MCP Registry listing: io.github.zereight/gitlab-mcp. One-liner: npx -y @zereight/mcp-gitlab@latest.

Without → With

Without this MCP

With this MCP

Paste MR URLs and diffs into chat

list_merge_request_changed_files → batched get_merge_request_file_diff

Hunt job logs in the GitLab UI

get_pipeline_job_output with pagination

Re-explain the project path every turn

project_id=group%2Fproject and merge_request_iid=123

Three install paths

Path

When

How

Local IDE

Cursor, Claude Code, Codex on your machine

stdio + PAT or local OAuth

Shared HTTP

Team or hosted MCP

Streamable HTTP URL + remote auth or MCP OAuth

Claude.ai

Claude web connectors

Public HTTPS + GITLAB_MCP_OAUTH

Install

Install in Cursor

Install the binary first (npm install -g @zereight/mcp-gitlab, or Homebrew brew tap zereight/gitlab-mcp https://github.com/zereight/gitlab-mcp then brew install zereight/gitlab-mcp/zereight-mcp-gitlab). Read the token without echo:

read -rs GITLAB_PERSONAL_ACCESS_TOKEN && export GITLAB_PERSONAL_ACCESS_TOKEN
# Claude Code
claude 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

# Codex
codex mcp add gitlab --env GITLAB_PERSONAL_ACCESS_TOKEN="$GITLAB_PERSONAL_ACCESS_TOKEN" --env GITLAB_API_URL=https://gitlab.com/api/v4 -- zereight-mcp-gitlab

Other clients: VS Code · GitHub Copilot · JSON clients · Cursor details

Agent paste-prompt

Copy this into an agent that can edit MCP config:

Install the GitLab MCP server (@zereight/mcp-gitlab) for this workspace.
Binary: zereight-mcp-gitlab (npm i -g @zereight/mcp-gitlab, or npx -y @zereight/mcp-gitlab@latest).
Auth: GITLAB_PERSONAL_ACCESS_TOKEN plus GITLAB_API_URL=https://gitlab.com/api/v4 (or GITLAB_USE_OAUTH=true).
Local: claude 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
Or: codex mcp add gitlab --env GITLAB_PERSONAL_ACCESS_TOKEN="$GITLAB_PERSONAL_ACCESS_TOKEN" --env GITLAB_API_URL=https://gitlab.com/api/v4 -- zereight-mcp-gitlab
Cursor: use the README deeplink or docs/clients/cursor.md.
Remote HTTP: point the client at https://mcp.example.com/mcp (Streamable HTTP). Claude.ai needs GITLAB_MCP_OAUTH on that host.
Default list: 40 tools (38 core + discover_tools + help). Call discover_tools to expand. Do not set GITLAB_TOOLSETS=all (loads ~all schemas, ~73k tokens). Do not enable the api toolset unless you accept its bypass risk.
Equal non-MCP path: npx skills add zereight/gitlab-mcp --skill gitlab-mcp-skill plus the zereight-mcp-gitlab CLI.

Remote HTTP

First-class option for a hosted or self-hosted server. Point the client at a Streamable HTTP URL:

{
  "mcpServers": {
    "gitlab": {
      "type": "http",
      "url": "https://mcp.example.com/mcp"
    }
  }
}
  • Hosted / Claude.ai: GITLAB_MCP_OAUTH=true on the server (see MCP OAuth)

  • Per-user PAT headers: REMOTE_AUTHORIZATION=true (see Remote Authorization)

  • Local Docker examples are in Usage

Skill + CLI (no MCP required)

Skill + CLI is an equal path, not a fallback. Same workflows, full payloads in a terminal, no MCP registration.

npx skills add zereight/gitlab-mcp --skill gitlab-mcp-skill
zereight-mcp-gitlab user whoami
zereight-mcp-gitlab mr list

See CLI without MCP and skills/gitlab-mcp/.

MCP vs Human CLI

Use MCP when

Use the CLI when

The agent needs structured tools in chat

You need the full payload (diffs, logs, artifacts)

jmespath or compact results are enough

GITLAB_MCP_COMPACT_RESULTS is on and you want the rest in a terminal

You already registered the server

You have a PAT or ran auth and do not want MCP

Human CLI is never compacted. Destructive tools and GITLAB_TOOL_POLICY_APPROVE tools need --yes.

Tips

project_id is a numeric ID or a URL-encoded path. Example: group group, project project, merge request !123 → project_id=group%2Fproject, merge_request_iid=123. Nested groups use %2F between every segment (group%2Fsubgroup%2Fproject).

FAQ

How do I authenticate? Local desktop: GITLAB_PERSONAL_ACCESS_TOKEN (or GITLAB_PERSONAL_ACCESS_TOKEN_FILE) is the simplest. Local OAuth is GITLAB_USE_OAUTH=true. Remote Claude.ai uses GITLAB_MCP_OAUTH. Multi-user HTTP uses REMOTE_AUTHORIZATION and a per-request token header.

Why do I only see ~40 tools? The default core toolset is 38 tools plus always-on discover_tools and help. That is intentional: a client sends every listed schema to the model up front. Call discover_tools with no args to list categories, then pass a category (pipelines, wiki, …) to activate it for this session. Session-only; with OAUTH_STATELESS_MODE=true persist a named GITLAB_TOOLSETS list. Do not set GITLAB_TOOLSETS=all — it loads ~all schemas (~73k tokens) and still does not enable api.

Local OAuth vs MCP OAuth vs remote auth? Local OAuth opens a browser on the same machine as the server. MCP OAuth is for a public HTTPS server and clients such as Claude.ai. Remote authorization forwards the caller's PAT or job token; there is no OAuth dance.

How do I shrink huge replies? Pass jmespath on any tool call. Or set GITLAB_MCP_COMPACT_RESULTS=true so oversized MCP replies become a preview plus a CLI command. Use the CLI when you need the full payload.

Why is the api toolset dangerous? gitlab_api_request bypasses group/project allowlists, other tool filters, and per-tool safety checks. Prompt injection can drive it. Enable it only by listing api in GITLAB_TOOLSETS. all, discover_tools, and GITLAB_TOOLS do not.

Cursor rule / CLAUDE.md snippet

GitLab merge requests, issues, and pipelines go through this MCP (@zereight/mcp-gitlab).
Start with the default core tools. Call discover_tools to expand. Do not set GITLAB_TOOLSETS=all.
Prefer list_merge_request_changed_files, then batched get_merge_request_file_diff.
Use jmespath or compact results; use the CLI for full diffs and job logs.

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?

  • Default 40 tools (38 core + discover_tools + help); 288 total — start lean; call discover_tools to activate more without CQRS-style grouping. GITLAB_TOOLSETS=all loads ~all schemas (~73k tokens); prefer discover-on-demand or Skill + CLI

  • 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-gitlab

GitLab MCP A (community CQRS-style)

GitLab official MCP server

Best for

AI agent workflows

Enterprise multi-instance / grouped tools

Built into GitLab, no separate install

Tool model

288 tools: 285 in toolsets + execute_graphql + discover_tools + help

~50–60 grouped browse_* / manage_* tools

Toolsets chosen with an HTTP header

MR review

2-step batched diff

Varies

get_merge_request with diffs

Node.js

>=20.0.0

Often >=24

Node.js 20+ for stdio via mcp-remote

License

MIT

Varies

Part of GitLab

tools/list size (measured 2026-11-05)

A client sends the whole tools/list result to the model at session start. Token estimate is UTF-8 bytes / 4.

Profile

Tools

JSON bytes

Est. tokens

Default (core + discover_tools + help)

40

46,943

11,736

GITLAB_TOOL_PROFILE=slim

39

45,935

11,484

GITLAB_TOOLSETS=all

286

293,906

73,477

Re-measure with npm run build && npm run test:mock (test/tools-list-budget.test.ts) after description or schema changes.

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.

Full comparison with the official GitLab MCP server →

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

Related MCP server: gitlab-mcp

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.21. If you always want the newest release, use npx -y @zereight/mcp-gitlab@latest instead. To try a fix merged to main before the next stable release, use npx -y @zereight/mcp-gitlab@next, a pre-release build that is not meant for production. The server prints a notice to stderr on startup when a newer version is available (disable with GITLAB_DISABLE_VERSION_CHECK=true).

Claude Desktop one-click install (MCP Bundle)

Every GitHub release after v2.3.1 ships a gitlab-mcp.mcpb MCP Bundle. Download the latest bundle and open it with Claude Desktop (or drag it into Settings → Extensions). Claude Desktop asks for your Personal Access Token (stored as a sensitive value) and lets you set GITLAB_API_URL, GITLAB_PERMISSION_MODE, GITLAB_TOOLSETS, and GITLAB_MASKING_ENABLED. No separate Node.js or npm install is needed.

To build the bundle from source, run npm run pack:mcpb (writes gitlab-mcp.mcpb).

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 - Named toolsets (replaces GITLAB_TOOLSETS; unset uses the lean core default). Do not pass all unless you accept ~73k schema tokens. 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 and download_job_artifacts save 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)

  • --list-summary-default=true - list_* tools and mr_discussions treat an omitted summary argument as true; summary: false still returns the full JSON (replaces GITLAB_MCP_LIST_SUMMARY_DEFAULT; default off)

  • --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. setup --cursor / setup --claude prints client config; doctor checks token, API URL, toolsets, and version. 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). With GITLAB_ALLOWED_PROJECT_IDS or a session project scope, only /projects/:id paths for an allowed project are accepted. Endpoints such as /search, /users, /groups/:id, and /runners are rejected. Body and query parameters that name another project are not checked. 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.

Mode

Enable with

Callback variable

GitLab redirect URI

Local OAuth

GITLAB_USE_OAUTH=true

GITLAB_OAUTH_REDIRECT_URI

http://127.0.0.1:8888/callback or your local callback

Remote MCP OAuth

GITLAB_MCP_OAUTH=true

GITLAB_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 Variable

Required

Description

GITLAB_MCP_OAUTH

✅

Set to true to enable

GITLAB_API_URL

✅

GitLab API base URL. Do not embed credentials (user:pass@) in the URL; they are ignored. A comma in a password must be written as %2C.

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_PROXY

optional

Set to true to use the MCP server's fixed /callback URL

GITLAB_OAUTH_ALLOWED_REDIRECT_URIS

optional

Client callback URLs that callback proxy mode will redirect to (default: Claude, ChatGPT, Cursor and loopback callbacks; defaults,<url> to add one)

GITLAB_OAUTH_SCOPES

optional

Comma-separated scopes (default: api,read_api,read_user)

GITLAB_OAUTH_ALLOWED_GROUPS

optional

Comma-separated group full paths — only members (and subgroup members) may use the server (replaces deprecated GITLAB_ALLOWED_GROUPS)

OAUTH_DISABLE_REFRESH_TOKEN

optional

Set to true to issue no refresh tokens: users re-authorize in the browser each time the GitLab access token expires (2 h), regardless of the session TTL

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 Variable

Required

Description

REMOTE_AUTHORIZATION

✅

Set to true to enable

STREAMABLE_HTTP

✅

Must be true

ENABLE_DYNAMIC_API_URL

optional

Allow per-request GitLab URL via X-GitLab-API-URL header

GITLAB_ALLOWED_HOSTS

optional

Comma-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_DISCOVERY

optional

Allow unauthenticated initialize, notifications/initialized, tools/list, and server/discover only (tool calls still require auth)

MCP_SERVER_URL / MCP_ALLOWED_HOSTS / MCP_ALLOWED_ORIGINS

optional

Allowed public /mcp host/origin values for DNS rebinding protection

MCP_TRUST_PROXY

optional

Trust 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_DISABLE_REFRESH_TOKEN

  • 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.

Streamable HTTP session timeout

Streamable HTTP sessions use the same SESSION_TIMEOUT_SECONDS idle timeout in every mode, including a server-side token without REMOTE_AUTHORIZATION or GITLAB_MCP_OAUTH: a session with no POST /mcp request for that long is closed, and its next request gets 404 so the client re-initializes. An open GET /mcp stream pauses the timer until the stream closes or the next POST /mcp arrives, so a client with a stream open still expires SESSION_TIMEOUT_SECONDS after its last POST.

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. The session belongs to the GitLab user of that token: a request with another user's token gets 404 Session not found, and GET / DELETE /mcp without a token get 401.

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 session is closed and its next request gets 404, so the client re-initializes with its auth headers.

  • 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). The per-IP limit uses a fixed 60-second window, counts per server process, and also covers GET /mcp; stateless mode skips the per-session limit. 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:

Variable

Required

Description

GITLAB_MCP_OAUTH

Yes

Set to true to enable

GITLAB_OAUTH_APP_ID

Yes

Client ID of the pre-registered GitLab OAuth application

MCP_SERVER_URL

Yes

Public HTTPS URL of your MCP server; also allowed for /mcp Host/Origin checks

GITLAB_API_URL

Yes

Your GitLab instance API URL (e.g. https://gitlab.com/api/v4). Do not embed credentials (user:pass@) in the URL; they are ignored. A comma in a password must be written as %2C.

STREAMABLE_HTTP

Yes

Must be true (SSE is not supported)

GITLAB_OAUTH_SCOPES

No

Comma-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_HOUR

No

Per-IP limit (fixed 1-hour window) 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.

OAUTH_DISABLE_REFRESH_TOKEN

No

Set true to drop refresh_token from /token responses and reject the refresh grant with invalid_grant, so users re-authorize in the browser when the GitLab access token expires. Default false. In callback proxy mode, MCP clients that follow this server's flow never receive a GitLab refresh token (in passthrough the client can get one from GitLab directly). This is a re-authorization policy for standard MCP clients, not a security boundary. Refresh tokens issued before enabling stay valid until revoked in GitLab under User Settings → Applications → Authorized applications → Revoke.

MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL

No

Set true for local HTTP dev only

Important Notes:

  • MCP OAuth only works with Streamable HTTP transport (SSE=true is incompatible)

  • Each user session stores its own OAuth token — sessions are fully isolated

  • Session timeout, rate limiting, and capacity limits apply identically to the REMOTE_AUTHORIZATION mode (SESSION_TIMEOUT_SECONDS, MAX_REQUESTS_PER_MINUTE, MAX_SESSIONS)

  • DCR rate limiting: POST /register is limited to OAUTH_REGISTER_RATE_LIMIT_PER_HOUR per client IP (default 20/hour). Separate from /mcp limits and GitLab API quotas. See environment-variables.md.

  • Header auth fallback: when Private-Token or JOB-TOKEN request headers are present, OAuth validation is skipped and the raw token is used directly for that session. This allows PATs and CI job tokens to be used alongside the OAuth flow on the same server instance. Authorization: Bearer is always treated as an OAuth token — use Private-Token for PAT-based header auth.

Agent Skill Files

Skill + CLI is an equal path to MCP (see Skill + CLI). Pre-built skill files are available in skills/gitlab-mcp/ for AI agents that support skill/instruction loading (Claude Code, GitHub Copilot, Cursor, etc.).

  • SKILL.md — Core guide (~800 tokens) with toolset overview, key workflows, and parameter hints

  • reference/ — Detailed workflow docs for code review, merge requests, issues, pipelines, and vulnerability triage

Install with the skills CLI:

npx skills add zereight/gitlab-mcp --skill gitlab-mcp-skill

Register the skill directory in your AI client to get optimal tool usage guidance without relying solely on the full ListTools response.

Tools 🛠️

  1. merge_merge_request - Merge a merge request

  2. approve_merge_request - Approve a merge request

  3. unapprove_merge_request - Unapprove a merge request

  4. get_merge_request_approval_state - Get merge request approval details including approvers

  5. get_merge_request_conflicts - Get the conflicts of a merge request

  6. list_merge_request_pipelines - List pipelines for a merge request with pagination

  7. execute_graphql - Execute a GitLab GraphQL query

  8. create_or_update_file - Create or update a file in a GitLab project

  9. search_repositories - Search for GitLab projects

  10. create_repository - Create a new GitLab project

  11. create_group - Create new group or subgroup

  12. get_file_contents - Get contents of a file or directory from a GitLab project

  13. push_files - Push multiple files in a single commit

  14. create_issue - Create a new issue

  15. create_merge_request - Create a new merge request

  16. fork_repository - Fork a project to your account or specified namespace

  17. create_branch - Create a new branch

  18. get_branch - Get branch details (commit, protection status)

  19. list_branches - List branches in project with search filter

  20. delete_branch - Delete branch from project

  21. list_protected_branches - List protected branches in a project, supports search filter

  22. get_protected_branch - Get details of a single protected branch (access levels, force push settings)

  23. protect_branch - Protect a repository branch (set push/merge/unprotect access levels)

  24. update_protected_branch - Update an existing protected branch rule in place (access levels, force push, code owner approval)

  25. unprotect_branch - Remove protection from a previously protected branch

  26. update_default_branch - Change the default branch of a project

  27. get_merge_request - Get details of a merge request (merge_request_iid or source_branch required). Set include_summaries=true for deployment/commit/approval summaries

  28. get_merge_request_diffs - Get the changes/diffs of a merge request (merge_request_iid or source_branch required)

  29. list_merge_request_changed_files - List changed file paths in a merge request without diff content (merge_request_iid or source_branch required)

  30. list_merge_request_diffs - List merge request diffs with pagination (merge_request_iid or source_branch required)

  31. get_merge_request_file_diff - Get diffs for specific files from a merge request (merge_request_iid or source_branch required)

  32. list_merge_request_versions - List all versions of a merge request

  33. get_merge_request_version - Get a specific version of a merge request

  34. get_branch_diffs - Get diffs between two branches or commits

  35. update_merge_request - Update a merge request (merge_request_iid or source_branch required)

  36. create_note - Create a new note (comment) to an issue or merge request

  37. create_merge_request_thread - Create a new thread on a merge request

  38. resolve_merge_request_thread - Resolve a thread on a merge request

  39. mr_discussions - List discussion items for a merge request

  40. get_merge_request_discussion - Get a single discussion item for a merge request

  41. delete_merge_request_discussion_note - Delete a discussion note on a merge request

  42. update_merge_request_discussion_note - Update a discussion note on a merge request

  43. create_merge_request_discussion_note - Add a new discussion note to an existing merge request thread

  44. create_merge_request_note - Add a new note to a merge request

  45. delete_merge_request_note - Delete an existing merge request note

  46. get_merge_request_note - Get a specific note for a merge request

  47. get_merge_request_notes - List notes for a merge request

  48. update_merge_request_note - Modify an existing merge request note

  49. get_draft_note - Get a single draft note from a merge request

  50. list_draft_notes - List draft notes for a merge request

  51. create_draft_note - Create a draft note for a merge request

  52. update_draft_note - Update an existing draft note

  53. delete_draft_note - Delete a draft note

  54. publish_draft_note - Publish a single draft note

  55. bulk_publish_draft_notes - Publish all draft notes for a merge request. Optionally sets reviewer_state and posts a summary note (GitLab 19.2+). Can set reviewer_state even with no drafts.

  56. list_merge_request_emoji_reactions - List all emoji reactions on a merge request

  57. list_merge_request_note_emoji_reactions - List all emoji reactions on a merge request note. Pass discussion_id for discussion thread replies.

  58. create_merge_request_emoji_reaction - Add an emoji reaction to a merge request (e.g. thumbsup, rocket, eyes)

  59. delete_merge_request_emoji_reaction - Remove an emoji reaction from a merge request

  60. create_merge_request_note_emoji_reaction - Add an emoji reaction to a merge request note. Pass discussion_id for discussion thread replies.

  61. delete_merge_request_note_emoji_reaction - Remove an emoji reaction from a merge request note. Pass discussion_id for discussion thread replies.

  62. update_issue_note - Modify an existing issue thread note

  63. create_issue_note - Add a note to an issue, optionally replying to a discussion thread

  64. list_issue_emoji_reactions - List all emoji reactions on an issue

  65. list_issue_note_emoji_reactions - List all emoji reactions on an issue note. Pass discussion_id for discussion thread replies.

  66. create_issue_emoji_reaction - Add an emoji reaction to an issue (e.g. thumbsup, rocket, eyes)

  67. delete_issue_emoji_reaction - Remove an emoji reaction from an issue

  68. create_issue_note_emoji_reaction - Add an emoji reaction to an issue note. Pass discussion_id for discussion thread replies.

  69. delete_issue_note_emoji_reaction - Remove an emoji reaction from an issue note. Pass discussion_id for discussion thread replies.

  70. list_issues - List issues (default: created by current user; use scope='all' for all)

  71. my_issues - List issues assigned to the authenticated user

  72. get_issue - Get one issue. Slim nested milestone by default; full_response=true for the complete milestone

  73. update_issue - Update an issue. Slim confirmation by default; full_response=true for the complete object

  74. update_issue_description_patch - Patch an issue description (search/replace or unified diff) without resending the full body. dry_run previews; create_note summarizes

  75. reorder_issue - Move an issue within the manual sort order shown on issue boards. move_after_id and move_before_id take the neighbor issue's global id (the id field), not its iid; pass at least one. Returns the reordered issue.

  76. delete_issue - Delete an issue

  77. list_todos - List GitLab to-do items for the current user

  78. mark_todo_done - Mark a GitLab to-do item as done

  79. mark_all_todos_done - Mark all pending GitLab to-do items as done for the current user

  80. list_issue_links - List all issue links for a specific issue

  81. list_issue_discussions - List discussions for an issue

  82. get_issue_link - Get a specific issue link

  83. create_issue_link - Create an issue link between two issues

  84. delete_issue_link - Delete an issue link

  85. list_namespaces - List all namespaces (users and groups) available to the current user. Filter by kind='group' for groups only.

  86. get_namespace - Get details of a namespace (user or group) by ID or path. Groups are namespaces with kind='group'.

  87. verify_namespace - Verify if a namespace path exists. Use parent_id to scope the check to a specific parent namespace — required for nested namespaces where the same path may exist under different parents.

  88. get_project - Get details of a specific project

  89. list_projects - List projects accessible by the current user

  90. update_project - Update project settings such as description, visibility, default branch, and feature access levels

  91. list_project_members - List members of a GitLab project

  92. list_group_members - List members of a GitLab group with optional name or username search

  93. list_labels - List labels for a project

  94. get_label - Get a single label from a project

  95. create_label - Create a new label in a project

  96. update_label - Update an existing label in a project

  97. delete_label - Delete a label from a project

  98. list_group_projects - List projects in a group

  99. list_wiki_pages - List wiki pages in a project

  100. get_wiki_page - Get details of a specific wiki page

  101. create_wiki_page - Create a wiki page in a project

  102. update_wiki_page - Update a wiki page in a project

  103. delete_wiki_page - Delete a wiki page from a project

  104. list_group_wiki_pages - List wiki pages in a group

  105. get_group_wiki_page - Get details of a specific group wiki page

  106. create_group_wiki_page - Create a wiki page in a group

  107. update_group_wiki_page - Update a wiki page in a group

  108. delete_group_wiki_page - Delete a wiki page from a group

  109. get_repository_tree - List files and directories in a repository

  110. list_pipelines - List pipelines with filtering options

  111. get_pipeline - Get details of a specific pipeline

  112. get_pipeline_variables - Get variables configured for a pipeline

  113. get_pipeline_test_report - Get pipeline test report

  114. get_pipeline_test_report_summary - Get pipeline test report summary

  115. delete_pipeline - Delete a pipeline. Requires the project Owner role, cannot be undone, and does not automatically delete child pipelines.

  116. update_pipeline_metadata - Update pipeline metadata

  117. list_deployments - List deployments with filtering options

  118. get_deployment - Get deployment details, including approval_summary, approvals, and pending_approval_count when GitLab provides them

  119. create_deployment - Create a deployment

  120. update_deployment - Update a deployment status

  121. delete_deployment - Delete a deployment

  122. list_deployment_merge_requests - List merge requests shipped with a deployment

  123. approve_deployment - Approve or reject a protected-environment deployment

  124. list_environments - List environments in a project

  125. get_environment - Get details of a specific environment

  126. update_environment - Update an environment

  127. delete_environment - Delete a stopped environment

  128. stop_environment - Stop an environment

  129. stop_stale_environments - Stop eligible stale environments; protected environments are excluded and environments are stopped, not deleted

  130. delete_review_app_environments - Schedule deletion of stopped review-app environments one week later; dry_run defaults to true and actual scheduling requires dry_run=false

  131. list_pipeline_triggers - List project pipeline trigger tokens

  132. get_pipeline_trigger - Get a project pipeline trigger

  133. create_pipeline_trigger - Create a project pipeline trigger

  134. update_pipeline_trigger - Update a project pipeline trigger

  135. delete_pipeline_trigger - Delete a project pipeline trigger

  136. trigger_pipeline - Trigger a pipeline with a pipeline trigger token

  137. list_pipeline_jobs - List all jobs in a specific pipeline

  138. list_pipeline_trigger_jobs - List trigger jobs (bridges) in a pipeline

  139. get_pipeline_job - Get details of a GitLab pipeline job number

  140. get_pipeline_job_output - Get a pipeline job trace, with end-based pagination or full-log substring/regex search

  141. validate_ci_lint - Validate provided GitLab CI/CD YAML content for a project

  142. validate_project_ci_lint - Validate an existing .gitlab-ci.yml configuration for a project

  143. list_ci_catalog_resources - List GitLab CI/CD Catalog resources/components visible to the user

  144. get_ci_catalog_resource - Get details for a GitLab CI/CD Catalog resource, including versions and components

  145. create_pipeline - Create a new pipeline for a branch or tag

  146. retry_pipeline - Retry a failed or canceled pipeline

  147. cancel_pipeline - Cancel a running pipeline

  148. list_pipeline_schedules - List pipeline schedules in a project, optionally filtered to active or inactive

  149. get_pipeline_schedule - Get details of a specific pipeline schedule, including its variables and last pipeline

  150. list_pipeline_schedule_pipelines - List the pipelines that a pipeline schedule has triggered

  151. create_pipeline_schedule - Create a new pipeline schedule for a branch or tag

  152. update_pipeline_schedule - Update an existing pipeline schedule

  153. delete_pipeline_schedule - Delete a pipeline schedule

  154. play_pipeline_schedule - Run a pipeline schedule immediately

  155. take_ownership_pipeline_schedule - Take ownership of a pipeline schedule

  156. get_pipeline_schedule_variable - Get a single variable of a pipeline schedule

  157. create_pipeline_schedule_variable - Create a variable for a pipeline schedule

  158. update_pipeline_schedule_variable - Update a variable of a pipeline schedule

  159. delete_pipeline_schedule_variable - Delete a variable from a pipeline schedule

  160. play_pipeline_job - Run a manual pipeline job

  161. play_pipeline_jobs - Play multiple manual pipeline jobs sequentially

  162. retry_pipeline_job - Retry a failed or canceled pipeline job

  163. cancel_pipeline_job - Cancel a running pipeline job

  164. erase_pipeline_job - Erase a pipeline job log and artifacts

  165. wait_for_pipeline - Wait for a pipeline to reach a terminal status

  166. wait_for_job - Wait for a job to reach a terminal status

  167. list_job_artifacts - List artifact files in a job's archive

  168. download_job_artifacts - Download job artifact archive (zip) and save it under the download directory

  169. get_job_artifact_file - Get content of a single file from a job's artifacts

  170. list_merge_requests - List merge requests (without project_id: user's MRs; with project_id: project MRs)

  171. list_group_merge_requests - List merge requests across all projects of a group and its subgroups

  172. list_milestones - List milestones with filtering options

  173. get_milestone - Get details of a specific milestone

  174. create_milestone - Create a new milestone

  175. edit_milestone - Edit an existing milestone

  176. delete_milestone - Delete a milestone

  177. get_milestone_issue - Get issues associated with a specific milestone

  178. get_milestone_merge_requests - Get merge requests associated with a specific milestone

  179. promote_milestone - Promote a milestone to the next stage

  180. get_milestone_burndown_events - Get burndown events for a specific milestone

  181. list_group_milestones - List group milestones with filtering options

  182. get_group_milestone - Get details of a specific group milestone

  183. create_group_milestone - Create a new group milestone

  184. edit_group_milestone - Edit an existing group milestone

  185. delete_group_milestone - Delete a group milestone

  186. get_group_milestone_issue - Get issues associated with a specific group milestone

  187. get_group_milestone_merge_requests - Get merge requests associated with a specific group milestone

  188. get_group_milestone_burndown_events - Get burndown events for a specific group milestone

  189. get_users - Get GitLab user details by usernames

  190. get_user - Get user details by ID

  191. whoami - Get current authenticated user details

  192. list_commits - List repository commits with filtering options

  193. get_commit - Get details of a specific commit

  194. get_commit_diff - Get changes/diffs of a specific commit

  195. get_file_blame - Get git blame for a file at a given ref. Each entry maps a contiguous range of source lines to the commit that last changed them (id, author, authored_date, message). Use range_start/range_end to limit blame to specific lines.

  196. list_commit_statuses - List statuses for a commit

  197. create_commit_status - Create or update the status of a commit

  198. list_group_iterations - List group iterations with filtering options

  199. get_group_iteration - Get a group iteration by ID, IID, or GraphQL GID

  200. update_group_iteration - Update a manual group iteration's title, description, or dates

  201. create_group_iteration - Create a group iteration, optionally in a given iteration cadence

  202. delete_group_iteration - Delete a group iteration by ID, IID, or GraphQL GID

  203. list_project_iterations - List the iterations available to a project with filtering options

  204. list_group_iteration_cadences - List a group's iteration cadences with filtering options

  205. create_group_iteration_cadence - Create an iteration cadence in a group

  206. update_group_iteration_cadence - Update an iteration cadence's title, description, schedule, or automation

  207. delete_group_iteration_cadence - Delete an iteration cadence

  208. upload_markdown - Upload a file for use in markdown content

  209. download_attachment - Download an uploaded file from a project (images returned as base64; other files, or images with local_path, are saved as new files under the download directory)

  210. health_check - Check auth and versions. Always includes mcp_server_version. When authenticated, also GitLab version, revision, and enterprise from GET /api/v4/version. Version lookup failures omit those fields instead of failing

  211. list_events - List events for the authenticated user (before/after: YYYY-MM-DD)

  212. get_project_events - List events for a project (before/after: YYYY-MM-DD)

  213. list_releases - List all releases for a project

  214. get_release - Get a release by tag name

  215. create_release - Create a new release

  216. update_release - Update an existing release

  217. delete_release - Delete a release (does not delete the tag)

  218. create_release_evidence - Create release evidence (Premium/Ultimate)

  219. download_release_asset - Download a release asset file by direct asset path

  220. list_tags - List repository tags for a project

  221. get_tag - Get a repository tag by name

  222. create_tag - Create a new repository tag

  223. delete_tag - Delete a repository tag

  224. get_tag_signature - Get the X.509 signature of a signed tag (404 if unsigned)

  225. list_protected_tags - List protected tags in a project

  226. get_protected_tag - Get details of a single protected tag or wildcard (create access levels)

  227. protect_tag - Protect a repository tag or wildcard (set who can create it)

  228. unprotect_tag - Remove protection from a previously protected tag or wildcard

  229. get_work_item - Get a work item with full details including status, hierarchy, type, and widgets

  230. list_work_items - List work items with filters (type, state, search, assignees, labels)

  231. create_work_item - Create a work item (issue, task, incident, epic, etc.) with full field support

  232. update_work_item - Update a work item (title, description, labels, assignees, state, parent, custom fields, etc.)

  233. convert_work_item_type - Convert a work item to a different type

  234. list_work_item_statuses - List available statuses for a work item type (Premium/Ultimate)

  235. list_custom_field_definitions - List custom field definitions for a work item type

  236. move_work_item - Move a work item to a different project

  237. list_work_item_notes - List notes and discussions on a work item

  238. create_work_item_note - Add a note to a work item (supports Markdown, internal notes, threads)

  239. list_work_item_emoji_reactions - List all emoji reactions on a work item

  240. list_work_item_note_emoji_reactions - List all emoji reactions on a work item note (comment, thread, or thread reply)

  241. create_work_item_emoji_reaction - Add an emoji reaction to a work item (e.g. thumbsup, rocket, eyes)

  242. delete_work_item_emoji_reaction - Remove an emoji reaction from a work item

  243. create_work_item_note_emoji_reaction - Add an emoji reaction to a work item note (comment, thread, or thread reply)

  244. delete_work_item_note_emoji_reaction - Remove an emoji reaction from a work item note (comment, thread, or thread reply)

  245. get_timeline_events - List timeline events for an incident

  246. create_timeline_event - Create a timeline event on an incident

  247. list_webhooks - List webhooks for a project or group

  248. create_webhook - Create a webhook on a project or group

  249. update_webhook - Update an existing project or group webhook

  250. delete_webhook - Delete a project or group webhook

  251. list_webhook_events - List recent webhook events (past 7 days)

  252. get_webhook_event - Get full details of a specific webhook event

  253. search_code - Search for code across all projects (requires advanced search or Zoekt)

  254. search_project_code - Search for code within a specific project (requires advanced search or Zoekt)

  255. search_group_code - Search for code within a specific group (requires advanced search or Zoekt)

  256. list_project_variables - List CI/CD variables for a project

  257. get_project_variable - Get a single CI/CD variable from a project

  258. create_project_variable - Create a CI/CD variable for a project

  259. update_project_variable - Update an existing CI/CD variable in a project

  260. delete_project_variable - Delete a CI/CD variable from a project

  261. list_group_variables - List CI/CD variables for a group

  262. get_group_variable - Get a single CI/CD variable from a group

  263. create_group_variable - Create a CI/CD variable for a group

  264. update_group_variable - Update an existing CI/CD variable in a group

  265. delete_group_variable - Delete a CI/CD variable from a group

  266. get_dependency_proxy_settings - Get dependency proxy settings for a group

  267. update_dependency_proxy_settings - Update dependency proxy settings for a group (enable/disable, credentials for authenticated Docker Hub pulls)

  268. list_dependency_proxy_blobs - List cached dependency proxy blobs for a group

  269. purge_dependency_proxy_cache - Schedule purge of all cached dependency proxy blobs for a group

  270. list_project_vulnerabilities - List vulnerabilities for a project with optional state, severity, and report type filters (GraphQL-backed, cursor pagination)

  271. get_vulnerability - Get full details of a specific vulnerability

  272. dismiss_vulnerability - Dismiss a vulnerability with a reason (acceptable_risk, false_positive, used_in_tests, mitigating_control, not_applicable) and optional comment

  273. confirm_vulnerability - Confirm a vulnerability as a real finding requiring remediation

  274. orbit_query - Execute a GitLab Orbit graph query over the indexed SDLC knowledge graph

  275. orbit_get_schema - Fetch the current GitLab Orbit graph schema (node and edge types)

  276. orbit_get_status - Check GitLab Orbit indexing status for the enabled scope

  277. orbit_list_tools - List the MCP tool definitions exposed by GitLab Orbit

  278. list_snippets - List snippets — project snippets when project_id is given, otherwise personal snippets

  279. get_snippet - Get a snippet's metadata. Set include_content=true to also fetch the raw file content.

  280. create_snippet - Create a snippet — project-scoped when project_id is given, otherwise a personal snippet. Requires title plus either file_name + content (single file) or files[] (multi-file); the two shapes cannot be mixed.

  281. update_snippet - Update an existing snippet (provide at least one field to change). For multi-file edits — renames, deletions, additions — pass files[] with action (create/update/delete/move) and previous_path. The file_name + content shortcut still works for single-file content replacement.

  282. delete_snippet - Delete a snippet

  283. list_project_runners - List runners available to a project (type, status, paused, tag_list). Omits registration and authentication tokens.

  284. get_runner - Get a runner's tag_list, run_untagged, locked, and access_level. When a project allowlist is active, the runner must be available to an allowed project. Omits registration and authentication tokens.

  285. rebase_merge_request - Rebase the source branch of a merge request onto its target branch

  286. gitlab_api_request - Send one GitLab REST call under /api/v4. Enabled only when GITLAB_TOOLSETS lists api. Readonly allows GET; modify rejects DELETE.

  287. discover_tools - List or activate a toolset for this session. Omit category to list; pass one to enable. Prefer this over GITLAB_TOOLSETS=all (loads ~all schemas). Session-only; with OAUTH_STATELESS_MODE=true persist GITLAB_TOOLSETS.

  288. help - Return a short GitLab workflow guide. Omit topic for the overview and topic list.

Wiki page titles vs. slugs

GitLab derives a wiki page's slug (its URL, /-/wikis/<slug>) from the page title. Passing title to update_wiki_page / update_group_wiki_page therefore renames the page and changes its URL — for nested pages it can also move the page to a different path — which breaks existing links.

To change only the displayed title while keeping the URL stable, do not pass title. Instead, store the display title in the page content's YAML front matter and update the content:

---
title: My Custom Display Title
---

Page body…

GitLab keeps the slug/URL untouched and shows the front-matter title in the UI. Read it back with get_wiki_page using render_html: true, which populates the front_matter field — the plain title field always reflects the slug-derived value.

Testing 🧪

The project includes comprehensive test coverage including remote authorization:

# Run all tests (API validation + remote auth)
npm test

# Run only remote authorization tests
npm run test:remote-auth

# Run all tests including readonly MCP tests
npm run test:all

# Run only API validation
npm run test:integration

All remote authorization tests use a mock GitLab server and do not require actual GitLab credentials.

Sponsor 💖

Sponsorships through GitHub Sponsors help cover GitLab E2E testing costs: a paid GitLab tier to test Premium/Ultimate features (such as milestone burndown charts and iterations) that the free test instance cannot reach, and the infrastructure for live API tests.

Available Tools

40 tools
create_issueB

Create a new issue. Open a new issue. Use update_issue for an existing issue and create_issue_note for discussion.

Inputs: title (required), project_id (required), labels, weight, +5 more.

create_issue_noteA

Add a note to an issue, optionally replying to a discussion thread. Add a note to an existing issue, optionally as a reply. Use update_issue for issue fields.

Inputs: body (required), issue_iid (required), project_id (required), jmespath, +2 more.

create_merge_requestA

Create a new merge request. Open a merge request from an existing source branch to a target. Use update_merge_request after it exists.

Inputs: title (required), project_id (required), source_branch (required), target_branch (required), +10 more.

create_merge_request_threadA

Create a new thread on a merge request. Start a review thread. Use create_merge_request_note for an unthreaded note and create_merge_request_discussion_note to reply.

Inputs: body (required), project_id (required), merge_request_iid (required), jmespath, +2 more.

discover_toolsA
Read-only

List or activate a toolset for this session. Omit category to list; pass one to enable. Prefer this over GITLAB_TOOLSETS=all (loads ~all schemas). Session-only; with OAUTH_STATELESS_MODE=true persist GITLAB_TOOLSETS=core,<category> instead. Categories: core, merge_requests, issues, repositories, branches, projects, labels, ci, groups, pipelines, milestones, wiki, releases, tags, snippets, users, workitems, webhooks, search, variables, dependency_proxy, vulnerabilities, orbit. Response lists already-active ones. api is explicit-only.

Inputs: category, jmespath.

get_branchA
Read-only

Get branch details (commit, protection status). To find resources, use the matching list or search tool.

Inputs: project_id (required), branch_name (required), jmespath.

get_commitB
Read-only

Get details of a specific commit. To find resources, use the matching list or search tool.

Inputs: sha (required), project_id (required), stats, jmespath.

get_commit_diffA
Read-only

Get changes/diffs of a specific commit. Return the file diffs for one commit. Use get_commit for metadata without the patch.

Inputs: sha (required), project_id (required), jmespath, full_diff.

get_file_blameA
Read-only

Get git blame for a file at a given ref. Each entry maps a contiguous range of source lines to the commit that last changed them (id, author, authored_date, message). Use range_start/range_end to limit blame to specific lines.

Inputs: ref (required), file_path (required), project_id (required), jmespath, +2 more.

get_file_contentsC
Read-only

Get contents of a file or directory from a GitLab project.

Inputs: ref, path, jmespath, file_path, +1 more.

get_issueA
Read-only

Get one issue. Slim nested milestone by default; full_response=true for the complete milestone. Use this for issue management. Use list_issues or my_issues to discover issues first.

Inputs: issue_iid (required), project_id (required), jmespath, full_response.

get_merge_requestA
Read-only

Get details of a merge request (merge_request_iid or source_branch required). Set include_summaries=true for deployment/commit/approval summaries. To find resources, use the matching list or search tool.

Inputs: project_id (required), jmespath, source_branch, include_summaries, +1 more.

get_merge_request_approval_stateA
Read-only

Get merge request approval details including approvers. Inspect approval rules and approvers before merging. Use approve_merge_request to change approval state.

Inputs: project_id (required), merge_request_iid (required), jmespath.

get_merge_request_diffsB
Read-only

Get the changes/diffs of a merge request (merge_request_iid or source_branch required). To find resources, use the matching list or search tool.

Inputs: project_id (required), view, jmespath, source_branch, +2 more.

get_merge_request_discussionA
Read-only

Get a single discussion item for a merge request. Fetch one discussion by id. Use mr_discussions for a collection and get_merge_request_note for a flat note.

Inputs: project_id (required), discussion_id (required), merge_request_iid (required), jmespath.

get_merge_request_file_diffA
Read-only

Get diffs for specific files from a merge request (merge_request_iid or source_branch required).

Inputs: file_paths (required), project_id (required), unidiff, jmespath, +2 more.

get_merge_request_noteA
Read-only

Get a specific note for a merge request. Fetch one note by id. Use get_merge_request_notes for a collection and mr_discussions for threads.

Inputs: note_id (required), project_id (required), merge_request_iid (required), jmespath.

get_merge_request_notesA
Read-only

List notes for a merge request. List flat notes. Use mr_discussions when thread structure and resolution state are required.

Inputs: project_id (required), merge_request_iid (required), page, sort, +3 more.

get_projectB
Read-only

Get details of a specific project. To find resources, use the matching list or search tool.

Inputs: project_id (required), jmespath.

get_repository_treeC
Read-only

List files and directories in a repository.

Inputs: project_id (required), ref, page, path, +5 more.

health_checkA
Read-only

Check auth and versions. Always includes mcp_server_version. When authenticated, also GitLab version, revision, and enterprise from GET /api/v4/version. Version lookup failures omit those fields instead of failing.

Inputs: jmespath.

helpA
Read-only

Return a short GitLab workflow guide. Omit topic for the overview and topic list. Topics: code-review, merge-requests, issues, pipelines, search, token-saving. Prefer discover_tools over GITLAB_TOOLSETS=all. With OAUTH_STATELESS_MODE=true persist GITLAB_TOOLSETS instead.

Inputs: topic, jmespath.

list_branchesB
Read-only

List branches in project with search filter. For one known resource, use the matching get tool.

Inputs: project_id (required), page, search, summary, +2 more.

list_commitsB
Read-only

List repository commits with filtering options. For one known resource, use the matching get tool.

Inputs: project_id (required), all, page, path, +11 more.

list_issue_discussionsB
Read-only

List discussions for an issue. List threaded discussions for an issue. Use list_issues or get_issue for issue records.

Inputs: issue_iid (required), project_id (required), page, summary, +2 more.

list_issuesA
Read-only

List issues (default: created by current user; use scope='all' for all). Use this for issue management. Optional project_id. Use get_issue when the iid is known and my_issues for assignments.

Inputs: page, scope, state, labels, +19 more.

list_labelsB
Read-only

List labels for a project. For one known resource, use the matching get tool.

Inputs: project_id (required), page, search, summary, +4 more.

list_merge_request_changed_filesA
Read-only

List changed file paths in a merge request without diff content (merge_request_iid or source_branch required).

Inputs: project_id (required), summary, jmespath, source_branch, +2 more.

list_merge_request_diffsA
Read-only

List merge request diffs with pagination (merge_request_iid or source_branch required). For one known resource, use the matching get tool.

Inputs: project_id (required), page, summary, unidiff, +4 more.

list_merge_requestsA
Read-only

List merge requests (without project_id: user's MRs; with project_id: project MRs). For one known resource, use the matching get tool.

Inputs: wip, page, sort, scope, +23 more.

list_project_membersA
Read-only

List members of a GitLab project. Search project members by name or username. Use list_group_members for a group.

Inputs: project_id (required), page, query, summary, +5 more.

list_projectsA
Read-only

List projects accessible by the current user. For one known resource, use the matching get tool.

Inputs: page, sort, owned, topic, +13 more.

mr_discussionsA
Read-only

List discussion items for a merge request. List complete discussion threads. Use get_merge_request_notes for flat notes.

Inputs: project_id (required), merge_request_iid (required), page, summary, +2 more.

my_issuesA
Read-only

List issues assigned to the authenticated user. Use this for issue management. Use list_issues for project-wide listing and get_issue for one issue. Requires classic read_user or fine-grained User:Read.

Inputs: page, state, labels, search, +8 more.

resolve_merge_request_threadA

Resolve a thread on a merge request. Mark an existing review thread resolved. Use update_merge_request_discussion_note to change note text.

Inputs: resolved (required), project_id (required), discussion_id (required), merge_request_iid (required), +1 more.

search_repositoriesA
Read-only

Search for GitLab projects. If the identifier is known, use a typed get or list tool.

Inputs: page, query, search, jmespath, +1 more.

update_issueA

Update an issue. Slim confirmation by default; full_response=true for the complete object. Change fields on an existing issue. Use update_issue_description_patch for a targeted description edit and create_issue_note for discussion.

Inputs: issue_iid (required), project_id (required), title, labels, +11 more.

update_issue_description_patchA

Patch an issue description (search/replace or unified diff) without resending the full body. dry_run previews; create_note summarizes.

Inputs: patch (required), issue_iid (required), patch_type (required), project_id (required), +4 more.

update_merge_requestA

Update a merge request (merge_request_iid or source_branch required). Use the create tool for new resources and a note tool for comments.

Inputs: project_id (required), draft, title, labels, +11 more.

whoamiA
Read-only

Get current authenticated user details. Requires classic read_user or fine-grained User:Read. Use get_user or get_users to look up another user.

Inputs: jmespath.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 40 tools

    Disambiguation3/5

    Most tools target distinct resources, but the merge request surface has several closely related note, discussion, and diff tools (e.g., get_merge_request_discussion vs get_merge_request_note vs mr_discussions, and list_merge_request_diffs vs get_merge_request_diffs vs get_merge_request_file_diff). Descriptions provide 'use X instead' guidance, but an agent still has meaningful risk of selecting the wrong granularity.

    Naming Consistency4/5

    The majority of tools follow a predictable verb_noun snake_case pattern (list_issues, get_merge_request, create_issue). There are notable deviations like mr_discussions, my_issues, whoami, help, and health_check, but these are limited and still readable.

    Tool Count2/5

    At 40 tools, the surface is heavy for a single MCP server and includes very granular merge request diff/note variants. While GitLab is a broad domain, the presence of discover_tools implies these should be split into toolsets rather than loaded all at once.

    Completeness2/5

    Core GitLab workflows are only partially covered: branch creation/deletion, MR merge/approve, label management, and user lookup tools are missing, even though related tools reference them (e.g., get_user, approve_merge_request, update_merge_request_discussion_note). Agents will hit dead ends for common write operations.

    Maintenance

    ActivityActive
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      MCP server for GitLab CI/CD — pipelines, jobs, schedules, branches, tags, merge requests and repository files. Works with any GitLab (SaaS gitlab.com or self-hosted) via python-gitlab.
      24
      273 PyPI
      2
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP server for interacting with GitLab API, supporting both self-hosted instances and gitlab.com. Provides tools for managing issues, merge requests, code review, pipelines, milestones, releases, search, and file access.
      729 npm
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Model Context Protocol (MCP) server for GitLab — exposes 1006 GitLab REST & GraphQL API operations as MCP tools (42 meta-tools / 57 enterprise), 24 resources, 38 prompts, and 17 completion types for AI assistants. Written in Go, single static binary, stdio and HTTP transport.
      2
      47
      MIT