Skip to content

Latest commit

 

History

History
606 lines (488 loc) · 124 KB

index.md

File metadata and controls

606 lines (488 loc) · 124 KB

Tools Reference

Complete catalog of every tool the GitLab MCP server exposes.

Which of these have an MCP tools/call test is tracked in Tool invocation coverage.

Setup first — if you haven't connected your Personal Access Token or OAuth credentials yet, follow one of the client setup guides or read Getting Started. Tools listed below will be unavailable until the server is authenticated.

Feature toggles

Toolsets are split into a default set (exposed automatically) and an opt-in set (must be explicitly enabled). The lists below are derived directly from TOOLSET_DEFINITIONS in tools/registry.ts.

Status Groups
Default — always exposed Core
Opt-in — must be enabled Projects & Namespaces, Projects & Files, Branches & Commits, Groups, Merge Requests, Issues, Labels, Work Items, CI Lint, Pipelines, Jobs & Deployments (legacy USE_PIPELINE=true is deprecated; removed in next major (v3.0.0)), Milestones (legacy USE_MILESTONE=true is deprecated; removed in next major (v3.0.0)), Wiki (legacy USE_GITLAB_WIKI=true is deprecated; removed in next major (v3.0.0)), Releases, Tags, Users & Events, Variables, Webhooks, Search, Dependency Proxy, Vulnerabilities, GitLab Orbit, Snippets
Explicit opt-in — not included in all or discover_tools Raw API
Not a toolset — discover_tools is always exposed; execute_graphql needs GITLAB_TOOLS Meta & GraphQL

How to enable opt-in groups (any one is sufficient):

  • GITLAB_TOOLSETS=<group,…> — comma-separated toolset IDs.
  • GITLAB_TOOLSETS=all — enables every group except explicit-only toolsets (api).
  • GITLAB_TOOLSETS=merge_requests,issues,repositories,branches,projects,labels,ci,groups,users — restores the pre-lean default set.
  • GITLAB_TOOLS=<tool,…> — enables individual tools regardless of group, except explicit-only tools such as gitlab_api_request.
  • USE_PIPELINE, USE_MILESTONE, and USE_GITLAB_WIKI are deprecated (removed in next major (v3.0.0)). Use GITLAB_TOOLSETS=core,pipelines and GITLAB_TOOLS=validate_ci_lint,validate_project_ci_lint, GITLAB_TOOLSETS=core,milestones, or GITLAB_TOOLSETS=core,wiki. If you already set GITLAB_TOOLSETS, append the toolset to your existing list instead of replacing it. If GITLAB_TOOLS is already set, append validate_ci_lint,validate_project_ci_lint instead of replacing that list.
  • Call the discover_tools MCP tool at runtime to activate categories for the current session.

Permission modes control which tools are exposed:

  • GITLAB_PERMISSION_MODE=readonly — hides every write tool regardless of toggles. Mixed tools (execute_graphql, gitlab_api_request) stay listed; their handlers reject writes.
  • GITLAB_PERMISSION_MODE=modify — allows create/update but blocks delete and teardown tools: every delete_* tool, erase_pipeline_job, purge_dependency_proxy_cache, the destructive teardown verbs cancel_pipeline, cancel_pipeline_job, stop_environment, stop_stale_environments, unprotect_branch, unprotect_tag, plus push_files delete/move actions.
  • GITLAB_READ_ONLY_MODE=true is deprecated (removed in next major (v3.0.0)) — same as readonly; use GITLAB_PERMISSION_MODE=readonly instead.

The modify guard applies to typed tools (tools/list and tools/call) and to destructive mutations sent through execute_graphql: any top-level mutation field whose name contains a deletion verb (delete, destroy, remove, prune, purge, erase) or a teardown verb (revoke, cancel, stop, terminate, unprotect, disable, deactivate, drop, unschedule). See Environment Variables.

See Environment Variables and CLI Arguments for the full list.

Legend

Marker Meaning
📖 Read-only — fetches data, does not modify GitLab state. Safe to invoke freely.
📖✏️ Reads and writes — can query or mutate. execute_graphql and gitlab_api_request stay available in readonly mode, which rejects their writes. download_attachment and download_job_artifacts only read GitLab but save files to the local disk in stdio mode; readonly mode lists them and rejects any call that would write a file.
✏️ Writes — creates, updates, or deletes data on GitLab. Confirm intent before running.

Browse by group

Each group has its own page with full parameter tables — click any tool name to jump to its details, or click the group title for the per-group view.

Lean default starter set for common MR, issue, repository, branch, project, label, and identity workflows. (38 tools)

Tool What it does R/W
list_merge_requests List merge requests (without project_id: user's MRs; with project_id: project MRs). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request Get details of a merge request (merge_request_iid or source_branch required). Set include_summaries=true for deployment/commit/approval summaries. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_approval_state Get merge request approval details including approvers. Use this to inspect approval rules and approvers before deciding whether a merge request can be merged; use approve_merge_request to change approval state. It is read-only and returns the approval-state response, while missing requests, unsupported GitLab versions, and permission failures are reported as errors. 📖
list_merge_request_changed_files List changed file paths in a merge request without diff content (merge_request_iid or source_branch required). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_file_diff Get diffs for specific files from a merge request (merge_request_iid or source_branch required). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_merge_request_diffs List merge request diffs with pagination (merge_request_iid or source_branch required). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_diffs Get the changes/diffs of a merge request (merge_request_iid or source_branch required). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
mr_discussions List discussion items for a merge request. Use this to list complete discussion threads for a merge request; use get_merge_request_notes when only flat notes are needed. It is read-only and returns threaded discussion items, while invalid merge request identifiers, missing resources, and permission failures are reported as errors. 📖
get_merge_request_discussion Get a single discussion item for a merge request. Use this to fetch one known merge request discussion by discussion identifier; use mr_discussions for a collection and get_merge_request_note for a flat note. It is read-only and returns the discussion item or an error for an invalid identifier, missing discussion, or insufficient permission. 📖
get_merge_request_note Get a specific note for a merge request. Use this to fetch one known merge request note by note identifier; use get_merge_request_notes for a collection and mr_discussions for threaded context. It is read-only and returns the note object or an error for an invalid identifier, missing note, or insufficient permission. 📖
get_merge_request_notes List notes for a merge request. Use this to list flat notes on a merge request; use mr_discussions when thread structure and resolution state are required. It is read-only and returns note records, while invalid identifiers, missing resources, and pagination or permission errors are reported by GitLab. 📖
create_merge_request Create a new merge request. Use this to open a new merge request from an existing source branch to a target branch; use update_merge_request after it exists. The operation creates remote review state, requires project access, and returns the new merge request or a validation, permission, branch, or duplicate-related error. ✏️
create_merge_request_thread Create a new thread on a merge request. Use this to start a review thread on a merge request; use create_merge_request_note for an unthreaded note and create_merge_request_discussion_note to reply to an existing thread. The operation creates remote review content, requires note permission, and returns the discussion or a position/permission/validation error. ✏️
resolve_merge_request_thread Resolve a thread on a merge request. Use this to mark an existing merge request review thread resolved; use update_merge_request_discussion_note when the note text itself must change. The operation changes review state, requires permission to resolve discussions, and returns the updated discussion or a missing-thread/permission error. ✏️
update_merge_request Update a merge request (merge_request_iid or source_branch required). Use the create tool for new resources and a note tool for comments. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_issues List issues (default: created by current user; use scope='all' for all). Use this for issue management: list GitLab issues, optionally scoped with project_id. Use get_issue when the issue iid is already known and my_issues for issues assigned to the current user. It is read-only and paginated, requires issue read permission, and returns issue records or GitLab errors for invalid identifiers, missing resources, or rate limits. 📖
my_issues List issues assigned to the authenticated user. Use this for issue management: list issues assigned to the authenticated user. Use list_issues for project-wide or author-scoped listing and get_issue for one issue. Resolving the current user requires classic read_user or fine-grained User:Read. It is read-only and paginated, requires authentication, and returns assigned issue records or permission/rate-limit errors. 📖
get_issue Get details of a specific issue. Returns the issue with a slim nested milestone by default; set full_response=true for the complete milestone object. Use this for issue management: inspect one issue's fields; use list_issues or my_issues to discover issues first. It is read-only, requires issue read permission, and returns the issue or an error when the identifier is invalid, the issue is missing, or access is denied. 📖
create_issue Create a new issue. Use this to open a new issue; use update_issue for an existing issue and create_issue_note to add discussion without changing issue fields. The operation creates remote project data, requires issue creation permission, and returns the new issue or a validation, permission, or duplicate-related error. ✏️
update_issue Update an issue. Returns a slim confirmation by default; set full_response=true for the complete updated issue object. Use this to change fields on an existing issue; use update_issue_description_patch for a targeted description edit that avoids sending the full body, and use create_issue_note for discussion. The operation mutates issue state, requires issue-edit permission, and returns the updated issue or a validation/permission/conflict error. ✏️
create_issue_note Add a note to an issue, optionally replying to a discussion thread. Use this to add a note to an existing issue, optionally as a reply to a discussion; use update_issue for issue fields and create_note only when the generic endpoint is required. The operation creates remote discussion content, requires note permission, and returns the note or a missing-issue/thread/permission error. ✏️
list_issue_discussions List discussions for an issue. Use this to inspect threaded discussions for an issue; use list_issues for issue records and get_issue for one issue's fields. It is read-only and returns discussion items, while invalid identifiers, missing issues, and permission failures are reported as errors. 📖
update_issue_description_patch Apply a patch (search/replace or unified diff) to an issue description. Reduces token usage by allowing small changes without sending the full description. Supports dry_run to preview changes and create_note to summarize updates. Use this for a targeted search/replace or unified-diff change to an issue description; use dry_run before applying an uncertain patch and create_note when an audit summary is wanted. It changes the issue description when not dry-running, requires issue-edit permission, and returns the patch result or a mismatch/validation/permission error. ✏️
get_file_contents Get contents of a file or directory from a GitLab project. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_repository_tree List files and directories in a repository. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
search_repositories Search for GitLab projects. If the identifier is known, use a typed get or list tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
get_branch Get branch details (commit, protection status). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_branches List branches in project with search filter. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_commits List repository commits with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_commit Get details of a specific commit. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_commit_diff Get changes/diffs of a specific commit. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_file_blame Get git blame for a file at a given ref. Each entry maps a contiguous range of source lines to the commit that last changed them (id, author, authored_date, message). Use range_start/range_end to limit blame to specific lines. 📖
get_project Get details of a specific project. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_projects List projects accessible by the current user. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
list_project_members List members of a GitLab project. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_labels List labels for a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
whoami Get current authenticated user details. Use this to identify the authenticated GitLab user; use get_user or get_users when looking up another user. It requires classic read_user or fine-grained User:Read. It is read-only and returns the current user profile, while missing credentials or GitLab permission failures are reported as errors. 📖
health_check Verify server status and authentication. Always reports the MCP server version (mcp_server_version). When authenticated, also reports the GitLab instance version from GET /api/v4/version (version, revision, enterprise). Version lookup failures do not fail the health check — those fields are omitted. Use this to verify server connectivity and authentication before making GitLab requests; use whoami when the authenticated user's identity is the goal. A 403 from GET /user with an insufficient_scope error means the token is accepted but User API scope is missing (read_user or fine-grained User:Read); the check stays ok, sets user_api_warning, and omits version metadata. Rate-limit and authentication-ban 403 responses stay unauthenticated. It does not mutate GitLab state and returns server/authentication status plus GitLab version details when available. Connection failures with no HTTP response return status error, authenticated false, and an error object (kind tls, dns, timeout, or network, plus code and message) instead of a protocol error. 📖

Project/namespace listing, member queries, group iterations, and server health. (11 tools)

Opt-in. Enable via GITLAB_TOOLSETS=projects (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 4 of these tools (get_project, list_projects, list_project_members, health_check) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
get_project Get details of a specific project. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_projects List projects accessible by the current user. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
update_project Update project settings such as description, visibility, default branch, and feature access levels. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_project_members List members of a GitLab project. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_group_members List members of a GitLab group with optional name or username search. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_namespaces List all namespaces (users and groups) available to the current user. Filter by kind='group' for groups only. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
get_namespace Get details of a namespace (user or group) by ID or path. Groups are namespaces with kind='group'. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
verify_namespace Verify if a namespace path exists. Use parent_id to scope the check to a specific parent namespace — required for nested namespaces where the same path may exist under different parents. 📖
list_group_projects List projects in a group. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_group_iterations List group iterations with filtering options. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
health_check Verify server status and authentication. Always reports the MCP server version (mcp_server_version). When authenticated, also reports the GitLab instance version from GET /api/v4/version (version, revision, enterprise). Version lookup failures do not fail the health check — those fields are omitted. Use this to verify server connectivity and authentication before making GitLab requests; use whoami when the authenticated user's identity is the goal. A 403 from GET /user with an insufficient_scope error means the token is accepted but User API scope is missing (read_user or fine-grained User:Read); the check stays ok, sets user_api_warning, and omits version metadata. Rate-limit and authentication-ban 403 responses stay unauthenticated. It does not mutate GitLab state and returns server/authentication status plus GitLab version details when available. Connection failures with no HTTP response return status error, authenticated false, and an error object (kind tls, dns, timeout, or network, plus code and message) instead of a protocol error. 📖

Project search/creation/fork plus the Files API for reading and writing repository content without shelling out to git. (7 tools)

Opt-in. Enable via GITLAB_TOOLSETS=repositories (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 3 of these tools (search_repositories, get_file_contents, get_repository_tree) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
search_repositories Search for GitLab projects. If the identifier is known, use a typed get or list tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
create_repository Create a new GitLab project. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️
get_file_contents Get contents of a file or directory from a GitLab project. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
push_files Push multiple files in a single commit. Use this to commit several file changes atomically; use create_or_update_file when only one path is involved. Each file defaults to action create; optional per-file action (create/update/delete/move) and encoding (text/base64) are additive. GITLAB_PERMISSION_MODE=modify rejects delete and move. The operation writes repository history on the selected branch, requires repository write permission, and returns the commit result or a validation, conflict, or protected-branch error. ✏️
create_or_update_file Create or update a file in a GitLab project. Use this for a single repository file when you know whether the target path is new or already exists; use push_files for a multi-file commit. Optional encoding (text or base64) defaults to GITLAB_REPO_FILE_ENCODING so existing callers stay unchanged. The operation creates or updates remote content in a commit, requires repository write permission, and returns the commit result or a conflict/validation error. ✏️
fork_repository Fork a project to your account or specified namespace. Use this to create a copy of an existing project in the current user's namespace or a permitted namespace; use search_repositories or get_project to inspect projects without copying them. The operation creates a new project, requires fork permission, and returns the forked project or a namespace/permission error. ✏️
get_repository_tree List files and directories in a repository. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖

Branch management, commit listing/inspection, file blame, and CI commit-status manipulation. (15 tools)

Opt-in. Enable via GITLAB_TOOLSETS=branches (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 6 of these tools (get_branch, list_branches, list_commits, get_commit, get_commit_diff, get_file_blame) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
create_branch Create a new branch. Use this to create a branch from a branch, tag, or commit; use get_branch or list_branches to inspect branches and protect_branch to configure protection afterward. The operation changes remote repository state, requires branch-creation permission, and returns the new branch or a validation, missing-ref, protected-project, or already-exists error. project_id accepts a numeric ID or URL-encoded path, branch is the new name, and ref selects its starting revision. ✏️
get_branch Get branch details (commit, protection status). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_branches List branches in project with search filter. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
delete_branch Delete branch from project. Use this only after confirming the branch name and intended data loss; use get_branch or list_branches before deletion and never use it to remove branch protection. The operation permanently removes a remote branch, requires branch-delete permission, and returns the deletion result or a protected-branch, missing-resource, or permission error. ✏️
list_protected_branches List protected branches in a project, supports search filter. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_protected_branch Get details of a single protected branch (access levels, force push settings). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
protect_branch Protect a repository branch (set push/merge/unprotect access levels). Use this to create or update protection rules for a branch or wildcard; use get_protected_branch to inspect existing rules first. The operation changes who may push, merge, or unprotect, may enable force-push or code-owner settings, requires maintainer-level permission, and returns the protection rule or a validation/permission error. ✏️
unprotect_branch Remove protection from a previously protected branch. Use this to remove protection from an existing branch; use protect_branch to change access levels without removing the rule. The operation changes repository security controls, requires permission to manage protected branches, and returns the result or an error when the branch is missing or policy forbids the change. ✏️
update_default_branch Change the default branch of a project. Use this to change which branch GitLab treats as the project's default; use create_branch to create a branch rather than changing project defaults. The operation changes project settings and may affect clone, merge request, and CI defaults, requires project-maintainer permission, and returns the updated project or a validation/permission error. ✏️
list_commits List repository commits with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_commit Get details of a specific commit. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_commit_diff Get changes/diffs of a specific commit. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_file_blame Get git blame for a file at a given ref. Each entry maps a contiguous range of source lines to the commit that last changed them (id, author, authored_date, message). Use range_start/range_end to limit blame to specific lines. 📖
list_commit_statuses List statuses for a commit. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_commit_status Create or update the status of a commit. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Create new groups and subgroups. (1 tools)

Opt-in. Enable via GITLAB_TOOLSETS=groups (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
create_group Create new group or subgroup. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️

MR lifecycle — create, update, merge, approve, plus diff/conflict inspection and the full discussion/note/draft API. (46 tools)

Opt-in. Enable via GITLAB_TOOLSETS=merge_requests (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 17 of these tools (get_merge_request_approval_state, get_branch, list_branches, get_merge_request, get_merge_request_diffs, list_merge_request_changed_files, list_merge_request_diffs, get_merge_request_file_diff, update_merge_request, create_merge_request, list_merge_requests, mr_discussions, get_merge_request_discussion, get_merge_request_note, get_merge_request_notes, create_merge_request_thread, resolve_merge_request_thread) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
merge_merge_request Merge a merge request. Use this only after checking the merge request approval, conflict, and pipeline state; use approve_merge_request to approve rather than merge. The operation changes repository state and may squash commits, schedule auto-merge, or delete the source branch, so it requires merge permission and returns GitLab's merge result or a mergeability error. Pass sha from get_merge_request (sha or diff_refs.head_sha); GitLab 19.2+ groups may reject merges without it. ✏️
rebase_merge_request Rebase the source branch of a merge request onto its target branch. Use this when the source branch is behind its target branch; use get_merge_request_conflicts to inspect conflicts and merge_merge_request to merge. The operation rewrites the source branch history with a force push and requires permission to push to that branch. With wait true (default), it polls until the rebase ends and returns the merge request plus previous_sha (its sha before the rebase) and head_changed. head_changed: false means that the head did not move; merge_error gives the reason when GitLab sends one. merge_error can keep a message from an earlier attempt, so it alone does not prove that this attempt failed. If the rebase still runs after timeout_seconds, it returns a timeout error while GitLab continues the rebase. With wait false, it returns GitLab's enqueue response (rebase_in_progress true) at once. Set skip_ci to skip the CI pipeline for the rebased branch. ✏️
approve_merge_request Approve a merge request. Use this to record an approval on an existing merge request; it does not merge the request or change its source branch. The operation changes review state, may require re-authentication or approval permission, and returns the updated approval result or a permission/state error. ✏️
unapprove_merge_request Unapprove a merge request. Use this to remove the current user's approval from an existing merge request; use merge_merge_request only when you intend to merge. The operation changes review state and requires approval permission, and GitLab returns the updated result or an error when the request or approval is unavailable. ✏️
get_merge_request_approval_state Get merge request approval details including approvers. Use this to inspect approval rules and approvers before deciding whether a merge request can be merged; use approve_merge_request to change approval state. It is read-only and returns the approval-state response, while missing requests, unsupported GitLab versions, and permission failures are reported as errors. 📖
get_branch Get branch details (commit, protection status). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_branches List branches in project with search filter. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_conflicts Get the conflicts of a merge request. Use this to inspect merge conflicts before attempting merge_merge_request; it reports conflicts and does not resolve them. It is read-only, requires access to the project and merge request, and returns GitLab's conflict data or an error when the request cannot be evaluated. 📖
list_merge_request_pipelines List pipelines for a merge request with pagination. Use this to inspect pipelines associated with one merge request; use list_pipelines for project-wide pipeline filtering. It is read-only and paginated, requires project access, and returns pipeline records or GitLab errors for invalid identifiers, missing resources, or rate limits. 📖
get_merge_request Get details of a merge request (merge_request_iid or source_branch required). Set include_summaries=true for deployment/commit/approval summaries. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_diffs Get the changes/diffs of a merge request (merge_request_iid or source_branch required). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_merge_request_changed_files List changed file paths in a merge request without diff content (merge_request_iid or source_branch required). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_merge_request_diffs List merge request diffs with pagination (merge_request_iid or source_branch required). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_file_diff Get diffs for specific files from a merge request (merge_request_iid or source_branch required). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_merge_request_versions List all versions of a merge request. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_merge_request_version Get a specific version of a merge request. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
update_merge_request Update a merge request (merge_request_iid or source_branch required). Use the create tool for new resources and a note tool for comments. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_merge_request Create a new merge request. Use this to open a new merge request from an existing source branch to a target branch; use update_merge_request after it exists. The operation creates remote review state, requires project access, and returns the new merge request or a validation, permission, branch, or duplicate-related error. ✏️
list_merge_requests List merge requests (without project_id: user's MRs; with project_id: project MRs). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_group_merge_requests List merge requests across all projects of a group and its subgroups. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_branch_diffs Get diffs between two branches or commits. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
mr_discussions List discussion items for a merge request. Use this to list complete discussion threads for a merge request; use get_merge_request_notes when only flat notes are needed. It is read-only and returns threaded discussion items, while invalid merge request identifiers, missing resources, and permission failures are reported as errors. 📖
get_merge_request_discussion Get a single discussion item for a merge request. Use this to fetch one known merge request discussion by discussion identifier; use mr_discussions for a collection and get_merge_request_note for a flat note. It is read-only and returns the discussion item or an error for an invalid identifier, missing discussion, or insufficient permission. 📖
create_merge_request_note Add a new note to a merge request. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_merge_request_note Modify an existing merge request note. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_merge_request_note Delete an existing merge request note. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_merge_request_note Get a specific note for a merge request. Use this to fetch one known merge request note by note identifier; use get_merge_request_notes for a collection and mr_discussions for threaded context. It is read-only and returns the note object or an error for an invalid identifier, missing note, or insufficient permission. 📖
get_merge_request_notes List notes for a merge request. Use this to list flat notes on a merge request; use mr_discussions when thread structure and resolution state are required. It is read-only and returns note records, while invalid identifiers, missing resources, and pagination or permission errors are reported by GitLab. 📖
delete_merge_request_discussion_note Delete a discussion note on a merge request. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_merge_request_discussion_note Update a discussion note on a merge request. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_merge_request_discussion_note Add a new discussion note to an existing merge request thread. Use this to reply inside an existing merge request discussion; use create_merge_request_thread to start a new thread and create_merge_request_note for a top-level note. The operation creates remote review content, requires note permission, and returns the new note or a missing-discussion/position/permission error. ✏️
get_draft_note Get a single draft note from a merge request. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_draft_notes List draft notes for a merge request. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_draft_note Create a draft note for a merge request. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_draft_note Update an existing draft note. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_draft_note Delete a draft note. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
publish_draft_note Publish a single draft note. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
bulk_publish_draft_notes Publish all draft notes for a merge request. Optionally sets reviewer_state and posts a summary note (GitLab 19.2+). Can set reviewer_state even with no drafts. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_merge_request_thread Create a new thread on a merge request. Use this to start a review thread on a merge request; use create_merge_request_note for an unthreaded note and create_merge_request_discussion_note to reply to an existing thread. The operation creates remote review content, requires note permission, and returns the discussion or a position/permission/validation error. ✏️
resolve_merge_request_thread Resolve a thread on a merge request. Use this to mark an existing merge request review thread resolved; use update_merge_request_discussion_note when the note text itself must change. The operation changes review state, requires permission to resolve discussions, and returns the updated discussion or a missing-thread/permission error. ✏️
list_merge_request_emoji_reactions List all emoji reactions on a merge request. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_merge_request_note_emoji_reactions List all emoji reactions on a merge request note. Pass discussion_id for discussion thread replies. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_merge_request_emoji_reaction Add an emoji reaction to a merge request (e.g. thumbsup, rocket, eyes). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_merge_request_emoji_reaction Remove an emoji reaction from a merge request. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_merge_request_note_emoji_reaction Add an emoji reaction to a merge request note. Pass discussion_id for discussion thread replies. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_merge_request_note_emoji_reaction Remove an emoji reaction from a merge request note. Pass discussion_id for discussion thread replies. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Issue CRUD, links, discussions and notes, todos, and emoji reactions. (24 tools)

Opt-in. Enable via GITLAB_TOOLSETS=issues (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 8 of these tools (create_issue, list_issues, my_issues, get_issue, update_issue, update_issue_description_patch, create_issue_note, list_issue_discussions) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
create_issue Create a new issue. Use this to open a new issue; use update_issue for an existing issue and create_issue_note to add discussion without changing issue fields. The operation creates remote project data, requires issue creation permission, and returns the new issue or a validation, permission, or duplicate-related error. ✏️
list_issues List issues (default: created by current user; use scope='all' for all). Use this for issue management: list GitLab issues, optionally scoped with project_id. Use get_issue when the issue iid is already known and my_issues for issues assigned to the current user. It is read-only and paginated, requires issue read permission, and returns issue records or GitLab errors for invalid identifiers, missing resources, or rate limits. 📖
my_issues List issues assigned to the authenticated user. Use this for issue management: list issues assigned to the authenticated user. Use list_issues for project-wide or author-scoped listing and get_issue for one issue. Resolving the current user requires classic read_user or fine-grained User:Read. It is read-only and paginated, requires authentication, and returns assigned issue records or permission/rate-limit errors. 📖
get_issue Get details of a specific issue. Returns the issue with a slim nested milestone by default; set full_response=true for the complete milestone object. Use this for issue management: inspect one issue's fields; use list_issues or my_issues to discover issues first. It is read-only, requires issue read permission, and returns the issue or an error when the identifier is invalid, the issue is missing, or access is denied. 📖
update_issue Update an issue. Returns a slim confirmation by default; set full_response=true for the complete updated issue object. Use this to change fields on an existing issue; use update_issue_description_patch for a targeted description edit that avoids sending the full body, and use create_issue_note for discussion. The operation mutates issue state, requires issue-edit permission, and returns the updated issue or a validation/permission/conflict error. ✏️
update_issue_description_patch Apply a patch (search/replace or unified diff) to an issue description. Reduces token usage by allowing small changes without sending the full description. Supports dry_run to preview changes and create_note to summarize updates. Use this for a targeted search/replace or unified-diff change to an issue description; use dry_run before applying an uncertain patch and create_note when an audit summary is wanted. It changes the issue description when not dry-running, requires issue-edit permission, and returns the patch result or a mismatch/validation/permission error. ✏️
delete_issue Delete an issue. Use this only after confirming the issue and intended permanent removal; use update_issue to close or edit an issue without deleting it. The operation permanently removes issue data, requires delete permission, and returns the deletion result or a missing-resource, permission, or policy error. ✏️
list_todos List GitLab to-do items for the current user. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
mark_todo_done Mark a GitLab to-do item as done. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️
mark_all_todos_done Mark all pending GitLab to-do items as done for the current user. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️
create_issue_note Add a note to an issue, optionally replying to a discussion thread. Use this to add a note to an existing issue, optionally as a reply to a discussion; use update_issue for issue fields and create_note only when the generic endpoint is required. The operation creates remote discussion content, requires note permission, and returns the note or a missing-issue/thread/permission error. ✏️
update_issue_note Modify an existing issue thread note. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_issue_links List all issue links for a specific issue. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_issue_discussions List discussions for an issue. Use this to inspect threaded discussions for an issue; use list_issues for issue records and get_issue for one issue's fields. It is read-only and returns discussion items, while invalid identifiers, missing issues, and permission failures are reported as errors. 📖
get_issue_link Get a specific issue link. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_issue_link Create an issue link between two issues. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_issue_link Delete an issue link. Use this to remove an existing relationship between two issues; use list_issue_links or get_issue_link to verify the link first. The operation changes issue relationships, requires issue-edit permission, and returns the result or an error when the link is missing or access is denied. ✏️
create_note Create a new note (comment) to an issue or merge request. Use this for a top-level comment on an issue or merge request when no typed discussion operation is needed; use create_merge_request_thread or create_issue_note for threaded replies. The operation creates remote discussion content, requires note permission, and returns the created note or a target/permission/validation error. ✏️
list_issue_emoji_reactions List all emoji reactions on an issue. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_issue_note_emoji_reactions List all emoji reactions on an issue note. Pass discussion_id for discussion thread replies. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_issue_emoji_reaction Add an emoji reaction to an issue (e.g. thumbsup, rocket, eyes). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_issue_emoji_reaction Remove an emoji reaction from an issue. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_issue_note_emoji_reaction Add an emoji reaction to an issue note. Pass discussion_id for discussion thread replies. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_issue_note_emoji_reaction Remove an emoji reaction from an issue note. Pass discussion_id for discussion thread replies. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Project label CRUD. (5 tools)

Opt-in. Enable via GITLAB_TOOLSETS=labels (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 1 of these tools (list_labels) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
list_labels List labels for a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_label Get a single label from a project. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_label Create a new label in a project. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_label Update an existing label in a project. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_label Delete a label from a project. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Modern unified API for issues, tasks, incidents, and other typed work items — including notes, emoji reactions, and incident timeline events. (18 tools)

Opt-in. Enable via GITLAB_TOOLSETS=workitems (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
get_work_item Get a work item with full details including status, hierarchy, type, and widgets. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_work_items List work items with filters (type, state, search, assignees, labels). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_work_item Create a work item (issue, task, incident, epic, etc.) with full field support. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_work_item Update a work item (title, description, labels, assignees, state, parent, custom fields, etc.). Use the create tool for new resources and a note tool for comments. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
convert_work_item_type Convert a work item to a different type. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_work_item_statuses List available statuses for a work item type (Premium/Ultimate). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_custom_field_definitions List custom field definitions for a work item type. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
move_work_item Move a work item to a different project. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_work_item_notes List notes and discussions on a work item. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_work_item_note Add a note to a work item (supports Markdown, internal notes, threads). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_work_item_emoji_reactions List all emoji reactions on a work item. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_work_item_note_emoji_reactions List all emoji reactions on a work item note (comment, thread, or thread reply). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_work_item_emoji_reaction Add an emoji reaction to a work item (e.g. thumbsup, rocket, eyes). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_work_item_emoji_reaction Remove an emoji reaction from a work item. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_work_item_note_emoji_reaction Add an emoji reaction to a work item note (comment, thread, or thread reply). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_work_item_note_emoji_reaction Remove an emoji reaction from a work item note (comment, thread, or thread reply). Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_timeline_events List timeline events for an incident. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_timeline_event Create a timeline event on an incident. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Validate .gitlab-ci.yml snippets and project pipeline configs. (4 tools)

Opt-in. Enable via GITLAB_TOOLSETS=ci (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
validate_ci_lint Validate provided GitLab CI/CD YAML content for a project. Checks without applying; create or update only after it passes. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
validate_project_ci_lint Validate an existing .gitlab-ci.yml configuration for a project. Checks without applying; create or update only after it passes. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_ci_catalog_resources List GitLab CI/CD Catalog resources/components visible to the user. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
get_ci_catalog_resource Get details for a GitLab CI/CD Catalog resource, including versions and components. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. 📖

Pipeline + job control (trigger, retry, cancel, play manual jobs, fetch logs/artifacts), project runners, and the deployments/environments view. (58 tools)

Opt-in. Enable via GITLAB_TOOLSETS=core,pipelines and GITLAB_TOOLS=validate_ci_lint,validate_project_ci_lint (or GITLAB_TOOLSETS=all). If you already set GITLAB_TOOLSETS, append pipelines to your existing list instead of replacing it. If GITLAB_TOOLS is already set, append validate_ci_lint,validate_project_ci_lint instead of replacing that list. USE_PIPELINE=true is deprecated (removed in next major (v3.0.0)).

Tool What it does R/W
list_pipelines List pipelines with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline Get details of a specific pipeline. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_variables Get variables configured for a pipeline. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_test_report Get pipeline test report. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_test_report_summary Get pipeline test report summary. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
delete_pipeline Delete a pipeline. Requires the project Owner role, cannot be undone, and does not automatically delete child pipelines. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_pipeline_metadata Update pipeline metadata. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_deployments List deployments with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_deployment Get deployment details, including approval_summary, approvals, and pending_approval_count when GitLab provides them. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_deployment Create a deployment. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_deployment Update a deployment status. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_deployment Delete a deployment. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_deployment_merge_requests List merge requests shipped with a deployment. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
approve_deployment Approve or reject a protected-environment deployment. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_environments List environments in a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_environment Get details of a specific environment. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
update_environment Update an environment. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_environment Delete a stopped environment. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
stop_environment Stop an environment. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
stop_stale_environments Stop eligible stale environments; protected environments are excluded and environments are stopped, not deleted. Use this to stop eligible stale environments in a project. GitLab excludes protected environments, and this operation stops environments without deleting them. It requires the necessary project permission and returns the result or a validation, permission, or rate-limit error. ✏️
delete_review_app_environments Schedule deletion of stopped review-app environments one week later; dry_run defaults to true and actual scheduling requires dry_run=false. Use this to clean up stopped review-app environments after verifying the scope. GitLab schedules deletion one week later rather than deleting environments immediately; dry_run defaults to true, so actual scheduling requires dry_run: false. It requires the necessary project permission and returns the cleanup result or a validation, permission, or rate-limit error. ✏️
list_pipeline_triggers List project pipeline trigger tokens. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_trigger Get a project pipeline trigger. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_pipeline_trigger Create a project pipeline trigger. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_pipeline_trigger Update a project pipeline trigger. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_pipeline_trigger Delete a project pipeline trigger. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
trigger_pipeline Trigger a pipeline with a pipeline trigger token. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_pipeline_jobs List all jobs in a specific pipeline. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_pipeline_trigger_jobs List trigger jobs (bridges) in a pipeline. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_job Get details of a GitLab pipeline job number. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_pipeline_job_output Get the output/trace of a pipeline job with optional pagination. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_pipeline Create a new pipeline for a branch or tag. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
retry_pipeline Retry a failed or canceled pipeline. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
cancel_pipeline Cancel a running pipeline. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_pipeline_schedules List pipeline schedules in a project, optionally filtered to active or inactive. Use this to survey a project's scheduled pipelines and their cron, next_run_at, and active state, optionally narrowed with scope to active or inactive; use list_pipelines for pipelines that already ran and get_pipeline_schedule when the schedule ID is known. The list response carries no variables — call get_pipeline_schedule for those — and includes inputs only for Maintainers, Owners, or the schedule owner. It is read-only and paginated, requires project access, and returns schedule records or an error when the project is missing or access is denied. 📖
get_pipeline_schedule Get details of a specific pipeline schedule, including its variables and last pipeline. Use this to inspect one schedule's cron, owner, last pipeline, variables, and inputs; use list_pipeline_schedules to discover schedule IDs and list_pipeline_schedule_pipelines for the pipelines it produced. It is read-only, returns variables and inputs only to Maintainers, Owners, or the schedule owner, and returns the schedule or an error when the schedule is missing or access is denied. 📖
list_pipeline_schedule_pipelines List the pipelines that a pipeline schedule has triggered. Use this to review the pipelines a schedule has actually triggered, for example to see whether the nightly run succeeded; use get_pipeline for one pipeline's full detail and list_pipelines for project-wide filtering. Narrow the result with scope, status, sort, and the created_* / updated_* date bounds. It is read-only and paginated, requires project access, and returns pipeline records or an error when the schedule is missing or access is denied. 📖
create_pipeline_schedule Create a new pipeline schedule for a branch or tag. Use this to add a recurring pipeline for a branch or tag; use create_pipeline to run a pipeline once now and update_pipeline_schedule once the schedule exists. ref accepts a short name or a full ref such as refs/heads/main, which you should prefer when a branch and tag share a name; cron_timezone defaults to UTC and active defaults to true. It creates remote CI configuration, requires the Developer, Maintainer, or Owner role plus permission to run pipelines on the target ref, and returns the new schedule or a validation, cron, ref, or permission error. ✏️
update_pipeline_schedule Update an existing pipeline schedule. Use this to change an existing schedule's cron, ref, description, inputs, or active flag; call take_ownership_pipeline_schedule first when the schedule belongs to another user, because GitLab rejects edits from non-owners. Every field is optional and GitLab reschedules the next run after the update. It changes remote CI configuration, requires the Developer, Maintainer, or Owner role and ownership of the schedule, and returns the updated schedule or a validation, cron, or permission error. ✏️
delete_pipeline_schedule Delete a pipeline schedule. Use this only after confirming the schedule with get_pipeline_schedule; use update_pipeline_schedule with active: false to pause a schedule instead of removing it. The operation permanently removes the schedule and its variables, requires the Developer, Maintainer, or Owner role and ownership of the schedule, and returns a confirmation or a missing-resource or permission error. ✏️
play_pipeline_schedule Run a pipeline schedule immediately. Use this to run a schedule's pipeline immediately without waiting for its cron; it does not shift next_run_at, so the regular cadence continues unchanged, and it does not modify the schedule itself. Use create_pipeline when you want a one-off pipeline that is unrelated to a schedule. It creates a pipeline on GitLab, requires ownership of the schedule and permission to run pipelines on its ref, is rate-limited to once per minute per schedule, and returns GitLab's acknowledgement message or a permission, rate-limit, or missing-schedule error. ✏️
take_ownership_pipeline_schedule Take ownership of a pipeline schedule. Use this to transfer a schedule's ownership to the authenticated user, which is the prerequisite for update_pipeline_schedule or delete_pipeline_schedule on someone else's schedule; it does not otherwise change the cron, ref, or variables. It changes remote ownership, requires the Maintainer or Owner role, and returns the schedule with its new owner or a permission or missing-schedule error. ✏️
get_pipeline_schedule_variable Get a single variable of a pipeline schedule. Use this to read one variable attached to a pipeline schedule by key; use get_pipeline_schedule to list every variable at once and get_project_variable for project-level CI/CD variables, which are a separate set. It is read-only, requires the Maintainer or Owner role or ownership of the schedule (GitLab 18.7 or later exposes this endpoint), and returns the variable or an error when the schedule, key, or permission is missing. 📖
create_pipeline_schedule_variable Create a variable for a pipeline schedule. Use this to attach a new variable to a pipeline schedule so its scheduled pipelines receive it; use update_pipeline_schedule_variable when the key already exists and create_project_variable for a project-wide variable. variable_type defaults to env_var and key is limited to 255 characters matching /[a-zA-Z0-9_]+/. It creates remote CI configuration, requires the Developer, Maintainer, or Owner role and ownership of the schedule, and returns the new variable or a validation, duplicate-key, or permission error. ✏️
update_pipeline_schedule_variable Update a variable of a pipeline schedule. Use this to change the value or type of an existing pipeline schedule variable; use create_pipeline_schedule_variable when the key does not exist yet. It changes remote CI configuration that scheduled pipelines consume, requires the Developer, Maintainer, or Owner role and ownership of the schedule, and returns the updated variable or a missing-key, validation, or permission error. ✏️
delete_pipeline_schedule_variable Delete a variable from a pipeline schedule. Use this only after confirming the key with get_pipeline_schedule or get_pipeline_schedule_variable; use update_pipeline_schedule_variable to change a value without removing it. The operation permanently removes the variable from the schedule so later scheduled pipelines no longer receive it, requires the Developer, Maintainer, or Owner role and ownership of the schedule, and returns a confirmation or a missing-key or permission error. ✏️
play_pipeline_job Run a manual pipeline job. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
play_pipeline_jobs Play multiple manual pipeline jobs sequentially. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
retry_pipeline_job Retry a failed or canceled pipeline job. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
cancel_pipeline_job Cancel a running pipeline job. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
erase_pipeline_job Erase a pipeline job log and artifacts. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
wait_for_pipeline Wait for a pipeline to reach a terminal status. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
wait_for_job Wait for a job to reach a terminal status. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_job_artifacts List artifact files in a job's archive. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
download_job_artifacts Download job artifact archive (zip) and save to a local path. Use this to retrieve a pipeline job's artifact archive; remote HTTP mode returns a download URL while local mode saves the archive to a local path. It is read-only on GitLab but creates a local file in stdio mode (rejected in readonly mode), requires job/project access, and returns the download result or an artifact/permission error. 📖✏️
get_job_artifact_file Get content of a single file from a job's artifacts. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_project_runners List runners available to a project. Use this when a job is stuck pending with no matching runner and you need the runners a project can use, including ancestor group runners and allowed instance runners. Filter with type, status, paused, and tag_list; the list payload includes id, description, runner_type, status, and paused (among other non-secret GitLab runner fields) but not tags — call get_runner for tag_list, run_untagged, locked, and access_level. It is read-only and paginated, requires Maintainer or Auditor access on the project, and never returns a runner registration token (runners_token) or runner authentication token. 📖
get_runner Get one runner by ID. Use this after list_project_runners when you already have a runner ID and need tag_list, run_untagged, locked, and access_level to explain a stuck pending job. Instance runner details are visible to authenticated users; group and project runners follow GitLab's role checks for that runner. When GITLAB_ALLOWED_PROJECT_IDS or a session project scope is active, the runner must appear on an allowed project's runner list before details are returned — pass project_id when more than one project is allowed — projects outside that allowlist are omitted, and groups are omitted because a project allowlist cannot verify them. GITLAB_PROJECT_ID alone is only the default project for that membership check when project_id is omitted. It does not omit other projects or groups. It is read-only and never returns a runner registration token (runners_token) or runner authentication token. token_expires_at is expiry metadata, not the token. 📖

Project and group milestone CRUD plus associated issues/MRs and burndown events. (17 tools)

Opt-in. Enable via GITLAB_TOOLSETS=core,milestones (or GITLAB_TOOLSETS=all). If you already set GITLAB_TOOLSETS, append milestones to your existing list instead of replacing it. USE_MILESTONE=true is deprecated (removed in next major (v3.0.0)).

Tool What it does R/W
list_milestones List milestones with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_milestone Get details of a specific milestone. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_milestone Create a new milestone. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
edit_milestone Edit an existing milestone. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_milestone Delete a milestone. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_milestone_issue Get issues associated with a specific milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_milestone_merge_requests Get merge requests associated with a specific milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
promote_milestone Promote a milestone to the next stage. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_milestone_burndown_events Get burndown events for a specific milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_group_milestones List group milestones with filtering options. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_group_milestone Get details of a specific group milestone. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_group_milestone Create a new group milestone. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
edit_group_milestone Edit an existing group milestone. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_group_milestone Delete a group milestone. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_group_milestone_issue Get issues associated with a specific group milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_group_milestone_merge_requests Get merge requests associated with a specific group milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_group_milestone_burndown_events Get burndown events for a specific group milestone. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖

Project and group wiki page CRUD. Attachment uploads where supported. (10 tools)

Opt-in. Enable via GITLAB_TOOLSETS=core,wiki (or GITLAB_TOOLSETS=all). If you already set GITLAB_TOOLSETS, append wiki to your existing list instead of replacing it. USE_GITLAB_WIKI=true is deprecated (removed in next major (v3.0.0)).

Tool What it does R/W
list_wiki_pages List wiki pages in a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_wiki_page Get details of a specific wiki page. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_wiki_page Create a wiki page in a project. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_wiki_page Update a wiki page in a project. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_wiki_page Delete a wiki page from a project. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_group_wiki_pages List wiki pages in a group. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_group_wiki_page Get details of a specific group wiki page. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_group_wiki_page Create a wiki page in a group. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_group_wiki_page Update a wiki page in a group. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_group_wiki_page Delete a wiki page from a group. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Release lifecycle, release evidence, and asset download. (7 tools)

Opt-in. Enable via GITLAB_TOOLSETS=releases (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_releases List all releases for a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_release Get a release by tag name. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_release Create a new release. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_release Update an existing release. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_release Delete a release (does not delete the tag). Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
create_release_evidence Create release evidence (Premium/Ultimate). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
download_release_asset Download a release asset file by direct asset path. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖

Tag listing, creation, deletion, signature inspection, and protected tag rules. (9 tools)

Opt-in. Enable via GITLAB_TOOLSETS=tags (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_tags List repository tags for a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_tag Get a repository tag by name. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_tag Create a new repository tag. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_tag Delete a repository tag. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
get_tag_signature Get the X.509 signature of a signed tag (404 if unsigned). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
list_protected_tags List protected tags in a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_protected_tag Get details of a single protected tag or wildcard (create access levels). To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
protect_tag Protect a repository tag or wildcard (set who can create it). Use this to protect a tag or wildcard such as v* so protected CI/CD variables reach tag pipelines; use get_protected_tag or list_protected_tags to inspect existing rules first. The operation changes who may create matching tags, requires maintainer-level permission, and returns the protection rule or a validation/permission error. ✏️
unprotect_tag Remove protection from a previously protected tag or wildcard. Use this to remove protection from an existing tag or wildcard. To change the create access level, use unprotect_tag first, then protect_tag; protect_tag creates a rule and does not update an existing rule. This change is unavailable in modify mode because unprotect_tag is blocked there. The operation changes repository security controls, requires permission to manage protected tags, and returns the result or an error when the tag is missing or policy forbids the change. ✏️

User lookup, the authenticated user (whoami), event streams, and markdown attachment upload/download. (7 tools)

Opt-in. Enable via GITLAB_TOOLSETS=users (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool. 1 of these tools (whoami) are already enabled by default via core; the toggle applies to the rest.

Tool What it does R/W
get_users Get GitLab user details by usernames. Read-only; missing resources, denied access, and rate limits return errors. 📖
get_user Get user details by ID. Read-only; missing resources, denied access, and rate limits return errors. 📖
whoami Get current authenticated user details. Use this to identify the authenticated GitLab user; use get_user or get_users when looking up another user. It requires classic read_user or fine-grained User:Read. It is read-only and returns the current user profile, while missing credentials or GitLab permission failures are reported as errors. 📖
list_events List events for the authenticated user (before/after: YYYY-MM-DD). Read-only; missing resources, denied access, and rate limits return errors. 📖
get_project_events List events for a project (before/after: YYYY-MM-DD). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
upload_markdown Upload a file for use in markdown content. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
download_attachment Download an uploaded file from a project (images returned as base64; other files, or images with local_path, are saved as new files under the download directory). Use this to retrieve a previously uploaded project attachment; remote mode returns inline base64 for images or a download URL, while local mode saves the file as a new file under the download directory (GITLAB_DOWNLOAD_DIR, default .gitlab-mcp-downloads). It is read-only with respect to GitLab but creates a local file in stdio mode (readonly mode returns images inline and rejects everything else), never replaces an existing file, requires project access, and returns the file content or an attachment/permission error. 📖✏️

Project and group CI/CD variable CRUD. (10 tools)

Opt-in. Enable via GITLAB_TOOLSETS=variables (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_project_variables List CI/CD variables for a project. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_project_variable Get a single CI/CD variable from a project. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_project_variable Create a CI/CD variable for a project. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_project_variable Update an existing CI/CD variable in a project. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_project_variable Delete a CI/CD variable from a project. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_group_variables List CI/CD variables for a group. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_group_variable Get a single CI/CD variable from a group. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_group_variable Create a CI/CD variable for a group. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_group_variable Update an existing CI/CD variable in a group. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_group_variable Delete a CI/CD variable from a group. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Create, update, and delete project or group webhooks, and inspect recent webhook events. (6 tools)

Opt-in. Enable via GITLAB_TOOLSETS=webhooks (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_webhooks List webhooks for a project or group. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_webhook Create a webhook on a project or group. If the resource already exists, use the update tool. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
update_webhook Update an existing project or group webhook. Use the create tool for new resources. Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
delete_webhook Delete a project or group webhook. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_webhook_events List recent webhook events (past 7 days). For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_webhook_event Get full details of a specific webhook event. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖

Code search across all visible projects, a specific project, or a specific group. (3 tools)

Opt-in. Enable via GITLAB_TOOLSETS=search (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
search_code Search for code across all projects (requires advanced search or Zoekt). If the identifier is known, use a typed get or list tool. Read-only; missing resources, denied access, and rate limits return errors. 📖
search_project_code Search for code within a specific project (requires advanced search or Zoekt). If the identifier is known, use a typed get or list tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
search_group_code Search for code within a specific group (requires advanced search or Zoekt). If the identifier is known, use a typed get or list tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖

Inspect and manage the GitLab dependency proxy cache settings, blob storage, and purge operations. (4 tools)

Opt-in. Enable via GITLAB_TOOLSETS=dependency_proxy (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
get_dependency_proxy_settings Get dependency proxy settings for a group. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
update_dependency_proxy_settings Update dependency proxy settings for a group (enable/disable, credentials for authenticated Docker Hub pulls). Changes GitLab data; needs permission and returns validation or conflict errors. project_id/group_id take a numeric ID or URL-encoded path. ✏️
list_dependency_proxy_blobs List cached dependency proxy blobs for a group. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
purge_dependency_proxy_cache Schedule purge of all cached dependency proxy blobs for a group. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

AI-assisted vulnerability triage — list findings, inspect details, dismiss with reason, or confirm for remediation. Backed by the GitLab GraphQL API; requires GitLab Ultimate. (4 tools)

Opt-in. Enable via GITLAB_TOOLSETS=vulnerabilities (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_project_vulnerabilities List vulnerabilities for a project with optional state, severity, and report type filters (GraphQL-backed, cursor pagination). Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_vulnerability Get full details of a specific vulnerability. Read-only; missing resources, denied access, and rate limits return errors. 📖
dismiss_vulnerability Dismiss a vulnerability with a reason (acceptable_risk, false_positive, used_in_tests, mitigating_control, not_applicable) and optional comment. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️
confirm_vulnerability Confirm a vulnerability as a real finding requiring remediation. Changes GitLab data; needs permission and returns validation or conflict errors. ✏️

Query the Orbit SDLC knowledge graph (Beta; Premium/Ultimate). Graph queries consume GitLab credits; schema, status, and tool listing are free. (4 tools)

Opt-in. Enable via GITLAB_TOOLSETS=orbit (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
orbit_query Execute a GitLab Orbit graph query over the indexed SDLC knowledge graph. Use this to answer cross-project relationship questions (blast radius, file-to-MR history, dependency fans) in one call instead of chaining list/get tools; use orbit_get_schema first when the node/edge types are unknown. It is read-only but each call consumes GitLab credits, requires Premium/Ultimate on an Orbit-enabled scope, and returns the graph result or a query/permission error. 📖
orbit_get_schema Fetch the current GitLab Orbit graph schema (node and edge types). Use this to learn the node and edge types available for orbit_query before writing a query; use orbit_get_status when the concern is index freshness rather than shape. It is read-only and free of credit charges, and returns the current graph schema or a permission error. 📖
orbit_get_status Check GitLab Orbit indexing status for the enabled scope. Use this to check whether Orbit indexing has completed before trusting orbit_query results; results reflect the last index cycle, not real-time state. It is read-only and free of credit charges, and returns the indexing status or a permission error. 📖
orbit_list_tools List the MCP tool definitions exposed by GitLab Orbit. Use this to see which MCP tool definitions Orbit itself exposes; use orbit_query to run graph queries directly. It is read-only and free of credit charges, and returns the tool definition list or a permission error. 📖

Snippet CRUD — list, get (with optional file content), create, update, and delete personal or project snippets. (5 tools)

Opt-in. Enable via GITLAB_TOOLSETS=snippets (or GITLAB_TOOLSETS=all), list individual tools in GITLAB_TOOLS=, or activate at runtime with the discover_tools MCP tool.

Tool What it does R/W
list_snippets List snippets — project snippets when project_id is given, otherwise personal snippets. For one known resource, use the matching get tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
get_snippet Get a snippet's metadata. Set include_content=true to also fetch the raw file content. To find resources, use the matching list or search tool. Read-only; missing resources, denied access, and rate limits return errors. project_id/group_id take a numeric ID or URL-encoded path. 📖
create_snippet Create a snippet — project-scoped when project_id is given, otherwise a personal snippet. Requires title plus either file_name + content (single file) or files[] (multi-file); the two shapes cannot be mixed. ✏️
update_snippet Update an existing snippet (provide at least one field to change). For multi-file edits — renames, deletions, additions — pass files[] with action (create/update/delete/move) and previous_path. The file_name + content shortcut still works for single-file content replacement. ✏️
delete_snippet Delete a snippet. Verify the target first with a get or list tool. Changes or removes GitLab data and may be irreversible; needs permission. project_id/group_id take a numeric ID or URL-encoded path. ✏️

Explicit opt-in escape hatch for one GitLab REST call under /api/v4. Not part of core, not enabled by GITLAB_TOOLSETS=all, and not activatable with discover_tools. (1 tools)

Explicit opt-in only. Enable by listing api in GITLAB_TOOLSETS (for example GITLAB_TOOLSETS=api or GITLAB_TOOLSETS=core,api). GITLAB_TOOLSETS=all, discover_tools, GITLAB_TOOLS, legacy USE_* flags, and GITLAB_TOOL_PROFILE do not enable it.

Tool What it does R/W
gitlab_api_request DANGER: bypasses group and project restrictions, tool allowlists (GITLAB_TOOLS and GITLAB_DENIED_TOOLS_REGEX on other tools), and individual tool safety checks. The full token scope is exposed. Send one GitLab REST call under /api/v4. Readonly mode allows GET only, and modify mode rejects DELETE. Enable it only by listing api in GITLAB_TOOLSETS; all, discover_tools, and GITLAB_TOOLS do not. Prompt injection can drive this tool, so operators who rely on group, project, or tool restrictions must not enable it. GITLAB_ALLOWED_PROJECT_IDS is enforced only for /projects/:id paths; other endpoints are not constrained. 📖✏️

Server diagnostics, tool discovery, and the GraphQL escape hatch. (2 tools)

Mixed availability. discover_tools is always exposed (the server re-adds it after every toolset filter). execute_graphql is not part of any toolset — enable it explicitly with GITLAB_TOOLS=execute_graphql. Tools excluded from the list (toolset / GITLAB_TOOLS / GITLAB_DENIED_TOOLS_REGEX) are also rejected on direct calls; GITLAB_TOOL_POLICY_HIDDEN tools stay callable only while they are otherwise enabled (toolset / GITLAB_TOOLS / permission mode) and do not match GITLAB_DENIED_TOOLS_REGEX; hiding a tool does not enable it.

Tool What it does R/W
execute_graphql Execute a GitLab GraphQL query. Use this only when a supported GitLab REST tool does not cover the requested operation; prefer a typed tool when one exists. The query is sent directly to GitLab and can include mutations when permission allows, so callers must treat it as potentially state-changing and handle GraphQL errors in the returned response. 📖✏️
discover_tools Discover and activate additional tool categories for this session. Available categories: core, merge_requests, issues, repositories, branches, projects, labels, ci, groups, pipelines, milestones, wiki, releases, tags, snippets, users, workitems, webhooks, search, variables, dependency_proxy, vulnerabilities, orbit. Already-active categories are listed in the response. Explicit-only toolsets are omitted; list them in GITLAB_TOOLSETS. Use this when a needed opt-in category is not currently exposed; omit category to inspect available categories, then call it with a category to activate that group for the current session. It changes only the session's tool registry, returns the active-tool summary, and does not change GitLab data. 📖

Argument schemas

Each group page includes a parameter table per tool, generated from the authoritative Zod schemas in schemas.ts. For runtime schema inspection from a connected MCP client, call the discover_tools tool.