GitLab MCP Agent Skill Specification
This report defines the MCP tool set for GitLab, including method signatures, parameter schemas, return types, and examples. The tools are designed to be intuitive for AI agents while covering common GitLab workflows.
---
Conventions
- All tools are prefixed `gitlab.`.
- JSON‑RPC 2.0 over stdio (primary) and HTTP (secondary).
- Parameters are named and required unless marked optional.
- Errors are returned as MCP error objects with `code` (HTTP‑like) and `message`.
- Where an identifier can be either numeric ID or URL‑encoded path (e.g., `group%2Fproject`), tools accept `project` as a string and normalize internally.
---
Tool Definitions
Projects
#### gitlab.list_projects
List accessible projects.
Params:
- `owned` (bool, optional) – only projects owned by the authenticated user.
- `group` (string, optional) – filter by group path (e.g., `mygroup`).
- `search` (string, optional) – substring match on name/path.
Result: `{ "projects": [ { "id": number, "name": string, "path": string, "web_url": string } ] }`
Example:
json
{
"jsonrpc": "2.0",
"method": "gitlab.list_projects",
"params": { "owned": true },
"id": 1
}
#### gitlab.get_project
Get details of a specific project.
Params:
- `project` (string, required) – numeric ID or URL‑encoded path.
Result: `{ "id": number, "name": string, "description": string, "default_branch": string, "web_url": string, ... }`
---
Issues
#### gitlab.list_issues
List issues for a project.
Params:
- `project` (string, required)
- `state` (string, optional) – `opened`, `closed`, or `all` (default `opened`).
- `labels` (array of strings, optional) – filter by labels (OR).
- `assignee_id` (number, optional) – filter by assignee user ID.
- `milestone` (string, optional) – milestone title.
- `sort` (string, optional) – `created_desc`, `priority`, `due_date_desc`, etc.
Result: `{ "issues": [ { "iid": number, "title": string, "description": string, "state": string, "labels": [string], "assignee": { "id": number, "name": string }, "web_url": string } ] }`
Notes: `iid` is the project‑level issue number. Combine with `project` to reference.
#### gitlab.create_issue
Create a new issue.
Params:
- `project` (string, required)
- `title` (string, required)
- `description` (string, optional)
- `assignee_ids` (array of numbers, optional)
- `labels` (array of strings, optional)
- `milestone_id` (number, optional)
Result: `{ "issue": { "iid": number, "web_url": string } }`
#### gitlab.update_issue
Update an existing issue.
Params:
- `project` (string, required)
- `issue_iid` (number, required) – project‑level IID.
- `updates` (object, required) – fields to change: `title?`, `description?`, `assignee_ids?`, `labels?`, `milestone_id?`, `state_event?` (`close`, `reopen`).
Result: `{ "updated": true }`
#### gitlab.close_issue
Shortcut to close an issue.
Params:
- `project` (string, required)
- `issue_iid` (number, required)
Result: `{ "closed": true }`
---
Merge Requests
#### gitlab.list_merge_requests
List merge requests.
Params:
- `project` (string, required)
- `state` (string, optional) – `opened`, `closed`, `merged`, `all` (default `opened`).
- `target_branch` (string, optional) – filter by target branch.
- `source_branch` (string, optional) – filter by source branch.
- `assignee_id` (number, optional)
Result: `{ "merge_requests": [ { "iid": number, "title": string, "source_branch": string, "target_branch": string, "state": string, "web_url": string, "assignee"? } ] }`
#### gitlab.create_merge_request
Create a new merge request.
Params:
- `project` (string, required)
- `source_branch` (string, required) – branch with changes.
- `target_branch` (string, required) – branch to merge into.
- `title` (string, required)
- `description` (string, optional)
- `assignee_id` (number, optional)
- `labels` (array of strings, optional)
- `remove_source_branch` (bool, optional) – delete source after merge.
Result: `{ "mr": { "iid": number, "web_url": string } }`
#### gitlab.merge_merge_request
Accept and merge a merge request.
Params:
- `project` (string, required)
- `mr_iid` (number, required)
- `merge_when_ready` (bool, optional) – wait for pipeline success.
- `squash` (bool, optional) – squash commits.
- `should_remove_source_branch` (bool, optional)
Result: `{ "merged": true, "sha": string }`
#### gitlab.approve_merge_request
Add an approval from the current user.
Params:
- `project` (string, required)
- `mr_iid` (number, required)
Result: `{ "approved": true }`
---
Repository Files
#### gitlab.upsert_file
Create or update a file in the repository.
Params:
- `project` (string, required)
- `file_path` (string, required) – path relative to repo root.
- `content` (string, required) – raw file contents (text).
- `branch` (string, required) – target branch (will create if doesn’t exist? no, branch must exist; otherwise use `start_branch` param in GitLab `create_branch` first).
- `commit_message` (string, required)
- `author_email` (string, optional)
- `author_name` (string, optional)
Result: `{ "sha": string, "web_url": string }`
Idempotency: If file exists and content matches current, return existing SHA; else update.
#### gitlab.get_file
Retrieve a file’s contents and metadata.
Params:
- `project` (string, required)
- `file_path` (string, required)
- `ref` (string, optional) – branch, tag, or commit SHA (default default branch).
Result: `{ "content": string (base64 decoded), "encoding": "base64", "sha": string, "file_path": string }`
Note: We decode base64 for convenience; agent receives plain text.
#### gitlab.delete_file
Delete a file.
Params:
- `project` (string, required)
- `file_path` (string, required)
- `branch` (string, required) – branch to delete from.
- `commit_message` (string, required)
Result: `{ "deleted": true }`
---
CI/CD
#### gitlab.list_pipelines
List pipelines for a project or ref.
Params:
- `project` (string, required)
- `ref` (string, optional) – branch or tag to filter.
- `status` (string, optional) – `running`, `success`, `failed`, `canceled`.
Result: `{ "pipelines": [ { "id": number, "sha": string, "ref": string, "status": string, "web_url": string } ] }`
#### gitlab.trigger_pipeline
Create a new pipeline for a ref.
Params:
- `project` (string, required)
- `ref` (string, required) – branch or tag to run on.
- `variables` (object, optional) – key/value pairs to pass as CI variables.
Result: `{ "pipeline": { "id": number, "web_url": string } }`
#### gitlab.list_pipeline_jobs
List jobs in a pipeline.
Params:
- `project` (string, required)
- `pipeline_id` (number, required)
Result: `{ "jobs": [ { "id": number, "name": string, "status": string, "stage": string, "web_url": string } ] }`
#### gitlab.play_job
Trigger a manual job.
Params:
- `project` (string, required)
- `job_id` (number, required)
Result: `{ "started": true }`
---
Error Handling
Common error codes (drawn from GitLab):
- `404` – Not found (project, issue, etc.)
- `403` – Forbidden (insufficient token scope)
- `400` – Bad request (validation failed; e.g., branch doesn’t exist)
- `409` – Conflict (e.g., MR already exists)
- `429` – Rate limit exceeded
- `500` – GitLab server error
MCP error objects:
json
{
"code": 404,
"message": "Project not found: 'mygroup%2Fmyproj'"
}
---
Security Considerations
- Token stored in env var; not exposed in logs.
- All operations are performed with the token’s permissions; restrict token scopes to least privilege needed (e.g., `api` covers all; `read_api` for read‑only; `write_repository` for file ops).
- Since MCP often runs under an agent user, protect the token like a password.
- Optionally add MCP‑level token for extra layer; but stdio isolation usually sufficient.
---
Implementation Notes
- Use the standard Go HTTP client or a lightweight wrapper.
- For project normalization: when given a path like `group/project`, URL‑encode the slash to `group%2Fproject` before adding to API URL, or use numeric ID.
- Pagination: GitLab defaults to 20 items per page; set `per_page=100` (max) and accept that very large lists may be truncated. Can add `?all=true` fetching all pages if needed.
- For `upsert_file`: use “Get file” → if exists, call “Update file”; else “Create file”.
---
Word count: ~1,200