# zereight/gitlab-mcp: A GitLab MCP Server Built Around Agent Workflows

> The @zereight/mcp-gitlab server exposes GitLab projects, merge requests, issues and pipelines to MCP clients over stdio, SSE or Streamable HTTP. It optimises for AI agent loops rather than for a small, tidy tool surface.

**zereight/gitlab-mcp** — First gitlab mcp for you, building together. Manage projects, merge requests, issues, pipelines, wiki, releases, tags, milestones, and more through stdio, SSE, and Streamable HTTP.

- Repository: https://github.com/zereight/gitlab-mcp
- Website: https://zereight.github.io/gitlab-mcp/
- Stars: 2,004 · Forks: 356
- Language: TypeScript
- License: MIT
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/zereight-gitlab-mcp

## What zereight/gitlab-mcp Is For

GitLab has a very large REST surface. An AI coding agent that wants to review a merge request has to know which endpoints to call, in what order, and how to keep the response small enough to stay inside a context window. zereight/gitlab-mcp exists to put that work behind a tool interface the agent can call directly.

The README describes it as an "Agent-workflow-optimized GitLab MCP" covering projects, merge requests, issues, pipelines, wiki, releases, tags and milestones. The audience is narrow and identifiable: people running an MCP client such as Claude Code, Cursor, VS Code, Copilot, Codex or Cline who want GitLab operations to happen inside the agent conversation rather than in a browser tab.

The repository is not archived, and the last push was on 2026-08-28, the same timestamp as the v2.1.54 release. Release cadence in the supplied history is tight: v2.1.52 on 2026-08-22, v2.1.53 on 2026-08-27, v2.1.54 on 2026-08-28. That is a project shipping often, not a frozen one.

## The 229-Tool Model and discover_tools

The design choice that separates this server from grouped alternatives is tool count. The README claims 229 tools plus a discover_tools tool, and argues this avoids "CQRS-style grouping". The stated workflow is that you start with a small toolset and activate more at runtime.

That is a real trade-off, and the project's own comparison table admits the other side of it. A community server with roughly 50 to 60 grouped browse_* and manage_* tools is positioned for "Enterprise multi-instance / grouped tools", while this one is positioned for "AI agent workflows". Fewer, broader tools are easier for a model to choose between. Many, narrow tools are easier to compose into a precise sequence but harder to select from, which is presumably why discover_tools exists as an entry point rather than everything being registered up front.

The merge request path shows the same instinct. Rather than one tool that returns a whole diff, the README describes a 2-step review: list_merge_request_changed_files, then batched get_merge_request_file_diff. Splitting listing from fetching is what lets an agent decide which files it actually needs before pulling content into context. If you have ever watched an agent swallow a 4,000-line diff and then summarise it badly, that split is the point.

The repository layout supports the description: there is a tools/ directory, a schemas.ts and a customSchemas.ts, and a Makefile target that regenerates docs/tools/*.md from tools/registry.ts. The tool reference is generated from code, not hand-written, which is the right call at this tool count.

## Installing and Running a First Read-Only Session

The README gives two install paths. Homebrew:

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

Or npm, which installs the @zereight/mcp-gitlab package globally:

```bash
npm install -g @zereight/mcp-gitlab
```

The examples use zereight-mcp-gitlab, described as "a less collision-prone alias for the legacy mcp-gitlab binary". Both names are declared in package.json's bin field, so either works. If your client cannot find the binary, the README says to use the absolute path from which zereight-mcp-gitlab.

If you would rather not install globally, the README recommends pinning npx to a specific version, for example npx -y @zereight/mcp-gitlab@2.1.53, or using @latest if you always want the newest release. The server prints a notice to stderr when a newer version exists, which you can turn off with GITLAB_DISABLE_VERSION_CHECK=true.

For a first run, take the safest configuration. The README notes that --read-only=true is deprecated in favour of --permission-mode=readonly, and the .env.example lists GITLAB_PERMISSION_MODE alongside the token and API URL. A client configuration using CLI arguments looks like this, which the README notes is useful for clients such as GitHub Copilot CLI that have trouble with environment variables:

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

After the client restarts, it should list the GitLab tools. The first thing worth doing is not creating anything. Ask the agent to list your projects, then to list the changed files on a merge request you already know. That exercises the discovery path and the MR listing step without writing to GitLab.

## Auth Choices Decide Which Transports You Can Use

There are four authentication methods, and they are not interchangeable. For local desktop use the README lists a Personal Access Token via GITLAB_PERSONAL_ACCESS_TOKEN as the simplest, and OAuth2 with GITLAB_USE_OAUTH as recommended for better security. For server deployments there is an MCP OAuth proxy via GITLAB_MCP_OAUTH for remote clients such as Claude.ai, and REMOTE_AUTHORIZATION for multi-user setups where each caller supplies a token.

There is a hard constraint buried in .env.example: SSE transport cannot be used with REMOTE_AUTHORIZATION. If you plan a multi-user remote deployment, that rules out the legacy SSE path and pushes you to Streamable HTTP. Transport priority is documented too: Streamable HTTP wins if STREAMABLE_HTTP=true, then SSE if SSE=true and STREAMABLE_HTTP is not true, then stdio as the fallback.

For OAuth without a localhost callback, the README documents a standalone device-flow command, zereight-mcp-gitlab auth, requiring GitLab 17.9 or later (17.2 to 17.8 need oauth2_device_grant_flow), followed by GITLAB_USE_OAUTH=true when starting the server. This matters for SSO environments and remote shells where a browser redirect to 127.0.0.1:8888/callback cannot complete.

One more token option sits in .env.example: GITLAB_JOB_TOKEN, which sends the token as a JOB-TOKEN header instead of Authorization: Bearer, intended for GitLab CI pipelines. The README does not spell out which tools behave differently under a job token's narrower scope, so treat that path as unverified until you try it.

## Self-Hosted GitLab, Docker and the API URL Detail

Self-hosting is a stated goal: "works with custom GitLab instances, proxy settings, and dynamic API URL routing". The relevant knobs are GITLAB_API_URL and the HTTP_PROXY, HTTPS_PROXY and NO_PROXY variables in .env.example, with NO_PROXY defaulting to localhost,127.0.0.1.

Watch the URL shape. The .env.example opens with GITLAB_API_URL=https://gitlab.com, but the CLI argument example in the README passes --api-url=https://gitlab.com/api/v4. The remote authorization block in .env.example also uses the /api/v4 form. If you point the server at an instance root when it expects the v4 path, or the reverse, expect failures that look like authentication problems rather than URL problems. This is the single easiest thing to get wrong on a first self-hosted setup.

The Dockerfile builds in two stages: node:22.21.1-bookworm-slim for the build, node:22.21.1-alpine for the release image, with EXPOSE 3002 and ENTRYPOINT ["node", "build/index.js"]. The comment at the top of the file explains the base image split: node:*-alpine uses musl and "crashes under QEMU arm64 emulation" during npm ci, so the builder stage stays on glibc. If you build multi-platform images yourself, that comment is the reason to keep the builder on bookworm-slim rather than simplifying to one Alpine stage.

There is also a stateless/ directory and a documented stateless mode for multi-pod HPA deployments, which is the configuration to look at if you intend to run more than one replica behind a load balancer. The README does not document session affinity requirements for the non-stateless SSE path, so horizontal scaling of the stateful transports is an open question.

## Where It Is the Wrong Tool, and What to Use Instead

The clearest limitation is the tool surface itself. 229 tools is a lot of context and a lot of selection ambiguity for a model. The README's answer is discover_tools and starting small, but that shifts the burden onto the agent to discover correctly. If you want a deliberately small set of grouped operations, this server is not shaped that way, and its own comparison table points at grouped community servers for that case.

Second, this is not a replacement for the GitLab CLI. glab is a command-line tool a human or a script invokes directly; zereight/gitlab-mcp is a server that an MCP client connects to. If your workflow is a shell script in CI, glab or plain curl against the GitLab API is simpler, has no Node runtime requirement and no MCP handshake. The MCP layer only pays for itself when the caller is a model choosing tools at runtime.

Third, the documentation is uneven. The README is explicit about auth, transports and client setup, and points to a hosted docs site for environment variables and the full tool reference. But it does not document rollback, and it does not describe what happens to in-flight requests when a Streamable HTTP session is interrupted. The CHANGELOG.md and the release list are where you would look for behavioural changes between versions, and the version numbers move fast enough that pinning matters.

A real alternative worth naming is the community GitLab MCP server the README compares against, which uses roughly 50 to 60 grouped browse_* and manage_* tools and often requires Node.js 24 or later. The difference is not quality, it is granularity: grouped tools mean fewer choices per turn, granular tools mean more precise composition. Pick based on how your agent behaves, not on tool count.

## Licence, Maintenance and Upgrade Cost

The licence is MIT, declared in both package.json and the LICENSE file, and the README links it from the badge row. MIT is permissive: you can use, modify and redistribute the server, including in commercial settings, provided the copyright notice and licence text are preserved. That is the general shape of the licence, not legal advice for your situation.

The Node requirement is >=18.17.0 with npm >=9.0.0 per package.json, and the Dockerfile pins Node 22.21.1. That is a lower floor than the community alternative's "often >=24" noted in the comparison table, which matters if you are deploying into an environment with an older runtime.

Upgrade cost is the part to think about before adopting. Releases landed on 2026-08-22, 2026-08-27 and 2026-08-28, and package.json shows 2.1.61 while the newest release in the supplied history is 2.1.54. With a moving tool surface and a tool count in the hundreds, a version bump can change what your agent sees. The README's own recommendation to pin npx to a specific version, and the GITLAB_DISABLE_VERSION_CHECK=true switch for the stderr notice, both point at the same practice: pin in your client config, read CHANGELOG.md before bumping, and re-check that your agent still finds the tools it depends on. There is no documented migration guide for tool renames, so budget for that manually.

## Conclusion

Adopt zereight/gitlab-mcp if your client is an MCP-speaking agent and you want GitLab merge request review, pipeline and issue work driven from inside that agent, on gitlab.com or a self-hosted instance. Do not adopt it if you want a small, stable tool surface, if you need a published rollback procedure, or if you have not first decided between PAT, OAuth2 and remote authorization, because that choice determines which transports are even available. Before you commit, run the server once with --permission-mode=readonly against a test project and confirm your client actually lists the tools you intend to call.

## FAQ

### What is zereight/gitlab-mcp?

It is an MCP server published as @zereight/mcp-gitlab that exposes GitLab projects, merge requests, issues, pipelines, wiki, releases, tags and milestones to MCP clients. It supports stdio, SSE and Streamable HTTP transports and is licensed MIT.

### How do I install the GitLab MCP server?

The README gives two paths: brew tap zereight/gitlab-mcp followed by brew install zereight/gitlab-mcp/zereight-mcp-gitlab, or npm install -g @zereight/mcp-gitlab. Without a global install you can pin npx to a version, for example npx -y @zereight/mcp-gitlab@2.1.53.

### Can I use a self-hosted GitLab MCP server?

Yes. The README states it works with custom GitLab instances, proxy settings and dynamic API URL routing, configured through GITLAB_API_URL plus the HTTP_PROXY, HTTPS_PROXY and NO_PROXY variables. Note that the README's CLI example uses the https://gitlab.com/api/v4 form while .env.example opens with https://gitlab.com.

### How do I set up zereight/gitlab-mcp in VS Code or Cursor?

The README links dedicated setup guides for VS Code and Cursor under docs/clients/. Both follow the general pattern of installing the package and referencing zereight-mcp-gitlab in the client's MCP configuration.

### Does zereight/gitlab-mcp work with Claude Code?

Yes, the repository includes a Claude Code Setup Guide under docs/clients/claude-code.md, and the README lists Claude Code among the supported clients alongside VS Code, Copilot, Codex and Cursor. For remote clients such as Claude.ai there is a separate MCP OAuth proxy mode.

### Does GitLab itself provide an official MCP server?

The README does not describe an official GitLab MCP server. zereight/gitlab-mcp is a third-party MIT-licensed project published on npm as @zereight/mcp-gitlab, and the README compares it against a community CQRS-style alternative rather than an official one.

## Sources

- [Official documentation](https://zereight.github.io/gitlab-mcp/)
- [Official README](https://github.com/zereight/gitlab-mcp#readme)
- [Project repository](https://github.com/zereight/gitlab-mcp)
- [Release notes](https://github.com/zereight/gitlab-mcp/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/zereight-gitlab-mcp
