Ir al contenido

Uso en CI/CD

gitlab-mcp-server puede ejecutarse dentro de jobs CI/CD como cualquier otra herramienta CLI. Hay dos modos de uso disponibles:

ModoLLM NecesarioCaso de usoDeterminismo
Determinista (JSON-RPC)NoOperaciones scriptadas: listar issues, publicar comentarios, crear releases✅ Determinista
Con LLM (cliente MCP headless)Flujos inteligentes: revisión de código, triaje de issues, análisis de MRs❌ No determinista

Ambos modos se autentican con un Personal Access Token (PAT) o Project Access Token. Los despliegues Enterprise/Premium con un token de scope api tienen acceso a toda la superficie de herramientas. Los despliegues GitLab.com tienen acceso al conjunto principal de herramientas más las herramientas adicionales específicas de Orbit.

API de GitLabMCP Server (stdio)Job CI/CDAPI de GitLabMCP Server (stdio)Job CI/CDinitialize (JSON-RPC vía stdin)capabilities (vía stdout)notifications/initializedtools/call {tool, arguments}REST API v4 / GraphQLRespuesta JSONCallToolResult (vía stdout)Parsear resultado con jq
  1. Descarga el binario desde GitHub Releases:

    Ventana de terminal
    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. Crea un Project Access Token con scope api (recomendado sobre PATs personales para CI).

  3. Almacena el token como variable CI/CD enmascarada llamada MCP_PAT.

Envía mensajes JSON-RPC directamente al servidor a través de stdio. Totalmente determinista — sin LLM ni API externa necesaria.

El servidor se comunica a través del protocolo MCP sobre stdin/stdout usando JSON-RPC 2.0. Cada interacción requiere un handshake initialize, una notificación initialized, y luego una o más solicitudes tools/call.

El nombre de herramienta que puede invocar un job depende de la superficie de herramientas activa. La predeterminada es dynamic y registra exactamente dos herramientas —gitlab_find_action y gitlab_execute_action—, así que un script llama a gitlab_execute_action con un ID canónico domain.action y un objeto params. Invocar una herramienta individual sobre la superficie predeterminada responde con {"code":-32602,"message":"unknown tool ..."}; como es un error JSON-RPC y no un resultado de herramienta, jq -s '.[1].result.content[0].text' imprime null y el job termina sin salida y sin fallar. Si prefieres una herramienta por operación, define GITLAB_MCP_TOOL_SURFACE=individual en las variables: del job: los nombres individuales empiezan por el dominio, no por el verbo (gitlab_issue_list, gitlab_mr_list, gitlab_project_get); consulta el Resumen de herramientas.

.gitlab-ci.yml
mcp-list-issues:
stage: test
image: debian:stable-slim
variables:
GITLAB_URL: ${CI_SERVER_URL}
GITLAB_TOKEN: ${MCP_PAT}
before_script:
- apt-get update && apt-get install -y --no-install-recommends ca-certificates 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_execute_action","arguments":{"action":"issue.list","params":{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened","per_page":5}}},"id":2}'
} | ./gitlab-mcp-server 2>/dev/null | jq -s '.[1]')
# jq -e para que un error JSON-RPC o un error de herramienta hagan fallar el
# job en lugar de imprimir "null" y salir con 0.
- jq -e 'has("error") | not' >/dev/null <<<"${RESULT}"
- jq -e '.result.isError != true' >/dev/null <<<"${RESULT}"
- jq -r '.result.content[0].text' <<<"${RESULT}"

Para pipelines con muchas llamadas, envuelve el protocolo en una función reutilizable:

Ventana de terminal
mcp_call() {
local action="$1"
local args="$2"
local response
response=$({
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_execute_action","arguments":{"action":"'"${action}"'","params":'"${args}"'}},"id":2}'
} | ./gitlab-mcp-server 2>/dev/null | jq -s '.[1]')
# Un error JSON-RPC y un error de herramienta son fallos distintos, y ninguno
# llega al estado de salida del pipeline anterior: sin estas comprobaciones la
# función imprime "null" y el job termina con éxito.
if jq -e 'has("error")' >/dev/null <<<"${response}"; then
echo "MCP ${action} ha fallado: $(jq -r '.error.message' <<<"${response}")" >&2
return 1
fi
if jq -e '.result.isError == true' >/dev/null <<<"${response}"; then
echo "MCP ${action} ha devuelto un error de herramienta: $(jq -r '.result.content[0].text' <<<"${response}")" >&2
return 1
fi
jq -r '.result.content[0].text' <<<"${response}"
}
# Uso
ISSUES=$(mcp_call "issue.list" '{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened"}')

Usa un cliente MCP headless para que un LLM seleccione y orqueste las herramientas. Ideal para flujos inteligentes como revisión de código, triaje de issues y generación de notas de release.

IBM mcp-cli soporta modo comando para flujos automatizados con LLM, con proveedores OpenAI, Anthropic, Azure, Gemini, Groq y Ollama local.

.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 "Revisa el merge request !${CI_MERGE_REQUEST_IID} en el proyecto ${CI_PROJECT_ID}. Comprueba calidad de código, problemas de seguridad y tests faltantes. Publica tu revisión como nota en el MR." \
--raw
rules:
- if: $CI_MERGE_REQUEST_IID

Para pipelines que no pueden usar APIs de LLM externas, ejecuta Ollama como servicio CI:

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 "Resume los últimos 5 merge requests del proyecto ${CI_PROJECT_ID}." \
--raw

Para pipelines con muchas llamadas a herramientas, el transporte HTTP evita la sobrecarga de inicio de proceso por llamada:

http-mode-pipeline:
script:
# Iniciar servidor HTTP en segundo plano
- ./gitlab-mcp-server --http --gitlab-url="${CI_SERVER_URL}" --http-addr=127.0.0.1:8080 &
- sleep 2
# Llamar herramientas vía 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_execute_action","arguments":{"action":"issue.list","params":{"project_id":"'"${CI_PROJECT_ID}"'","state":"opened"}}},"id":2}' \
| jq '.result.content[0].text'

Consulta Servidor HTTP para detalles completos.

Más allá de ejecutar el servidor en pipelines, GitLab MCP Server proporciona herramientas completas de gestión CI/CD que los asistentes de IA pueden usar interactivamente. Están disponibles mediante la superficie dinámica find/execute predeterminada y mediante meta-herramientas explícitas con GITLAB_MCP_TOOL_SURFACE=meta.

El dominio pipeline gestiona el ciclo de vida completo de los pipelines. Sus acciones son IDs pipeline.<acción> para gitlab_execute_action en la superficie dinámica predeterminada (las acciones de programaciones llevan pipeline_schedule. en su lugar, como se indica más abajo) y los valores de action de la meta-herramienta gitlab_pipeline con GITLAB_MCP_TOOL_SURFACE=meta:

AcciónDescripción
listListar pipelines con filtrado por estado, ref
getObtener detalles y estado del pipeline
createDisparar un nuevo pipeline con variables
cancelCancelar un pipeline en ejecución
retryReintentar un pipeline fallido
deleteEliminar un pipeline
variablesListar variables del pipeline
test_reportObtener el informe de tests de un pipeline
waitEsperar a la finalización del pipeline con polling
latestObtener el último pipeline de una ref
test_report_summaryObtener el resumen del informe de tests de un pipeline
update_metadataActualizar los metadatos de un pipeline (nombre)
trigger_*Gestión de tokens de trigger de pipeline (list, get, create, update, delete, run)
schedule_*CRUD de programaciones de pipeline (list, get, create, update, delete, run, take ownership, list triggered pipelines); prefijo pipeline_schedule. en la superficie dinámica
schedule_*_variableCRUD de variables de programación (create, edit, delete); mismo prefijo en la superficie dinámica

Las filas de programaciones pertenecen al dominio pipeline_schedule, así que en la superficie dinámica sus IDs se leen pipeline_schedule.schedule_list, pipeline_schedule.schedule_run, pipeline_schedule.schedule_take_ownership, pipeline_schedule.schedule_list_triggered_pipelines, pipeline_schedule.schedule_create_variable, pipeline_schedule.schedule_edit_variable, etc.; en la superficie meta son valores de action de gitlab_pipeline como el resto de la tabla.

El dominio job proporciona gestión completa de jobs. Sus acciones son IDs job.<acción> para gitlab_execute_action en la superficie dinámica predeterminada y los valores de action de la meta-herramienta gitlab_job con GITLAB_MCP_TOOL_SURFACE=meta:

AcciónDescripción
listListar jobs de un pipeline
getObtener detalles del job
playEjecutar un job manual
cancelCancelar un job en ejecución
retryReintentar un job fallido
traceObtener la salida del log del job
artifactsListar artefactos del job
download_artifactsDescargar el archivo de artefactos de un job
download_single_*Descargar un único fichero de los artefactos de un job, por ID de job o por ref y nombre de job
keep_artifactsConservar los artefactos más allá de su caducidad
delete_artifactsEliminar los artefactos de un job (una variante a nivel de proyecto elimina los de todos los jobs)
eraseBorrar el log y los artefactos de un job
list_projectListar jobs de todo un proyecto
list_bridgesListar los jobs de trigger (bridge) de un pipeline
waitEsperar a la finalización del job con polling

Las dos descargas de un único fichero son job.download_single_artifact (por ID de job) y job.download_single_artifact_by_ref (por ref y nombre de job); la eliminación a nivel de proyecto es job.delete_project_artifacts.

Dominio (meta-herramienta)AccionesDescripción
template (gitlab_template)lint, lint_projectValidar sintaxis de .gitlab-ci.yml
ci_variable (gitlab_ci_variable)list, get, create, update, deleteGestionar variables CI/CD
environment (gitlab_environment)list, get, create, update, delete, stop, deployment_*Gestionar entornos y despliegues

Disparar un pipeline con variables personalizadas en la superficie dinámica predeterminada:

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

Con GITLAB_MCP_TOOL_SURFACE=meta la misma llamada es gitlab_pipeline con { "action": "create", "params": { ... } }; las meta-herramientas solo aceptan action y params en el nivel superior, así que los parámetros van anidados en params en ambas superficies.

Para la referencia completa de herramientas, consulta Resumen de herramientas.

PrácticaRecomendación
Tipo de tokenProject Access Token — limitado a un proyecto, auditable
Scopeapi para acceso completo, read_api para flujos de solo lectura
ExpiraciónMáximo 90 días, rotar antes de que expire
AlmacenamientoVariable CI/CD enmascarada — nunca commitear al repositorio
Multi-proyectoUsar Group Access Tokens para flujos entre proyectos
ErrorSolución
not found / permiso denegadoVerifica que el binario se descargó para la plataforma correcta, ejecuta chmod +x
401 UnauthorizedComprueba que la variable MCP_PAT está configurada y el token no ha expirado
x509: certificate signed by unknown authorityConfigura GITLAB_MCP_SKIP_TLS_VERIFY=true
Timeout en respuestas grandesAñade argumento per_page para limitar resultados
Errores de proveedor en mcp-cliVerifica las variables de API key, prueba pip install --upgrade mcp-cli

Preguntas frecuentes

¿Puedo usar gitlab-mcp-server en CI/CD sin un LLM?

Sí. El modo determinista envía mensajes JSON-RPC 2.0 directamente al servidor por stdio, sin LLM ni API externa. Cada interacción realiza un handshake initialize, envía un mensaje notifications/initialized y luego emite una o más solicitudes tools/call, y el resultado se parsea con jq. Este modo es totalmente determinista, lo que lo hace ideal para operaciones scriptadas como listar issues, publicar comentarios o crear releases.

¿Qué tipo de token de GitLab debería usar en pipelines CI/CD?

Usa un Project Access Token limitado a un solo proyecto y almacénalo como variable CI/CD enmascarada, nunca commiteada al repositorio. Elige el scope api para acceso completo o read_api para flujos de solo lectura, define una expiración máxima de 90 días y rota el token antes de que expire. Para flujos que abarcan varios proyectos, usa un Group Access Token.

¿Cómo bloqueo un script CI hasta que un pipeline de GitLab termine?

Ejecuta la acción wait de pipelines: gitlab_execute_action con action: 'pipeline.wait' en la superficie dinámica predeterminada, o la meta-herramienta gitlab_pipeline con action: 'wait' cuando GITLAB_MCP_TOOL_SURFACE=meta. Consulta el pipeline hasta que alcanza un estado terminal (success, failed o canceled), lo que permite que un script CI se bloquee hasta que un pipeline disparado termine. La acción job.wait (gitlab_job con wait en la superficie meta) hace lo mismo para jobs individuales.

¿Debería usar transporte stdio o HTTP en CI?

Usa stdio para llamadas ocasionales, porque cada llamada inicia y termina un proceso de servidor. Para pipelines con muchas llamadas a herramientas, arranca el servidor una vez en modo HTTP con --http y llámalo en http://127.0.0.1:8080/mcp para evitar la sobrecarga de inicio de proceso por llamada. Ambos transportes se autentican con un Personal Access Token o un Project Access Token.