{
  "markdown": "# gitlab-ci-mcp\n\n<!-- mcp-name: io.github.mshegolev/gitlab-ci-mcp -->\n\n[![PyPI](https://img.shields.io/pypi/v/gitlab-ci-mcp.svg?logo=pypi&logoColor=white)](https://pypi.org/project/gitlab-ci-mcp/)\n[![Python](https://img.shields.io/pypi/pyversions/gitlab-ci-mcp.svg?logo=python&logoColor=white)](https://pypi.org/project/gitlab-ci-mcp/)\n[![License: MIT](https://img.shields.io/pypi/l/gitlab-ci-mcp.svg)](LICENSE)\n[![Downloads](https://static.pepy.tech/badge/gitlab-ci-mcp/month)](https://pepy.tech/project/gitlab-ci-mcp)\n\nMCP server for GitLab CI/CD. Lets an LLM agent (Claude Code, Cursor, OpenCode, DevX Agent, etc.) work with pipelines, jobs, schedules, branches, tags, merge requests and repository files.\n\nPython, [FastMCP](https://github.com/modelcontextprotocol/python-sdk), stdio transport.\n\nWorks with any GitLab — SaaS `gitlab.com` or self-hosted / on-prem. Designed with corporate networks in mind: configurable `NO_PROXY` handling, optional SSL-verify toggle, per-project scoping via env vars.\n\n## Design highlights\n\n- **Tool annotations** — every tool carries `readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint` so MCP clients can classify operations (e.g. ask for confirmation only on destructive ones like `gitlab_merge_mr`, `gitlab_delete_schedule`).\n- **Structured output on every tool** — each tool declares a TypedDict return type, so FastMCP auto-generates an `outputSchema` and every result carries `structuredContent` alongside a pre-rendered markdown text block. Clients that can render structured data use it; agents that prefer compact text get the markdown. No `response_format` parameter needed.\n- **Structured errors** — authentication, 404, 403, 429 (rate-limit), 5xx, missing-env errors are converted to actionable `ToolError` messages (e.g. _\"GitLab authentication failed… verify GITLAB_TOKEN has `api` scope\"_) and surfaced as `isError=True` results.\n- **Pydantic input validation** — every argument has typed constraints (ranges, lengths, literals) auto-exposed as JSON Schema.\n- **Project scoping per call** — every tool accepts an optional `project_path` that overrides `GITLAB_PROJECT_PATH` for cross-project queries.\n- **Pagination** — list tools return a `pagination` block with `page`, `total`, `has_more`, `next_page` and a next-page hint in the markdown footer.\n- **MCP Context integration** — `gitlab_pipeline_health` and `gitlab_get_job_log` are `async` and emit `info` logs / `report_progress` events through the MCP Context so clients can show progress bars.\n- **MCP Resources** — `gitlab://project/info` and `gitlab://project/ci-config` mirror common lookups for clients that prefer the Resource model over tools.\n- **Lifespan management** — `python-gitlab` HTTP sessions are closed cleanly on server shutdown via an `asynccontextmanager` lifespan hook.\n- **Log grep** — `gitlab_get_job_log` accepts `grep_pattern` + `grep_context` (surrounding lines) for regex-filtering megabyte-scale CI logs without pulling the whole trace into agent context.\n\n### Threading model\n\nFastMCP automatically runs synchronous tools in a worker thread\n(`anyio.to_thread.run_sync`), so they do not block the asyncio event loop —\n`python-gitlab` is a synchronous library and wrapping every call in\n`asyncio.to_thread` ourselves would be ceremony. Tools that benefit from the\nMCP Context (progress, info logs) are written as `async def` and explicitly\nwrap `python-gitlab` calls with `asyncio.to_thread`.\n\n## Features\n\n23 tools covering the everyday CI/CD surface:\n\n**Pipelines**\n`gitlab_list_pipelines` · `gitlab_get_pipeline` · `gitlab_get_pipeline_jobs` · `gitlab_get_job_log` · `gitlab_trigger_pipeline` · `gitlab_retry_pipeline` · `gitlab_cancel_pipeline` · `gitlab_pipeline_health`\n\n**Schedules**\n`gitlab_list_schedules` · `gitlab_create_schedule` · `gitlab_update_schedule` · `gitlab_delete_schedule`\n\n**Branches & tags**\n`gitlab_list_branches` · `gitlab_list_tags` · `gitlab_compare_branches`\n\n**Merge requests**\n`gitlab_list_merge_requests` · `gitlab_get_merge_request` · `gitlab_get_merge_request_changes` · `gitlab_create_merge_request` · `gitlab_merge_mr`\n\n**Repository & project**\n`gitlab_get_file` · `gitlab_list_repository_tree` · `gitlab_project_info`\n\n### Pipeline health report\n\n`gitlab_pipeline_health` returns a ready-to-read summary over 7/30 days:\n\n```\nLast 7d:  96.4%  up   | 27/28 success\nLast 30d: 92.1%       | 105/114 success\nLast 10:  success success success failed success ...\n```\n\nHandy for on-call / triage: `покажи health master за последние 7 дней`.\n\n## Installation\n\nRequires Python 3.10+.\n\n```bash\n# via uvx (recommended)\nuvx --from gitlab-ci-mcp gitlab-ci-mcp\n\n# or via pip/pipx\npipx install gitlab-ci-mcp\n```\n\n## Configuration\n\nAll config is via environment variables:\n\n| Variable | Required | Description |\n| --- | --- | --- |\n| `GITLAB_URL` | **yes** | Base URL, e.g. `https://gitlab.example.com` |\n| `GITLAB_TOKEN` | **yes** | Personal Access Token with `api` scope |\n| `GITLAB_PROJECT_PATH` | **yes** | Default project, e.g. `my-org/my-repo` |\n| `GITLAB_SSL_VERIFY` | no | `true` (default) / `false` |\n| `GITLAB_NO_PROXY_DOMAINS` | no | Comma-separated domains to add to `NO_PROXY` (useful in corp networks behind a local HTTP proxy — e.g. `.corp.example.com,gitlab.internal`) |\n\nEvery tool accepts an optional `project_path` arg that overrides `GITLAB_PROJECT_PATH` per call — useful for cross-project queries.\n\n## Claude Code\n\n**Full walkthrough:** [docs/claude-code.md](docs/claude-code.md) — prerequisites, two install paths, multi-project setup, self-hosted GitLab behind a corp proxy, troubleshooting, uninstall.\n\nShort version:\n\n```bash\nclaude mcp add gitlab uvx --from gitlab-ci-mcp gitlab-ci-mcp \\\n  --env GITLAB_URL=https://gitlab.example.com \\\n  --env GITLAB_TOKEN=glpat-xxxxxx \\\n  --env GITLAB_PROJECT_PATH=my-org/my-repo\n```\n\nOr in `~/.claude.json` / project `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"gitlab\": {\n      \"type\": \"stdio\",\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"gitlab-ci-mcp\", \"gitlab-ci-mcp\"],\n      \"env\": {\n        \"GITLAB_URL\": \"https://gitlab.example.com\",\n        \"GITLAB_TOKEN\": \"${GITLAB_TOKEN}\",\n        \"GITLAB_PROJECT_PATH\": \"my-org/my-repo\",\n        \"GITLAB_SSL_VERIFY\": \"true\"\n      }\n    }\n  }\n}\n```\n\nCheck:\n\n```bash\nclaude mcp list\n# gitlab: uvx --from gitlab-ci-mcp gitlab-ci-mcp - ✓ Connected\n```\n\n## Cursor / OpenCode / DevX Agent\n\nSame idea — point the MCP config to `uvx --from gitlab-ci-mcp gitlab-ci-mcp` with the env vars above. See each tool's own MCP config syntax.\n\n## Example prompts\n\n```\nчто сломалось в последнем pipeline master\n```\n\n```\nпокажи health master за 7 дней для проекта my-org/other-repo\n```\n\n```\nсоздай MR из feature/foo в master с title \"feat: foo\"\n```\n\n```\nпокажи содержимое .gitlab-ci.yml из master\n```\n\n## Rate limits & connection reuse\n\nGitLab enforces a per-user rate limit (typically 2000 req/h for the REST API,\nconfigurable by the admin — see your instance's `/admin/application_settings/network`).\n\n- The server caches one `python-gitlab` HTTP session **per `project_path`**, so\n  repeated tool calls against the same project reuse the connection and do not\n  re-authenticate each time.\n- List tools default to `per_page=20` to keep a single call within a small\n  number of API requests.\n- If you hit a `429 Too Many Requests`, the error handler returns an actionable\n  message — wait and try again with larger `per_page` or fewer calls.\n\n## Self-hosted GitLab behind a corporate proxy\n\nWhen your laptop has a local HTTP proxy (e.g. `http://127.0.0.1:3128` for corp web access) but GitLab is on the intranet, the proxy intercepts and kills internal requests. Two options:\n\n1. Set `GITLAB_NO_PROXY_DOMAINS` — the server will add them to `NO_PROXY` at startup **and clear `HTTP_PROXY`/`HTTPS_PROXY` from its own process** so they don't affect GitLab traffic.\n2. Pass explicitly empty `HTTP_PROXY=\"\"` etc. in the MCP `env` section.\n\n## Development\n\n```bash\ngit clone https://github.com/mshegolev/gitlab-ci-mcp\ncd gitlab-ci-mcp\npython -m venv .venv && . .venv/bin/activate\npip install -e '.[dev]'\npytest\n```\n\nRun the server directly (stdio transport, waits on stdin for MCP messages):\n\n```bash\nGITLAB_URL=... GITLAB_TOKEN=... GITLAB_PROJECT_PATH=... gitlab-ci-mcp\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n## Acknowledgements\n\nBuilt on [python-gitlab](https://github.com/python-gitlab/python-gitlab) and the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).\n",
  "bytes": 8457,
  "sha": "7885daef78b274399ea66670881457d11119bfb67536eced756ec9b6127d6c52",
  "repo_slug": "mshegolev/gitlab-ci-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mshegolev_gitlab_ci_mcp_abc25266/readme"
}