A side-by-side look at the Gitlab MCP Server and Gitlab Ci MCP MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Gitlab MCP Server for version control work as a local process; choose Gitlab Ci MCP for version control as a local process. You can also run both side by side in one mcpServers block.
GITLAB_TOKEN.gitlab_execute_action, gitlab_find_action.GITLAB_URL, GITLAB_TOKEN, GITLAB_PROJECT_PATH, GITLAB_SSL_VERIFY, GITLAB_NO_PROXY_DOMAINS.gitlab_list_branches, gitlab_list_tags, gitlab_compare_branches.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Version Control | Version Control |
| Quality signal | 63/100 · Good | 57/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | Not declared | API key required |
| Pricing | Not declared | BYOK (pay the provider) |
| Required env vars | GITLAB_TOKEN | GITLAB_URLGITLAB_TOKENGITLAB_PROJECT_PATHGITLAB_SSL_VERIFYGITLAB_NO_PROXY_DOMAINS |
| Verified owner | Community listing | Community listing |
| GitHub stars | 45 | 2 |
| Directory activity | 2 views 0 installs 0 upvotes | 3 views 0 installs 0 upvotes |
| Tools | 2 | 23 |
| Full listing | View Gitlab MCP Server | View Gitlab Ci MCP |
gitlab_execute_actionExecute one GitLab catalog action by canonical ID or alias. Always pass params as an object. Destructive actions require top-level confirm=true. Use find first only when action or params are unclear. Example: {"action":"issue.list","params":{"project_id":"group/project"}}gitlab_find_actionSearch the local GitLab action catalog. Read-only and no GitLab API call. Use when the action ID or params are unclear. Returns schemas, hints, destructive flags, and execute examples. Example: {"query":"issue list"}gitlab_list_branchesList branches of a project, optionally filtered by substring.
Includes ``default``, ``protected`` and ``merged`` flags, and the short id
of the tip commit with its title and date.
Examples:
- "List all branches with 'release' in name" → ``search='release'``
- "Next page of branches" → ``page=2``
- Don't use when you want to check if a specific branch exists by exact name —
use ``gitlab_get_file`` on that ref and look at the error instead.
gitlab_list_tagsList tags of a project, newest first.
Useful for release-note generation or checking the last shipped version.
Examples:
- "What was the last release tag" → default call, take the first item
- "All v2.x releases" → ``search='v2.'``
gitlab_compare_branchesCompare two branches — returns up to 30 commits and the list of changed files.
Use for "what's in ``release/x.y`` vs ``master``?" or for release-note drafting.
Examples:
- "What's new in release/1.5 vs master" → ``source='release/1.5'``, ``target='master'``
- Don't use to fetch full diffs of an MR — use ``gitlab_get_merge_request_changes``.
gitlab_list_merge_requestsList merge requests of a project, optionally filtered by state.
Examples:
- "What MRs are open right now" → default (state='opened')
- "What merged last week" → ``state='merged'`` then filter by ``updated_at`` client-side
- "Everything regardless of state" → ``state='all'``
- Don't use when you have an MR IID — use ``gitlab_get_merge_request`` for detail.
gitlab_get_merge_requestGet full information about a merge request by internal ID (``iid``).
Includes state, branches, author, assignees, reviewers, labels, conflict
status, description and timestamps.
Examples:
- "Show me the description and state of !42" → ``mr_iid=42``
- Don't use to see changed files — use ``gitlab_get_merge_request_changes``.
gitlab_get_merge_request_changesList changed files in a merge request with truncated diffs (2KB per file).
Useful for code-review-style queries ("what changed in !42?"). Diffs beyond
2KB are truncated — fetch the raw file via ``gitlab_get_file`` for full
content.
Examples:
- "What did MR !42 change" → ``mr_iid=42``
- If you need full content of a changed file, use ``gitlab_get_file``
with the MR's source branch.
gitlab_create_merge_requestCreate a merge request from ``source_branch`` into ``target_branch``.
**Not idempotent**: creates a new MR each call. Check existing MRs first
via ``gitlab_list_merge_requests`` if you want to avoid duplicates.
Examples:
- "Open an MR from feature/login to master" → ``source_branch='feature/login'``
- "Open a WIP MR with a label" → ``title='Draft: ...'``, ``labels=['wip']``
- Don't use to merge an already-open MR — use ``gitlab_merge_mr``.
gitlab_merge_mrPerform the actual merge if GitLab reports the MR can be merged.
**Destructive**: writes to the target branch. Checks ``merge_status`` first
and returns ``status='cannot_merge'`` if conflicts exist or pipelines are
required.
Examples:
- "Merge !42" → ``mr_iid=42``
- Don't call without checking ``gitlab_get_merge_request`` first when you suspect conflicts.
gitlab_list_pipelinesList recent pipelines of a project, newest first.
Use for triage ("show failed pipelines on master"), release readiness checks,
or feeding pipeline IDs into follow-up calls. Read-only and idempotent.
Returns ``PipelinesListOutput``: ``project``, ``count``, ``pagination`` and
``pipelines[]`` (each ``PipelineSummary``). The tool result additionally
carries a markdown table in its text content.
Examples:
- "Show failed pipelines on master" → ``status='failed'``, ``ref='master'``
- "Last nightly schedule runs" → ``source='schedule'``
- "Second page of pipelines" → ``page=2``
- Don't use when you have a specific pipeline ID — use ``gitlab_get_pipeline`` instead.
gitlab_get_pipelineGet a single pipeline with full timing details.
Useful right after ``gitlab_list_pipelines`` — lists only return summaries.
Returns status, ref, source, durations (queued/total), and started/finished timestamps.
Examples:
- "Why was pipeline 123 slow" → check ``queued_duration`` and ``duration`` fields
- "Is pipeline 456 still running" → look at ``status``
- Don't use to see individual jobs — use ``gitlab_get_pipeline_jobs``.
gitlab_get_pipeline_jobsList jobs of a pipeline with stage, status, duration and web URL.
Use after noticing a failed pipeline to drill down into which specific job
broke and fetch its log via ``gitlab_get_job_log``.
Examples:
- "What jobs are in pipeline 123" → ``pipeline_id=123``
- "Which job failed in pipeline 456" → filter result by ``status='failed'`` client-side
- Don't use for overall pipeline status — use ``gitlab_get_pipeline`` instead.
gitlab_get_job_logFetch the trace/log of a job, with optional regex filter.
Two modes:
* Default: return the last ``tail`` lines (token-efficient, good for
"why did this just fail?").
* With ``grep_pattern``: return only matching lines with
``grep_context`` surrounding lines on each side — ideal for finding
"ERROR" / "Traceback" in megabyte-scale CI logs without pulling the
whole trace into context.
Examples:
- "Why did job 789 fail" → default tail=100, look at the end of the log
- "Show me the first stage output of job 789" → ``tail=5000`` and scan for stage separator
- "Find every Traceback in job 789" → ``grep_pattern='Traceback'``, ``grep_context=5``
- "All ERROR lines from job 789" → ``grep_pattern='ERROR|FAIL'``
Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"jmrplens-gitlab-mcp-server": {
"command": "npx",
"args": [
"-y",
"@jmrp.io/gitlab-mcp-server"
],
"env": {
"GITLAB_TOKEN": "YOUR_GITLAB_TOKEN_HERE"
}
}
}
}
{
"mcpServers": {
"mshegolev-gitlab-ci-mcp": {
"command": "uvx",
"args": [
"--from",
"gitlab-ci-mcp",
"gitlab-ci-mcp"
],
"env": {
"GITLAB_URL": "YOUR_GITLAB_URL_HERE",
"GITLAB_TOKEN": "YOUR_GITLAB_TOKEN_HERE",
"GITLAB_PROJECT_PATH": "YOUR_GITLAB_PROJECT_PATH_HERE",
"GITLAB_SSL_VERIFY": "YOUR_GITLAB_SSL_VERIFY_HERE",
"GITLAB_NO_PROXY_DOMAINS": "YOUR_GITLAB_NO_PROXY_DOMAINS_HERE"
}
}
}
}