Skip to content

CI/CD Usage

gitlab-mcp-server can run inside CI/CD jobs just like any other CLI tool. Two usage modes are available:

| Mode | LLM Required | Use Case | Determinism | | ------------------------------------ | :----------: | ---------------------------------------------------------------- | :--------------------: | | Deterministic (JSON-RPC) | No | Scripted operations: list issues, post comments, create releases | ✅ Fully deterministic | | LLM-driven (headless MCP client) | Yes | Intelligent workflows: code review, issue triage, MR analysis | ❌ Non-deterministic |

Both modes authenticate with a Personal Access Token (PAT) or Project Access Token. Enterprise/Premium deployments using a token with api scope have access to the full tool surface. GitLab.com deployments have access to the core tool set plus additional Orbit-specific tools.

sequenceDiagram
    participant CI as CI/CD Job
    participant MCP as MCP Server (stdio)
    participant GL as GitLab API

    CI->>MCP: initialize (JSON-RPC via stdin)
    MCP-->>CI: capabilities (via stdout)
    CI->>MCP: notifications/initialized
    CI->>MCP: tools/call {tool, arguments}
    MCP->>GL: REST API v4 / GraphQL
    GL-->>MCP: JSON response
    MCP-->>CI: CallToolResult (via stdout)
    CI->>CI: Parse result with jq
  1. Download the binary from GitHub Releases:

    Terminal window
    curl -sSL "https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server-linux-amd64" \
    -o gitlab-mcp-server
    chmod +x gitlab-mcp-server
  2. Create a Project Access Token with api scope (recommended over personal PATs for CI).

  3. Store the token as a masked CI/CD variable named MCP_PAT.

Send JSON-RPC messages directly to the server via stdio. Fully deterministic — no LLM or external API needed.

The server communicates via the MCP protocol over stdin/stdout using JSON-RPC 2.0. Each interaction requires an initialize handshake, an initialized notification, then one or more tools/call requests.

.gitlab-ci.yml
mcp-list-issues:
stage: test
image: alpine:latest
variables:
GITLAB_URL: ${CI_SERVER_URL}
GITLAB_TOKEN: ${MCP_PAT}
before_script:
- apk add --no-cache curl jq
- curl -sSL "https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server-linux-amd64"
-o gitlab-mcp-server
- chmod +x gitlab-mcp-server
script:
- |
RESULT=$({
echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"ci","version":"1.0"}},"id":1}'
echo '{"jsonrpc":"2.0","method":"notifications/initialized"}'
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"gitlab_list_issues","arguments":{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened","per_page":5}},"id":2}'
} | ./gitlab-mcp-server 2>/dev/null | jq -s '.[1].result.content[0].text')
- echo "${RESULT}"

For pipelines with many tool calls, wrap the protocol in a reusable function:

Terminal window
mcp_call() {
local tool="$1"
local args="$2"
{
echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"ci","version":"1.0"}},"id":1}'
echo '{"jsonrpc":"2.0","method":"notifications/initialized"}'
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"'"${tool}"'","arguments":'"${args}"'},"id":2}'
} | ./gitlab-mcp-server 2>/dev/null | jq -s '.[1].result.content[0].text' -r
}
# Usage
ISSUES=$(mcp_call "gitlab_list_issues" '{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened"}')

Use a headless MCP client to let an LLM drive tool selection and orchestration. Ideal for intelligent workflows like code review, issue triage, and release notes generation.

IBM mcp-cli supports command mode for scriptable LLM-driven workflows, with OpenAI, Anthropic, Azure, Gemini, Groq, and local Ollama providers.

.gitlab-ci.yml
auto-review:
stage: review
image: python:3.12-slim
variables:
GITLAB_URL: ${CI_SERVER_URL}
GITLAB_TOKEN: ${MCP_PAT}
OPENAI_API_KEY: ${OPENAI_KEY}
before_script:
- apt-get update && apt-get install -y curl
- curl -sSL "https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server-linux-amd64"
-o gitlab-mcp-server
- chmod +x gitlab-mcp-server
- pip install --quiet mcp-cli
script:
- |
cat > server_config.json << 'EOF'
{
"mcpServers": {
"gitlab": {
"command": "./gitlab-mcp-server",
"env": {
"GITLAB_URL": "${GITLAB_URL}",
"GITLAB_TOKEN": "${GITLAB_TOKEN}"
}
}
}
}
EOF
- |
mcp-cli cmd \
--config-file server_config.json \
--server gitlab \
--provider openai \
--model gpt-4o \
--prompt "Review merge request !${CI_MERGE_REQUEST_IID} in project ${CI_PROJECT_ID}. Check for code quality, security issues, and missing tests. Post your review as a note on the MR." \
--raw
rules:
- if: $CI_MERGE_REQUEST_IID

For pipelines that cannot use external LLM APIs, run Ollama as a CI service:

local-llm-review:
stage: review
image: python:3.12-slim
services:
- name: ollama/ollama:latest
alias: ollama
variables:
GITLAB_URL: ${CI_SERVER_URL}
GITLAB_TOKEN: ${MCP_PAT}
OLLAMA_HOST: http://ollama:11434
before_script:
- apt-get update && apt-get install -y --no-install-recommends curl
- curl -sSL "https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server-linux-amd64"
-o gitlab-mcp-server
- chmod +x gitlab-mcp-server
- pip install --quiet mcp-cli
- curl -s "${OLLAMA_HOST}/api/pull" -d '{"name":"qwen2.5-coder:7b"}'
script:
- |
cat > server_config.json << 'EOF'
{
"mcpServers": {
"gitlab": {
"command": "./gitlab-mcp-server",
"env": {
"GITLAB_URL": "${GITLAB_URL}",
"GITLAB_TOKEN": "${GITLAB_TOKEN}"
}
}
}
}
EOF
- |
mcp-cli cmd \
--config-file server_config.json \
--server gitlab \
--provider ollama \
--model qwen2.5-coder:7b \
--prompt "Summarize the latest 5 merge requests in project ${CI_PROJECT_ID}." \
--raw

For pipelines that make many tool calls, the HTTP transport avoids per-call process startup overhead:

http-mode-pipeline:
script:
# Start HTTP server in background
- ./gitlab-mcp-server --http --gitlab-url="${CI_SERVER_URL}" --http-addr=127.0.0.1:8080 &
- sleep 2
# Call tools via HTTP
- |
curl -s -X POST http://127.0.0.1:8080/mcp \
-H "Content-Type: application/json" \
-H "PRIVATE-TOKEN: ${MCP_PAT}" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"gitlab_list_issues","arguments":{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened"}},"id":2}' \
| jq '.result.content[0].text'

See HTTP Server Mode for full details.

Beyond running the server in pipelines, GitLab MCP Server provides comprehensive CI/CD management tools that AI assistants can use interactively. These are available through the default dynamic find/execute surface and through explicit meta-tools with TOOL_SURFACE=meta.

The gitlab_pipeline meta-tool manages the full pipeline lifecycle:

| Action | Description | | --------------------- | ---------------------------------------------------------------------------------------- | | list | List pipelines with filtering by status, ref | | get | Get pipeline details and status | | create | Trigger a new pipeline with variables | | cancel | Cancel a running pipeline | | retry | Retry a failed pipeline | | delete | Delete a pipeline | | variables | List pipeline variables | | test_report | Get test report for a pipeline | | wait | Wait for pipeline completion with polling | | schedule_* | Pipeline schedule CRUD (list, get, create, edit, delete, run, take_ownership) | | schedule_*_variable | Schedule variable CRUD (list_variables, create_variable, edit_variable, delete_variable) | | trigger_* | Pipeline trigger token management (list, get, create, update, delete) |

The gitlab_job meta-tool provides complete job management:

| Action | Description | | ------------------- | ---------------------------------------- | | list | List jobs for a pipeline | | get | Get job details | | play | Trigger a manual job | | cancel | Cancel a running job | | retry | Retry a failed job | | trace | Get job log output | | artifacts | List job artifacts | | download_artifact | Download a specific artifact | | delete_artifacts | Delete job artifacts | | wait | Wait for job completion with polling |

| Meta-tool | Actions | Description | | -------------------- | ------------------------------------------------------------------- | ----------------------------------- | | gitlab_template | lint, lint_project | Validate .gitlab-ci.yml syntax | | gitlab_ci_variable | list, get, create, update, delete | Manage CI/CD variables | | gitlab_environment | list, get, create, update, delete, stop, deployment_* | Manage environments and deployments |

Trigger a pipeline with custom variables using JSON-RPC:

{
"tool": "gitlab_pipeline",
"arguments": {
"action": "create",
"project": "my-group/my-project",
"ref": "main",
"variables": [
{ "key": "DEPLOY_ENV", "value": "staging", "variable_type": "env_var" },
{ "key": "CONFIG", "value": "...", "variable_type": "file" }
]
}
}

For the complete tool reference, see Tools Overview.

| Practice | Recommendation | | ------------- | ---------------------------------------------------------------- | | Token type | Project Access Token — scoped to a single project, auditable | | Scope | api for full access, read_api for read-only workflows | | Expiration | 90 days maximum, rotate before expiry | | Storage | Masked CI/CD variable — never commit to repository | | Multi-project | Use Group Access Tokens for cross-project workflows |

| Error | Solution | | ----------------------------------------------- | --------------------------------------------------------------- | | not found / permission denied | Verify binary downloaded for correct platform, run chmod +x | | 401 Unauthorized | Check MCP_PAT variable is set and token not expired | | x509: certificate signed by unknown authority | Set GITLAB_SKIP_TLS_VERIFY=true | | Timeout on large responses | Add per_page argument to limit results | | mcp-cli provider errors | Verify API key variables, check pip install --upgrade mcp-cli |