Ir al contenido

Línea de comandos

gitlab-mcp-server [flags]
gitlab-mcp-server --probe [flags] [target]

Sin flags, el servidor sirve stdio y lee su configuración del entorno, de ~/.gitlab-mcp-server.env y del fichero que nombren --env-file o GITLAB_MCP_ENV_FILE. Si se arranca a mano en un terminal interactivo y GITLAB_URL o GITLAB_TOKEN siguen sin definir tras leer esos ficheros, imprime lo que necesita y espera; consulta Primer arranque sin configuración.

Los flags los analiza el paquete flag estándar de Go, que decide algunas cosas que conviene saber:

  • Un flag admite uno o dos guiones: -http y --http son el mismo flag. Esta página escribe dos.
  • El valor va tras = o tras un espacio (--http-addr=:9090 o --http-addr :9090). Un flag booleano solo toma valor tras =: --stateless=false desactiva el modo sin estado, mientras que --stateless false lo pone a true y termina los flags en la palabra false.
  • El análisis se detiene en el primer argumento que no es un flag, así que el destino de --probe va al final: nada de lo que venga después se lee como flag.
  • Una duración usa la sintaxis de Go: 90s, 30m, 1h30m. 0 no necesita unidad, y cualquier otro número sin unidad se rechaza.
  • Un flag que el binario no define, o un valor que su tipo no puede analizar, detiene el programa antes de que haga nada: el analizador imprime el error y su propia lista alfabética de todos los flags, y el código de salida es 2. La ayuda completa es --help.

Un servidor stdio construye su configuración a partir del entorno. De los flags, lee los generales, los respaldados por variables de entorno y los de telemetría; los flags del modo HTTP solo los lee un servidor que sirve HTTP. (--tool-search lee --tool-surface y --tier, y --probe lee --tls-cert, pero ambos terminan antes de elegir transporte.)

Una ejecución stdio que recibe un flag del modo HTTP lo ignora y lo dice una vez al arrancar, en WARN, nombrando cada flag junto con la variable que stdio lee en su lugar cuando la hay: --max-request-body-bytes, por ejemplo, nombra GITLAB_MCP_STDIO_MAX_LINE_BYTES, que acota ese mismo mensaje en stdio. Cuando --transport=auto eligió stdio, un flag para el que stdio no tiene ningún ajuste (el listener, el pool, la puerta de autenticación) se nombra en INFO, porque esa línea de comandos se escribió para cualquiera de los dos transportes; un flag para el que stdio tiene variable sigue en WARN.

Cuando ignorar el flag costaría más que un ajuste, una ejecución stdio se niega a arrancar, sale con 1 y nombra el ajuste que hay que usar, también con --transport=auto e incluso si esa variable ya pide lo mismo:

  • --read-only o --safe-mode a true, o un --exclude-tools que nombre algo: ignorarlo serviría lo que pide retirar. Fija GITLAB_MCP_READ_ONLY, GITLAB_MCP_SAFE_MODE o GITLAB_MCP_EXCLUDE_TOOLS en su lugar.
  • Un --gitlab-url que no nombra la instancia a la que conecta la ejecución stdio: stdio conecta a la que nombre GITLAB_URL, https://gitlab.com si no está definida, y enviaría allí GITLAB_TOKEN. Fija GITLAB_URL a la instancia en su lugar. Un --gitlab-url que nombra esa misma instancia, se escriba como se escriba, solo se nombra: se comparan en forma canónica, así que https://GitLab.example.com:443/ nombra https://gitlab.example.com.

Un valor que no pide nada (--read-only=false, un --exclude-tools vacío) solo se nombra, como cualquier otro flag ignorado.

En modo HTTP, los ajustes se resuelven en tres capas, de mayor a menor prioridad: un flag pasado explícitamente, después su variable de entorno y después el valor predeterminado integrado. Un flag pasado con el mismo valor que su predeterminado cuenta como pasado, así que una variable perdida no puede desplazar una línea de comandos deliberada.

En las tablas siguientes, la columna Variable nombra la variable de entorno que un flag escribe (los flags respaldados por variables de entorno) o a la que recurre cuando no se pasa (cualquier otro flag que tenga una); ninguna significa que el flag no tiene equivalente en el entorno. La columna Predeterminado es el valor con el que se registra el flag; cuando está vacío y representa algo, la descripción dice qué.

FlagTipoPredeterminadoVariableDescripción
-h, --helpboolfalseningunaImprime la ayuda completa: todos los flags agrupados por lo que configuran, las variables de entorno y ejemplos de configuración JSON. Las dos grafías imprimen el mismo texto
--versionboolfalseningunaImprime gitlab-mcp-server <version> (commit: <commit>) y termina
--shutdownboolfalseningunaTermina todas las demás instancias en marcha de este binario y sale; consulta Modo de apagado
--probeboolfalseningunaPregunta al /health de la instancia en marcha y sale con 0 cuando responde 200: es el HEALTHCHECK de la imagen de contenedor. Un destino opcional tras los flags (una URL, unix:<path> o host:port) se sondea en lugar del listener descubierto; consulta Modo sonda
--tool-searchstring(vacío)ningunaBusca en el catálogo canónico de acciones y termina; consulta Búsqueda de herramientas. Lee --tool-surface y --tier si se pasan, y si no GITLAB_MCP_TOOL_SURFACE y GITLAB_MCP_TIER. No necesita credenciales de GitLab
--env-filestring(vacío)Fija GITLAB_MCP_ENV_FILEUn fichero dotenv que se carga además de ~/.gitlab-mcp-server.env. Es el mismo ajuste que GITLAB_MCP_ENV_FILE, y prevalece sobre ella. Usa una ruta absoluta: una relativa sigue al cliente al directorio en el que arranque el servidor, y el arranque lo avisa
--transportstring(vacío)ningunaTransporte que se sirve: stdio, http o auto. Vacío deja la decisión a --http; si se dan ambos, gana --transport y lo dice al arrancar. auto lee el descriptor de fichero 0 y sirve HTTP solo cuando la entrada estándar es el dispositivo nulo, que es lo que da un contenedor arrancado sin -i, y stdio en cualquier otro caso. Cualquier otro valor sale con 2
--httpboolfalseningunaSirve HTTP en lugar de stdio

Una ejecución que recibe más de uno de los flags de un solo uso ejecuta el primero de -h/--help, --version, --shutdown, --probe y --tool-search, en ese orden, e ignora el resto. Un --transport no válido se rechaza antes que cualquiera de ellos, --help incluido.

Siete ajustes que antes solo se fijaban con una variable de entorno tienen un flag cada uno, para que una sola línea de comandos pueda configurar todo el servidor. Un flag pasado escribe su variable antes de que nada lea la configuración, así que cada ajuste conserva un único lector y un flag pasado explícitamente gana a una variable exportada. Un flag que no se pasa no escribe nada, y por eso los siete se registran con un valor predeterminado vacío: decide la variable, o el valor predeterminado integrado que se indica abajo. Los dos transportes leen los siete.

FlagTipoPredeterminadoVariableDescripción
--log-levelstring(vacío)Fija GITLAB_MCP_LOG_LEVELVerbosidad del registro: debug, info, warn (o warning) o error. Sin definir, o con cualquier otro valor, registra en info
--client-compatstring(vacío)Fija GITLAB_MCP_CLIENT_COMPATCompatibilidad de respuesta por cliente: off la desactiva, y cualquier otra cosa, sin definir incluido, significa auto. Consulta Compatibilidad de clientes
--upload-max-file-sizestring(vacío)Fija GITLAB_MCP_UPLOAD_MAX_FILE_SIZEMayor fichero local que acepta una herramienta de subida o de lectura de ficheros: un número de bytes, o un número con sufijo KB, MB o GB en mayúsculas o minúsculas (múltiplos de 1024). Sin definir significa 2GB, y el techo es 1 TB. En stdio, un valor que no se puede analizar, o que supera el techo, impide arrancar; en modo HTTP se registra en WARN y el servidor usa 2GB o el techo en su lugar
--yolo-modestring(vacío)Fija GITLAB_MCP_YOLO_MODE1, true o yes omite la confirmación de las acciones destructivas en todas las superficies: sin pregunta en las superficies meta e individual, y sin necesidad de confirm: true en la dinámica por defecto (consulta Acciones destructivas); cualquier otro valor la mantiene. Cuando la variable está definida decide ella, y AUTOPILOT solo se consulta cuando no lo está, así que --yolo-mode=false anula un AUTOPILOT=true heredado
--description-substitutionsstring(vacío)Fija GITLAB_MCP_DESCRIPTION_SUBSTITUTIONSPares viejo=nuevo separados por comas que se aplican en orden a cada descripción y título listados, para validadores estrictos de gateways MCP (la barra invertida escapa \,, \= y \\). Un valor mal formado impide arrancar. Consulta Compatibilidad de clientes
--allow-private-instancesstring(vacío)Fija GITLAB_MCP_ALLOW_PRIVATE_INSTANCEStrue permite que un destino que no eligió quien opera este servidor sea una dirección privada, de loopback, CGNAT, de enlace local, local única o no especificada: una instancia que alguien nombró en la cabecera GITLAB-URL con --allow-any-gitlab-url, o un salto de redirección que salió del host de la instancia configurada. Una dirección nombrada en --gitlab-url o GITLAB_URL nunca se comprueba, y las direcciones de metadatos de la nube siguen rechazadas diga lo que diga. Consulta Destinos salientes
--pprof-addrstring(vacío)Fija GITLAB_MCP_PPROF_ADDRSirve los manejadores de perfilado de Go (net/http/pprof) en esta dirección, en un listener propio que arranca antes que el transporte, para poder tomar un perfil de CPU del arranque. Solo se acepta localhost o una IP de loopback (127.0.0.1:6060, [::1]:6060, localhost:6060); cualquier otro host se rechaza al arrancar, porque un perfil de heap es una copia de la memoria del proceso y los manejadores no piden credencial. Vacío no sirve nada

--allow-private-instances lee su valor como un booleano de Go (true, 1, t), y cualquier otra cosa significa false; la decisión detrás de la exención es el ADR-0022.

GITLAB_TOKEN no tiene flag. Un token en la línea de comandos es visible para cualquier usuario de la máquina con ps, queda en la contabilidad de procesos y acaba en el historial del shell, así que el entorno es la única forma de dárselo a un servidor stdio; en modo HTTP cada cliente envía el suyo en una cabecera de la petición. La clave de seudonimización de la telemetría, GITLAB_MCP_TELEMETRY_IDENTITY_KEY, no tiene flag por el mismo motivo.

Estos cuatro los leen los dos transportes: un despliegue stdio es justo el caso que le importa a quien vigila su propia máquina. La telemetría está desactivada por defecto, y el endpoint, las credenciales, el muestreo y el agrupado salen de las variables estándar OTEL_EXPORTER_OTLP_*, que leen los propios exportadores. Consulta OpenTelemetry.

FlagTipoPredeterminadoVariableDescripción
--telemetryboolfalseGITLAB_MCP_TELEMETRYExporta trazas, métricas y logs de OpenTelemetry por OTLP. OTEL_SDK_DISABLED=true lo veta diga lo que diga el flag. Un pipeline de telemetría que no arranca se registra, y el servidor sigue sirviendo
--telemetry-identitystringnoneGITLAB_MCP_TELEMETRY_IDENTITYQué registra la telemetría sobre quién hizo una llamada: none no registra a nadie, pseudonymous un resumen HMAC por proceso que correlaciona las llamadas de una persona sin nombrarla, full el id y el nombre de usuario de GitLab. Un valor que no reconoce se registra en ERROR y no se registra nada sobre quien llama. Consulta Registrar quién hizo la llamada
--telemetry-identity-rotationstring(vacío)GITLAB_MCP_TELEMETRY_IDENTITY_ROTATIONCuánto vive una clave de seudonimización generada, p. ej. 24h. Vacío o 0 la mantiene lo que dure el proceso, y 30 días (720h) es el techo; un valor que no se puede analizar o que lo supera se registra en ERROR y no se registra nada sobre quien llama. Se ignora, con un aviso al arrancar, cuando GITLAB_MCP_TELEMETRY_IDENTITY_KEY está definida
--telemetry-tool-namestringautoGITLAB_MCP_TELEMETRY_TOOL_NAMESi gen_ai.tool.name es una dimensión de métrica: auto la mantiene en las superficies dinámica y meta y la quita en la individual, donde un millar de herramientas agotaría el límite de cardinalidad del SDK; on y off la fuerzan. Un valor que no reconoce se registra y se lee como auto

Los 42 flags siguientes solo los lee un servidor que sirve HTTP; lo que hace con ellos una ejecución stdio se describe en Qué flags lee cada transporte. Se agrupan como los agrupa --help.

FlagTipoPredeterminadoVariableDescripción
--http-addrstring:8080ningunaDirección de escucha. host:port escucha por TCP (localhost:8080, :9090, 127.0.0.1:8080); un valor que contiene un separador de ruta (/run/gitlab-mcp.sock) escucha en un socket unix, lo que elimina el tramo de red hasta un proxy de la misma máquina en vez de cifrarlo. Consulta Escuchar en un socket unix o con TLS
--http-socket-modestring(vacío)ningunaModo de permisos, en octal, para un socket unix indicado en --http-addr: de 0001 a 0777, con o sin prefijo 0o. Vacío significa 0660, que deja conectar al propietario y al grupo y a nadie más, así que un proxy inverso llega al servidor compartiendo grupo con él
--tls-certstring(vacío)ningunaFichero de certificado PEM. Sirve HTTPS en el propio listener, para un despliegue cuyo proxy no comparte máquina. Requiere --tls-key, y cada uno se rechaza sin el otro. El par se carga al arrancar, así que una errata falla ahí; después, los dos ficheros se comprueban en cada handshake y se releen cuando cualquiera cambia, de modo que una rotación no necesita reinicio, y un par que no carga conserva el certificado anterior con un aviso. TLS 1.2 es el mínimo
--tls-keystring(vacío)ningunaFichero de clave privada PEM que corresponde a --tls-cert
--statelessbooltrueningunaHTTP streamable sin sesiones (SEP-2567), la única forma en que se sirve el protocolo 2026-07-28 por HTTP: sin Mcp-Session-Id, cada POST autónomo, GET y DELETE respondidos con 405. --stateless=false restaura las sesiones con estado heredadas y avisa al arrancar. Consulta Modo sin estado
--json-responseboolfalseningunaResponde con cuerpos application/json en lugar de text/event-stream (SSE). Un cuerpo JSON lleva una respuesta y ninguna otra trama, así que las notificaciones de progreso se descartan con --stateless y solo llegan a un cliente con estado por un stream GET que mantenga abierto; el arranque avisa siempre que se activa el flag
--max-request-body-bytesint640ningunaMayor cuerpo de petición HTTP streamable, en bytes; 0 usa el valor predeterminado del SDK (4 MiB). Un cuerpo mayor se rechaza con 413, y un valor negativo al arrancar. En stdio, ese mismo mensaje lo acota GITLAB_MCP_STDIO_MAX_LINE_BYTES
--session-timeoutduration30mGITLAB_MCP_SESSION_TIMEOUTTimeout de sesión MCP inactiva, como mucho 24h. Solo se aplica con --stateless=false, porque con el transporte sin estado por defecto la sesión de cada POST termina con su respuesta. Una sesión que ningún cliente borra ocupa una de las plazas de sesión del proceso hasta que caduca, y con 0 hasta que el pool desaloja su credencial, de lo que avisa el arranque
--http-idle-timeoutduration0ningunaTimeout de conexión inactiva del servidor HTTP. 0 desactiva el cierre por inactividad, así que --session-timeout es la vida efectiva; un valor positivo recicla antes las conexiones inactivas, y uno negativo se rechaza
FlagTipoPredeterminadoVariableDescripción
--gitlab-urllist(vacío)GITLAB_URLURL de la instancia de GitLab. Obligatoria en modo HTTP, por el flag o por GITLAB_URL, salvo que se pase --allow-any-gitlab-url: un despliegue que no ha dicho a qué GitLab sirve haría sus peticiones al host que nombre quien llama en GITLAB-URL, con el token que esa persona aporte. Repetible, o separada por comas (la variable admite la misma lista): publicar varias las lista todas en el campo authorization_servers de RFC 9728 y convierte GITLAB-URL en una elección obligatoria entre ellas, porque elegir por quien llama enviaría su token a una instancia que nunca nombró; un valor que nombre cualquier otra se rechaza, no se ignora. Consulta Publicar más de una instancia
--allow-any-gitlab-urlboolfalseningunaArranca sin publicar ninguna instancia y deja que GITLAB-URL nombre cualquier host. La respuesta vuelve a quien llama, así que esto convierte el servidor en un proxy para cualquiera que alcance el listener: es para el despliegue local de un único usuario en el que quien opera es quien llama, y se rechaza salvo que --http-addr escuche en una dirección de loopback o en un socket unix. Avisa al arrancar incluso ahí, y no tiene variable a propósito, para que un despliegue que lo usa lo diga en su propia línea de comandos. No amplía a qué pueden resolver esos hosts: una instancia nombrada por quien llama en una dirección privada, de loopback o de enlace local sigue necesitando --allow-private-instances. Un --gitlab-url pasado junto a él gana, y entonces no cambia nada
--skip-tls-verifyboolfalseGITLAB_MCP_SKIP_TLS_VERIFYOmite la verificación del certificado TLS al llamar a GitLab (saliente; sin relación con --tls-cert). --auth-mode=oauth lo rechaza para cualquier instancia que no sea loopback, porque los tokens bearer se reenvían allí en cada llamada: instala la CA en el almacén de confianza del sistema, o apunta SSL_CERT_FILE a un paquete de certificados, en su lugar
--tierstring(vacío)GITLAB_MCP_TIERFuerza el nivel de licencia: free (o ce), premium o ultimate, usado tal cual sin comprobar la licencia. Vacío lo detecta por entrada del pool de token y URL, a partir de la licencia de la instancia y después de los planes de los namespaces, con free como último recurso y un aviso cuando la instancia es una compilación Enterprise Edition. La variable solo puede fijar un nivel, nunca deshacerlo
--ignore-scopesboolfalseGITLAB_MCP_IGNORE_SCOPESOmite el filtro de scopes y la reducción a solo lectura y registra todas las herramientas que permita el nivel. Los scopes del token se siguen leyendo, así que uno que no lleva ni read_api ni api se sigue rechazando, y la concesión de un token de grano fino sigue decidiendo lo que se le muestra

Superficie de herramientas y modos de protección

Sección titulada «Superficie de herramientas y modos de protección»
FlagTipoPredeterminadoVariableDescripción
--tool-surfacestring(vacío)GITLAB_MCP_TOOL_SURFACECatálogo de herramientas: dynamic, que es lo que sirve el valor vacío, meta o individual. Consulta Resumen de herramientas
--capability-surfacestringfullGITLAB_MCP_CAPABILITY_SURFACERecursos y prompts: full, o minimal, que conserva el manifiesto gitlab://tools y deja fuera los recursos opcionales de datos de GitLab, las guías de flujo de trabajo y los prompts
--meta-param-schemastringopaqueGITLAB_MCP_META_PARAM_SCHEMAEstrategia del esquema de entrada de las meta-herramientas: opaque, compact (unas 8,7 veces el tamaño de opaque) o full (unas 18,3 veces). Solo afecta a los esquemas de las meta-herramientas; la forma exacta de llamada de cada acción sigue disponible en gitlab://tools/{id}
--embedded-resourcesbooltrueGITLAB_MCP_EMBEDDED_RESOURCESIncrusta la URI canónica gitlab:// del recurso en los resultados de las herramientas de tipo get; false la omite
--exclude-toolsstring(vacío)GITLAB_MCP_EXCLUDE_TOOLSNombres de herramienta, de grupo o IDs canónicos de acción, separados por comas, que se retiran en todas las superficies y de los recursos, suscripciones, prompts y completados de argumentos que devuelven los mismos objetos. Las mismas grafías alcanzan las utilidades independientes (gitlab_interactive, interactive.issue_create, discover_project.resolve). Una entrada que no nombra nada es un aviso, no un rechazo, que se escribe la primera vez que se construye cada catálogo, y el nivel y la reducción por scopes del token forman parte de lo que es un catálogo, así que puede repetirse
--read-onlyboolfalseGITLAB_MCP_READ_ONLYRetira todas las acciones que modifican; las lecturas siguen funcionando en todas las superficies. Gana a --safe-mode cuando se activan los dos
--safe-modeboolfalseGITLAB_MCP_SAFE_MODEIntercepta todas las acciones que modifican y responde con una tarjeta de vista previa, que nombra la acción (la herramienta en la superficie individual) y muestra en JSON los argumentos que habría enviado, en lugar de ejecutarla; las lecturas siguen funcionando
FlagTipoPredeterminadoVariableDescripción
--auth-modestringlegacyGITLAB_MCP_AUTH_MODElegacy (la cabecera PRIVATE-TOKEN, o Authorization: Bearer) u oauth (verificación bearer de RFC 9728), que exige un --gitlab-url https para cada instancia publicada (http solo en loopback) y un --public-url válido. Consulta Modo OAuth
--public-urlstring(vacío)GITLAB_MCP_PUBLIC_URLOrigen accesible desde fuera de este despliegue (scheme://host[:port][/path]): https (http solo para un host de loopback), sin fragmento y sin barra final. Obligatoria con --auth-mode=oauth, donde es el identificador de recurso protegido de RFC 9728 y de ella se deriva la URL de metadatos. Opcional en modo legacy, donde su origen se añade a los orígenes de confianza
--oauth-cache-ttlduration15mGITLAB_MCP_OAUTH_CACHE_TTLCuánto se guarda en caché la identidad de un token OAuth verificado, de 1m a 2h; solo se usa con --auth-mode=oauth. La caché guarda como mucho 10.000 identidades sea cual sea el TTL, y cuando está llena descarta una caducada o, si no la hay, la usada hace más tiempo
--oauth-client-uidstring(vacío)GITLAB_MCP_OAUTH_CLIENT_UIDuids de aplicaciones OAuth de GitLab, separados por comas, cuyos tokens admite este despliegue. Vacío admite cualquier credencial que acepte la instancia; ponerlo rechaza también los tokens de acceso personal, que no pertenecen a ninguna aplicación. Sustituye a la vinculación de audiencia, que GitLab no ofrece; consulta el ADR-0019
--revalidate-intervalduration15mGITLAB_MCP_SESSION_REVALIDATE_INTERVALCada cuánto se revalida contra GitLab una credencial del pool, como mucho 24h. 0 detiene la comprobación periódica, pero una entrada cuya credencial tenga más de 1h se reconstruye igualmente, lo que repite la sonda y termina cualquier sesión con estado que tenga
--resource-documentationstring(vacío)ningunaURL https publicada como resource_documentation de RFC 9728. Apúntala a una página que describa tu propia aplicación OAuth (su client ID y sus URI de redirección registradas), para que un cliente que llega desde un desafío 401 encuentre lo que necesita: RFC 9728 no define ningún campo para un identificador de cliente, así que esta es la única forma sancionada de llevar a un cliente hasta uno. Vacío publica la página Aplicación OAuth de este proyecto
--resource-policy-uristring(vacío)ningunaURL https publicada como resource_policy_uri de RFC 9728: tu página sobre lo que hace este despliegue con los datos a los que llega con los tokens que acepta. Vacío omite el campo, el valor correcto para un despliegue sin esa página, porque un campo opcional ausente es mejor que un enlace roto en una pantalla de consentimiento
--resource-tos-uristring(vacío)ningunaURL https publicada como resource_tos_uri de RFC 9728: tus condiciones de servicio. Vacío omite el campo

Las tres URLs --resource-* se comprueban al arrancar en cualquiera de los dos modos, porque se publican en cuanto se activa OAuth: cada una debe ser una URL https absoluta, o http en un host de loopback.

FlagTipoPredeterminadoVariableDescripción
--max-http-clientsint100GITLAB_MCP_MAX_HTTP_CLIENTSMáximo de entradas (token, URL de GitLab) que guarda el pool, de 1 a 10000. Acota entradas, no las sesiones ni las llamadas que retienen: esas las acota el proceso según su límite de descriptores, 192 llamadas retenidas y 96 sesiones con estado a la vez bajo un límite duro de 1024, y ningún flag mueve ninguno de los dos. Consulta Peticiones retenidas a la vez
--pool-idle-timeoutduration1hGITLAB_MCP_POOL_IDLE_TIMEOUTRecupera una entrada de credencial del pool tras este tiempo sin usarse, como mucho 24h; 0 mantiene las entradas hasta que el límite de tamaño las desaloje. Una entrada con una suscripción viva nunca está inactiva según esta medida
--action-timeoutduration65mGITLAB_MCP_ACTION_TIMEOUTCancela una acción que siga en marcha tras este tiempo, como mucho 24h; 0 lo desactiva. El timeout se aplica también en stdio, donde la variable es la única forma de fijarlo. Está por encima de la espera más larga que ofrece cualquier acción (una espera de pipeline se limita a 3600 s), así que termina un manejador que ninguna otra cosa acota y no una espera legítima, y acota también una transferencia de ficheros
--drain-delayduration0GITLAB_MCP_DRAIN_DELAYTras SIGTERM, mantiene el listener abierto y responde /health con 503 draining durante este tiempo antes de cerrarlo, para que un balanceador que sondea /health saque antes la instancia de la rotación. 0 cierra al instante, y el máximo es 5m. Ponlo al menos en un intervalo de sondeo; consulta Verificación de salud
--rate-limit-rpsfloat10GITLAB_MCP_RATE_LIMIT_RPSLímite de tasa por credencial, en peticiones por segundo, sobre toda llamada que llega a GitLab (tools/call, resources/read, resources/subscribe, subscriptions/listen, prompts/get), más completion/complete en un bucket propio con diez veces la tasa y el burst, y tools/list en un bucket propio que se rellena diez veces más despacio, con el mismo burst. Un listado se cobra además primero, en las herramientas que lleva, a un bucket que comparte todo el proceso: 3000 herramientas por segundo con 48000 disponibles, no configurable. 0 los desactiva todos, y el máximo es 1000. Stdio ignora el flag y lo dice: allí el interruptor es GITLAB_MCP_RATE_LIMIT_RPS, que por defecto vale 0. Consulta Limitación de tasa
--rate-limit-burstint40GITLAB_MCP_RATE_LIMIT_BURSTTamaño del token bucket, como mucho 10000. Mientras --rate-limit-rps está por encima de 0 debe ser al menos 1
--auth-failure-limitint10GITLAB_MCP_AUTH_FAILURE_LIMITAutenticaciones fallidas que una dirección puede producir dentro de --auth-failure-window antes de quedar bloqueada el resto de la ventana, de 0 a 100000. 0 desactiva este presupuesto en lugar de bloquear al primer fallo. Consulta Presupuestos de autenticación
--auth-failure-windowduration1mGITLAB_MCP_AUTH_FAILURE_WINDOWVentana en la que cuenta el presupuesto de fallos, y el paso con el que se construye la escalada de credenciales distintas: una ventana, después diez, después sesenta. Como mucho 24h; 0 desactiva los dos presupuestos, porque sin ella la escalada no tiene paso
--auth-distinct-token-limitint50GITLAB_MCP_AUTH_DISTINCT_TOKEN_LIMITCredenciales distintas que una dirección puede tener rechazadas dentro de --auth-distinct-token-window antes de quedar bloqueada, cada vez durante más tiempo, de 0 a 100000; 0 desactiva este presupuesto. Una persona tiene un token y una flota tras un NAT tiene uno cada máquina, así que solo un ataque de rociado de credenciales alcanza este recuento. Una credencial que el pool ya tiene se sigue sirviendo desde una dirección bloqueada
--auth-distinct-token-windowduration10mGITLAB_MCP_AUTH_DISTINCT_TOKEN_WINDOWVentana en la que cuenta el presupuesto de credenciales distintas, como mucho 24h; 0 desactiva ese presupuesto
--trusted-originsstring(vacío)GITLAB_MCP_TRUSTED_ORIGINSOrígenes absolutos (scheme://host[:port]; una IP sirve para un despliegue local), separados por comas, autorizados a hacer peticiones cross-origin desde un navegador. * acepta cualquier origen y desactiva la protección. Vacío no añade ninguno, aunque el origen de --public-url es de confianza de todos modos. Una entrada mal formada impide arrancar. Consulta Protección cross-origin
--trusted-proxy-headerstring(vacío)ningunaCabecera HTTP que lleva la dirección real del cliente tras un proxy inverso (p. ej. CF-Connecting-IP, X-Forwarded-For, X-Real-IP), para que los presupuestos de autenticación carguen a quien llama y no al proxy. Solo se cree en una conexión desde una dirección de --trusted-proxies, que exige
--trusted-proxiesstring(vacío)ningunaDirecciones o rangos CIDR, separados por comas, de los proxies inversos cuya --trusted-proxy-header se cree (p. ej. 127.0.0.1,10.0.0.0/8). Desde cualquier otro par la cabecera se ignora y se carga al propio par, así que quien llega directamente al listener no puede elegir la dirección contra la que cuentan sus fallos. Con X-Forwarded-For el valor se lee desde la derecha, saltando los saltos que están en la lista, así que el primer salto que no está en ella es el cliente; un salto que no es una dirección carga al par. Obligatoria junto a --trusted-proxy-header, y se rechaza sin ella

El servidor lee su configuración del entorno y habla JSON-RPC por la entrada y la salida estándar, que es como lo ejecutan clientes MCP como VS Code, Claude Desktop y Cursor. Los ajustes que define este proyecto se llaman GITLAB_MCP_<NAME>; GITLAB_URL, GITLAB_TOKEN y todas las variables OTEL_* conservan su nombre sin prefijo, y GITLAB_URL vale por defecto https://gitlab.com, así que solo hace falta para una instancia autogestionada.

Ventana de terminal
# Configuración desde el entorno
export GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
gitlab-mcp-server
# Configuración desde ~/.gitlab-mcp-server.env, o desde un fichero nombrado en GITLAB_MCP_ENV_FILE
gitlab-mcp-server

Un .env en el directorio actual no se lee: ese directorio pertenece al repositorio que abrió el cliente, no a quien opera el servidor. Si existe, se nombra en WARN al arrancar. Las grafías que tenían las variables antes de 2.8.0 no las lee nada desde 3.1.0: una que siga definida se nombra al arrancar con la variable a la que hay que renombrarla, y GITLAB_READ_ONLY, GITLAB_SAFE_MODE y EXCLUDE_TOOLS impiden el arranque, porque ignorar una serviría lo que retiraba. La referencia de variables de entorno tiene la regla completa.

El servidor escucha en un endpoint HTTP, y cada cliente envía su propio token de GitLab en cada petición, en la cabecera PRIVATE-TOKEN o como Authorization: Bearer, así que no hace falta GITLAB_TOKEN al arrancar. La instancia no es opcional: nombra la que sirve este despliegue, o las varias, con --gitlab-url o GITLAB_URL. Publicar varias convierte la cabecera GITLAB-URL en una elección obligatoria entre ellas, y no publicar ninguna solo es posible con --allow-any-gitlab-url. Consulta Modo servidor HTTP para el despliegue en sí.

Ventana de terminal
# Una instancia (todos los clientes usan la URL fija; reemplázala para GitLab autogestionado)
gitlab-mcp-server --http --gitlab-url=https://gitlab.com
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --http-addr=localhost:9090
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --max-http-clients=50 --session-timeout=1h
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --auth-mode=oauth --public-url=https://mcp.example.com --oauth-cache-ttl=15m
# HTTP streamable sin estado (el predeterminado) con respuestas JSON planas
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --json-response
# Sesiones con estado heredadas con un tope de 1 MiB en el cuerpo de la petición
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --stateless=false --max-request-body-bytes=1048576
# Varias instancias (la cabecera GITLAB-URL pasa a ser obligatoria y debe nombrar una de ellas)
gitlab-mcp-server --http --gitlab-url=https://gitlab.com,https://gitlab.example.com

Si se arranca a mano en un terminal, o con doble clic, en modo stdio y GITLAB_TOKEN o GITLAB_URL siguen sin definir tras leer los ficheros dotenv (basta con que falte una), el servidor imprime en stderr qué es y qué necesita, espera a que se pulse Enter y sale con 0. La espera importa en Windows, donde un programa de consola abierto con doble clic cierra su ventana en cuanto termina, así que un mensaje impreso justo antes de terminar es un mensaje que nadie lee.

Un cliente MCP nunca llega a esa pantalla: un cliente conecta tuberías, no un terminal, que es la prueba que usa el servidor. Sustituyó a un asistente de configuración interactivo que escribía ~/.gitlab-mcp-server.env; la configuración MCP vive en el propio JSON del cliente, que es donde la pone Primeros pasos.

--tool-search busca en el catálogo canónico de acciones, no en las herramientas registradas de un servidor, y termina. El catálogo es el mismo en todas las superficies (la superficie dinámica por defecto registra solo dos herramientas), así que las acciones encontradas también lo son; la superficie solo decide cómo nombra cada fila la llamada. No necesita credenciales de GitLab y no hace ninguna petición.

  • La consulta se divide por espacios, y cada término debe aparecer, sin distinguir mayúsculas, en el ID canónico de una acción, su nombre de herramienta individual, su nombre de meta-herramienta, su descripción, sus alias o sus etiquetas.
  • La superficie y el nivel salen de --tool-surface y --tier si se pasan, y si no de GITLAB_MCP_TOOL_SURFACE y GITLAB_MCP_TIER, leídas de los mismos ficheros dotenv que lee el servidor, así que un despliegue stdio busca lo que sirve. Sin ninguno de los dos, el nivel es free, así que una acción que solo sirve un nivel superior necesita --tier.
  • Una superficie o un nivel que no se pueden analizar salen con 1.

Los resultados van a stdout, ordenados por ID canónico, bajo una línea que dice cómo llamar a una acción listada en esa superficie:

Found <n> action(s) matching "issue list" (tier free, dynamic surface):
Call gitlab_execute_action with {"action": "<ACTION>", "params": {...}}. TOOL is the name the individual surface would register.
ACTION TOOL DESCRIPTION

ACTION es el ID canónico, que es lo que recibe gitlab_execute_action en la superficie dinámica. TOOL es el nombre de la herramienta individual en las superficies dinámica e individual, o la meta-herramienta del grupo seguida de action=<name> en la superficie meta; - marca una acción que la superficie individual no registra. DESCRIPTION se corta en 80 caracteres. Una consulta que no coincide con nada imprime No actions found matching con la consulta, el nivel y la superficie.

--shutdown termina todas las demás instancias en marcha de este binario y sale. Está pensado para actualizadores externos, como pe-agnostic-store, que detienen los servidores en marcha antes de reemplazar el binario en disco.

Ventana de terminal
gitlab-mcp-server --shutdown
  1. Lista los procesos de la máquina y se queda con los que tienen su mismo nombre, una vez quitados de ambos un sufijo de plataforma como -linux-amd64 y una extensión .exe, dejándose fuera a sí mismo.
  2. Si no encuentra ninguno, sale con 0 sin escribir nada.
  3. Envía a cada uno una terminación ordenada: SIGTERM en Unix, TerminateProcess en Windows.
  4. Comprueba cada 200 ms, durante un máximo de cinco segundos, si han terminado.
  5. Mata a la fuerza los que sigan en marcha cuando pasan los cinco segundos.
  6. Sale con 0. Solo un fallo al listar los procesos sale con 1.

Escribe estas líneas en stderr:

  • shutdown: found N running instance(s), al encontrarlas
  • shutdown: all instances terminated, cuando no queda ninguna en marcha
  • shutdown: force-killed M instance(s), cuando hubo que matar alguna
  • shutdown: error listing processes: <error>, cuando falló el listado

--probe es el HEALTHCHECK de la imagen de contenedor (cada 30 s, con un timeout de cinco segundos). Pregunta al /health de la instancia en marcha y sale con 0 cuando responde 200, sin que haya que decirle dónde escucha esa instancia.

Ventana de terminal
# Lo que ejecuta la imagen: encuentra el servidor en este contenedor y sondea su listener
gitlab-mcp-server --probe
# Sondear un listener conocido: una URL, un socket unix, o host:port
gitlab-mcp-server --probe --tls-cert=/etc/ssl/mcp.crt https://127.0.0.1:8443
gitlab-mcp-server --probe unix:/run/gitlab-mcp/server.sock
gitlab-mcp-server --probe 127.0.0.1:9090

Sin destino:

  1. Encuentra las demás instancias de este binario con la misma búsqueda que usa --shutdown, y se salta las invocaciones de sonda, apagado, versión y ayuda y cualquier proceso cuya línea de comandos no puede leer.
  2. Lee --http-addr, --tls-cert, --transport y --http de la línea de comandos de cada instancia, empezando por el pid más bajo. Un argumento tras un -- suelto no se lee, porque tampoco era un flag para ese proceso.
  3. Resuelve --transport auto como lo hizo el servidor, leyendo el descriptor de fichero 0 de la instancia en procfs: /dev/null significa HTTP, y cualquier otra cosa stdio. Donde no se puede leer procfs, se supone HTTP y decide la conexión.
  4. Una instancia que sirve stdio no tiene nada que sondear y se da por sana mientras está en marcha.
  5. Una instancia HTTP se sondea donde escucha. Un host sin especificar, como :8080, 0.0.0.0:8080 o [::]:8080, se alcanza en 127.0.0.1, a una ruta se conecta como socket unix, y --tls-cert significa HTTPS. Un listener TLS se verifica fijando el certificado: debe presentar justo el certificado que nombra su --tls-cert, que la sonda lee del mismo fichero y usa como única raíz de confianza, así que un certificado autofirmado en una dirección de loopback se puede sondear sin fiarse de lo que responda ahí.
  6. La primera instancia, por orden de pid, que sirve stdio o responde 200 da la sonda por sana. Si ninguna lo hace, o no hay ninguna instancia en marcha, sale con 1.

Un destino dado tras los flags se sondea en su lugar: una URL http:// o https:// (su ruta, o /health si no nombra ninguna), unix:<path> o una ruta suelta para un socket unix, o host:port para HTTP plano. Un destino https:// se fija al --tls-cert de la propia sonda, que debe ir antes del destino, y sin él recibe la verificación estándar contra las raíces del sistema. Un destino que no es ninguna de estas cosas sale con 2.

Cada intento está acotado a tres segundos, y la ejecución entera a cuatro, dentro del timeout de cinco segundos de la imagen: los intentos van uno tras otro, así que dos listeners inalcanzables a tres segundos cada uno lo superarían y la sonda moriría sin veredicto. La sonda nunca pasa por un proxy, y escribe una línea en stderr, con el prefijo probe:, que dice qué instancia respondió o por qué no respondió ninguna. Un listener que escucha en el puerto 0 no se puede descubrir, porque la línea de comandos dice 0; dale a la sonda la dirección que indica el log del servidor.

Ventana de terminal
# Imprimir la versión
gitlab-mcp-server --version
# Mostrar la ayuda completa con todos los flags, las variables y ejemplos de configuración JSON
gitlab-mcp-server --help
# Arrancar el servidor stdio (lee ~/.gitlab-mcp-server.env para lo que falte en el entorno)
gitlab-mcp-server
# Arrancar el servidor HTTP en otro puerto
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --http-addr=:9090
# Varias instancias (los clientes eligen una con la cabecera GITLAB-URL)
gitlab-mcp-server --http --gitlab-url=https://gitlab.com,https://gitlab.example.com --http-addr=:8080
# Despliegue local de un único usuario: ninguna instancia publicada, GITLAB-URL puede nombrar cualquier host
gitlab-mcp-server --http --allow-any-gitlab-url --http-addr=127.0.0.1:8080
# GitLab autogestionado con certificado autofirmado y un timeout de sesión más largo
gitlab-mcp-server --http --gitlab-url=https://gitlab.example.com --skip-tls-verify --session-timeout=2h
# Una herramienta por acción
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --tool-surface=individual
# La superficie dinámica con la superficie reducida de recursos y prompts
gitlab-mcp-server --http --gitlab-url=https://gitlab.com --tool-surface=dynamic --capability-surface=minimal
# Encontrar las acciones que listan issues, en la superficie que esté configurada
gitlab-mcp-server --tool-search "issue list"
# Buscar en el catálogo Ultimate desde un despliegue Free
gitlab-mcp-server --tier=ultimate --tool-search "epic"
# Terminar todas las instancias en marcha (lo usan los actualizadores externos)
gitlab-mcp-server --shutdown
# Verificación de salud del contenedor: sondear la instancia en marcha donde escucha
gitlab-mcp-server --probe

Consulta Herramientas dinámicas para ver qué registra la superficie por defecto y cómo llegan al catálogo gitlab_find_action y gitlab_execute_action.

CódigoSignificado
0Un final normal: un apagado por señal (SIGINT o SIGTERM), --version, -h/--help, un --tool-search completado, --shutdown haya encontrado o no algo que detener, un --probe que obtuvo respuesta o encontró una instancia que sirve stdio, y la pantalla de primer arranque una vez pulsado Enter
1Un error de configuración (entre ellos, una ejecución stdio que recibe --read-only, --safe-mode o --exclude-tools pidiendo retirar algo o un --gitlab-url que nombra otra instancia, y una ejecución HTTP que no nombra ninguna instancia sin --allow-any-gitlab-url), un error en el que se detiene el servidor, un --tool-search cuya superficie o nivel no se pueden analizar, un --shutdown que no pudo listar los procesos, o un --probe al que nadie respondió
2Un flag que el binario no define o un valor que su tipo no puede analizar, --transport con un valor distinto de stdio, http o auto, o --probe con un destino que no es una URL, una ruta de socket ni host:port