GitLab MCP Server

Works GitLab merge requests, issues, pipelines and repositories from an MCP client

By zereight (individual) TypeScript Local · stdio Git and code hostingDevOps and monitoring

91 popularity score ★ 2.1k ↓ 208k/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs GITLAB_PERSONAL_ACCESS_TOKEN. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add gitlab -e GITLAB_PERSONAL_ACCESS_TOKEN=<GITLAB_PERSONAL_ACCESS_TOKEN> -- npx -y @zereight/mcp-gitlab@latest
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": [
        "-y",
        "@zereight/mcp-gitlab@latest"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": [
        "-y",
        "@zereight/mcp-gitlab@latest"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "gitlab": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@zereight/mcp-gitlab@latest"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.gitlab]
command = "npx"
args = ["-y", "@zereight/mcp-gitlab@latest"]

[mcp_servers.gitlab.env]
GITLAB_PERSONAL_ACCESS_TOKEN = "<GITLAB_PERSONAL_ACCESS_TOKEN>"
Gemini CLITerminal
gemini mcp add --scope user -e GITLAB_PERSONAL_ACCESS_TOKEN=<GITLAB_PERSONAL_ACCESS_TOKEN> gitlab npx -- -y @zereight/mcp-gitlab@latest
Local (Docker)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs GITLAB_PERSONAL_ACCESS_TOKEN. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add gitlab -e GITLAB_PERSONAL_ACCESS_TOKEN=<GITLAB_PERSONAL_ACCESS_TOKEN> -- docker run -i --rm -e GITLAB_PERSONAL_ACCESS_TOKEN zereight050/gitlab-mcp
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "gitlab": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITLAB_PERSONAL_ACCESS_TOKEN",
        "zereight050/gitlab-mcp"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "gitlab": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITLAB_PERSONAL_ACCESS_TOKEN",
        "zereight050/gitlab-mcp"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "gitlab": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITLAB_PERSONAL_ACCESS_TOKEN",
        "zereight050/gitlab-mcp"
      ],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "<GITLAB_PERSONAL_ACCESS_TOKEN>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.gitlab]
command = "docker"
args = ["run", "-i", "--rm", "-e", "GITLAB_PERSONAL_ACCESS_TOKEN", "zereight050/gitlab-mcp"]

[mcp_servers.gitlab.env]
GITLAB_PERSONAL_ACCESS_TOKEN = "<GITLAB_PERSONAL_ACCESS_TOKEN>"
Gemini CLITerminal
gemini mcp add --scope user -e GITLAB_PERSONAL_ACCESS_TOKEN=<GITLAB_PERSONAL_ACCESS_TOKEN> gitlab docker -- run -i --rm -e GITLAB_PERSONAL_ACCESS_TOKEN zereight050/gitlab-mcp

Settings 12

Set together: auth
GITLAB_PERSONAL_ACCESS_TOKEN secret Required: GitLab personal access token. Alternatives: GITLAB_PERSONAL_ACCESS_TOKEN_FILE, GITLAB_USE_OAUTH, GITLAB_JOB_TOKEN, GITLAB_AUTH_COOKIE_PATH, REMOTE_AUTHORIZATION or GITLAB_MCP_OAUTH.
GITLAB_PERSONAL_ACCESS_TOKEN_FILE Optional: Path to a file holding the token, instead of the token itself.
GITLAB_USE_OAUTH Optional: Sign in through a browser OAuth flow instead of a token; needs GITLAB_OAUTH_CLIENT_ID.
GITLAB_API_URL Optional: Address of the GitLab instance; required when GITLAB_MCP_OAUTH is on. Default https://gitlab.com.
GITLAB_PERMISSION_MODE Optional: full, modify (no deletes or teardown) or readonly; an invalid value stops it at start. Default full.
GITLAB_TOOLSETS Optional: Comma-separated toolsets to expose, or all; replaces the core set. Default core.
GITLAB_TOOLS Optional: Extra single tools to expose on top of the chosen toolsets.
GITLAB_DENIED_TOOLS_REGEX Optional: Regular expression of tool names to hide.
GITLAB_ALLOWED_PROJECT_IDS Optional: Comma-separated project IDs the tools may touch.
STREAMABLE_HTTP Optional: Serve Streamable HTTP on PORT instead of stdio. Default false.
GITLAB_MCP_COMPACT_RESULTS Optional: Shorten large tool results to save context. Default false.
GITLAB_MCP_LIST_SUMMARY_DEFAULT Optional: When true, list tools and mr_discussions return summaries unless a call sets summary to false. Default false.

In a container, a setting goes in with -e NAME=value after docker run.

What it does

GitLab MCP Server, published by zereight as the npm package @zereight/mcp-gitlab, gives an assistant working access to a GitLab account on GitLab.com or on a self-managed instance. Through the GitLab REST and GraphQL APIs it can browse and edit repository files, branches and commits, open, review, comment on and merge merge requests, file and update issues and work items, and start, retry, cancel and read CI/CD pipelines and job logs. Further toolsets reach wikis, milestones, iterations and their cadences, releases, tags, snippets, deployments and environments, CI/CD variables, webhooks, vulnerability findings and code search.

Its tool registry holds 288 tools. Out of the box it exposes 40 of them: the core set of 38, plus discover_tools and a help tool that returns short GitLab workflow guides. That keeps the tool list short. The assistant can switch on another category mid-session through discover_tools, or the operator picks sets up front with GITLAB_TOOLSETS or single tools with GITLAB_TOOLS. A raw REST passthrough, gitlab_api_request, exists but loads only when its toolset is named explicitly. The server also offers three prompts (merge request review, pipeline failure triage, vulnerability triage) and three short help documents as resources.

By default it talks over stdio. With STREAMABLE_HTTP=true (or the older SSE=true) it serves HTTP instead, which is the route for remote, shared deployments and for Claude.ai through its built-in MCP OAuth proxy (GITLAB_MCP_OAUTH). GITLAB_PERMISSION_MODE can hold it to read-only calls or to edits without deletes. Long list results can be trimmed: with GITLAB_MCP_LIST_SUMMARY_DEFAULT=true the list tools and mr_discussions return summaries unless a call asks for full output. The same package doubles as a command-line GitLab client with auth, doctor and setup commands.

What it needs

RuntimeNode.js 20+Docker
Runs onmacOS, Windows, Linux
GitLabFreeGitLab.com or a self-managed instance; the token's own scopes and the user's roles bound what it can do

Node 20 or later runs the npx command. Docker runs the image instead. Make a GitLab personal access token (User settings > Access tokens), with the read_api scope for reading only or api for changes, and pass it as GITLAB_PERSONAL_ACCESS_TOKEN. For a self-managed instance also set GITLAB_API_URL. Without a token or one of the other sign-in settings it stops at start.

Limits

  • Not covered Only the 38 core tools plus discover_tools and help are on by default; other categories need discover_tools during a session or GITLAB_TOOLSETS / GITLAB_TOOLS.
  • Limit A category switched on through discover_tools lasts for that session only. With OAUTH_STATELESS_MODE=true, the multi-pod HTTP setup, name it in GITLAB_TOOLSETS instead.
  • Not covered Setting GITLAB_TOOLSETS replaces the core set rather than adding to it, so core must be listed too if it is still wanted.
  • Not covered gitlab_api_request is not enabled by 'all' or by discover_tools; it loads only when the api toolset is named explicitly.
  • Limit search_code works only on instances with advanced search or Zoekt code search enabled.
  • Rate limit Over HTTP, new connections are capped per client IP by MAX_REQUESTS_PER_MINUTE (429 above it) and sessions by MAX_SESSIONS (default 1000, then 503).
  • Limit The README's Docker examples set SSE or STREAMABLE_HTTP and publish port 3002, so they start an HTTP listener rather than a stdio server.
  • Limit USE_GITLAB_WIKI, USE_MILESTONE, USE_PIPELINE and GITLAB_READ_ONLY_MODE are deprecated and will be removed in v3.0.0.
  • Limit Not made by GitLab: it is a community project; GitLab ships its own MCP endpoint in recent GitLab versions.

Who it suits

Suits developers who want an assistant to do day-to-day GitLab work, from reviewing and merging merge requests to filing issues and chasing failed pipelines, on GitLab.com or on a self-managed instance, using a personal token they already control. Because it can also run over HTTP with each caller's own token or OAuth, it suits teams that host one shared endpoint. Those who only want an assistant to look should set GITLAB_PERMISSION_MODE=readonly and a read_api token. It is not GitLab's own product; where an organisation prefers a vendor-run endpoint with no extra process, the README points to GitLab's built-in MCP server at /api/v4/mcp on recent GitLab versions.

Tools 60 of 288

33 only read, 23 change things, 4 can delete or overwrite.

discover_tools
Lists the tool categories that are off and switches one on for the session
health_check
Reports the server version, whether the token works and the GitLab instance version
whoami
Shows the GitLab user the current token belongs to
list_projects
Lists projects the token can see
get_project
Fetches one project's details
search_repositories
Searches GitLab projects by name
list_project_members
Lists a project's members and their roles
get_file_contents
Reads a file or directory from a repository at a given ref
get_repository_tree
Lists files and folders in a repository path
create_or_update_file changes
Writes one file to a branch as a commit
push_files changes
Commits several files to a branch in one push
get_file_blame
Shows which commit last changed each line of a file
list_branches
Lists a project's branches
create_branch changes
Creates a branch from a ref
delete_branch deletes
Deletes a branch
list_commits
Lists commits on a ref or path
get_commit
Fetches one commit
get_commit_diff
Shows the changes in one commit
list_merge_requests
Lists merge requests with filters
get_merge_request
Fetches a merge request by IID or source branch
get_merge_request_approval_state
Shows which approvals a merge request has and still needs
list_merge_request_changed_files
Lists the files a merge request touches
get_merge_request_file_diff
Fetches the diff of chosen files in a merge request
list_merge_request_diffs
Lists a merge request's diffs page by page
mr_discussions
Lists the discussion threads on a merge request
create_merge_request changes
Opens a merge request
update_merge_request changes
Edits a merge request's title, description, labels or assignees
merge_merge_request changes
Merges a merge request
rebase_merge_request changes
Rebases a merge request's source branch
create_merge_request_thread changes
Starts a review thread, optionally on a diff line
resolve_merge_request_thread changes
Marks a review thread resolved or unresolved
create_draft_note changes
Adds a draft review comment that stays private until published
bulk_publish_draft_notes changes
Publishes all pending draft review comments at once
list_issues
Lists issues with filters
my_issues
Lists issues assigned to the token's user
get_issue
Fetches one issue
create_issue changes
Opens an issue
update_issue changes
Edits an issue's fields or state
delete_issue deletes
Deletes an issue
create_issue_note changes
Comments on an issue
update_issue_description_patch changes
Edits part of an issue description by patch instead of a full rewrite
reorder_issue changes
Moves an issue in the manual order used on issue boards, next to a neighbour given by its global id
list_labels
Lists a project's labels
list_pipelines
Lists CI/CD pipelines
get_pipeline
Fetches one pipeline
create_pipeline changes
Starts a pipeline on a ref
retry_pipeline changes
Re-runs a pipeline's failed jobs
cancel_pipeline changes
Cancels a running pipeline
get_pipeline_job_output
Reads a CI job's log
wait_for_pipeline
Waits until a pipeline finishes and reports the result
list_deployments
Lists a project's deployments
list_environments
Lists a project's environments
create_project_variable changes
Adds a CI/CD variable to a project
delete_project_variable deletes
Removes a CI/CD variable
create_webhook changes
Adds a project webhook
list_project_vulnerabilities
Lists security findings for a project
search_code
Searches code across GitLab (needs advanced search or Zoekt on the instance)
download_attachment changes
Fetches a file uploaded to a project; images come back inline, other files are saved to the download folder
execute_graphql changes
Runs a GraphQL query or mutation against the instance
gitlab_api_request deletes
Sends any REST call to the GitLab API with the server's token (explicit opt-in only)

Resources 3

gitlab-mcp://docs/auth-setup
How to set up sign-in for the server
gitlab-mcp://docs/toolsets
The toolsets and how to switch them on
gitlab-mcp://docs/permission-modes
What the full, modify and readonly modes allow

Prompts 3

review_merge_request
Walks through reviewing one merge request (project_id, merge_request_iid)
triage_pipeline_failure
Works out why a pipeline failed (project_id, pipeline_id)
triage_vulnerabilities
Sorts a project's security findings (project_id)

Similar servers