Back to Browse

Gitlab MCP Server

Developer ToolsLow Risk9.8MCP RegistryLocal
Free

Server data from the Official MCP Registry

GitLab MCP server for MCP 2026-07-28: projects, MRs, files, reviews, pipelines, CI/CD, issues

About

GitLab MCP server for MCP 2026-07-28: projects, MRs, files, reviews, pipelines, CI/CD, issues

Security Report

9.8
Low Risk9.8Low Risk

Valid MCP server (1 strong, 3 medium validity signals). 1 known CVE in dependencies Package registry verified. Imported from the Official MCP Registry. Trust signals: trusted author (7/7 approved).

3 files analyzed ยท 2 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.

file_system

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 (token mode). Optional after `mcp-gitlab auth login`; also accepts GITLAB_PAT, GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_API_TOKENRequired

Environment variable: GITLAB_TOKEN

GitLab instance URL (e.g. https://gitlab.com)Optional

Environment variable: GITLAB_URL

Restrict to read-only operations (true/false)Optional

Environment variable: GITLAB_READ_ONLY

Same as GITLAB_READ_ONLY; shared name across the mcp-* servers. Either being truthy locks the server read-only and nothing can turn it off at runtimeOptional

Environment variable: MCP_READ_ONLY

Authentication mode: token (default) or oauth (OAuth 2.1 proxy; streamable-http only)Optional

Environment variable: GITLAB_AUTH

Application ID of the GitLab OAuth app (oauth mode, or local sign-in on a self-managed instance)Optional

Environment variable: GITLAB_OAUTH_CLIENT_ID

Secret of the GitLab OAuth app (oauth mode)Required

Environment variable: GITLAB_OAUTH_CLIENT_SECRET

Public URL of this server, no trailing slash (oauth mode); redirect URI is <base>/auth/callbackOptional

Environment variable: GITLAB_OAUTH_BASE_URL

Space-separated GitLab scopes required on every request (oauth mode; default api)Optional

Environment variable: GITLAB_OAUTH_SCOPES

FastMCP JWT signing key, >=32 random chars (oauth mode; defaults to one derived from the client secret)Required

Environment variable: GITLAB_OAUTH_JWT_KEY

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-vish288-mcp-gitlab": {
      "env": {
        "GITLAB_URL": "your-gitlab-url-here",
        "GITLAB_AUTH": "your-gitlab-auth-here",
        "GITLAB_TOKEN": "your-gitlab-token-here",
        "MCP_READ_ONLY": "your-mcp-read-only-here",
        "GITLAB_READ_ONLY": "your-gitlab-read-only-here",
        "GITLAB_OAUTH_SCOPES": "your-gitlab-oauth-scopes-here",
        "GITLAB_OAUTH_JWT_KEY": "your-gitlab-oauth-jwt-key-here",
        "GITLAB_OAUTH_BASE_URL": "your-gitlab-oauth-base-url-here",
        "GITLAB_OAUTH_CLIENT_ID": "your-gitlab-oauth-client-id-here",
        "GITLAB_OAUTH_CLIENT_SECRET": "your-gitlab-oauth-client-secret-here"
      },
      "args": [
        "mcp-gitlab"
      ],
      "command": "uvx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

mcp-gitlab

PyPI version PyPI downloads Python License: MIT CI MCP Registry

mcp-gitlab is a Model Context Protocol (MCP) server for the GitLab REST API. It gives AI assistants 91 tools, 7 resources, and 6 prompts to manage projects, merge requests, pipelines, CI/CD variables, approvals, issues, and code reviews. Works with Claude Desktop, Claude Code, Cursor, Windsurf, VS Code Copilot, and any MCP-compatible client. Runs in one of two modes: with writes, or locked read-only (MCP_READ_ONLY=true) so the 57 write tools are never offered to the model.

Supports GitLab.com and self-hosted GitLab instances (CE/EE). No GitLab Duo or Premium required.

Supports the MCP 2026-07-28 specification, often called MCP 2.0, and stays compatible with 2025-11-25 clients.

Built with FastMCP 4.x, httpx, and Pydantic.

Install: uvx mcp-gitlab | PyPI | MCP Registry | Changelog

uvx mcp-gitlab                          # with writes
MCP_READ_ONLY=true uvx mcp-gitlab       # locked read-only: write tools are not listed

1-Click Installation

Install in Cursor

Install in VS Code Install in VS Code Insiders

๐Ÿ’ก Tip: For other AI assistants (Claude Code, Windsurf, IntelliJ, Gemini CLI), visit the GitLab MCP Installation Gateway.

Prerequisite: Install uv first (required for all uvx install flows). Install uv.

Claude Code

# with writes
claude mcp add gitlab -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx -- uvx mcp-gitlab
# locked read-only
claude mcp add gitlab -e MCP_READ_ONLY=true -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx -- uvx mcp-gitlab

Windsurf & IntelliJ

Windsurf: Add to ~/.codeium/windsurf/mcp_config.json IntelliJ: Add to Settings | Tools | MCP Servers

Note: The actual server config starts at gitlab inside the mcpServers object. Remove MCP_READ_ONLY to allow writes.

{
  "mcpServers": {
    "gitlab": {
      "command": "uvx",
      "args": ["mcp-gitlab"],
      "env": {
        "GITLAB_URL": "https://gitlab.example.com",
        "GITLAB_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "MCP_READ_ONLY": "true"
      }
    }
  }
}

Gemini CLI

# with writes
gemini mcp add -s user -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx gitlab uvx mcp-gitlab
# locked read-only
gemini mcp add -s user -e MCP_READ_ONLY=true -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx gitlab uvx mcp-gitlab

VS Code

Add to .vscode/mcp.json. Remove MCP_READ_ONLY to allow writes.

{
  "servers": {
    "gitlab": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-gitlab"],
      "env": {
        "GITLAB_URL": "https://gitlab.example.com",
        "GITLAB_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "MCP_READ_ONLY": "true"
      }
    }
  }
}

Codex

# with writes
codex mcp add gitlab --env GITLAB_URL=https://gitlab.example.com --env GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx -- uvx mcp-gitlab
# locked read-only
codex mcp add gitlab --env MCP_READ_ONLY=true --env GITLAB_URL=https://gitlab.example.com --env GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx -- uvx mcp-gitlab

pip / uv

uv pip install mcp-gitlab

Drop MCP_READ_ONLY to allow writes. On a shared or hosted server put it in the deployer's env, not the client config.

Configuration

VariableRequiredDefaultDescription
GITLAB_URLYes-GitLab instance URL (e.g. https://gitlab.example.com)
GITLAB_TOKENYes, unless signed in with mcp-gitlab auth login-Authentication token (see below)
MCP_READ_ONLYNofalseShared name across the mcp-* servers. Any value other than false/0/no/off/empty locks the server read-only: the 57 write tools and write-workflow prompts are not listed, and nothing can turn it back off at runtime
GITLAB_READ_ONLYNofalsePer-server alias for MCP_READ_ONLY; either one locks the server read-only. --read-only can only raise the lock
GITLAB_HTTP_BEARER_TOKENNo-Bearer token (min 16 chars) required to bind an HTTP transport to a non-loopback host; clients send Authorization: Bearer <token>; token mode only
GITLAB_TIMEOUTNo30Request timeout in seconds
GITLAB_SSL_VERIFYNotrueSet to false to skip SSL verification
GITLAB_AUTHNotokentoken (PAT from env) or oauth (OAuth 2.1 proxy; see below)

Supported Token Types

The server checks these environment variables in order โ€” first match wins:

  1. GITLAB_TOKEN
  2. GITLAB_PAT
  3. GITLAB_PERSONAL_ACCESS_TOKEN
  4. GITLAB_API_TOKEN

These accept any of the following token types:

Token TypeFormatUse Case
Personal access tokenglpat-xxxUser-level access with api scope
OAuth2 tokenoauth-xxxOAuth app integrations
CI job token$CI_JOB_TOKENGitLab CI pipeline access

Sign in without a token

Use this when you run the server for yourself over stdio and have no personal access token. mcp-gitlab auth login signs you in to GitLab as a public OAuth client and stores the tokens locally. The server then reads them at startup and refreshes them on its own. This is not OAuth mode; the server stays in token mode and nothing on the MCP wire changes.

Three commands:

mcp-gitlab auth login     # device flow by default; add --web for the browser flow
mcp-gitlab auth status    # show the stored account, scopes, and token freshness
mcp-gitlab auth logout    # revoke the token at GitLab and delete the local copy

auth login prints a code and a URL. Open the URL, enter the code, and approve. The server then works with GITLAB_URL set and no token.

Client ID

Each sign-in needs an OAuth application ID. Resolution order: --client-id, then GITLAB_OAUTH_CLIENT_ID, then a built-in default for https://gitlab.com.

The gitlab.com default is not registered yet. Until it is, set GITLAB_OAUTH_CLIENT_ID or pass --client-id for gitlab.com too.

Register an app (self-managed, or gitlab.com until the default ships)

Create an application under User Settings โ†’ Applications โ†’ Add new application with these settings:

FieldValue
Namemcp-gitlab
Redirect URIhttp://127.0.0.1/callback (loopback IP, no port)
Confidentialunchecked (public client)
Scopesapi, read_api

Use 127.0.0.1, not localhost. The device flow needs GitLab 17.9 or later; on older instances use mcp-gitlab auth login --web.

Storage and precedence

Credentials live in ~/.config/mcp-gitlab/credentials.json, one entry per GitLab URL, mode 0600. An environment token always wins: if GITLAB_TOKEN is set, the server uses it and ignores the stored credentials.

Pass --scopes read_api for a read-only session; the server then blocks write tools before any API call.

OAuth 2.1 (remote deployments)

For a server shared by several people, --auth oauth turns mcp-gitlab into an MCP 2026-07-28 resource server with GitLab as the upstream OAuth provider: each user signs in with their own GitLab account, every request runs with that user's token, and no personal access token is configured on the server. Use it when you host the server once and multiple users connect to it; keep the default --auth token for a single-user local setup.

OAuth mode requires --transport streamable-http (OAuth applies to HTTP only; stdio keeps using the environment token).

1. Register a GitLab OAuth application (User Settings โ†’ Applications, or a group/instance application). Set the redirect URI to <base>/auth/callback (e.g. https://mcp.example.com/auth/callback), mark it confidential, and grant the api scope (or read_api for a read-only deployment). Copy the Application ID and Secret.

2. Configure the server:

VariableRequiredDefaultDescription
GITLAB_URLYes-GitLab instance; also the upstream authorization server
GITLAB_OAUTH_CLIENT_IDYes-Application ID (oauth mode, or local sign-in)
GITLAB_OAUTH_CLIENT_SECRETYes-Its secret
GITLAB_OAUTH_BASE_URLYes-Public URL of this server, no trailing slash (e.g. https://mcp.example.com). Resource URL is <base>/mcp
GITLAB_OAUTH_SCOPESNoapiSpace-separated GitLab scopes required on every request. For a read-only OAuth deployment set read_api here and MCP_READ_ONLY=true, so write tools are hidden server-wide and per-user tokens lack write scope
GITLAB_OAUTH_JWT_KEYNoderivedFastMCP JWT signing key, โ‰ฅ 32 random chars. Set it in production so client registrations survive a client-secret rotation
FASTMCP_HOMENoplatform data dirThe encrypted token store lives at $FASTMCP_HOME/oauth-proxy/<fingerprint>/
GITLAB_URL=https://gitlab.com GITLAB_AUTH=oauth \
  GITLAB_OAUTH_CLIENT_ID=... GITLAB_OAUTH_CLIENT_SECRET=... \
  GITLAB_OAUTH_BASE_URL=https://mcp.example.com \
  uvx mcp-gitlab --transport streamable-http

Point an MCP client (or the MCP Inspector, pnpm dlx @modelcontextprotocol/inspector) at <base>/mcp; it discovers the authorization server, runs the OAuth flow, and each tool call then uses that user's GitLab token. A read_api-only token can read but is refused writes with an actionable hint.

Full guide, client setup and troubleshooting: docs/oauth.md.

Compatibility

ClientSupportedInstall Method
Claude DesktopYesclaude_desktop_config.json
Claude CodeYesclaude mcp add
CursorYesOne-click deeplink or .cursor/mcp.json
VS Code CopilotYesOne-click deeplink or .vscode/mcp.json
WindsurfYes~/.codeium/windsurf/mcp_config.json
Any MCP clientYesstdio or HTTP transport

Protocol support

mcp-gitlab implements the Model Context Protocol. It supports the 2026-07-28 specification, often called MCP 2.0. It stays compatible with 2025-11-25 clients.

  • Specification: MCP 2026-07-28 (MCP 2.0). Verified over stdio and streamable-http.
  • Legacy clients: 2025-11-25 clients still work.
  • Built on: FastMCP 4.x and the MCP Python SDK 2.x.
  • Transports: stdio (default) and streamable-http (recommended for remote). The sse (HTTP+SSE) transport still works, but the 2026-07-28 specification deprecates it. The server prints a warning when you use it.
  • Capabilities: tools, resources, and prompts. The server uses no roots, sampling, logging, elicitation, or resource subscriptions, so the 2026-07-28 deprecations do not affect it.

Error results

An expected failure (a 404, a 401, a validation error, or a write that reaches the read-only guard) comes back as a tool result with the protocol-level isError flag set, so a client can detect and self-correct instead of parsing an "error" key out of an otherwise successful result. In locked read-only mode the write tools are hidden, so calling one returns an Unknown tool error; the read-only envelope is the guard's own response, returned only when a client reaches a write tool anyway (a cached listing, or a future untagged tool). The body is a JSON object with error and, where it helps, status_code, body, and an actionable hint. That object is the result's text content; the error sets no structuredContent, because a strict client (the TypeScript MCP SDK) validates structuredContent against the tool's output schema even on an isError result and the schema would reject the error body. An unexpected bug is also an isError result but carries only TypeName: message text, likewise with no structuredContent.

A successful result carries the response as a JSON object in both the pretty text content and structuredContent (the object itself, not the old {"result": "<json string>"} wrapper a strict client would otherwise reject). Tools advertise no outputSchema: upstream GitLab fields pass through untyped, so a new API field never breaks a schema; a typed schema is opt-in per tool via output_schema= when a client needs one.

Tools (91)

CategoryCountTools
Projects4get, create, delete, update merge settings
Project Approvals10get/update config, CRUD approval rules (project + MR)
Groups6list, get, share/unshare project, share/unshare group
Branches3list, create, delete
Commits4list, get (with diff), create, compare
Repository Files4get file (at ref, line range), list tree, search code, blame
Merge Requests15list, get, create, update, merge, merge-sequence, rebase, changes, approve, unapprove, get approvals, list pipelines, list commits, subscribe, unsubscribe
MR Notes6list, add, delete, update, award emoji, remove emoji
MR Discussions4list, create (inline + multi-line), reply, resolve
Draft Notes4create (inline, auto-filled SHAs), list, publish all, delete
Pipelines5list, get (with jobs), create, retry, cancel
Jobs4retry, play, cancel, get log
Tags4list, get, create, delete
Releases5list, get, create, update, delete
CI/CD Variables8CRUD for project variables, CRUD for group variables
Issues5list, get, create, update, add comment

Projects

ToolDescription
gitlab_get_projectGet project details
gitlab_create_projectCreate a new project
gitlab_delete_projectDelete a project
gitlab_update_project_merge_settingsUpdate merge settings

Project Approvals

ToolDescription
gitlab_get_project_approvalsGet approval config
gitlab_update_project_approvalsUpdate approval settings
gitlab_list_project_approval_rulesList approval rules
gitlab_create_project_approval_ruleCreate approval rule
gitlab_update_project_approval_ruleUpdate approval rule
gitlab_delete_project_approval_ruleDelete approval rule
gitlab_list_mr_approval_rulesList MR approval rules
gitlab_create_mr_approval_ruleCreate MR approval rule
gitlab_update_mr_approval_ruleUpdate MR approval rule
gitlab_delete_mr_approval_ruleDelete MR approval rule

Groups

ToolDescription
gitlab_list_groupsList groups
gitlab_get_groupGet group details
gitlab_share_project_with_groupShare project with group
gitlab_unshare_project_with_groupUnshare project from group
gitlab_share_group_with_groupShare group with group
gitlab_unshare_group_with_groupUnshare group from group

Branches

ToolDescription
gitlab_list_branchesList branches
gitlab_create_branchCreate a branch
gitlab_delete_branchDelete a branch

Commits

ToolDescription
gitlab_list_commitsList commits
gitlab_get_commitGet commit (with optional diff)
gitlab_create_commitCreate commit with file actions
gitlab_compareCompare branches/tags/commits

Repository Files

ToolDescription
gitlab_get_fileGet decoded file content at a ref (optional line range), with metadata
gitlab_list_treeList repository tree entries (files and directories) at a ref
gitlab_search_codeSearch a project's code (scope=blobs); depends on the instance's search backend
gitlab_get_blameGet git blame for a file at a ref, optionally limited to a line range

Merge Requests

ToolDescription
gitlab_list_mrsList merge requests
gitlab_get_mrGet MR details
gitlab_create_mrCreate merge request
gitlab_update_mrUpdate merge request
gitlab_merge_mrMerge a merge request
gitlab_merge_mr_sequenceMerge multiple MRs in order
gitlab_rebase_mrRebase a merge request
gitlab_mr_changesGet MR file changes
gitlab_approve_mrApprove a merge request
gitlab_unapprove_mrRemove approval from a merge request
gitlab_get_mr_approvalsGet MR approval state
gitlab_list_mr_pipelinesList MR pipelines
gitlab_list_mr_commitsList MR commits
gitlab_subscribe_mrSubscribe to MR notifications
gitlab_unsubscribe_mrUnsubscribe from MR notifications

MR Notes

ToolDescription
gitlab_list_mr_notesList MR comments
gitlab_add_mr_noteAdd comment to MR
gitlab_delete_mr_noteDelete MR comment
gitlab_update_mr_noteUpdate MR comment
gitlab_award_emojiAward emoji to note
gitlab_remove_emojiRemove emoji from note

MR Discussions

ToolDescription
gitlab_list_mr_discussionsList discussions
gitlab_create_mr_discussionCreate discussion (inline + multi-line)
gitlab_reply_to_discussionReply to discussion
gitlab_resolve_discussionResolve/unresolve discussion

Draft Notes

ToolDescription
gitlab_create_draft_noteCreate an unpublished draft note (inline SHAs auto-filled from the MR's latest version)
gitlab_list_draft_notesList the current user's unpublished draft notes
gitlab_publish_draft_notesPublish ALL pending draft notes at once ("Submit review")
gitlab_delete_draft_noteDelete a single unpublished draft note

Pipelines

ToolDescription
gitlab_list_pipelinesList pipelines
gitlab_get_pipelineGet pipeline (with optional jobs)
gitlab_create_pipelineTrigger pipeline
gitlab_retry_pipelineRetry failed jobs
gitlab_cancel_pipelineCancel pipeline

Jobs

ToolDescription
gitlab_retry_jobRetry a job
gitlab_play_jobTrigger manual job
gitlab_cancel_jobCancel a job
gitlab_get_job_logGet job log output (last 200 lines by default; tail_lines=0 for all)

Tags

ToolDescription
gitlab_list_tagsList tags
gitlab_get_tagGet tag details
gitlab_create_tagCreate a tag
gitlab_delete_tagDelete a tag

Releases

ToolDescription
gitlab_list_releasesList releases
gitlab_get_releaseGet release details
gitlab_create_releaseCreate a release
gitlab_update_releaseUpdate a release
gitlab_delete_releaseDelete a release

CI/CD Variables

ToolDescription
gitlab_list_variablesList project variables
gitlab_create_variableCreate project variable
gitlab_update_variableUpdate project variable
gitlab_delete_variableDelete project variable
gitlab_list_group_variablesList group variables
gitlab_create_group_variableCreate group variable
gitlab_update_group_variableUpdate group variable
gitlab_delete_group_variableDelete group variable

Issues

ToolDescription
gitlab_list_issuesList issues
gitlab_get_issueGet issue details
gitlab_create_issueCreate an issue
gitlab_update_issueUpdate an issue
gitlab_add_issue_commentAdd comment to issue

Resources (7)

The server exposes curated workflow guides as MCP resources that clients can read on demand.

URINameDescription
resource://rules/gitlab-ciGitLab CI/CD Pipeline PatternsStage design, job rules, caching, artifacts, needs DAG, multi-project pipelines
resource://rules/git-workflowGit Workflow StandardsBranch naming, trunk-based flow, merge vs rebase, protected branches
resource://rules/mr-hygieneMerge Request Best PracticesMR size, description templates, review checklists, thread resolution
resource://rules/conventional-commitsConventional Commits SpecCommit types, scopes, breaking changes, changelog generation
resource://guides/code-reviewCode Review StandardsReview priorities, inline comments, approval workflows, nit vs blocker
resource://guides/codeownersGitLab CODEOWNERS ReferenceSyntax, section owners, approval rules, pattern matching
resource://guides/approval-workflowApproval Workflow GuideApproval types, project vs MR-level rules, SHA safety, merge readiness

Prompts (6)

The server provides MCP prompts โ€” reusable multi-tool workflow templates that clients can surface as slash commands.

PromptParametersWorkflow
review_mrproject_id, mr_iidFetch MR โ†’ check pipeline โ†’ review changes โ†’ write discussion notes
approve_mrproject_id, mr_iidCheck approvals โ†’ verify pipeline โ†’ review changes โ†’ approve or request changes
diagnose_pipelineproject_id, pipeline_idFetch pipeline โ†’ identify failed jobs โ†’ get logs โ†’ suggest fix
prepare_releaseproject_id, tag_name, refCompare commits since last tag โ†’ draft changelog โ†’ create tag + release
setup_branch_protectionproject_idReview settings โ†’ configure merge method โ†’ set approval rules
triage_issuesproject_id, labelList open issues โ†’ categorize โ†’ prioritize โ†’ identify duplicates

Usage Examples

Projects & Branches

"Get details for project my-org/api-gateway"
โ†’ gitlab_get_project(project_id="my-org/api-gateway")

"Create a feature branch from main"
โ†’ gitlab_create_branch(project_id="123", branch_name="feat/login", ref="main")

"Delete all branches merged into main"
โ†’ gitlab_list_branches(project_id="123") โ†’ filter merged โ†’ gitlab_delete_branch for each

Merge Requests & Code Review

"Open a merge request from feat/login to main"
โ†’ gitlab_create_mr(project_id="123", source_branch="feat/login", target_branch="main", title="Add login")

"Review MR !42 โ€” list changes and add inline comments"
โ†’ gitlab_mr_changes(project_id="123", mr_iid=42)
โ†’ gitlab_create_mr_discussion(project_id="123", mr_iid=42, body="nit: ...", new_path="src/auth.py", new_line=15)

"Merge MR !42 after resolving all threads"
โ†’ gitlab_list_mr_discussions(project_id="123", mr_iid=42) โ†’ resolve unresolved
โ†’ gitlab_merge_mr(project_id="123", mr_iid=42, squash=True)

Pipelines & CI/CD

"Show failed pipelines on main this week"
โ†’ gitlab_list_pipelines(project_id="123", ref="main", status="failed")

"Retry a failed pipeline"
โ†’ gitlab_retry_pipeline(project_id="123", pipeline_id=456)

"Get the build log for job 789"
โ†’ gitlab_get_job_log(project_id="123", job_id=789, tail_lines=100)

Issues

"Create a bug report in project 123"
โ†’ gitlab_create_issue(project_id="123", title="Login page 500 error", labels=["bug","P1"])

"Find open issues assigned to me"
โ†’ gitlab_list_issues(project_id="123", state="opened", assignee_username="johndoe")

Security Considerations

  • Token scope: Use the minimum required scope. api scope grants full access; prefer read_api for read-only deployments.
  • Read-only mode: Set MCP_READ_ONLY=true (or GITLAB_READ_ONLY=true) in the launch you control and the server starts locked: the 57 write tools and the write-workflow prompts are not listed, a call to one returns "Unknown tool", and the guard refuses any write that still reaches it. Nothing lifts the lock at runtime โ€” not a false from another source, not a .env file, not tool arguments; any value other than false/0/no/off/empty locks, and --read-only can only raise it. The lock is only as strong as the launch: set it where users cannot edit it (a managed MCP config such as Claude Code managed-mcp.json, a container, k8s or systemd env, or a hosted HTTP deployment). A user who starts the server themselves controls its environment. In OAuth mode also set GITLAB_OAUTH_SCOPES=read_api so each user's GitLab token lacks write scope.
  • SSL verification: GITLAB_SSL_VERIFY=true by default. Only disable for self-signed certificates in trusted networks.
  • CI/CD variable masking: gitlab_list_variables and gitlab_list_group_variables automatically mask values of variables marked as masked in GitLab, returning ***MASKED*** instead of the actual value.
  • MCP tool annotations: Each tool declares readOnlyHint, destructiveHint, and idempotentHint for client-side permission prompts.
  • Credential storage: The server reads GITLAB_TOKEN from the environment and never writes it. mcp-gitlab auth login stores OAuth tokens in ~/.config/mcp-gitlab/credentials.json (mode 0600) and refreshes them in place.

Rate Limits & Permissions

Rate Limits

GitLab enforces per-user rate limits (default: 2000 requests/minute for authenticated users). When rate-limited, tools return a 429 error with a hint to wait before retrying. Paginated endpoints default to 20 results per page; use per_page (max 100) to reduce the number of API calls.

Required Permissions

OperationMinimum GitLab Role
Read projects, MRs, pipelines, issues, files/tree/blame/code searchReporter
Create branches, MRs, issues, draft notes (create/publish/delete)Developer
Merge MRs, manage CI/CD variablesMaintainer
Delete projects, manage approval rulesMaintainer/Owner
Share projects/groupsOwner (or Admin)

CLI & Transport Options

# Default: stdio transport (for MCP clients)
uvx mcp-gitlab

# HTTP transport โ€” streamable-http is recommended for remote use
uvx mcp-gitlab --transport streamable-http --port 9000

# SSE transport โ€” deprecated by MCP 2026-07-28; still works, prints a warning
uvx mcp-gitlab --transport sse --host 127.0.0.1 --port 8000

# OAuth 2.1 mode (per-user GitLab sign-in; streamable-http only) โ€” see "OAuth 2.1" above
uvx mcp-gitlab --auth oauth --transport streamable-http

# Local sign-in for stdio without a token โ€” see "Sign in without a token" above
mcp-gitlab auth login|status|logout

# CLI overrides for config
GITLAB_TOKEN=glpat-xxx uvx mcp-gitlab --gitlab-url https://gitlab.example.com --read-only

--gitlab-token still works but is deprecated and hidden from --help: it exposes the token to ps and shell history. Use GITLAB_TOKEN.

--auth {token,oauth} selects the authentication mode (token by default); oauth requires --transport streamable-http.

In token mode an HTTP transport serves every tool with the single GITLAB_TOKEN to anyone who reaches the port, so binding to a non-loopback --host is refused unless you set GITLAB_HTTP_BEARER_TOKEN (โ‰ฅ 16 chars; clients send it as Authorization: Bearer <token>) or switch to --auth oauth for per-user sign-in. The default 127.0.0.1 bind needs neither.

The server loads .env files from the working directory automatically via python-dotenv.

Docker

A minimal non-root image builds straight from this repo (uv, the committed uv.lock). The image defaults to locked read-only (MCP_READ_ONLY=true); override it to allow writes.

docker build -t mcp-gitlab .

# locked read-only (the image default) โ€” stdio for an MCP client
docker run --rm -i \
  -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx \
  mcp-gitlab

# allow writes: override the read-only default
docker run --rm -i \
  -e MCP_READ_ONLY=false \
  -e GITLAB_URL=https://gitlab.example.com -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx \
  mcp-gitlab

For an HTTP transport, append --transport streamable-http --host 0.0.0.0; a non-loopback bind in token mode needs GITLAB_HTTP_BEARER_TOKEN (โ‰ฅ 16 chars) or GITLAB_AUTH=oauth (see above).

FAQ

Does mcp-gitlab support MCP 2.0?

Yes. It supports the MCP 2026-07-28 specification, often called MCP 2.0. It also stays compatible with 2025-11-25 clients.

Does it work with self-hosted GitLab?

Yes. It works with GitLab.com and self-hosted GitLab (CE and EE). It needs no GitLab Duo or Premium.

Which transports does it support?

It supports stdio (the default) and streamable-http. The sse transport still works, but the 2026-07-28 specification deprecates it. OAuth 2.1 mode (--auth oauth) is available on streamable-http only.

Can I run mcp-gitlab read-only so the assistant cannot merge, push or comment?

Yes. Start it with MCP_READ_ONLY=true (or GITLAB_READ_ONLY=true). The 57 write tools and the write-workflow prompts are then not listed at all, so the model never sees them; a call to one returns "Unknown tool", and nothing can turn writes back on while the process runs. Set it in a launch you control โ€” a managed MCP config, a container or systemd env, or a hosted deployment โ€” because a user who starts the server themselves can start it without the variable.

What token scopes does it need?

Use a token with the api scope for full access. Use the read_api scope for read-only deployments. The server reads a GITLAB_TOKEN from the environment and never writes it; tokens from mcp-gitlab auth login are stored in ~/.config/mcp-gitlab/credentials.json.

Which AI assistants work with it?

It works with Claude Desktop, Claude Code, Cursor, Windsurf, VS Code Copilot, and any MCP-compatible client.

How do I install mcp-gitlab?

Run uvx mcp-gitlab, or add it to your MCP client configuration. See the installation section above.

Related MCP Servers

  • mcp-atlassian-extended โ€” Jira + Confluence integration (22 tools, 15 resources, 5 prompts)
  • mcp-coda โ€” Coda integration (53 tools, 12 resources, 5 prompts)
  • mcp-argocd โ€” Argo CD integration (37 tools, 7 resources, 7 prompts)

Development

git clone https://github.com/vish288/mcp-gitlab.git
cd mcp-gitlab
uv sync --all-extras

uv run pytest --cov
uv run ruff check .
uv run ruff format --check .

License

MIT

Reviews

No reviews yet

Be the first to review this server!