GitLab MCP Server

编码与调试

by ttpears

让 LLM 深度探索和分析 GitLab 实例,支持搜索、代码浏览、Issue 管理,并兼容自托管与 GitLab.com 认证。

什么是 GitLab MCP Server

让 LLM 深度探索和分析 GitLab 实例,支持搜索、代码浏览、Issue 管理,并兼容自托管与 GitLab.com 认证。

README

GitLab MCP Server

npm version npm downloads CI Container License: MIT

<img src="assets/logo.svg" width="80" align="right" alt="gitlab-mcp"/>

A community MCP server for GitLab — works with any GitLab tier (Free, Premium, Ultimate), no GitLab Duo required. PAT-based auth. Streamable HTTP and stdio transports.

bash
npx @ttpears/gitlab-mcp-server

Choose your deployment

You're runningGo to
Claude Code or another IDE/AI tool, just for youSolo IDE
LibreChat for a team with a service-account read tokenLibreChat — service-account reads
LibreChat where every operation should use the calling user's tokenLibreChat — strict per-user

Solo IDE

Claude Code (recommended)

bash
claude mcp add gitlab \
  --env GITLAB_URL=https://gitlab.com \
  --env GITLAB_TOKEN=glpat-your-pat \
  -- npx -y @ttpears/gitlab-mcp-server

--scope controls where the configuration lives:

  • --scope local (default) — only this user, only this project
  • --scope user — shared across all of your projects
  • --scope project — written to .mcp.json in the project root, intended for team check-in

For team check-in, use a ${VAR} placeholder so the PAT itself stays out of git:

json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": ["-y", "@ttpears/gitlab-mcp-server"],
      "env": {
        "GITLAB_URL": "https://gitlab.com",
        "GITLAB_TOKEN": "${GITLAB_TOKEN}"
      }
    }
  }
}

Each contributor exports GITLAB_TOKEN in their shell; Claude Code expands it on launch.

Cold start

If launching via npx adds noticeable latency, install once:

bash
npm install -g @ttpears/gitlab-mcp-server

…and replace npx -y @ttpears/gitlab-mcp-server with gitlab-mcp-server in your config.

Claude Desktop

Option A — MCPB one-click install: download gitlab-mcp-community-${VERSION}.mcpb from the latest GitHub Release and drag it onto the Claude Desktop window. Fill in your GitLab URL and a Personal Access Token when prompted; the token is stored in your OS keychain. Use a read_api-scoped PAT for read-only access, or an api-scoped PAT to also allow writes (create_issue, create_merge_request, etc.).

Option B — manual config: add to claude_desktop_config.json:

json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": ["-y", "@ttpears/gitlab-mcp-server"],
      "env": {
        "GITLAB_URL": "https://gitlab.com",
        "GITLAB_TOKEN": "glpat-your-pat"
      }
    }
  }
}

LibreChat — service-account reads

A read-only service token covers reads (so anyone in the workspace can ask questions). Each user supplies their own PAT for writes through LibreChat's customUserVars.

LibreChat's documented extension point is docker-compose.override.yml — the fragments below assume you're adding gitlab-mcp there alongside LibreChat's own api, mongodb, etc.

.env

env
GITLAB_URL=https://gitlab.example.com
GITLAB_READ_TOKEN=glpat-readonly-service-token   # read_api scope only

Use https://gitlab.com for SaaS GitLab; use your own host for self-hosted.

docker-compose.override.yml

yaml
services:
  gitlab-mcp:
    image: ghcr.io/ttpears/gitlab-mcp:1.14.0
    env_file:
      - .env
    networks:
      - librechat
    restart: unless-stopped

env_file reads GITLAB_URL and GITLAB_READ_TOKEN from .env. No port mapping needed — LibreChat's api container reaches gitlab-mcp over the shared librechat network. Add ports: ["8008:8008"] only if you need to hit it from the host (e.g. for curl http://localhost:8008/health).

Then:

bash
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d gitlab-mcp api

api is restarted alongside so it re-reads librechat.yaml.

librechat.yaml

yaml
mcpServers:
  gitlab:
    type: streamable-http
    url: http://gitlab-mcp:8008/
    startup: false                # don't connect until the user supplies their PAT
    initTimeout: 30000
    timeout: 120000
    headers:
      Authorization: "Bearer {{GITLAB_PAT}}"
      X-GitLab-Url: "{{GITLAB_URL_OVERRIDE}}"   # only honored when GITLAB_PIN_HOST=false (default pins to GITLAB_URL)
    customUserVars:
      GITLAB_PAT:
        title: "GitLab Personal Access Token"
        description: "Your GitLab PAT with api scope. Used for issues, MRs, and comments you create or edit."
      GITLAB_URL_OVERRIDE:
        title: "GitLab URL (optional)"
        description: "Leave blank to use the workspace default. Override only if your account is on a different GitLab instance."

initTimeout / timeout are forgiving defaults for slower internal networks and large schemas — drop them if SaaS GitLab feels snappy.

Server-side env vars use ${VAR}. Per-user vars use {{VAR}}. They are not interchangeable.


LibreChat — strict per-user

Every call must carry a user PAT. No service-account fallback. Reads as well as writes are gated on the user's token.

Add MCP Server (UI path — recommended)

  1. Host gitlab-mcp somewhere LibreChat can reach. For a quick standalone host:

    bash
    docker run -d --restart unless-stopped \
      -p 8008:8008 \
      -e GITLAB_URL=https://gitlab.example.com \
      --name gitlab-mcp \
      ghcr.io/ttpears/gitlab-mcp:1.14.0
    

    Or, when running alongside LibreChat in the same compose project, drop it into docker-compose.override.yml (no token env vars):

    yaml
    services:
      gitlab-mcp:
        image: ghcr.io/ttpears/gitlab-mcp:1.14.0
        environment:
          GITLAB_URL: https://gitlab.example.com
        networks:
          - librechat
        restart: unless-stopped
    
  2. In LibreChat → MCP ServersAdd MCP Server:

    • URL: https://your-host/ (or http://gitlab-mcp:8008/ if same network)
    • Authentication: API Key → check User provides key → header format Bearer
    • Save
  3. Each user fills in their PAT through the MCP Tool Select Dialog when configuring an agent.

librechat.yaml equivalent

yaml
mcpServers:
  gitlab:
    type: streamable-http
    url: http://gitlab-mcp:8008/
    startup: false
    initTimeout: 30000
    timeout: 120000
    headers:
      Authorization: "Bearer {{GITLAB_PAT}}"
    customUserVars:
      GITLAB_PAT:
        title: "GitLab Personal Access Token"
        description: "Your GitLab PAT with api scope."

The container needs no env-configured token at all in this mode — every request is rejected unless Authorization: Bearer … is present.


Hosting for a remote LibreChat

The server speaks plain HTTP. For LibreChat-as-a-service or any cross-network deployment, terminate TLS at a reverse proxy. Common patterns:

  • Caddy — auto-TLS via Let's Encrypt:

    caddyfile
    mcp.example.com {
      reverse_proxy gitlab-mcp:8008
    }
    
  • Traefik — Docker labels on the gitlab-mcp service.

  • Cloudflare Tunnel — no public IP needed; expose gitlab-mcp:8008 through the tunnel.

The Authorization and Mcp-Session-Id headers must pass through unchanged. Most defaults handle this fine.


OAuth for remote users

For a publicly hosted instance where each user signs in with their own GitLab identity — and modern MCP clients (Claude.ai, Claude Code) connect with no manual token setup — enable brokered OAuth 2.1. The server then acts as its own OAuth Authorization Server in front of GitLab:

  • advertises Protected Resource Metadata (RFC 9728) and Authorization Server Metadata (RFC 8414) at the standard .well-known endpoints,
  • supports Dynamic Client Registration (RFC 7591), so clients self-register,
  • runs authorization-code + PKCE against both the MCP client and GitLab (dual-PKCE) behind one fixed GitLab callback,
  • gates the MCP endpoints with bearer validation — unauthenticated requests get 401 + WWW-Authenticate pointing at the resource metadata (the discovery trigger),
  • mints its own opaque tokens and keeps each user's GitLab token server-side (no token passthrough).

Setup

  1. Register one GitLab application (instance/group/user → Applications):

    • Redirect URI: https://<your-host>/gitlab/callback
    • Scopes: api (read + write) or read_api
    • Confidential: yes (recommended) → you get a client secret; or mark it public for PKCE-only.
  2. Run the server (HTTP mode) with no GITLAB_TOKEN — identity comes from each user's OAuth login:

    bash
    MCP_TRANSPORT=http GITLAB_MCP_PORT=8008 \
    GITLAB_URL=https://gitlab.example.com \
    GITLAB_MCP_OAUTH=true \
    MCP_SERVER_URL=https://gitlab-mcp.example.com \
    GITLAB_OAUTH_CLIENT_ID=<application id> \
    GITLAB_OAUTH_CLIENT_SECRET=<application secret> \
    GITLAB_OAUTH_SCOPES=api \
    npx -y @ttpears/gitlab-mcp-server
    
  3. Point an MCP client at https://gitlab-mcp.example.com/ — it discovers the metadata, registers, and walks the user through GitLab sign-in automatically.

MCP_SERVER_URL must be HTTPS (terminate TLS at your reverse proxy) and must match the host the GitLab redirect URI is registered under. Token/registration state is in-memory, so run a single instance (or add a shared store) per issuer.


How this differs from GitLab's official MCP server

GitLab ships an official MCP server (Beta) that requires Premium/Ultimate and GitLab Duo.

This serverGitLab official
GitLab tierFree, Premium, UltimatePremium / Ultimate only
GitLab Duo requiredNoYes
AuthPAT, or brokered OAuth 2.1 + Dynamic Client RegistrationOAuth 2.0 Dynamic Client Registration
Transportstdio + streamable HTTPstdio + HTTP
Multi-userPer-call PAT, OAuth per-user, or service-account fallbackOAuth per-user
GraphQL schema discoveryYes — introspect & run custom queriesNo
Repository browsing & file readingYesNo
Update issues / MRs / notesYesNo (create only)
Delete issues / notesYesNo
CI/CD pipeline managementYesYes
MR diffs & commitsYesYes
Time tracking & timelogsYesNo
MR reviewer & approval statusYesNo
Iteration / milestone trackingYesNo
Project statistics dashboardYesNo
Group member listingYesNo
Semantic code searchNoYes (requires additional setup)

Choose this server for Free/CE, GraphQL flexibility, LibreChat multi-user, or brokered OAuth without GitLab Duo. Choose the official server for Premium+Duo with semantic code search.


Tools

Search & Discovery

ToolDescription
search_gitlabGlobal search across projects, issues, and merge requests
search_projectsFind repositories by name or description
search_issuesSearch issues globally or within a project (filter by assignee, author, labels, state)
search_merge_requestsFind merge requests by username or within a project
search_usersFind team members and contributors
search_groupsDiscover groups and organizations
search_labelsSearch labels in a project or group
list_group_membersList group members with access levels
browse_repositoryExplore directory structure and files
get_file_contentRead file contents for code analysis

Read Operations

ToolDescription
get_projectDetailed project information
get_issuesList project issues with pagination
get_merge_requestsList project merge requests with pagination
get_merge_request_pipelinesGet CI/CD pipelines for a merge request
get_pipeline_jobsGet jobs for a specific pipeline
get_merge_request_diffsGet diff statistics for a merge request
get_merge_request_commitsGet commits for a merge request
get_notesGet notes/comments on an issue or merge request
list_milestonesList milestones with progress statistics
list_iterationsList iterations/sprints (Premium/Ultimate)
get_time_trackingGet time estimate, spent, and timelogs
get_merge_request_reviewersGet MR approval and reviewer status
get_project_statisticsAggregate project stats dashboard
get_user_issuesGet all issues assigned to a user
get_user_merge_requestsGet MRs authored by or assigned to a user
get_work_itemFetch a work item (issue, task, epic, incident, OKR) by ID with full widget data
list_work_itemsList work items in a group or project, filtered by type and state
list_broadcast_messagesList instance-wide broadcast messages
get_broadcast_messageGet a specific broadcast message by ID
list_my_todosAuthenticated user's to-do inbox — notifications about issues, MRs, mentions, reviews requested
list_my_eventsAuthenticated user's activity feed — pushes, MRs, comments, approvals
list_user_eventsAnother user's public activity feed by username or ID
list_project_eventsActivity events for a specific project
resolve_pathResolve a path to a project or group
get_available_queriesDiscover available GraphQL operations
execute_custom_queryRun custom GraphQL queries

Write Operations (require user authentication)

ToolDescription
create_issueCreate new issues
create_merge_requestCreate new merge requests
create_noteAdd a comment/note to an issue or merge request
update_issueUpdate title, description, assignees, labels, due date
update_merge_requestUpdate title, description, assignees, reviewers, labels
update_noteEdit the body of an existing comment
delete_issueDelete an issue (issue author or maintainer required)
delete_noteDelete a comment (note author or maintainer required)
manage_pipelineRetry or cancel a CI/CD pipeline
create_broadcast_messageCreate a broadcast message (instance admin)
update_broadcast_messageUpdate a broadcast message (instance admin)
delete_broadcast_messageDelete a broadcast message (instance admin)
mark_todo_doneMark a single to-do item as done
mark_all_todos_doneMark all pending to-do items as done for the authenticated user
restore_todoRestore a previously-done to-do item back to pending

Configuration

Environment variables

VariableDescriptionDefault
GITLAB_URLGitLab instance URLhttps://gitlab.com
GITLAB_TOKENFull-access fallback token (reads + writes)
GITLAB_READ_TOKENRead-only fallback token (writes always rejected)
GITLAB_PIN_HOSTForce every request to GITLAB_URL, ignoring per-call/header gitlabUrl (SSRF guard). Set false to serve multiple instancestrue
GITLAB_ALLOW_SHARED_ESCAPE_HATCHAllow execute_custom_query / execute_rest_read / execute_rest_write to run on the shared token (otherwise they require per-call credentials)false
GITLAB_MAX_PAGE_SIZEMaximum items per page (1–100)50
GITLAB_TIMEOUTRequest timeout in milliseconds30000
GITLAB_MAX_CONCURRENCYMax concurrent in-flight requests to GitLab (excess queue, never rejected). 0 = unlimited16
GITLAB_ANALYTICS_MAX_PROJECTSCap on projects scanned per group-analytics fan-out (logs when bounded)500
GITLAB_MCP_PORTHTTP server port8008
MCP_TRANSPORTTransport mode (http for LibreChat)stdio
TRUST_PROXYExpress trust proxy when behind a reverse proxy (hop count like 1, boolean, or IP/subnet list). Needed for correct per-IP OAuth rate limiting behind traefik/nginxunset
GITLAB_MCP_OAUTHEnable brokered OAuth 2.1 (HTTP mode) — see OAuth for remote usersfalse
MCP_SERVER_URLPublic HTTPS URL of this server (OAuth issuer/resource id) — required when OAuth is on
GITLAB_OAUTH_CLIENT_IDGitLab application id — required when OAuth is on
GITLAB_OAUTH_CLIENT_SECRETGitLab application secret (omit for a public/PKCE-only app)
GITLAB_OAUTH_SCOPESSpace-separated GitLab scopes to requestapi
GITLAB_OAUTH_CALLBACK_PATHPath of the fixed GitLab redirect URI/gitlab/callback
GITLAB_OAUTH_ALLOWED_GROUPSRestrict the connector to members of these GitLab groups (comma/space separated full-paths; subgroups included). Empty = any authenticated userunset
REDIS_URLBack OAuth broker state with Redis (survives redeploys, enables >1 replica). Unset = in-memoryunset
REDIS_KEY_PREFIXBase namespace for Redis keys (issuer host is appended)gitlab-mcp

GITLAB_TOKEN and GITLAB_READ_TOKEN are mutually exclusive; setting both is a startup error.

Removed in 1.14.0

  • GITLAB_AUTH_MODE — the three-way enum is gone. Pick your deployment shape by which env var you set; see Choose your deployment.
  • GITLAB_SHARED_ACCESS_TOKEN — rename to GITLAB_TOKEN (full access) or GITLAB_READ_TOKEN (read-only).

Old env vars trigger a deprecation warning at startup and are otherwise ignored.


Troubleshooting

"This operation requires authentication" / "Write operation requires a user token":

  • For LibreChat: check the user filled in their PAT in the MCP Tool Select Dialog (or in their customUserVars).
  • For Claude Code: confirm GITLAB_TOKEN is set in the MCP server's env block.
  • If you set GITLAB_READ_TOKEN, write operations against it are rejected by design — supply per-call user creds for writes.

Connection issues with LibreChat:

  • type: streamable-http (not sse).
  • URL is the Docker service name (http://gitlab-mcp:8008/), not localhost, when LibreChat and gitlab-mcp share a Docker network.
  • docker logs gitlab-mcp shows session init and request lines.

Schema introspection failed:

  • GitLab 12.0+ with GraphQL API enabled.
  • Verify GITLAB_URL is reachable from the container.

Debug logging:

bash
NODE_ENV=development GITLAB_TOKEN=glpat-... npm start

Health check (HTTP mode):

bash
curl http://localhost:8008/health

Changelog

See CHANGELOG.md. Releases before 1.14.0 are in GitHub releases.

License

MIT

常见问题

GitLab MCP Server 是什么?

让 LLM 深度探索和分析 GitLab 实例,支持搜索、代码浏览、Issue 管理,并兼容自托管与 GitLab.com 认证。

相关 Skills

前端设计

by anthropics

Universal
热门

面向组件、页面、海报和 Web 应用开发,按鲜明视觉方向生成可直接落地的前端代码与高质感 UI,适合做 landing page、Dashboard 或美化现有界面,避开千篇一律的 AI 审美。

想把页面做得既能上线又有设计感,就用前端设计:组件到整站都能产出,难得的是能避开千篇一律的 AI 味。

编码与调试
未扫描165.3k

网页应用测试

by anthropics

Universal
热门

用 Playwright 为本地 Web 应用编写自动化测试,支持启动开发服务器、校验前端交互、排查 UI 异常、抓取截图与浏览器日志,适合调试动态页面和回归验证。

借助 Playwright 一站式验证本地 Web 应用前端功能,调 UI 时还能同步查看日志和截图,定位问题更快。

编码与调试
未扫描165.3k

网页构建器

by anthropics

Universal
热门

面向复杂 claude.ai HTML artifact 开发,快速初始化 React + Tailwind CSS + shadcn/ui 项目并打包为单文件 HTML,适合需要状态管理、路由或多组件交互的页面。

在 claude.ai 里做复杂网页 Artifact 很省心,多组件、状态和路由都能顺手搭起来,React、Tailwind 与 shadcn/ui 组合效率高、成品也更精致。

编码与调试
未扫描165.3k

相关 MCP Server

GitHub

编辑精选

by GitHub

热门

GitHub 是 MCP 官方参考服务器,让 Claude 直接读写你的代码仓库和 Issues。

这个参考服务器解决了开发者想让 AI 安全访问 GitHub 数据的问题,适合需要自动化代码审查或 Issue 管理的团队。但注意它只是参考实现,生产环境得自己加固安全。

编码与调试
89.1k

by Context7

热门

Context7 是实时拉取最新文档和代码示例的智能助手,让你告别过时资料。

它能解决开发者查找文档时信息滞后的问题,特别适合快速上手新库或跟进更新。不过,依赖外部源可能导致偶尔的数据延迟,建议结合官方文档使用。

编码与调试
60.0k

by tldraw

热门

tldraw 是让 AI 助手直接在无限画布上绘图和协作的 MCP 服务器。

这解决了 AI 只能输出文本、无法视觉化协作的痛点——想象让 Claude 帮你画流程图或白板讨论。最适合需要快速原型设计或头脑风暴的开发者。不过,目前它只是个基础连接器,你得自己搭建画布应用才能发挥全部潜力。

编码与调试
49.5k

评论