Skip to main content
Glama

GitLab MCP Server


What it is

GitLab MCP Server lets an AI agent (Claude Desktop, Claude Code, Cursor, Zed, VS Code, or any Model Context Protocol client) talk directly to GitLab. It is a typed, paginated, schema-validated bridge to the GitLab REST API, exposed as 86 MCP tools. It is not a wrapper around glab and it does not screen-scrape.

It runs against gitlab.com or any self-hosted GitLab instance, and authenticates with a personal access token, an OAuth Bearer token forwarded by an upstream gateway, or a read-only token for safe demos.


Related MCP server: gitlab mcp

Why it exists

Anthropic released MCP on November 25, 2024. The reference servers covered Google Drive, Slack, GitHub, Git, Postgres, and Puppeteer. There was no GitLab server. The Yoda Digital engineering team runs on self-hosted GitLab, so the official examples did not help us, and the early community ports were not yet trying to cover the GitLab surface area properly.

We wrote one for ourselves. Group projects, activity tracking, the operations our DevOps actually needed. We open-sourced it on March 18, 2025, expecting maybe five people to find it useful.

A year on the project has 86 tools, working stdio / SSE / Streamable HTTP transports, PAT and OAuth modes, a Docker image on ghcr.io, and a Helm chart written almost entirely by an external contributor we had never met. Releases 0.4.0 and 0.5.0 are mostly someone else's code now, which is the best problem an open-source maintainer can have.


Quick start

Local clients (stdio)

For Claude Desktop, Cursor, Zed, and any client that runs MCP servers as a local subprocess. Add this to your client's MCP config (for Claude Desktop, that's claude_desktop_config.json):

{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": ["-y", "@yoda.digital/gitlab-mcp-server"],
      "env": {
        "GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-…",
        "GITLAB_API_URL": "https://gitlab.com/api/v4"
      }
    }
  }
}

Self-hosted? Replace GITLAB_API_URL with your instance, e.g. https://gitlab.example.com/api/v4. Want a safe demo with no write access? Add "GITLAB_READ_ONLY_MODE": "true". Per-IDE notes are in docs/CURSOR_INTEGRATION.md.

Remote (Streamable HTTP, OAuth-gated)

For shared deployments and modern remote MCP clients, run the server as an HTTP service. Network-exposed deployments require AUTH_MODE=oauth — the server refuses to start with AUTH_MODE=pat on a non-loopback bind. See SECURITY.md for the threat model.

docker run --rm -p 3000:3000 \
  -e HOST=0.0.0.0 \
  -e AUTH_MODE=oauth \
  -e USE_STREAMABLE_HTTP=true \
  ghcr.io/yoda-digital/mcp-gitlab-server:latest

Then front the container with a gateway that injects Authorization: Bearer <token> per connection — the server forwards that Bearer to GitLab as the per-connection PAT. Point clients at http://your-gateway/mcp.

Operational details, probe configuration, and troubleshooting are in docs/OPERATIONS.md.


What's in the box

86 tools, grouped by surface:

  • Repositories: search, create, fork, get and update project metadata.

  • Files and branches: read, create, update, and delete files; multi-file commits; branches (list, create, delete); repository tree.

  • Tags and releases: list and create tags; list and create releases.

  • Issues: create, list, update, notes, threaded discussions.

  • Merge requests: create, update, merge, rebase; approvals; auto-merge; notes, discussions, changes, commits.

  • CI/CD: pipelines (list, get, trigger, retry, cancel), jobs (list, get, log, retry, cancel), environments.

  • Wikis: project and group wikis, including attachments.

  • Groups and members: groups CRUD, subgroups, project and group members.

  • Labels and milestones: list, create, update; protected branches: list, protect, unprotect.

  • Users and meta: current user, list/get user, project events, commit history.

Full tool list in CLAUDE.md. Per-tool docs for selected tools in docs/api/.

Read-only mode (GITLAB_READ_ONLY_MODE=true) filters every mutating tool out at registration time. A misbehaving agent cannot see them, let alone call them.


Transports

Transport

When to use

Flag

stdio

Local clients (Claude Desktop, Cursor, Zed). The default.

(default)

SSE

Remote clients still on the legacy SSE spec.

USE_SSE=true

Streamable HTTP

Remote clients on the current MCP Streamable HTTP spec.

USE_STREAMABLE_HTTP=true

Streamable HTTP runs POST /mcp, GET /mcp, and DELETE /mcp, with session management via the MCP-Session-Id header. The /healthz endpoint returns 503 when active sessions exceed HEALTHZ_MAX_SESSIONS, intended for Kubernetes liveness and readiness probes.


Authentication

Two modes. The right one depends on whether the HTTP transport is reachable from the network.

OAuth per connection (AUTH_MODE=oauth, the default for network-exposed deployments). The server holds no static token. Every MCP connection brings its own Authorization: Bearer <token>, which the server forwards to GitLab as the effective PAT for that connection. Run it behind a gateway that handles your IdP. This is how you operate one shared deployment for an entire team. Required whenever bind is non-loopback.

PAT mode (AUTH_MODE=pat, loopback only). The server holds one personal access token in GITLAB_PERSONAL_ACCESS_TOKEN. The HTTP transport runs without authentication in this mode, so the server enforces a loopback-only bind (HOST=127.0.0.1) and refuses to start otherwise. Right choice for stdio clients and single-tenant local dev. Not supported in Helm — see the chart's auth-validation guard.


Configuration

Variable

Default

Purpose

GITLAB_PERSONAL_ACCESS_TOKEN

Required in PAT mode.

GITLAB_API_URL

https://gitlab.com/api/v4

GitLab API base URL. Point at your self-hosted instance if needed.

GITLAB_READ_ONLY_MODE

false

Hide all write tools.

AUTH_MODE

pat

pat (loopback only) or oauth (any bind).

HOST

127.0.0.1

Bind address for HTTP transports. Set to 0.0.0.0 to expose to the network — but only with AUTH_MODE=oauth, otherwise startup refuses.

USE_SSE

false

Enable legacy SSE transport.

USE_STREAMABLE_HTTP

false

Enable MCP Streamable HTTP transport.

PORT

3000

HTTP listen port for SSE and Streamable HTTP.

CORS_ALLOW_ORIGINS

(empty)

Comma-separated allowlist. Empty means * in PAT-loopback mode (local dev only); empty in OAuth mode means deny. Wildcard is never emitted on a non-loopback bind.

HEALTHZ_MAX_SESSIONS

10000

/healthz flips to 503 above this threshold.

.env.example ships in the repo for local development.


Deployment

Docker

ghcr.io/yoda-digital/mcp-gitlab-server:latest

Multi-stage build on node:24-alpine. Runs as non-root (uid 1000) with all capabilities dropped. Compatible with read-only root filesystems and the seccompProfile: RuntimeDefault Kubernetes pod-security setting. Image tags follow semver on releases; latest tracks the most recent tagged release.

Kubernetes (Helm)

helm install gitlab-mcp oci://ghcr.io/yoda-digital/charts/gitlab-mcp

The chart defaults to AUTH_MODE=oauth so a vanilla install is auth-gated. Front the Service with an Ingress or gateway that injects Authorization: Bearer <token> per connection.

The chart ships liveness and readiness probes against /healthz, an optional PodDisruptionBudget, ConfigMap and Secret with rolling-restart annotations, and five fail-loud guards that refuse to render bad configurations:

  • AUTH_MODE=pat with non-loopback HOST (CWE-306 — see chart/templates/auth-validation.yaml)

  • empty PAT in PAT mode without existingSecret

  • both existingSecret and inline secret.GITLAB_PERSONAL_ACCESS_TOKEN set (a silent precedence trap, otherwise)

  • PDB minAvailable >= replicaCount (drain deadlock)

  • both minAvailable and maxUnavailable set on the PDB (Kubernetes rejects this combination at admission)

values.yaml is annotated for helm-docs, and chart/README.md is regenerated and drift-checked in CI.


Security

Vulnerabilities go through GitHub's Private Vulnerability Reporting, not public issues. Threat model and scope are in SECURITY.md.

A few things that are true about the supply chain. Every npm publish is signed with Sigstore provenance via OIDC Trusted Publishing. CodeQL runs on every push and PR with the security-extended and security-and-quality query packs. Dependabot is on, grouped, and weekly. npm audit reports zero vulnerabilities at the current release. main requires PRs, status checks, squash or rebase merges, and linear history.

Read-only mode is enforced at tool registration, not at the request boundary. If a regression lets a write tool execute under GITLAB_READ_ONLY_MODE=true, that is a security bug. Please report it.


Where this fits in the ecosystem

There are several ways to combine GitLab and MCP. Pick the one that matches your situation:

  • GitLab's own built-in MCP server at https://<your-instance>/api/v4/mcp. 15 tools, requires GitLab Premium or Ultimate, OAuth integrated with your GitLab IdP. The right choice if you have the subscription and 15 tools is enough surface area for your agents.

  • zereight/gitlab-mcp, the largest community implementation. Broader auth surface (PAT, OAuth2 browser flow, OAuth proxy, remote authorization), more tools. A good fit if you want maximum coverage and do not mind a larger project to reason about.

  • mcpland/gitlab-mcp, with a policy-engine focus. OAuth2 PKCE, multi-instance routing, cookie-based auth. Good for tightly controlled enterprise deployments.

  • This server (@yoda.digital/gitlab-mcp-server). 86 tools, three transports, PAT and OAuth, Sigstore-provenanced npm releases, a non-root multi-stage Docker image, and a Helm chart with fail-loud guards. Good if you want a smaller, security-mature project that lands cleanly into a Kubernetes deployment.

None of these is universally best, and we will not pretend otherwise.


Contributing

PRs welcome. The shape we ask for:

  1. Fork, branch (feature/*, fix/*, docs/*, refactor/*).

  2. Conventional Commits (feat:, fix:, docs:, chore:, …). They drive the changelog.

  3. Add or update vitest tests for behavior changes. npm test is the gate.

  4. Open a PR. CI runs build-and-test, CodeQL, Dockerfile lint, Helm lint and template smoke test, and a Helm chart README drift check.

Local setup:

git clone https://github.com/yoda-digital/mcp-gitlab-server.git
cd mcp-gitlab-server
npm install
npm test
npm run dev

Full guidelines are in CONTRIBUTING.md. AI-assisted contribution rules are in ai_code_of_conduct.md. Code of Conduct: CODE_OF_CONDUCT.md. A few good first issue tickets live in the issue tracker.


Contributors

This project has more authors than its origin suggests.

Ion (Nalyk) Calmîș is the original author and maintainer. CTO at Yoda Digital.

Olivier Gintrand (@ecthelion77) wrote the OAuth per-connection authentication path, the MCP Streamable HTTP transport, the multi-stage Dockerfile, and the Helm chart, including the fail-loud guards. Releases 0.4.0 and 0.5.0 are mostly his work, merged via PR #42 and PR #44.

Thomas Léveil (@thomasleveil) and BenSchoweCONPORT sent early PRs.

Dependabot is responsible for most of the chore commits in the changelog and never sleeps.

If you have sent a PR or a security report and you are not on this list, that is a bug. Please open an issue.


License

MIT.



Built with ❤️ by Yoda.Digital

Install Server
A
license - permissive license
C
quality
C
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
6Releases (12mo)
Issues opened vs closed

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yoda-digital/mcp-gitlab-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server