Docker
La imagen se publica como ghcr.io/jmrplens/gitlab-mcp-server y se replica como docker.io/jmrplens/gitlab-mcp-server en Docker Hub, con una etiqueta <versión> y latest en ambos registros, para linux/amd64 y linux/arm64. Cada release la construye con atestaciones de procedencia y SBOM y la firma por digest con Cosign. Dentro: una base Alpine con certificados CA y datos de zona horaria, el binario en /usr/local/bin/gitlab-mcp-server, un usuario no-root appuser (UID 10001), el puerto 8080 expuesto y un HEALTHCHECK que ejecuta gitlab-mcp-server --probe, que pregunta por /health al servidor en marcha allá donde escuche (la imagen 2.7.5 lanza wget contra el puerto 8080 en su lugar).
Stdio: la imagen como servidor MCP local
Sección titulada «Stdio: la imagen como servidor MCP local»docker run -i --rm -e GITLAB_TOKEN ghcr.io/jmrplens/gitlab-mcp-server:latest-e GITLAB_TOKEN sin valor reenvía la variable desde el entorno que el cliente le da a docker, de modo que el token vive en el bloque env del cliente y no en la línea de comandos. Docker descarga la imagen en la primera ejecución. La entrada de cliente que lanza este comando está en Configura tu cliente más abajo; con Claude Code el registro es esa misma línea de comandos, y tampoco lleva token:
export GITLAB_TOKEN=glpat-xxxxclaude mcp add gitlab --transport stdio \ -- docker run -i --rm -e GITLAB_TOKEN ghcr.io/jmrplens/gitlab-mcp-server:latestClaude Code le pasa su propio entorno a docker, que es de donde -e GITLAB_TOKEN toma el valor, así que expórtalo en la shell desde la que lanzas el cliente (tu perfil de shell lo hace duradero) o añádelo después al bloque env de la entrada. Un contenedor tiene su propio sistema de archivos y nunca lee ~/.gitlab-mcp-server.env, que es como el resto de canales aportan el token; el reenvío es el equivalente del contenedor.
Los botones de un clic para VS Code, Cursor, LM Studio y Kiro del Inicio rápido registran exactamente esta entrada, y el manifiesto de Plugins de agente también la ejecuta.
Variables de entorno
Sección titulada «Variables de entorno»En modo stdio cada ajuste es una variable de entorno, y cada una que uses necesita su propio -e NOMBRE para que Docker la copie dentro del contenedor. La lista que reenvía la configuración del plugin incluido es una buena plantilla: GITLAB_URL, GITLAB_TOKEN, GITLAB_MCP_SKIP_TLS_VERIFY, GITLAB_MCP_TOOL_SURFACE, GITLAB_MCP_CAPABILITY_SURFACE, GITLAB_MCP_META_PARAM_SCHEMA, GITLAB_MCP_TIER, GITLAB_MCP_READ_ONLY, GITLAB_MCP_SAFE_MODE, GITLAB_MCP_EMBEDDED_RESOURCES, GITLAB_MCP_EXCLUDE_TOOLS, GITLAB_MCP_IGNORE_SCOPES, GITLAB_MCP_UPLOAD_MAX_FILE_SIZE, GITLAB_MCP_ALLOWED_IMPORT_DIRS, GITLAB_MCP_RATE_LIMIT_RPS, GITLAB_MCP_RATE_LIMIT_BURST, GITLAB_MCP_CLIENT_COMPAT y GITLAB_MCP_LOG_LEVEL. Qué hace cada una está en la página de Configuración.
HTTP: la imagen como servicio
Sección titulada «HTTP: la imagen como servicio»Arrancado sin -i, el contenedor no tiene una entrada estándar por la que hablar y escucha en el puerto 8080, pero no arranca hasta que le digas a qué GitLab sirve:
docker run --rm -p 8080:8080 ghcr.io/jmrplens/gitlab-mcp-server:latest \ --http --http-addr=0.0.0.0:8080 --gitlab-url=https://gitlab.comUn despliegue que no nombra ninguna instancia haría peticiones al host que quien llama ponga en la cabecera GITLAB-URL, con el token que esa misma persona enviara, así que se rechaza al arrancar. --allow-any-gitlab-url lo acepta para un despliegue local de un único usuario y avisa, pero solo si --http-addr liga loopback o un socket unix, así que dentro de un contenedor que liga 0.0.0.0 no sirve: publica las instancias. Cada cliente envía además su propio token de GitLab en cada petición, y el servidor no guarda ninguno. Para endurecer el contenedor como hace el despliegue de referencia:
docker run -d \ --name gitlab-mcp \ --read-only \ --tmpfs /tmp:rw,size=64m \ --cap-drop=ALL \ --security-opt=no-new-privileges:true \ -p 8080:8080 \ ghcr.io/jmrplens/gitlab-mcp-server:latest \ --http \ --http-addr=0.0.0.0:8080 \ --gitlab-url=https://gitlab.com# Publica cada instancia; la cabecera GITLAB-URL elige entre ellas y es# obligatoria, porque elegir por quien llama enviaría su token a otra partedocker run -d \ --name gitlab-mcp \ --read-only \ --tmpfs /tmp:rw,size=64m \ --cap-drop=ALL \ --security-opt=no-new-privileges:true \ -p 8080:8080 \ ghcr.io/jmrplens/gitlab-mcp-server:latest \ --http \ --http-addr=0.0.0.0:8080 \ --gitlab-url=https://gitlab.com \ --gitlab-url=https://gitlab.example.comUn cliente HTTP apunta entonces a http://localhost:8080/mcp con type: "http" y su propio token en una cabecera PRIVATE-TOKEN (el modo de autenticación legacy, que es el predeterminado), y http://localhost:8080/health responde sin credencial:
curl -X POST http://localhost:8080/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "PRIVATE-TOKEN: glpat-tu-token" \ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'En modo HTTP la configuración viene de flags y no de variables (--tool-surface, --tier, --read-only, --safe-mode, --skip-tls-verify, etcétera), que es lo que el docker-compose.yml del repositorio pasa en su línea command. El modo OAuth, el rate limiting, TLS en el propio listener, el dimensionado y la configuración de cliente para este transporte están en la página del Servidor HTTP.
Etiquetas y registros
Sección titulada «Etiquetas y registros»latestsigue a la release más nueva;2.7.5y cualquier otra etiqueta de versión se quedan fijas. Fija una etiqueta de versión en producción, o fija el digest para una inmutabilidad total:ghcr.io/jmrplens/gitlab-mcp-server:2.7.5@sha256:8eec1825b266712cd544bf1b2144e55c1eb711b4540def40e963a664c4e97168es la forma que usa elserver.jsondel MCP Registry para la release actual.ghcr.io/jmrplens/gitlab-mcp-serverydocker.io/jmrplens/gitlab-mcp-serverllevan las mismas imágenes: la etiqueta2.7.5resuelve al mismo digest en ambos. La documentación usaghcr.io; usa el nombre de Docker Hub si ese es el registro que permite tu red.- La imagen lleva la etiqueta
io.modelcontextprotocol.server.name=io.github.jmrplens/gitlab-mcp-server, que es como el MCP Registry valida su propiedad.
Configura tu cliente
Sección titulada «Configura tu cliente»La entrada stdio para un cliente de escritorio es el comando docker run de arriba, repartido entre command y args, con el token en env:
{ "mcpServers": { "gitlab": { "command": "docker", "args": ["run", "-i", "--rm", "-e", "GITLAB_TOKEN", "ghcr.io/jmrplens/gitlab-mcp-server:latest"], "env": { "GITLAB_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx" } } }}Para una instancia autogestionada añade "-e", "GITLAB_URL" a args y "GITLAB_URL": "https://gitlab.example.com" a env: la variable tiene que estar definida y reenviada a la vez. Las pestañas por cliente del Inicio rápido muestran dónde va este JSON en cada cliente; sustituye su command y su env por los de arriba. VS Code usa un mapa servers con "type": "stdio" en lugar de mcpServers.
Actualizar y desinstalar
Sección titulada «Actualizar y desinstalar»El servidor nunca se actualiza a sí mismo, y dentro de un contenedor no debería: descarga la imagen más nueva y arranca un contenedor nuevo a partir de ella.
docker pull ghcr.io/jmrplens/gitlab-mcp-server:latestUn cliente stdio que ejecuta docker run --rm usa la imagen descargada en su siguiente arranque. Para un servicio HTTP, recrea el contenedor (docker compose pull && docker compose up -d con el archivo Compose de referencia, o docker rm -f gitlab-mcp y el docker run de arriba). Con una etiqueta de versión, cambia la etiqueta y descarga esa. Para desinstalar, para cualquier contenedor y elimina la imagen:
docker rmi ghcr.io/jmrplens/gitlab-mcp-server:latesty quita la entrada gitlab de la configuración de tu cliente. Son los comandos estándar de Docker; nada en la imagen los cambia.