{"id":43312681,"url":"https://github.com/ttpears/gitlab-mcp","last_synced_at":"2026-05-22T03:12:01.935Z","repository":{"id":310087337,"uuid":"1038654799","full_name":"ttpears/gitlab-mcp","owner":"ttpears","description":"Community GitLab MCP Server — works with any GitLab tier (Free/Premium/Ultimate), no Duo required. GraphQL schema discovery, repo browsing, multi-client support (Claude Code, LibreChat).","archived":false,"fork":false,"pushed_at":"2026-05-13T03:54:20.000Z","size":6286,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-13T05:26:09.226Z","etag":null,"topics":["claude","gitlab","graphql","llm","mcp","model-context-protocol"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@ttpears/gitlab-mcp-server","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ttpears.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-15T15:41:08.000Z","updated_at":"2026-05-13T03:53:53.000Z","dependencies_parsed_at":"2026-02-22T06:01:00.925Z","dependency_job_id":null,"html_url":"https://github.com/ttpears/gitlab-mcp","commit_stats":null,"previous_names":["ttpears/gitlab-mcp"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/ttpears/gitlab-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttpears%2Fgitlab-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttpears%2Fgitlab-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttpears%2Fgitlab-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttpears%2Fgitlab-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttpears","download_url":"https://codeload.github.com/ttpears/gitlab-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttpears%2Fgitlab-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33326805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-21T12:23:38.849Z","status":"online","status_checked_at":"2026-05-22T02:00:06.671Z","response_time":265,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","gitlab","graphql","llm","mcp","model-context-protocol"],"created_at":"2026-02-01T21:31:00.248Z","updated_at":"2026-05-22T03:12:01.925Z","avatar_url":"https://github.com/ttpears.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitLab MCP Server\n\n[![npm version](https://img.shields.io/npm/v/@ttpears/gitlab-mcp-server)](https://www.npmjs.com/package/@ttpears/gitlab-mcp-server)\n[![npm downloads](https://img.shields.io/npm/dm/@ttpears/gitlab-mcp-server)](https://www.npmjs.com/package/@ttpears/gitlab-mcp-server)\n[![CI](https://github.com/ttpears/gitlab-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ttpears/gitlab-mcp/actions/workflows/ci.yml)\n[![Container](https://img.shields.io/badge/ghcr.io-ttpears%2Fgitlab--mcp-2496ED?logo=docker\u0026logoColor=white)](https://github.com/ttpears/gitlab-mcp/pkgs/container/gitlab-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\u003cimg src=\"assets/logo.svg\" width=\"80\" align=\"right\" alt=\"gitlab-mcp\"/\u003e\n\nA 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.\n\n```bash\nnpx @ttpears/gitlab-mcp-server\n```\n\n---\n\n## Choose your deployment\n\n| You're running | Go to |\n|---|---|\n| Claude Code or another IDE/AI tool, just for you | [Solo IDE](#solo-ide) |\n| LibreChat for a team with a service-account read token | [LibreChat — service-account reads](#librechat--service-account-reads) |\n| LibreChat where every operation should use the calling user's token | [LibreChat — strict per-user](#librechat--strict-per-user) |\n\n---\n\n## Solo IDE\n\n### Claude Code (recommended)\n\n```bash\nclaude mcp add gitlab \\\n  --env GITLAB_URL=https://gitlab.com \\\n  --env GITLAB_TOKEN=glpat-your-pat \\\n  -- npx -y @ttpears/gitlab-mcp-server\n```\n\n`--scope` controls where the configuration lives:\n\n- `--scope local` (default) — only this user, only this project\n- `--scope user` — shared across all of your projects\n- `--scope project` — written to `.mcp.json` in the project root, intended for team check-in\n\nFor team check-in, use a `${VAR}` placeholder so the PAT itself stays out of git:\n\n```json\n{\n  \"mcpServers\": {\n    \"gitlab\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@ttpears/gitlab-mcp-server\"],\n      \"env\": {\n        \"GITLAB_URL\": \"https://gitlab.com\",\n        \"GITLAB_TOKEN\": \"${GITLAB_TOKEN}\"\n      }\n    }\n  }\n}\n```\n\nEach contributor exports `GITLAB_TOKEN` in their shell; Claude Code expands it on launch.\n\n### Cold start\n\nIf launching via `npx` adds noticeable latency, install once:\n\n```bash\nnpm install -g @ttpears/gitlab-mcp-server\n```\n\n…and replace `npx -y @ttpears/gitlab-mcp-server` with `gitlab-mcp-server` in your config.\n\n### Claude Desktop\n\n**Option A — MCPB one-click install:** download\n`gitlab-mcp-community-${VERSION}.mcpb` from the\n[latest GitHub Release](https://github.com/ttpears/gitlab-mcp/releases/latest)\nand drag it onto the Claude Desktop window. Fill in your GitLab URL and a\nPersonal Access Token when prompted; the token is stored in your OS keychain.\nUse a `read_api`-scoped PAT for read-only access, or an `api`-scoped PAT to\nalso allow writes (create_issue, create_merge_request, etc.).\n\n**Option B — manual config:** add to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"gitlab\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@ttpears/gitlab-mcp-server\"],\n      \"env\": {\n        \"GITLAB_URL\": \"https://gitlab.com\",\n        \"GITLAB_TOKEN\": \"glpat-your-pat\"\n      }\n    }\n  }\n}\n```\n\n---\n\n## LibreChat — service-account reads\n\nA read-only service token covers reads (so anyone in the workspace can ask\nquestions). Each user supplies their own PAT for writes through LibreChat's\n`customUserVars`.\n\nLibreChat's documented extension point is `docker-compose.override.yml` — the\nfragments below assume you're adding `gitlab-mcp` there alongside LibreChat's\nown `api`, `mongodb`, etc.\n\n### `.env`\n\n```env\nGITLAB_URL=https://gitlab.example.com\nGITLAB_READ_TOKEN=glpat-readonly-service-token   # read_api scope only\n```\n\nUse `https://gitlab.com` for SaaS GitLab; use your own host for self-hosted.\n\n### `docker-compose.override.yml`\n\n```yaml\nservices:\n  gitlab-mcp:\n    image: ghcr.io/ttpears/gitlab-mcp:1.14.0\n    env_file:\n      - .env\n    networks:\n      - librechat\n    restart: unless-stopped\n```\n\n`env_file` reads `GITLAB_URL` and `GITLAB_READ_TOKEN` from `.env`. No port\nmapping needed — LibreChat's `api` container reaches `gitlab-mcp` over the\nshared `librechat` network. Add `ports: [\"8008:8008\"]` only if you need to\nhit it from the host (e.g. for `curl http://localhost:8008/health`).\n\nThen:\n\n```bash\ndocker compose -f docker-compose.yml -f docker-compose.override.yml up -d gitlab-mcp api\n```\n\n`api` is restarted alongside so it re-reads `librechat.yaml`.\n\n### `librechat.yaml`\n\n```yaml\nmcpServers:\n  gitlab:\n    type: streamable-http\n    url: http://gitlab-mcp:8008/\n    startup: false                # don't connect until the user supplies their PAT\n    initTimeout: 30000\n    timeout: 120000\n    headers:\n      Authorization: \"Bearer {{GITLAB_PAT}}\"\n      X-GitLab-Url: \"{{GITLAB_URL_OVERRIDE}}\"   # optional; lets a user point at a different GitLab\n    customUserVars:\n      GITLAB_PAT:\n        title: \"GitLab Personal Access Token\"\n        description: \"Your GitLab PAT with api scope. Used for issues, MRs, and comments you create or edit.\"\n      GITLAB_URL_OVERRIDE:\n        title: \"GitLab URL (optional)\"\n        description: \"Leave blank to use the workspace default. Override only if your account is on a different GitLab instance.\"\n```\n\n`initTimeout` / `timeout` are forgiving defaults for slower internal networks\nand large schemas — drop them if SaaS GitLab feels snappy.\n\n\u003e Server-side env vars use `${VAR}`. Per-user vars use `{{VAR}}`. They are not interchangeable.\n\n---\n\n## LibreChat — strict per-user\n\nEvery call must carry a user PAT. No service-account fallback. Reads as well\nas writes are gated on the user's token.\n\n### Add MCP Server (UI path — recommended)\n\n1. Host gitlab-mcp somewhere LibreChat can reach. For a quick standalone host:\n\n   ```bash\n   docker run -d --restart unless-stopped \\\n     -p 8008:8008 \\\n     -e GITLAB_URL=https://gitlab.example.com \\\n     --name gitlab-mcp \\\n     ghcr.io/ttpears/gitlab-mcp:1.14.0\n   ```\n\n   Or, when running alongside LibreChat in the same compose project, drop it\n   into `docker-compose.override.yml` (no token env vars):\n\n   ```yaml\n   services:\n     gitlab-mcp:\n       image: ghcr.io/ttpears/gitlab-mcp:1.14.0\n       environment:\n         GITLAB_URL: https://gitlab.example.com\n       networks:\n         - librechat\n       restart: unless-stopped\n   ```\n\n2. In LibreChat → **MCP Servers** → **Add MCP Server**:\n   - **URL:** `https://your-host/` (or `http://gitlab-mcp:8008/` if same network)\n   - **Authentication:** API Key → check **User provides key** → header format **Bearer**\n   - **Save**\n\n3. Each user fills in their PAT through the MCP Tool Select Dialog when configuring an agent.\n\n### `librechat.yaml` equivalent\n\n```yaml\nmcpServers:\n  gitlab:\n    type: streamable-http\n    url: http://gitlab-mcp:8008/\n    startup: false\n    initTimeout: 30000\n    timeout: 120000\n    headers:\n      Authorization: \"Bearer {{GITLAB_PAT}}\"\n    customUserVars:\n      GITLAB_PAT:\n        title: \"GitLab Personal Access Token\"\n        description: \"Your GitLab PAT with api scope.\"\n```\n\nThe container needs no env-configured token at all in this mode — every\nrequest is rejected unless `Authorization: Bearer …` is present.\n\n---\n\n## Hosting for a remote LibreChat\n\nThe server speaks plain HTTP. For LibreChat-as-a-service or any cross-network\ndeployment, terminate TLS at a reverse proxy. Common patterns:\n\n- **Caddy** — auto-TLS via Let's Encrypt:\n\n  ```caddyfile\n  mcp.example.com {\n    reverse_proxy gitlab-mcp:8008\n  }\n  ```\n\n- **Traefik** — Docker labels on the `gitlab-mcp` service.\n- **Cloudflare Tunnel** — no public IP needed; expose `gitlab-mcp:8008` through the tunnel.\n\nThe `Authorization` and `Mcp-Session-Id` headers must pass through unchanged. Most defaults handle this fine.\n\n---\n\n## How this differs from GitLab's official MCP server\n\nGitLab ships an [official MCP server](https://docs.gitlab.com/user/gitlab_duo/model_context_protocol/mcp_server/) (Beta) that requires **Premium/Ultimate** and **GitLab Duo**.\n\n| | This server | GitLab official |\n|---|---|---|\n| **GitLab tier** | Free, Premium, Ultimate | Premium / Ultimate only |\n| **GitLab Duo required** | No | Yes |\n| **Auth** | Personal Access Token | OAuth 2.0 Dynamic Client Registration |\n| **Transport** | stdio + streamable HTTP | stdio + HTTP |\n| **Multi-user** | Per-call PAT or service-account fallback | OAuth per-user |\n| **GraphQL schema discovery** | Yes — introspect \u0026 run custom queries | No |\n| **Repository browsing \u0026 file reading** | Yes | No |\n| **Update issues / MRs / notes** | Yes | No (create only) |\n| **Delete issues / notes** | Yes | No |\n| **CI/CD pipeline management** | Yes | Yes |\n| **MR diffs \u0026 commits** | Yes | Yes |\n| **Time tracking \u0026 timelogs** | Yes | No |\n| **MR reviewer \u0026 approval status** | Yes | No |\n| **Iteration / milestone tracking** | Yes | No |\n| **Project statistics dashboard** | Yes | No |\n| **Group member listing** | Yes | No |\n| **Semantic code search** | No | Yes (requires additional setup) |\n\n**Choose this server** for Free/CE, GraphQL flexibility, or LibreChat\nmulti-user. **Choose the official server** for Premium+Duo with semantic\ncode search, or if you prefer OAuth.\n\n---\n\n## Tools\n\n### Search \u0026 Discovery\n| Tool | Description |\n|------|-------------|\n| `search_gitlab` | Global search across projects, issues, and merge requests |\n| `search_projects` | Find repositories by name or description |\n| `search_issues` | Search issues globally or within a project (filter by assignee, author, labels, state) |\n| `search_merge_requests` | Find merge requests by username or within a project |\n| `search_users` | Find team members and contributors |\n| `search_groups` | Discover groups and organizations |\n| `search_labels` | Search labels in a project or group |\n| `list_group_members` | List group members with access levels |\n| `browse_repository` | Explore directory structure and files |\n| `get_file_content` | Read file contents for code analysis |\n\n### Read Operations\n| Tool | Description |\n|------|-------------|\n| `get_project` | Detailed project information |\n| `get_issues` | List project issues with pagination |\n| `get_merge_requests` | List project merge requests with pagination |\n| `get_merge_request_pipelines` | Get CI/CD pipelines for a merge request |\n| `get_pipeline_jobs` | Get jobs for a specific pipeline |\n| `get_merge_request_diffs` | Get diff statistics for a merge request |\n| `get_merge_request_commits` | Get commits for a merge request |\n| `get_notes` | Get notes/comments on an issue or merge request |\n| `list_milestones` | List milestones with progress statistics |\n| `list_iterations` | List iterations/sprints (Premium/Ultimate) |\n| `get_time_tracking` | Get time estimate, spent, and timelogs |\n| `get_merge_request_reviewers` | Get MR approval and reviewer status |\n| `get_project_statistics` | Aggregate project stats dashboard |\n| `get_user_issues` | Get all issues assigned to a user |\n| `get_user_merge_requests` | Get MRs authored by or assigned to a user |\n| `get_work_item` | Fetch a work item (issue, task, epic, incident, OKR) by ID with full widget data |\n| `list_work_items` | List work items in a group or project, filtered by type and state |\n| `list_broadcast_messages` | List instance-wide broadcast messages |\n| `get_broadcast_message` | Get a specific broadcast message by ID |\n| `list_my_todos` | Authenticated user's to-do inbox — notifications about issues, MRs, mentions, reviews requested |\n| `list_my_events` | Authenticated user's activity feed — pushes, MRs, comments, approvals |\n| `list_user_events` | Another user's public activity feed by username or ID |\n| `list_project_events` | Activity events for a specific project |\n| `resolve_path` | Resolve a path to a project or group |\n| `get_available_queries` | Discover available GraphQL operations |\n| `execute_custom_query` | Run custom GraphQL queries |\n\n### Write Operations (require user authentication)\n| Tool | Description |\n|------|-------------|\n| `create_issue` | Create new issues |\n| `create_merge_request` | Create new merge requests |\n| `create_note` | Add a comment/note to an issue or merge request |\n| `update_issue` | Update title, description, assignees, labels, due date |\n| `update_merge_request` | Update title, description, assignees, reviewers, labels |\n| `update_note` | Edit the body of an existing comment |\n| `delete_issue` | Delete an issue (issue author or maintainer required) |\n| `delete_note` | Delete a comment (note author or maintainer required) |\n| `manage_pipeline` | Retry or cancel a CI/CD pipeline |\n| `create_broadcast_message` | Create a broadcast message (instance admin) |\n| `update_broadcast_message` | Update a broadcast message (instance admin) |\n| `delete_broadcast_message` | Delete a broadcast message (instance admin) |\n| `mark_todo_done` | Mark a single to-do item as done |\n| `mark_all_todos_done` | Mark all pending to-do items as done for the authenticated user |\n| `restore_todo` | Restore a previously-done to-do item back to pending |\n\n---\n\n## Configuration\n\n### Environment variables\n\n| Variable | Description | Default |\n|---|---|---|\n| `GITLAB_URL` | GitLab instance URL | `https://gitlab.com` |\n| `GITLAB_TOKEN` | Full-access fallback token (reads + writes) | — |\n| `GITLAB_READ_TOKEN` | Read-only fallback token (writes always rejected) | — |\n| `GITLAB_MAX_PAGE_SIZE` | Maximum items per page (1–100) | `50` |\n| `GITLAB_TIMEOUT` | Request timeout in milliseconds | `30000` |\n| `GITLAB_MCP_PORT` | HTTP server port | `8008` |\n| `MCP_TRANSPORT` | Transport mode (`http` for LibreChat) | `stdio` |\n\n`GITLAB_TOKEN` and `GITLAB_READ_TOKEN` are **mutually exclusive**; setting both is a startup error.\n\n### Removed in 1.14.0\n\n- `GITLAB_AUTH_MODE` — the three-way enum is gone. Pick your deployment shape by which env var you set; see [Choose your deployment](#choose-your-deployment).\n- `GITLAB_SHARED_ACCESS_TOKEN` — rename to `GITLAB_TOKEN` (full access) or `GITLAB_READ_TOKEN` (read-only).\n\nOld env vars trigger a deprecation warning at startup and are otherwise ignored.\n\n---\n\n## Troubleshooting\n\n**\"This operation requires authentication\" / \"Write operation requires a user token\":**\n- For LibreChat: check the user filled in their PAT in the MCP Tool Select Dialog (or in their `customUserVars`).\n- For Claude Code: confirm `GITLAB_TOKEN` is set in the MCP server's `env` block.\n- If you set `GITLAB_READ_TOKEN`, write operations against it are rejected by design — supply per-call user creds for writes.\n\n**Connection issues with LibreChat:**\n- `type: streamable-http` (not `sse`).\n- URL is the Docker service name (`http://gitlab-mcp:8008/`), not localhost, when LibreChat and gitlab-mcp share a Docker network.\n- `docker logs gitlab-mcp` shows session init and request lines.\n\n**Schema introspection failed:**\n- GitLab 12.0+ with GraphQL API enabled.\n- Verify `GITLAB_URL` is reachable from the container.\n\n**Debug logging:**\n\n```bash\nNODE_ENV=development GITLAB_TOKEN=glpat-... npm start\n```\n\n**Health check (HTTP mode):**\n\n```bash\ncurl http://localhost:8008/health\n```\n\n---\n\n## Changelog\n\nSee [`CHANGELOG.md`](./CHANGELOG.md). Releases before 1.14.0 are in\n[GitHub releases](https://github.com/ttpears/gitlab-mcp/releases).\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttpears%2Fgitlab-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttpears%2Fgitlab-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttpears%2Fgitlab-mcp/lists"}