Branches
Branch management in one project: read and list branches, create one from a branch, tag or commit, delete one or every branch already merged, and protect a branch with the access levels allowed to push and to merge, then read, update or remove that protection.
branch.rule_list reads the branch rules GitLab assembles over GraphQL: for each protected branch pattern, who may push and merge, its approval rules and its external status checks, in one answer where the REST API needs several calls.
Sample questions
Section titled “Sample questions”- “List the branches of project 42”
- “Create a branch called feature-login from main”
- “Delete every branch already merged into main”
- “Who can push to main?”
How to call it
Section titled “How to call it”- Dynamic, the default surface: call
gitlab_execute_actionwithactionset to the action’s ID, such asbranch.create, and its parameters inparams.gitlab_find_actionfinds an ID from a description of the task. - Meta (
GITLAB_MCP_TOOL_SURFACE=meta): callgitlab_branchwithactionset to the action’s name, such ascreate, and its parameters inparams. - Individual (
GITLAB_MCP_TOOL_SURFACE=individual): call the action’s own tool, such asgitlab_branch_create, with its parameters as the arguments.
Availability
Section titled “Availability”Every tier serves the whole group, on self-managed instances and on GitLab.com alike.
Read-only actions: 5 of 11, the ones a deployment in read-only mode keeps.
Actions
Section titled “Actions”The description of each action, and of each of its parameters, is the text the server serves for it on the default surface, quoted as served. A destructive action runs only once confirmed, unless GITLAB_MCP_YOLO_MODE (or AUTOPILOT) skips that step: the dynamic surface needs confirm: true on gitlab_execute_action, and the other two take a confirm parameter or the client’s prompt (Destructive actions). A parameter followed by a tier in parentheses is served only from that tier on.
| Action | Individual |
|---|---|
branch.create | gitlab_branch_create |
branch.delete | gitlab_branch_delete |
branch.delete_merged | gitlab_branch_delete_merged |
branch.get | gitlab_branch_get |
branch.get_protected | gitlab_protected_branch_get |
branch.list | gitlab_branch_list |
branch.list_protected | gitlab_protected_branches_list |
branch.protect | gitlab_branch_protect |
branch.rule_list | gitlab_list_branch_rules |
branch.unprotect | gitlab_branch_unprotect |
branch.update_protected | gitlab_protected_branch_update |
branch.create
Section titled “branch.create”Create a branch from a source ref (branch, tag, or commit SHA). Returns: the created branch with its head commit object, protection and default flags, and web URL. See also:
branch.list,merge_request.create,repository.compare.
- Meta-tool:
gitlab_branch, actioncreate - Individual tool:
gitlab_branch_create - Tier: Free
- Behavior: writes, not idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | New branch name (param ‘branch_name’ not ‘branch’ or ‘name’) |
project_id | string/integer | yes | Project ID or URL-encoded path |
ref | string | yes | Branch name, tag, or commit SHA to create from |
branch.delete
Section titled “branch.delete”Delete a single branch by name. Returns: a success confirmation. Fails for protected or default branches. See also:
branch.list,branch.unprotect.
- Meta-tool:
gitlab_branch, actiondelete - Individual tool:
gitlab_branch_delete - Tier: Free
- Behavior: writes, destructive (needs confirmation), idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Branch name to delete |
project_id | string/integer | yes | Project ID or URL-encoded path |
branch.delete_merged
Section titled “branch.delete_merged”Delete all branches merged into the default branch. Returns: a success confirmation. Protected and default branches are skipped. See also:
branch.list,merge_request.list.
- Meta-tool:
gitlab_branch, actiondelete_merged - Individual tool:
gitlab_branch_delete_merged - Tier: Free
- Behavior: writes, destructive (needs confirmation), idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
project_id | string/integer | yes | Project ID or URL-encoded path |
branch.get
Section titled “branch.get”Get a single branch by name. Returns: the branch with protection, default, and merged flags, push/merge permissions, the head commit object, and web URL. See also:
branch.list,branch.protect,branch.unprotect.
- Meta-tool:
gitlab_branch, actionget - Individual tool:
gitlab_branch_get - Tier: Free
- Behavior: read-only, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Branch name to retrieve (param ‘branch_name’ not ‘branch’) |
project_id | string/integer | yes | Project ID or URL-encoded path |
branch.get_protected
Section titled “branch.get_protected”Get a single protected branch or wildcard rule by name. Returns: the rule with push, merge, and unprotect access-level arrays, allow-force-push, and CODEOWNERS-approval flags. See also:
branch.list_protected,branch.update_protected,branch.unprotect.
- Meta-tool:
gitlab_branch, actionget_protected - Individual tool:
gitlab_protected_branch_get - Tier: Free
- Behavior: read-only, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Name of the protected branch |
project_id | string/integer | yes | Project ID or URL-encoded path |
branch.list
Section titled “branch.list”List repository branches in one project with optional search/regex filtering, ordering, and offset or keyset pagination. Returns: matching branches with protection, default, merged flags, the head commit object, and pagination metadata. See also:
branch.get,branch.create,repository.compare.
- Meta-tool:
gitlab_branch, actionlist - Individual tool:
gitlab_branch_list - Tier: Free
- Behavior: read-only, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
project_id | string/integer | yes | Project ID or URL-encoded path |
order_by | string | no | Column to order results by (e.g. name, updated) |
page | integer | no | Page number to fetch, 1-based. Defaults to 1. Use the next_page field from the previous response to paginate forward. |
page_token | string | no | Keyset pagination cursor: record id at which to fetch the next page, taken from the previous keyset response. Only used when pagination=‘keyset’. |
pagination | string | no | Pagination method: ‘keyset’ for keyset-based pagination on large ordered result sets, or ‘offset’ (the default). Keyset avoids deep-offset cost. |
per_page | integer | no | Items per page. Defaults to 20, minimum 1, maximum 100. Use 100 to minimize round trips when the result set is large. |
regex | string | no | Filter branches whose names match this regular expression |
search | string | no | Filter branches by name (substring match) |
sort | string (asc, desc) | no | Sort direction (asc, desc) |
branch.list_protected
Section titled “branch.list_protected”List protected branches and wildcard rules for a project with optional search, ordering, and offset or keyset pagination. Returns: protected rules with push/merge/unprotect access-level arrays and pagination metadata. See also:
branch.get_protected,branch.protect,branch.update_protected.
- Meta-tool:
gitlab_branch, actionlist_protected - Individual tool:
gitlab_protected_branches_list - Tier: Free
- Behavior: read-only, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
project_id | string/integer | yes | Project ID or URL-encoded path |
order_by | string | no | Column to order results by (e.g. name) |
page | integer | no | Page number to fetch, 1-based. Defaults to 1. Use the next_page field from the previous response to paginate forward. |
page_token | string | no | Keyset pagination cursor: record id at which to fetch the next page, taken from the previous keyset response. Only used when pagination=‘keyset’. |
pagination | string | no | Pagination method: ‘keyset’ for keyset-based pagination on large ordered result sets, or ‘offset’ (the default). Keyset avoids deep-offset cost. |
per_page | integer | no | Items per page. Defaults to 20, minimum 1, maximum 100. Use 100 to minimize round trips when the result set is large. |
search | string | no | Filter protected branches by name (substring match) |
sort | string (asc, desc) | no | Sort direction (asc, desc) |
branch.protect
Section titled “branch.protect”Protect a branch or wildcard with push/merge/unprotect access levels and optional fine-grained allowed_to_push/merge/unprotect entries. Returns: the protected rule with its access-level arrays. Idempotent: returns the existing rule when the branch is already protected. See also:
branch.unprotect,branch.get_protected,branch.update_protected.
- Meta-tool:
gitlab_branch, actionprotect - Individual tool:
gitlab_branch_protect - Tier: Free
- Behavior: writes, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Branch name or wildcard (e.g. ‘main’ or ‘release/*’) |
project_id | string/integer | yes | Project ID or URL-encoded path |
allow_force_push | boolean | no | Allow force push to this branch |
allowed_to_merge | object[] | no | Fine-grained merge access entries (by user, group, deploy key, or access level) |
allowed_to_push | object[] | no | Fine-grained push access entries (by user, group, deploy key, or access level) |
allowed_to_unprotect | object[] | no | Fine-grained unprotect access entries (by user, group, deploy key, or access level) |
code_owner_approval_required (Premium) | boolean | no | Require CODEOWNERS approval for changes to matching files |
merge_access_level | integer (0, 30, 40, 60) | no | Access level for merge: 0=No access, 30=Developer, 40=Maintainer, 60=Admin (GitLab Self-Managed only). Use an integer. |
push_access_level | integer (0, 30, 40, 60) | no | Access level for push: 0=No access, 30=Developer, 40=Maintainer, 60=Admin (GitLab Self-Managed only). Use an integer. |
unprotect_access_level | integer (30, 40, 60) | no | Access level allowed to unprotect: 30=Developer, 40=Maintainer, 60=Admin (GitLab Self-Managed only). 0 (No access) is not valid here. Use an integer. |
branch.rule_list
Section titled “branch.rule_list”List a project’s aggregated branch protection rules by full project path. Returns: each branch rule with its id, matched pattern, default and protected flags, matching branch count, branch protection settings (who may push, merge and unprotect, allow force push, code-owner approval required, security-policy flags), approval rules with eligible approvers, external status checks, and keyset pagination metadata. Pages forward only: this GitLab connection takes first and after, and rejects last and before. See also:
branch.list_protected,branch.get_protected,project.get.
- Meta-tool:
gitlab_branch, actionrule_list - Individual tool:
gitlab_list_branch_rules - Tier: Free
- Behavior: read-only, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
project_path | string | yes | required,Project full path (e.g. my-group/my-project) |
after | string | no | Cursor for forward pagination (from previous response end_cursor) |
first | integer | no | Number of items to return (default 20, max 100) |
branch.unprotect
Section titled “branch.unprotect”Remove protection from a branch (idempotent). Returns: a status and message confirming protection removed or already absent. See also:
branch.protect,branch.get_protected,branch.delete.
- Meta-tool:
gitlab_branch, actionunprotect - Individual tool:
gitlab_branch_unprotect - Tier: Free
- Behavior: writes, destructive (needs confirmation), idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Name of the protected branch to remove |
project_id | string/integer | yes | Project ID or URL-encoded path |
branch.update_protected
Section titled “branch.update_protected”Update an existing protected branch rule: allow-force-push, CODEOWNERS approval, rename, or fine-grained allowed_to_push/merge/unprotect entries. Returns: the updated rule with its access-level arrays. See also:
branch.get_protected,branch.list_protected,branch.protect.
- Meta-tool:
gitlab_branch, actionupdate_protected - Individual tool:
gitlab_protected_branch_update - Tier: Free
- Behavior: writes, idempotent
| Parameter | Type | Mandatory | Description |
|---|---|---|---|
branch_name | string | yes | Name of the protected branch to update |
project_id | string/integer | yes | Project ID or URL-encoded path |
allow_force_push | boolean | no | Allow force push to this branch |
allowed_to_merge | object[] | no | Fine-grained merge access entries (by user, group, deploy key, or access level) |
allowed_to_push | object[] | no | Fine-grained push access entries (by user, group, deploy key, or access level) |
allowed_to_unprotect | object[] | no | Fine-grained unprotect access entries (by user, group, deploy key, or access level) |
code_owner_approval_required (Premium) | boolean | no | Require CODEOWNERS approval |
name | string | no | New name or wildcard for the protected branch rule (rename) |