GitLab
For: tenant administrators and plugin users.
Connect GitLab issues, merge requests, pipelines and repositories through GitLab's MCP server. The connector supports GitLab.com, self-managed GitLab and GitLab Dedicated, uses your tenant's OAuth application, and receives GitLab webhooks as events.
| Manifest name | gitlab (hub name ai.oz0/gitlab), kind: connector |
| Tools | gitlab: GitLab's MCP server, https://<host>/api/v4/mcp; gitlab_events: the webhooks' normaliser, which reaches nothing |
| Connection | gitlab: authorization code with PKCE on your own non-confidential OAuth application, the mcp scope, refreshed by the edge |
| Event source | gitlab: issue, merge request and pipeline events, checked against the webhook's secret token |
| Agent | gitlab, a generic delegate on the default alias |
| Pin | snapshots/gitlab.json (21 functions) and the toolsets header |
| Egress | The connection's host only: gitlab.com, or your instance's |
Sources, read 2026-10-17: GitLab MCP server, its tools, OAuth 2.0 identity provider API, GitLab as an OAuth 2.0 provider, webhooks and webhook events.
Functions
The tool sends X-Gitlab-Enabled-Mcp-Server-Toolsets: core,work_items,merge_requests,repository,ci with every
request, so GitLab lists those toolsets and meta, and never duo_agent_platform (which needs a GitLab Duo licence),
wikis or code_security. The plugin pins 21 of the functions GitLab lists there, and the connection gives a token
to those only: GitLab's other functions (merging, committing, running pipelines) show in the catalog but cannot be
called through this plugin.
| Function | Does | Asks a person by default |
|---|---|---|
gitlab.list_work_items | Lists or searches issues and other work items in a project or group | no |
gitlab.get_work_item | Reads one work item, with its notes when asked | no |
gitlab.get_work_item_types | Lists the work item types a project or group has | no |
gitlab.list_merge_requests | Lists or searches merge requests | no |
gitlab.get_merge_request | Reads a merge request, with its diffs, commits, notes or pipelines when asked | no |
gitlab.list_pipelines | Lists a project's pipelines | no |
gitlab.get_pipeline | Reads a pipeline, with its jobs when asked | no |
gitlab.get_job | Reads a CI/CD job, with its log when asked | no |
gitlab.get_repository_file | Reads a file at a branch, tag or commit | no |
gitlab.list_repository_tree | Lists a directory | no |
gitlab.list_commits | Lists commits | no |
gitlab.get_commit | Reads a commit, with its diff when asked | no |
gitlab.list_branches | Lists branches | no |
gitlab.get_project, gitlab.list_projects | Reads a project, lists projects | no |
gitlab.get_user | Reads a user, or the signed-in one | no |
gitlab.search | Searches the instance | no |
gitlab.search_labels | Searches a project's or group's labels | no |
gitlab.get_mcp_server_version | Reads the MCP server's version | no |
gitlab.save_note | Comments on a work item or merge request | yes |
gitlab.save_work_item | Creates an issue, or changes one (title, description, labels, state) | yes |
The two writes wait for an operator who did not start the job, unless your tool policy names other deciders.
Connect it
- Allow MCP access at GitLab. On GitLab.com an Owner allows access to the MCP server for the top-level group; on a self-managed instance or Dedicated an administrator allows it for the instance.
- Create an OAuth application at GitLab, for a user, a group or the instance: clear Confidential (it has no
client secret), select the
mcpscope, and give it the redirect URL thatoz0 connection show gitlabprints under "calls back". - Connect. The host defaults to
gitlab.com; give your instance's for a self-managed one or Dedicated:
oz0 connection set gitlab --param host=gitlab.example.com --param client_id=<the application ID>
oz0 connection start gitlab # opens GitLab's sign-in; the edge keeps and refreshes the token
The person who connects signs in as themselves, and every call acts as them, within what GitLab lets them see and do. The edge refreshes the token before it expires (GitLab's live two hours) and asks for the connection to be connected again when GitLab refuses a refresh. A changed host gets no token until the connection is connected again for it, so a token GitLab issued for one instance never goes to another.
A host on a private network needs it allowed: oz0 server start --connect-allow-net <CIDR>.
Webhooks as events
Point a project's or group's webhook at https://<edge>/events/<tenant>/gitlab, with Secret token set to the
value of the tenant secret GITLAB_WEBHOOK_TOKEN (oz0 secret set GITLAB_WEBHOOK_TOKEN --signing --host <edge>:7443 reads it from standard input; the edge takes it only as a signing key bound to its own address),
and select issue, merge request and pipeline events. The edge compares X-Gitlab-Token with the secret before
anything reads the delivery, and takes a redelivery once by its Idempotency-Key. A routine fires
on them:
triggers:
- name: opened
event:
source: gitlab
types: [issue]
filter: event.action == 'open'
Each event has a type (issue, merge_request or pipeline), an action (GitLab's, such as open, update,
merge, or a pipeline's status, such as failed), a subject (group/project#7, group/project!3,
group/project/pipelines/31), attributes for filters (project, iid, state, branches, labels, failed jobs) and the
text an agent reads, which is outside input: what an issue's author wrote is in it.
GitLab sends every kind of work item under its issue events. Only issues (and Service Desk issues) become issue
events, with attributes.work_item_type set to Issue; tasks, incidents, epics, objectives and key results are
accepted and ignored, so GitLab never counts them as failed deliveries and never turns the webhook off for them.
Limits
- Writes ask a person by default (
save_noteandsave_work_item, through the plugin's suggested policy, which an admin may switch with a reason; up to 1.0.0 underrequires_approval, and an update from it keeps asking), and are not safe to repeat: GitLab's MCP server takes no idempotency key, so asave_notesent twice comments twice. Orchestrator Zero makes an approved call once. - No push of changes. The plugin cannot apply a reviewed changeset: its
writes are
save_noteandsave_work_item. When it can, it refuses a change to a plugin's tests or rules, and to CODEOWNERS or CI workflows, without the second approval those need, asoz0_github.push_changesdoes (protected paths). - The AI label goes at the start of
save_note'sbodyandsave_work_item'sdescription: GitLab reads nothing Orchestrator Zero sends beside the call, so the node puts the tenant's label in the text people read, after the approval. A work item's title carries no label. - No annotations or output schemas from GitLab. GitLab documents neither for its MCP tools. The plugin marks the
reads read-only and the writes as writes, and declares the output schemas of the single-object reads (
get_*) from what GitLab's documentation says they return, with no required fields; the lists and searches answer in text.
Rate limits
GitLab.com allows 60 MCP requests a minute per user on Free and 600 on Premium and Ultimate, and counts them toward its general limits too; a self-managed instance's administrator sets one instance-wide limit. Each call is one session of its own. Above the limit GitLab answers 429 and the call is not made. A read is called again after the wait GitLab asks for, once your tenant approved the plugin's listing; a write is not, and the agent reads an error that says it is retryable and how long GitLab asks to wait.
- Sign-in. OAuth only, on your own application. Personal, project and group access tokens of the legacy kind
cannot carry the
mcpscope (GitLab answers 403), fine-grained personal access tokens are not offered, and dynamic client registration is not used. - A refresh replaces the token in force. GitLab revokes the access token a refresh replaces, so a call that read the old token a moment before can fail once with 401; the next call gets the new one.
- Webhooks with a secret token, not a signing token. GitLab's signing token (HMAC per the Standard Webhooks specification, GitLab 19.0 and later) is not checked yet; set the secret token, which GitLab sends over TLS.
- Issues only, of the work items. Tasks, incidents, epics, objectives and key results arrive under GitLab's issue events and are ignored, not refused, so they never count against the webhook.
- No EU regional host on GitLab.com. GitLab Dedicated and self-managed instances run where their owner chooses.
- Licence. The toolsets the plugin uses are on GitLab's Free tier; nothing it calls needs GitLab Duo.
- Installing or updating runs the delegate's eval as the quality gate, on the tenant's own models.
- Tested against a fake of GitLab's server and OAuth endpoints, shaped from GitLab's documentation, not against GitLab itself. "Verified" means the project tested, pinned and secured the plugin, never that GitLab endorses it.
ServiceNow
The verified plugin ai.oz0/servicenow - a ServiceNow instance's incidents, requested items and tasks on its Table API, incident changes as events, and ServiceNow's own MCP server as an option.
Support triage
The verified plugin ai.oz0/support-triage - new tickets in Jira Service Management or ServiceNow triaged by an agent, routed and noted through the ticket system's connector, and acknowledged by mail, each write after a person approves it.