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:

ModeLLM RequiredUse CaseDeterminism
Deterministic (JSON-RPC)NoScripted operations: list issues, post comments, create releases✅ Fully deterministic
LLM-driven (headless MCP client)YesIntelligent 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:

ActionDescription
listList pipelines with filtering by status, ref
getGet pipeline details and status
createTrigger a new pipeline with variables
cancelCancel a running pipeline
retryRetry a failed pipeline
deleteDelete a pipeline
variablesList pipeline variables
test_reportGet test report for a pipeline
waitWait for pipeline completion with polling
schedule_*Pipeline schedule CRUD (list, get, create, edit, delete, run, take_ownership)
schedule_*_variableSchedule 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:

ActionDescription
listList jobs for a pipeline
getGet job details
playTrigger a manual job
cancelCancel a running job
retryRetry a failed job
traceGet job log output
artifactsList job artifacts
download_artifactDownload a specific artifact
delete_artifactsDelete job artifacts
waitWait for job completion with polling
Meta-toolActionsDescription
gitlab_templatelint, lint_projectValidate .gitlab-ci.yml syntax
gitlab_ci_variablelist, get, create, update, deleteManage CI/CD variables
gitlab_environmentlist, 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.

PracticeRecommendation
Token typeProject Access Token — scoped to a single project, auditable
Scopeapi for full access, read_api for read-only workflows
Expiration90 days maximum, rotate before expiry
StorageMasked CI/CD variable — never commit to repository
Multi-projectUse Group Access Tokens for cross-project workflows
ErrorSolution
not found / permission deniedVerify binary downloaded for correct platform, run chmod +x
401 UnauthorizedCheck MCP_PAT variable is set and token not expired
x509: certificate signed by unknown authoritySet GITLAB_SKIP_TLS_VERIFY=true
Timeout on large responsesAdd per_page argument to limit results
mcp-cli provider errorsVerify API key variables, check pip install --upgrade mcp-cli

Can I use gitlab-mcp-server in CI/CD without an LLM?

Section titled “Can I use gitlab-mcp-server in CI/CD without an LLM?”

Yes. The deterministic mode sends JSON-RPC 2.0 messages directly to the server over stdio, with no LLM or external API involved. Each interaction performs an initialize handshake, sends a notifications/initialized message, then issues one or more tools/call requests, and you parse the result with jq. This mode is fully deterministic, making it ideal for scripted operations such as listing issues, posting comments, or creating releases.

Which GitLab token type should I use in CI/CD pipelines?

Section titled “Which GitLab token type should I use in CI/CD pipelines?”

Use a Project Access Token scoped to a single project and store it as a masked CI/CD variable, never committed to the repository. Choose the api scope for full access or read_api for read-only workflows, set a maximum 90-day expiration, and rotate the token before it expires. For workflows that span several projects, use a Group Access Token instead.

How do I block a CI script until a GitLab pipeline finishes?

Section titled “How do I block a CI script until a GitLab pipeline finishes?”

Call the gitlab_pipeline meta-tool with the wait action. It polls the pipeline until it reaches a terminal state (success, failed, or canceled), which lets a CI script block until a triggered pipeline completes. The gitlab_job meta-tool offers an equivalent wait action for individual jobs.

Should I use stdio or HTTP transport in CI?

Section titled “Should I use stdio or HTTP transport in CI?”

Use stdio for occasional tool calls, because each call spawns and tears down a server process. For pipelines that make many tool calls, start the server once in HTTP mode with --http and call it over http://127.0.0.1:8080/mcp to avoid per-call process startup overhead. Both transports authenticate with a Personal Access Token or Project Access Token.