GitLab MCP Server
Connect FlowTrux workflows to GitLab merge requests, review threads, CI pipelines, job logs, branches and files - gitlab.com or self-managed
The GitLab MCP server provides 13 tools for merge requests, line-anchored review comments, approvals, CI pipelines and job logs, branches, and reading and searching repository files. It works with gitlab.com and with self-managed GitLab (15.7 or newer).
Setup
- Create an access token in GitLab - a personal, group or project access token with the
apiscope. Theread_apiscope is enough if workflows only read. - In FlowTrux, go to Resources > MCP Servers > Add Server (OWNER or ADMIN) and choose GitLab.
- Give it a Name and fill in:
| Field | Required | Description |
|---|---|---|
| Base URL | No | https://gitlab.com by default; your instance's address for self-managed GitLab |
| Access Token | Yes | The token (glpat-…) |
- Under Available in workspaces, pick the workspaces, then click Add Server.
The token's role on a project decides what it may change: Developer or above for branches, merge requests and comments; Reporter can read and comment on a merge request but not push. A 403 means the role or scope is missing; a 404 means a wrong path or a project the token cannot see (GitLab hides private projects behind 404).
Addressing
- Projects are addressed by path -
group/project, with sub-groupsgroup/sub/project- or by numeric id. Pass the path as written. - Merge requests are addressed by their
iid: the number in the merge request's URL (!42→42), not the globalid.
Tools
Merge requests
list_merge_requests
List a project's merge requests, optionally filtered by state and/or source branch. Newest first.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
state | string | No | Filter by state (default opened). One of: opened, closed, merged, locked, all. |
source_branch | string | No | Only MRs whose source branch is exactly this name. |
per_page | number | No | Results per page (default 20, max 100). |
get_merge_request
Get one merge request: title, description, state, author, source/target branches, SHAs (diff_refs), pipeline summary, approval/merge status, web_url.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
get_merge_request_diff
The merge request's changed files with unified diffs. All changed files are always listed; the diff text is capped at about 200 KB in file order, and truncated says when the cap was reached.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
create_merge_request
Open a merge request. draft: true prefixes the title with Draft: so GitLab blocks merging until it is marked ready.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
source_branch | string | Yes | Branch with the changes. |
target_branch | string | Yes | Branch to merge into (e.g. main). |
title | string | Yes | MR title. |
description | string | No | MR description (Markdown). |
draft | boolean | No | Open as a draft (default false). |
labels | array of string | No | Label names to apply. |
remove_source_branch | boolean | No | Delete the source branch when merged (default false). |
approve_merge_request
Approve a merge request as the token's user. Fails with 401 if that user already approved or may not approve (for example the author, where self-approval is off).
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
Review comments
list_merge_request_notes
Human comments on an MR in chronological order — general notes and line-anchored review notes (with path/line). GitLab's system notes ("added 1 commit", label changes…) are dropped.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
add_merge_request_note
Post a general (not line-anchored) comment on an MR. Markdown.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
body | string | Yes | Comment text (GitLab-flavoured Markdown). |
add_merge_request_discussion
Start a review thread anchored to one line of one file in the MR diff. The diff_refs are fetched from the MR for you. line is a line number in the NEW version of the file (default) — pass side=old for a line that only exists in the old version (a deleted line).
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | Yes | Merge request IID - the number in the merge request URL (!42 → 42), not the global id. |
body | string | Yes | Comment text (Markdown). |
path | string | Yes | File path as it appears in the MR diff (new_path). |
line | number | Yes | Line number in the file to anchor the comment to. |
side | string | No | Which version of the file the line number refers to (default new). One of: new, old. |
A line-anchored comment on a line that is not part of the diff is rejected by GitLab - anchor it to a changed line or post a general note instead.
CI pipelines
get_pipeline_status
Latest pipeline for an MR (pass iid) or for a branch/tag/SHA (pass ref), with per-job status — enough to see which job failed and get its job id for get_job_log.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
iid | number | No | Merge request IID — takes precedence over ref. |
ref | string | No | Branch, tag or commit SHA. Used when iid is not given. |
get_job_log
The log of one CI job - its last ~20 KB, where the failure usually is. Get job_id from get_pipeline_status.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
job_id | number | Yes | Numeric job id. |
A pipeline in manual or pending has not failed - it is waiting.
Branches and files
create_branch
Create a branch from an existing branch, tag or commit SHA.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
branch | string | Yes | New branch name. |
ref | string | Yes | Source branch / tag / SHA to branch from (e.g. main). |
get_file
Read one file from the repository at a branch, tag or commit SHA, as text. For source and configuration files, not binaries.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
path | string | Yes | File path inside the repo, e.g. src/app.ts. |
ref | string | No | Branch, tag or SHA (default: the project's default branch). |
search_code
Search file contents in one project (GitLab blob search). Matches are whole words / substrings, not regex. Returns the file path and a snippet around each hit with its starting line.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | Project path group/project (sub-groups: group/sub/project) or numeric project id. |
query | string | Yes | Search text. Filter with GitLab syntax, e.g. foo filename:*.ts or foo path:src. |
ref | string | No | Branch / tag to search (default: default branch). |
per_page | number | No | Max results (default 20, max 100). |
Reviewing a merge request, step by step
get_merge_request- state, branches, the head pipeline and merge status.get_merge_request_diff- every changed file with its diff. Iftruncatedis true, files after the cut are listed with an empty diff; read one withget_fileat the merge request'sshawhen it matters.list_merge_request_notes- what reviewers already said.- Comment:
add_merge_request_discussionfor a remark on a specific line (lineis in the new file unlessside: "old"),add_merge_request_notefor anything general.
Examples
AI review on every new merge request:
Webhook (GitLab merge request event) → Action:MCP(gitlab, get_merge_request_diff, {project: "{{trigger.data.project.path_with_namespace}}", iid: {{trigger.data.object_attributes.iid}}}) → Agent (review the diff, tools: gitlab:add_merge_request_discussion, gitlab:add_merge_request_note)
Explain a failed pipeline:
Webhook (pipeline failed) → Action:MCP(gitlab, get_pipeline_status, {project: "group/app", ref: "main"}) → Loop over failed jobs → Action:MCP(gitlab, get_job_log, {project: "group/app", job_id: "{{item.id}}"}) → Agent (summarize the error) → Slack (post to #ci)
Open a draft merge request:
Manual → Action:MCP(gitlab, create_branch, {project: "group/app", branch: "docs/update", ref: "main"}) → … → Action:MCP(gitlab, create_merge_request, {project: "group/app", source_branch: "docs/update", target_branch: "main", title: "Update docs", draft: true})