<!-- Generated by `just docs` from catalog/toolkits/gitlab.yaml, catalog/expansions/gitlab.yaml, catalog/evals/scorecard.json. Edit the source, not this file. -->

# GitLab

Source control and CI/CD. Manage projects, issues, merge requests, pipelines, commits, and branches, and search an instance.

| Property | Value |
| --- | --- |
| Slug | `gitlab` |
| Definition version | `0.1.0` |
| Base URL | `https://gitlab.com/api/v4` |
| Auth schemes | `oauth2`, `api_key` |
| Action tools | 36 |
| By class | 20 read, 13 write, 3 destructive |
| Triggers | 0 |
| Provider rate limit | 2000 requests per 1m, per account |

## Measured routing accuracy

51 golden cases replayed through the router over the whole index: measured over corpus `ea4f12ad2948` (65 toolkits, 2283 tools indexed and 13 declared uncallable), 36 cases written by hand and 15 cases from the paraphrase pass. A case counts as top-1 when its gold tool ranked first and top-8 when it reached the slate at all.

| Measure | Cases | Share |
| --- | --- | --- |
| top-1 | 25/51 | 49.0% |
| top-8 | 44/51 | 86.3% |

The sweep is offline: the reranker is a deterministic identity fake that returns candidates in the order retrieval produced them, so top-1 measures retrieval order rather than a reranked slate. `just eval-live` measures the same cases through the live reranker.

## Authentication

Connect an entity with `ConnectionsService.InitiateConnection`, naming this toolkit's slug. Credentials stay in the connections vault; callers hold connected-account ids only.

### `oauth2`

| Property | Value |
| --- | --- |
| Authorization URL | `https://gitlab.com/oauth/authorize` |
| Token URL | `https://gitlab.com/oauth/token` |
| Default scopes | `api` |
| Refresh tokens | yes, the refresh daemon renews ahead of expiry |

### `api_key`

| Property | Value |
| --- | --- |
| Placement | `header` |
| Name | `PRIVATE-TOKEN` |
| Rendered as | `{key}` |

Submit the key with `ConnectionsService` rather than putting it in a request; it is sealed at rest and never returned.

## Tools

36 action tools. The catalog-wide slug is `gitlab.<tool>`, which is what `search_tools` returns and `call_tool` takes.

### `gitlab.get_project`

Get one GitLab project's details by id or path: description, default branch, visibility, star and fork counts, open issue count. Use for a specific known project. To find projects by keyword, use search.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Numeric project id or URL-encoded path with namespace, e.g. "group%2Fproject" or "42". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `default_branch` | string |  |
| `description` | string |  |
| `forks_count` | integer |  |
| `id` | integer |  |
| `name` | string |  |
| `open_issues_count` | integer |  |
| `path_with_namespace` | string |  |
| `star_count` | integer |  |
| `visibility` | string |  |
| `web_url` | string |  |

Also retrieved by: "what's this codebase about", "how many stars does it have", "is it public or private", "pull up info on this repo", "check out this project's details".

### `gitlab.list_projects`

List GitLab projects the signed-in user owns or is a member of, optionally filtered by a keyword. Use when the user says my projects, our repos, or what am I working on in GitLab. For a broader instance keyword search, use search.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `membership` | boolean | no | True to list only projects the user is a member of. |
| `order_by` | string, one of created_at, updated_at, name, last_activity_at | no | Sort field. Defaults to created_at. |
| `owned` | boolean | no | True to list only projects the user owns. |
| `per_page` | integer | no | Results per page, max 100. |
| `search` | string | no | Filter projects by name, e.g. "billing". |

Also retrieved by: "what am I working on", "show my repos", "everything I've built so far", "stuff under my account", "what do I have access to".

### `gitlab.create_project`

Create a new GitLab project. Use when the user wants to start, set up, or make a new repo or project on GitLab. Optionally private and initialized with a README.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | Short project description. |
| `initialize_with_readme` | boolean | no | True to create an initial commit with an empty README. |
| `name` | string | **yes** | New project name, e.g. "billing-service". |
| `namespace_id` | integer | no | Group or user namespace id to create the project under. |
| `visibility` | string, one of private, internal, public | no | Project visibility. Defaults to private. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | integer |  |
| `name` | string |  |
| `path_with_namespace` | string |  |
| `visibility` | string |  |
| `web_url` | string |  |

Also retrieved by: "spin up a new codebase", "I need a fresh repository", "kick off a new project", "scaffold something brand new", "set up a place for this code to live".

### `gitlab.delete_project`

Permanently delete a whole GitLab project, including its issues, merge requests, and history. Irreversible once the retention period passes. Use only when the user explicitly asks to delete or remove a project they own. Not for a single branch or file.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `api`. Calls `DELETE /projects/{{params.project_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path to delete. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `deleted` | boolean |  |

Also retrieved by: "nuke this repository", "get rid of this codebase for good", "wipe this off the platform", "I don't want this project anymore", "tear the whole thing down".

### `gitlab.fork_project`

Fork a GitLab project into the signed-in user's namespace or a group. Use when the user wants their own copy of someone else's GitLab project to work on or contribute from.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/fork`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | no | Optional new name for the fork. |
| `namespace_id` | integer | no | Optional group or user namespace id to fork into. |
| `project_id` | string | **yes** | Numeric id or URL-encoded path of the project to fork. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `forked_from_project` | object |  |
| `forked_from_project.id` | integer |  |
| `forked_from_project.path_with_namespace` | string |  |
| `id` | integer |  |
| `name` | string |  |
| `path_with_namespace` | string |  |
| `web_url` | string |  |

Also retrieved by: "I want to contribute to this project", "copy this repo to my account", "make my own version of their code", "grab a copy so I can hack on it".

### `gitlab.list_branches`

List a GitLab project's branches with the head commit of each. Use when the user asks what branches exist or wants to pick a branch for another call.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/repository/branches`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `search` | string | no | Filter branches by name substring. |

Also retrieved by: "what versions of the code are there", "show me the different lines of work", "which branch should I use", "see the feature branches".

### `gitlab.get_branch`

Get one GitLab branch by name: its head commit, whether it is merged, and whether it is protected. Use when the user names a specific branch. For the full list, use list_branches.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/repository/branches/{{params.branch}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `branch` | string | **yes** | Branch name, e.g. "feature/login". |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `commit` | object |  |
| `commit.id` | string |  |
| `commit.short_id` | string |  |
| `commit.title` | string |  |
| `default` | boolean |  |
| `merged` | boolean |  |
| `name` | string |  |
| `protected` | boolean |  |
| `web_url` | string |  |

Also retrieved by: "what's the latest commit on that line of work", "is this one protected", "has this been merged already", "details on one specific branch".

### `gitlab.create_branch`

Create a new branch in a GitLab project from a source branch, tag, or commit. Use when the user wants to cut, start, or branch off a new line of work.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/repository/branches`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `branch` | string | **yes** | Name for the new branch, e.g. "fix-login". |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `ref` | string | **yes** | Source branch, tag, or commit sha to branch from. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `commit` | object |  |
| `commit.id` | string |  |
| `commit.short_id` | string |  |
| `name` | string |  |

Also retrieved by: "cut a new line of work off main", "start a fresh line for this feature", "branch off from the release tag".

### `gitlab.delete_branch`

Delete a single branch from a GitLab project. Irreversible once the branch's commits are unreachable from any other ref. Use only when the user explicitly asks to delete or remove a branch, not a whole project.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `api`. Calls `DELETE /projects/{{params.project_id}}/repository/branches/{{params.branch}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `branch` | string | **yes** | Name of the branch to delete. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `deleted` | boolean |  |

Also retrieved by: "take this branch off the repo", "clean up an old line of work", "this one's done, get rid of it".

### `gitlab.list_commits`

List commits on a GitLab project, newest first. Use when the user asks for recent changes, commit history, or who changed what. Filterable by branch, author, file path, and date range. For one commit's diff, use get_commit_diff.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/repository/commits`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | no | Only commits touching this file or directory. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `ref_name` | string | no | Branch or tag to list from. Defaults to the default branch. |
| `since` | string (date-time) | no | Only commits after this ISO 8601 timestamp. |
| `until` | string (date-time) | no | Only commits before this ISO 8601 timestamp. |

Also retrieved by: "what's been happening in this repo lately", "who touched this last", "show me the timeline of changes", "recent work on this project".

### `gitlab.get_commit`

Get one GitLab commit by sha: its full message, author, and change stats. Use when the user asks what a specific commit changed. For the line-level diff, use get_commit_diff; for history, use list_commits.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/repository/commits/{{params.sha}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `sha` | string | **yes** | Commit sha, e.g. "a1b2c3d". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `author_name` | string |  |
| `created_at` | string (date-time) |  |
| `id` | string |  |
| `message` | string |  |
| `short_id` | string |  |
| `stats` | object |  |
| `stats.additions` | integer |  |
| `stats.deletions` | integer |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "what did that change actually do", "details on a single change", "who wrote this particular commit".

### `gitlab.get_commit_diff`

Get the line-level diff for one GitLab commit: files changed and the patch for each. Use when the user wants to review or see exactly what a commit changed, not just its message.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/repository/commits/{{params.sha}}/diff`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `sha` | string | **yes** | Commit sha to diff. |

Also retrieved by: "show me the diff for that one", "what lines actually changed here", "let me see the patch for this change".

### `gitlab.list_issues`

List issues in one GitLab project: tickets, bugs, tasks, feature requests. Filterable by state, labels, and assignee. For queries across the whole instance, use search.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/issues`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_username` | string | no | Only issues assigned to this username. |
| `labels` | string | no | Comma-separated label names, e.g. "bug,priority::high". |
| `order_by` | string, one of created_at, updated_at, priority | no | Sort field. Defaults to created_at. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `search` | string | no | Filter by keyword in title and description. |
| `state` | string, one of opened, closed, all | no | Which issues to list. Defaults to opened. |

Also retrieved by: "what's on our plate for this repo", "show me the open tickets", "what bugs are outstanding", "backlog for this project".

### `gitlab.get_issue`

Get a single GitLab issue by its project-scoped number (iid): full description, state, labels, and assignees. Use when the user names a specific issue like "issue 42". For lists, use list_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/issues/{{params.issue_iid}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_iid` | integer | **yes** | Issue number within the project, e.g. 42. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `assignees` | array of object |  |
| `assignees[].username` | string |  |
| `author` | object |  |
| `author.username` | string |  |
| `description` | string |  |
| `iid` | integer |  |
| `labels` | array of string |  |
| `state` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "pull up that one ticket", "look at bug number forty two", "details on this specific report".

### `gitlab.create_issue`

Open a new issue on a GitLab project. Use when the user wants to file a bug report, log a ticket, create a task, or request a feature. Optionally set labels, assignees, and a milestone at creation.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/issues`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_ids` | array of integer | no | User ids to assign. |
| `description` | string | no | Issue description, markdown allowed. |
| `labels` | string | no | Comma-separated label names to apply, e.g. "bug". |
| `milestone_id` | integer | no | Milestone id to attach. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `title` | string | **yes** | Issue title, e.g. "Login fails with SSO accounts". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `iid` | integer |  |
| `state` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "flag this problem for the team", "log a task for someone to pick up", "write up a feature idea", "report something broken".

### `gitlab.update_issue`

Edit an existing GitLab issue: retitle it, rewrite the description, close or reopen it, or replace labels and assignees. Use when the user wants to close a ticket, mark it done, reopen it, or change its details.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PUT /projects/{{params.project_id}}/issues/{{params.issue_iid}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_ids` | array of integer | no | Replacement assignee user ids. Omit to leave unchanged. |
| `description` | string | no | New description, markdown allowed. |
| `issue_iid` | integer | **yes** | Issue number to update. |
| `labels` | string | no | Replacement comma-separated label set. Omit to leave unchanged. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `state_event` | string, one of close, reopen | no | Set "close" to close, "reopen" to reopen. |
| `title` | string | no | New title. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `iid` | integer |  |
| `state` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "mark this ticket as done", "reopen that old bug", "change the title on this one", "this is fixed now".

### `gitlab.list_issue_notes`

Read the notes, comments, and discussion left on a GitLab issue. Use when the user wants the conversation, replies, or updates people left on a ticket.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/issues/{{params.issue_iid}}/notes`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_iid` | integer | **yes** | Issue number. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Also retrieved by: "what did people say on this ticket", "read the back and forth on that one", "catch up on the conversation there".

### `gitlab.create_issue_note`

Post a note or comment on a GitLab issue. Use when the user wants to reply, respond, leave a note, or give a status update on a ticket.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/issues/{{params.issue_iid}}/notes`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `body` | string | **yes** | Note text, markdown allowed. |
| `issue_iid` | integer | **yes** | Issue number to comment on. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `body` | string |  |
| `created_at` | string (date-time) |  |
| `id` | integer |  |

Also retrieved by: "tell them the status on this ticket", "drop a note on that one", "let people know what's going on with this bug".

### `gitlab.list_labels`

List the labels defined on a GitLab project with their colors and descriptions. Use when the user asks what labels or tags exist, or before labeling an issue or merge request with create_issue or update_issue.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/labels`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `search` | string | no | Filter labels by name substring. |

Also retrieved by: "what tags do we use here", "show me the options for marking things", "what categories can I apply to a ticket".

### `gitlab.list_merge_requests`

List merge requests in a GitLab project: pending merges, proposed changes, code waiting for review. Filterable by state and branch. For one merge request's details, use get_merge_request.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/merge_requests`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `order_by` | string, one of created_at, updated_at | no | Sort field. Defaults to created_at. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `search` | string | no | Filter by keyword in title and description. |
| `source_branch` | string | no | Filter by source branch name. |
| `state` | string, one of opened, closed, merged, all | no | Which merge requests to list. Defaults to opened. |
| `target_branch` | string | no | Filter by target branch name, e.g. "main". |

Also retrieved by: "what code is waiting on review", "show me open MRs", "what's queued up to merge".

### `gitlab.get_merge_request`

Get one GitLab merge request by number (iid): title, description, branches, merge status, and whether it has conflicts. Use when the user names a specific merge request. For its changed files, use list_merge_request_changes.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `merge_request_iid` | integer | **yes** | Merge request number, e.g. 512. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `author` | object |  |
| `author.username` | string |  |
| `description` | string |  |
| `has_conflicts` | boolean |  |
| `iid` | integer |  |
| `merge_status` | string |  |
| `source_branch` | string |  |
| `state` | string |  |
| `target_branch` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "pull up that one code submission", "details on this specific proposal", "what's in this particular change request".

### `gitlab.create_merge_request`

Open a merge request proposing changes from one branch into another on GitLab. Use when the user wants to open an MR, submit their branch for review, or propose merging a feature branch.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/merge_requests`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_ids` | array of integer | no | User ids to assign as reviewers or owners. |
| `description` | string | no | Merge request description, markdown allowed. |
| `labels` | string | no | Comma-separated label names to apply. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `source_branch` | string | **yes** | Branch with the changes, e.g. "fix-login". |
| `target_branch` | string | **yes** | Branch to merge into, e.g. "main". |
| `title` | string | **yes** | Merge request title. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `iid` | integer |  |
| `state` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "put my branch up for review", "send this code for review", "propose these changes to the team".

### `gitlab.update_merge_request`

Edit an open GitLab merge request: retitle it, rewrite the description, close or reopen it, or retarget the base branch. Use when the user wants to change or close a merge request without merging it. Merging is merge_merge_request.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PUT /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | New description, markdown allowed. |
| `labels` | string | no | Replacement comma-separated label set. Omit to leave unchanged. |
| `merge_request_iid` | integer | **yes** | Merge request number to update. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `state_event` | string, one of close, reopen | no | Set "close" to close without merging, "reopen" to reopen. |
| `target_branch` | string | no | New target branch name. |
| `title` | string | no | New title. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `iid` | integer |  |
| `state` | string |  |
| `title` | string |  |
| `web_url` | string |  |

Also retrieved by: "change the description on that one", "close this without merging it", "update the target branch for this one".

### `gitlab.merge_merge_request`

Merge an open GitLab merge request into its target branch. Use when the user says merge it, land it, or ship it. Changes the target branch permanently; optionally squash commits or remove the source branch.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `api`. Calls `PUT /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}/merge`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `merge_commit_message` | string | no | Custom message for the merge commit. |
| `merge_request_iid` | integer | **yes** | Merge request number to merge. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `should_remove_source_branch` | boolean | no | True to delete the source branch after merging. |
| `squash` | boolean | no | True to squash all commits into one before merging. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `iid` | integer |  |
| `merge_commit_sha` | string |  |
| `state` | string |  |

Also retrieved by: "land this change already", "ship this branch into main", "this is good to go, merge it".

### `gitlab.list_merge_request_changes`

List the files changed in a GitLab merge request with the diff for each. Use when the user asks what a merge request touches or wants to review its diff.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}/diffs`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `merge_request_iid` | integer | **yes** | Merge request number. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Also retrieved by: "what files does this touch", "show me everything modified here", "review the diff on this submission".

### `gitlab.list_merge_request_notes`

Read the notes, comments, and review discussion left on a GitLab merge request. Use when the user wants the feedback, replies, or approval status people left on a merge request.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}/notes`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `merge_request_iid` | integer | **yes** | Merge request number. |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Also retrieved by: "did anyone sign off on this", "what feedback came back on this", "is this approved yet".

### `gitlab.create_merge_request_note`

Post a note or comment on a GitLab merge request. Use when the user wants to reply, respond, or leave review feedback on a merge request. To approve or sign off, use approve_merge_request instead.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}/notes`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `body` | string | **yes** | Note text, markdown allowed. |
| `merge_request_iid` | integer | **yes** | Merge request number to comment on. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `body` | string |  |
| `created_at` | string (date-time) |  |
| `id` | integer |  |

Also retrieved by: "give this code some quick feedback", "send back a comment on this one", "I want to weigh in on this change".

### `gitlab.approve_merge_request`

Approve a GitLab merge request as the signed-in user. Use when the user wants to approve, sign off on, or give the thumbs up to a merge request. Does not merge it; use merge_merge_request for that.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/merge_requests/{{params.merge_request_iid}}/approve`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `merge_request_iid` | integer | **yes** | Merge request number to approve. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `sha` | string | no | Head commit sha to approve, to guard against a stale review. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `approvals_left` | integer |  |
| `approved` | boolean |  |
| `iid` | integer |  |

Also retrieved by: "give this code the thumbs up", "sign off on this one", "I'm happy with this, approve it".

### `gitlab.list_pipelines`

List CI/CD pipelines for a GitLab project, newest first. Use when the user asks about build status, recent runs, or what's currently building. Filterable by branch and status.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/pipelines`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `ref` | string | no | Filter by branch or tag name. |
| `status` | string, one of created, running, pending, success, failed, canceled, skipped | no | Filter by pipeline status. |

Also retrieved by: "what's the build status", "show me recent CI runs", "is anything currently building".

### `gitlab.get_pipeline`

Get one GitLab CI/CD pipeline by id: status, duration, ref, and triggering commit. Use when the user asks whether a specific build passed or how long it took. For its jobs, use list_pipeline_jobs.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/pipelines/{{params.pipeline_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `pipeline_id` | integer | **yes** | Pipeline id. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `created_at` | string (date-time) |  |
| `duration` | integer |  |
| `id` | integer |  |
| `iid` | integer |  |
| `ref` | string |  |
| `sha` | string |  |
| `status` | string |  |
| `web_url` | string |  |

Also retrieved by: "did that build pass", "how long did the last run take", "details on one specific CI run".

### `gitlab.create_pipeline`

Trigger a new GitLab CI/CD pipeline run on a branch or tag. Use when the user wants to kick off, start, or rerun a build outside of a push. Optionally pass CI/CD variables for that run.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/pipeline`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `ref` | string | **yes** | Branch or tag to run the pipeline on. |
| `variables` | array of object | no | CI/CD variables for this run, each an object with a key and a value, e.g. a key of "ENV" and a value of "staging". |
| `variables[].key` | string | no |  |
| `variables[].value` | string | no |  |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | integer |  |
| `iid` | integer |  |
| `ref` | string |  |
| `status` | string |  |
| `web_url` | string |  |

Also retrieved by: "kick off a new build", "rerun CI on this branch", "trigger the deploy job".

### `gitlab.retry_pipeline`

Retry the failed or canceled jobs of a GitLab pipeline. Use when the user wants to rerun, retry, or try again on a build that did not pass. Creates no new pipeline; it retries the existing one.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/pipelines/{{params.pipeline_id}}/retry`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `pipeline_id` | integer | **yes** | Pipeline id to retry. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | integer |  |
| `status` | string |  |
| `web_url` | string |  |

Also retrieved by: "try that failed build again", "rerun the jobs that didn't pass", "give it another shot without starting over".

### `gitlab.cancel_pipeline`

Cancel a running or pending GitLab pipeline. Use when the user wants to stop, abort, or cancel a build in progress. The pipeline can be retried afterward with retry_pipeline.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /projects/{{params.project_id}}/pipelines/{{params.pipeline_id}}/cancel`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `pipeline_id` | integer | **yes** | Pipeline id to cancel. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | integer |  |
| `status` | string |  |

Also retrieved by: "stop this build in progress", "abort the running job", "kill this CI run".

### `gitlab.list_pipeline_jobs`

List the jobs that make up a GitLab pipeline, with the stage and status of each. Use when the user asks which job failed, how long a stage took, or what's still running in a build.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/pipelines/{{params.pipeline_id}}/jobs`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `pipeline_id` | integer | **yes** | Pipeline id. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `scope` | string, one of created, pending, running, failed, success, canceled, skipped | no | Filter jobs by status. |

Also retrieved by: "which step failed in that build", "what's still running in this pipeline", "break down the stages of this run".

### `gitlab.search`

Search across every GitLab project the signed-in user can see, by scope: projects, issues, merge requests, milestones, or users. Use for instance-wide lookups where the project is not already known. For one known project, use search_in_project.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /search`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `scope` | string, one of projects, issues, merge_requests, milestones, users | **yes** | What kind of result to search for. |
| `search` | string | **yes** | Search query text. |

Also retrieved by: "find something across every project", "look this up instance-wide", "where else does this show up".

### `gitlab.search_in_project`

Search inside one GitLab project by scope: code, commits, issues, merge requests, milestones, or wiki pages. Use when the user wants to find where something appears in a specific repo's code or history. For an instance-wide lookup, use search.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /projects/{{params.project_id}}/search`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `per_page` | integer | no | Results per page, max 100. |
| `project_id` | string | **yes** | Numeric project id or URL-encoded namespace path. |
| `scope` | string, one of blobs, commits, issues, merge_requests, milestones, wiki_blobs, notes | **yes** | What kind of result to search for within the project. |
| `search` | string | **yes** | Search query text. |

Also retrieved by: "hunt for this inside one repo", "dig through this project's history for it", "find where this appears in this codebase".
