Variables de entorno
Esta página recoge todas las variables que lee el servidor: los 45 ajustes GITLAB_MCP_*, GITLAB_URL, GITLAB_TOKEN, AUTOPILOT, las variables OTEL_* de la especificación de OpenTelemetry y las pocas que lee por su cuenta el runtime de Go. Configuración explica las opciones que fijan casi todos los despliegues y cómo ponerlas en un cliente; la referencia de la línea de comandos cubre todos los flags.
Cómo leer las tablas
Sección titulada «Cómo leer las tablas»- Predeterminado es lo que significa una variable sin definir o vacía. Un valor vacío cuenta como no definido en todas partes.
- Transporte dice qué modo lee la variable. HTTP; stdio la valida significa que un servidor stdio la interpreta y se niega a arrancar ante un valor no válido, aunque nunca la use.
- Flag es la grafía en la línea de comandos. Un flag solo se lee en modo HTTP salvo que la celda diga ambos: un servidor stdio toma todo lo demás del entorno, nombra al arrancar el flag de solo HTTP que recibió y lo ignora (cuatro de ellos pueden impedir el arranque; consulta la referencia de la línea de comandos).
- Un valor no válido impide el arranque salvo que la fila diga otra cosa. Las filas que avisan y conservan un valor predeterminado lo hacen a propósito, y dicen por qué.
Sintaxis de los valores
Sección titulada «Sintaxis de los valores»| Tipo | Qué se acepta |
|---|---|
| Booleano | Las grafías booleanas de Go: true, false, 1, 0, t, f, en minúsculas, mayúsculas o con inicial mayúscula. Tres excepciones: GITLAB_MCP_YOLO_MODE y AUTOPILOT leen 1, true y yes (sin distinguir mayúsculas) como verdadero y cualquier otra cosa como falso; GITLAB_MCP_TELEMETRY y OTEL_SDK_DISABLED solo leen true y false (sin distinguir mayúsculas), y avisan de cualquier otra cosa y la tratan como falso; GITLAB_MCP_ALLOW_PRIVATE_INSTANCES trata como falso, sin decir nada, todo lo que no se puede interpretar, porque desactiva una protección |
| Duración | Sintaxis de duración de Go: 90s, 15m, 1h30m. 0 solo se acepta donde la fila dice que desactiva algo, y allí solo escrito como 0 a secas: 0s impide el arranque, aunque el flag del mismo nombre lo acepta (#1171). GITLAB_MCP_TELEMETRY_IDENTITY_ROTATION acepta las dos formas. Los plazos OTEL_*, en cambio, son milisegundos enteros (una trampa que conviene conocer) |
| Tamaño | Un número de bytes, o un número con sufijo KB, MB o GB en mayúsculas o minúsculas. Los sufijos son potencias de 1024 |
| Lista | Separada por comas, sin los espacios que rodean cada entrada. Una lista de directorios usa en cambio el separador de rutas del sistema operativo: : en Linux y macOS, ; en Windows |
Conexión y credenciales
Sección titulada «Conexión y credenciales»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_URL | https://gitlab.com en stdio; ninguno en modo HTTP | Una URL http:// o https:// con host. En modo HTTP, una lista separada por comas | Ambos | --gitlab-url | En stdio, la instancia a la que se envía el token. En modo HTTP, la instancia o instancias que publica el despliegue: obligatoria salvo que se pase --allow-any-gitlab-url, y con varias la cabecera de petición GITLAB-URL es obligatoria y debe nombrar una de ellas. Con GITLAB_MCP_AUTH_MODE=oauth toda instancia debe ser https, y http solo se acepta para un host de loopback. Un servidor stdio arrancado a mano en una terminal con esta variable o GITLAB_TOKEN sin definir tras leer los ficheros dotenv muestra una pantalla de primer arranque y espera a Intro en lugar de servir |
GITLAB_TOKEN | Ninguno: es obligatoria en stdio | Un token de acceso personal de GitLab (glpat-...); consulta Qué token | stdio | Ninguno, a propósito | La credencial con la que se hace cada llamada. No tiene flag porque un token en la línea de comandos queda a la vista de todos los usuarios de la máquina con ps, lo recoge la contabilidad de procesos y acaba en el historial de la shell. El modo HTTP nunca la lee: cada petición trae su propio token |
GITLAB_MCP_SKIP_TLS_VERIFY | false | Booleano | Ambos | --skip-tls-verify | Omite la verificación del certificado de la instancia GitLab. El modo HTTP la rechaza con GITLAB_MCP_AUTH_MODE=oauth para cualquier instancia que no sea de loopback, porque los tokens bearer irían a cualquier host que respondiera. Una CA privada en el almacén de confianza del sistema, o SSL_CERT_FILE (consulta Leídas por el runtime de Go), no necesita flag |
GITLAB_MCP_ALLOW_PRIVATE_INSTANCES | false | Booleano; lo que no se puede interpretar es falso | Ambos | --allow-private-instances (ambos) | Permite que un destino que el operador no eligió resuelva a una dirección de loopback, privada, CGNAT 100.64.0.0/10, de enlace local, local única o no especificada: una instancia que quien llama nombró en GITLAB-URL con --allow-any-gitlab-url, o un salto de redirección que salió del host de la instancia configurada. Una dirección que nombren GITLAB_URL o --gitlab-url nunca se comprueba, y las direcciones de metadatos de la nube siguen rechazadas diga lo que diga (Conexiones salientes) |
Qué token
Sección titulada «Qué token»| Token | Qué le sirve el servidor |
|---|---|
Clásico, scope api | Todas las acciones que permite el tier |
Clásico, scope read_api | Solo las acciones de lectura: el servidor lee los scopes del token al arrancar y le construye una superficie de solo lectura |
De grano fino (su lista de scopes dice granular) | Lo que alcanza su concesión, decidido acción por acción frente a los permisos que declara GitLab, cuando el token concede Personal Access Token: Read y Metadata: Read y la instancia ejecuta la versión de la que se registró la tabla de permisos; si no, todo salvo las acciones que ningún token de grano fino alcanza (Tokens de grano fino) |
Ni read_api ni api | Nada. Un servidor stdio sigue respondiendo al saludo de MCP y rechaza todos los métodos del catálogo (tools/list, tools/call, los métodos de recursos y prompts, los autocompletados y subscriptions/listen) con -40300 y un mensaje que pide crear un token con read_api, o con api para escribir también, y reiniciar con él. El modo HTTP rechaza un token así con 403 |
Un token cuyos scopes no se pueden leer se sirve como si pudiera escribir, y el propio 403 de GitLab responde a la llamada que no puede hacer. GITLAB_MCP_IGNORE_SCOPES omite la restricción a solo lectura y el filtro por scopes, nunca el mínimo de read_api.
Superficie de herramientas y comportamiento
Sección titulada «Superficie de herramientas y comportamiento»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_TOOL_SURFACE | dynamic | dynamic, meta, individual | Ambos | --tool-surface | Qué catálogo de herramientas se registra: dos herramientas de búsqueda y ejecución (dynamic), un despachador por dominio (meta) o una herramienta por acción |
GITLAB_MCP_CAPABILITY_SURFACE | full | full, minimal | Ambos | --capability-surface | minimal conserva el manifiesto gitlab://tools y quita los demás recursos, los prompts, las guías de flujo y las suscripciones a recursos |
GITLAB_MCP_META_PARAM_SCHEMA | opaque | opaque, compact, full, sin distinguir mayúsculas | Ambos | --meta-param-schema | Cómo describen las meta-herramientas sus params en tools/list: un sobre opaco, o un esquema por acción solo con los nombres de las propiedades (compact) o completo. Según lo medido, ocupan unas 8,7 y 18,3 veces el esquema opaco. Solo cambia el listado de la superficie meta: ningún handler, ningún resultado de búsqueda y ninguna entrada de gitlab://tools |
GITLAB_MCP_TIER | Detectado | free (o ce), premium, ultimate, sin distinguir mayúsculas | Ambos | --tier | Definido, el tier se usa tal cual sin comprobar la licencia. Sin definir, se detecta con GET /license (que solo puede leer un administrador en instancias autogestionadas, y nadie en GitLab.com) y después con los planes de los namespaces que administra el token (GET /namespaces, el plan real en GitLab.com y siempre default en autogestionadas), leídos de 100 en 100 durante 10 páginas como mucho y deteniéndose en el primer ultimate. Si ninguno responde, el tier es free, y una instancia enterprise lo dice en WARN nombrando esta variable. El modo HTTP lo detecta por credencial salvo que esté fijado |
GITLAB_MCP_READ_ONLY | false | Booleano | Ambos | --read-only | Quita todas las acciones que modifican, acción por acción y no herramienta por herramienta, así que las lecturas siguen funcionando en todas las superficies: una meta-herramienta conserva sus acciones de lectura, y gitlab_execute_action de la superficie dinámica se queda, anotada como de solo lectura, para las lecturas que puede encaminar (Modo de solo lectura) |
GITLAB_MCP_SAFE_MODE | false | Booleano | Ambos | --safe-mode | Responde a una acción que modifica con una tarjeta de vista previa que nombra la acción y repite sus argumentos en lugar de ejecutarla; las lecturas se siguen ejecutando. Si ambos están activos, gana el modo de solo lectura (Modo seguro) |
GITLAB_MCP_EMBEDDED_RESOURCES | true | Booleano | Ambos | --embedded-resources | Añade el recurso canónico gitlab:// como bloque de recurso incrustado a los resultados de las acciones get que tienen uno (Formato de salida). Pon false para un cliente que no tolere el bloque de contenido duplicado |
GITLAB_MCP_EXCLUDE_TOOLS | Vacío | Lista de nombres de herramienta, nombres de grupo o IDs canónicos de acción, como gitlab_admin,gitlab_runner,project.delete | Ambos | --exclude-tools | Quita lo que nombra en todas las superficies, y de los recursos, suscripciones, prompts y autocompletados que devuelven los mismos objetos. Las utilidades independientes responden a las mismas tres grafías: gitlab_interactive quita los cuatro flujos guiados, interactive.issue_create (o su herramienta en las superficies meta e individual, gitlab_interactive_issue_create) uno de ellos, y discover_project.resolve (o gitlab_discover_project) el descubrimiento de proyectos. Una entrada que no nombra nada se registra en WARN en lugar de rechazarse, porque una misma configuración se suele reutilizar entre tiers |
GITLAB_MCP_IGNORE_SCOPES | false | Booleano | Ambos | --ignore-scopes | Registra todas las herramientas que permite el tier, sean cuales sean los scopes del token. Los scopes se siguen leyendo, así que un token por debajo de read_api se sigue rechazando, y la concesión de un token de grano fino sigue decidiendo lo que se le muestra |
GITLAB_MCP_CLIENT_COMPAT | auto | off (sin distinguir mayúsculas) lo desactiva; cualquier otro valor significa auto | Ambos | --client-compat (ambos) | En auto, una sesión que se identifica como OpenAI Codex recibe la priority fraccionaria de sus anotaciones redondeada a 0 o 1, porque las compilaciones incluidas en ChatGPT.app rechazan una fracción (Perfiles de compatibilidad por cliente). Es una desviación deliberada de la especificación |
GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS | Vacío | Pares old=new separados por comas y aplicados en orden; una barra invertida escapa \, \= \\. Como mucho 32 pares, 256 bytes por mitad | Ambos | --description-substitutions (ambos) | Reescribe las descripciones y títulos listados de herramientas, prompts, recursos y plantillas de recursos para validadores estrictos de pasarelas MCP, nunca nombres, URIs, valores de enum ni resultados de herramientas. Un old vacío o un escape desconocido impiden el arranque. Una reescritura que haría crecer una cadena por encima del doble de su longitud, o de 512 bytes más cuando eso es mayor, deja esa cadena como estaba. Una lista activa se anuncia una vez en WARN |
GITLAB_MCP_YOLO_MODE | false | 1, true, yes (sin distinguir mayúsculas) son verdadero; cualquier otra cosa es falso | Ambos | --yolo-mode (ambos) | En todas las superficies, deja que una acción destructiva, como un borrado, se ejecute sin confirmación: sin pregunta a un cliente que admite elicitación, sin rechazo para uno que no puede preguntar, y sin necesidad de confirm: true en la superficie dinámica por defecto (Acciones destructivas). Si está definida, decide ella, así que --yolo-mode=false anula un AUTOPILOT=true heredado |
AUTOPILOT | Sin definir | Como GITLAB_MCP_YOLO_MODE | Ambos | Ninguno | Un alias que fijan otras herramientas de agentes, que solo se consulta cuando GITLAB_MCP_YOLO_MODE está vacía. Sigue sin prefijo a propósito y nunca genera aviso |
GITLAB_MCP_UPLOAD_MAX_FILE_SIZE | 2GB | Tamaño, positivo, como mucho 1 TB | Ambos | --upload-max-file-size (ambos) | El mayor fichero que acepta una herramienta de subida o de lectura de ficheros. Un servidor stdio rechaza al arrancar un valor no válido o demasiado grande; el modo HTTP avisa y usa el valor predeterminado, o el máximo de 1 TB |
GITLAB_MCP_ACTION_TIMEOUT | 65m | Duración; 0 lo desactiva; como mucho 24h | Ambos | --action-timeout | Cancela una acción que sigue en marcha pasado este tiempo. El valor predeterminado está por encima de la espera más larga que ofrece cualquier acción (la espera de un pipeline se limita a una hora), y también termina una subida o descarga de fichero que siga en marcha al llegar al límite, así que súbelo para ficheros demasiado grandes para moverse en ese tiempo |
Ficheros locales
Sección titulada «Ficheros locales»Estas tres amplían dónde puede tocar una herramienta la máquina en la que corre el servidor. El directorio de trabajo, salvo que sea la raíz de un sistema de ficheros o exactamente tu directorio personal, y el directorio temporal del sistema operativo están siempre permitidos. Una ruta se resuelve a través de todos sus enlaces simbólicos antes de comprobarla, y un directorio listado que no existe se omite con un WARN. Solo se aplican a un servidor stdio: el modo HTTP rechaza toda ruta local.
| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_ALLOWED_UPLOAD_DIRS | Vacío | Lista de directorios | stdio | Ninguno | Más directorios desde los que una herramienta puede leer un fichero local: toda entrada file_path y directory_path |
GITLAB_MCP_ALLOWED_DOWNLOAD_DIRS | Vacío | Lista de directorios | stdio | Ninguno | Más directorios en los que una herramienta puede escribir una descarga (output_path). El destino se vuelve a comprobar cuando ya existen sus directorios padre, y el fichero se escribe a su lado con un nombre temporal y solo se renombra sobre él cuando está completo, así que una descarga fallida o cancelada deja output_path como estaba |
GITLAB_MCP_ALLOWED_IMPORT_DIRS | Vacío | Lista de directorios | stdio | Ninguno | Más directorios desde los que se puede leer un archivo de importación de proyecto o de grupo. El archivo debe ser un fichero .tar.gz regular y, fuera de Windows, sin permiso de escritura para el grupo ni para otros |
Límites del transporte y diagnóstico
Sección titulada «Límites del transporte y diagnóstico»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_STDIO_MAX_LINE_BYTES | 4194304 (4 MiB) | Un número positivo de bytes, sin máximo | stdio | Ninguno | El mensaje stdio más largo que se ensambla. Una línea más larga se rechaza y se responde en lugar de acumularse, así que un cliente no puede hacer crecer el proceso enviando una. El valor predeterminado coincide con el límite de cuerpo HTTP del propio SDK, así que ambos transportes rechazan los mismos mensajes; súbelo solo para un cliente que incrusta cargas base64 grandes. Un valor no interpretable o no positivo avisa y conserva el predeterminado, porque un número mal escrito no debería tumbar al cliente junto con el servidor |
GITLAB_MCP_MAX_LISTEN_STREAMS | 64 | Un entero no negativo; 0 quita el techo | Ambos | Ninguno | Cuántos streams subscriptions/listen puede mantener abiertos una credencial. Un listen es una petición que el cliente deja abierta, medida en torno a un descriptor de fichero y entre 55 y 100 KB de memoria por stream, y un cliente real abre unos pocos. 0 quita ese techo y nada más: una credencial con un stream abierto sigue contando como ocupada y se mantiene en el pool. Un segundo techo de 512 por proceso no es configurable, porque el primero se multiplica por tantos tokens como tenga quien llama. Un valor no válido avisa y conserva 64 |
GITLAB_MCP_LOG_LEVEL | info | debug, info, warn (o warning), error, sin distinguir mayúsculas; cualquier otra cosa significa info | Ambos | --log-level (ambos) | Nivel de detalle del log JSON que el servidor escribe en stderr |
GITLAB_MCP_PPROF_ADDR | Vacío | host:puerto cuyo host es localhost o una dirección de loopback (127.0.0.1:6060, [::1]:6060) | Ambos | --pprof-addr (ambos) | Sirve los handlers de profiling de Go bajo /debug/pprof/ en un listener propio, que arranca antes que el transporte y se detiene con el proceso. Cualquier otro host, o ninguno, impide el arranque: un perfil del heap es una copia de la memoria del proceso y los handlers no piden credencial. Vacío no sirve nada |
GITLAB_MCP_ENV_FILE | Vacío | Una ruta a un fichero dotenv, preferiblemente absoluta | Ambos | --env-file (ambos) | Un fichero dotenv que cargar además del fichero personal. Consulta Ficheros dotenv |
Pool HTTP y sesiones
Sección titulada «Pool HTTP y sesiones»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_MAX_HTTP_CLIENTS | 100 | Un entero positivo, como mucho 10000 | HTTP; stdio la valida | --max-http-clients | Cuántas entradas (token, URL de GitLab) mantiene el pool. Acota entradas, no las llamadas ni las sesiones que contienen: esas las acota el proceso por su límite de descriptores (192 llamadas retenidas y 96 sesiones con estado con un límite duro de 1024), y nada lo configura (Dimensionado) |
GITLAB_MCP_SESSION_TIMEOUT | 30m | Una duración positiva, como mucho 24h. La variable rechaza 0, que el flag sí acepta | HTTP; stdio la valida | --session-timeout | Tiempo de inactividad de una sesión MCP con estado, así que solo con --stateless=false: con el transporte sin estado predeterminado, la sesión de cada POST termina con su respuesta. Una sesión que ningún cliente borra ocupa uno de los huecos de sesión del proceso hasta que caduca |
GITLAB_MCP_POOL_IDLE_TIMEOUT | 1h | Duración; 0 lo desactiva; como mucho 24h | HTTP; stdio la valida | --pool-idle-timeout | Recupera la entrada del pool de una credencial tras este tiempo sin uso. Una entrada con una suscripción viva nunca está inactiva según esta medida |
GITLAB_MCP_SESSION_REVALIDATE_INTERVAL | 15m | Duración; 0 detiene la comprobación periódica; como mucho 24h | HTTP; stdio la valida | --revalidate-interval | Cada cuánto se vuelve a comprobar cada credencial del pool. Con 0, una entrada cuya credencial tiene más de una hora se reconstruye igualmente, lo que la vuelve a comprobar. Fíjate en el nombre más corto del flag |
GITLAB_MCP_DRAIN_DELAY | 0 | Duración, como mucho 5m | HTTP; stdio la valida | --drain-delay | Tras SIGTERM, mantiene abierto el listener y responde a /health con 503 draining durante este tiempo antes de cerrarlo, para que un balanceador que consulta /health saque antes la instancia. Ponlo al menos en un intervalo de sondeo; 0 cierra de inmediato |
Autenticación HTTP
Sección titulada «Autenticación HTTP»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_AUTH_MODE | legacy | legacy, oauth, en minúsculas | HTTP; stdio la valida | --auth-mode | legacy acepta un token por petición en PRIVATE-TOKEN o Authorization: Bearer. oauth solo acepta un token bearer, lo verifica contra GitLab y publica metadatos de recurso protegido RFC 9728; exige GITLAB_MCP_PUBLIC_URL y una instancia https (Servidor HTTP) |
GITLAB_MCP_PUBLIC_URL | Vacío | Una URL absoluta https://host[:puerto][/ruta] sin barra final ni fragmento; http solo para localhost, 127.0.0.1 o ::1 | HTTP; stdio la valida en oauth | --public-url | La dirección accesible desde fuera del despliegue. Obligatoria con oauth, donde es el identificador de recurso RFC 9728; en modo legacy es opcional, y su origen es de confianza para peticiones cross-origin del navegador |
GITLAB_MCP_TRUSTED_ORIGINS | Vacío | Lista de orígenes absolutos (esquema://host[:puerto]), o * | HTTP | --trusted-origins | Orígenes a los que se permite hacer peticiones cross-origin desde el navegador. Vacía, rechaza todo POST cross-origin del navegador salvo el del origen de GITLAB_MCP_PUBLIC_URL, que es de confianza en cualquier caso; * acepta cualquier origen y desactiva la protección (Protección cross-origin) |
GITLAB_MCP_OAUTH_CACHE_TTL | 15m | Duración de 1m a 2h | HTTP; stdio la valida | --oauth-cache-ttl | Cuánto tiempo se reutiliza una identidad OAuth verificada. La caché guarda como mucho 10000 identidades sea cual sea la duración y, para hacer sitio, descarta una caducada o, si no hay ninguna, la que lleva más tiempo sin usarse; a la vez se ejecutan como mucho 16 verificaciones, y ninguna de las dos cifras es configurable (La caché de identidades del servidor) |
GITLAB_MCP_OAUTH_CLIENT_UID | Vacío | Lista de uids de aplicaciones OAuth de GitLab | HTTP | --oauth-client-uid | Solo admite tokens emitidos para estas aplicaciones. Vacía, admite cualquier credencial que acepte la instancia; definida, rechaza los tokens de acceso personal, que no pertenecen a ninguna aplicación. GitLab no publica vinculación de audiencia, así que esta es la comprobación de destinatario disponible (ADR-0019, Admitir solo tu propia aplicación) |
Límites de frecuencia y presupuestos de autenticación
Sección titulada «Límites de frecuencia y presupuestos de autenticación»| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_RATE_LIMIT_RPS | 0 en stdio, 10 en modo HTTP | Un número no negativo, como mucho 1000; 0 lo desactiva | Ambos | --rate-limit-rps | Límite por credencial, en peticiones por segundo, de 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. Un listado se cobra además, en las herramientas que lleva, a un bucket que comparte todo el proceso (3000 por segundo, 48000 disponibles, no configurable). 0 los apaga todos. En stdio esta variable es el único interruptor (Limitar la frecuencia de invocación de herramientas) |
GITLAB_MCP_RATE_LIMIT_BURST | 40 | Un entero de 0 a 10000 | Ambos | --rate-limit-burst | El tamaño del bucket mientras el límite está activo. Con el limitador activo, una ráfaga menor que 1 impide el arranque en los dos transportes |
GITLAB_MCP_AUTH_FAILURE_LIMIT | 10 | Un entero de 0 a 100000; 0 lo desactiva | HTTP; stdio la valida | --auth-failure-limit | Autenticaciones fallidas que puede producir una dirección dentro de la ventana de fallos antes de quedar bloqueada. 0 apaga este presupuesto en lugar de bloquear al primer fallo (Presupuestos de autenticación) |
GITLAB_MCP_AUTH_FAILURE_WINDOW | 1m | Duración; 0 lo desactiva; como mucho 24h | HTTP; stdio la valida | --auth-failure-window | La ventana 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. 0 apaga también el presupuesto de credenciales distintas |
GITLAB_MCP_AUTH_DISTINCT_TOKEN_LIMIT | 50 | Un entero de 0 a 100000; 0 lo desactiva | HTTP; stdio la valida | --auth-distinct-token-limit | Credenciales distintas que una dirección puede ver rechazadas dentro de la ventana de credenciales distintas antes de quedar bloqueada, cada vez durante más tiempo. Una persona tiene un token y una flota tras un NAT tiene uno por máquina, así que este recuento solo lo produce un ataque |
GITLAB_MCP_AUTH_DISTINCT_TOKEN_WINDOW | 10m | Duración; 0 lo desactiva; como mucho 24h | HTTP; stdio la valida | --auth-distinct-token-window | La ventana en la que cuenta el presupuesto de credenciales distintas |
Telemetría
Sección titulada «Telemetría»La telemetría está desactivada por defecto y solo va a un colector que configures tú; la página de OpenTelemetry explica qué registra y cómo enviarla.
| Variable | Predeterminado | Acepta | Transporte | Flag | Qué hace |
|---|---|---|---|---|---|
GITLAB_MCP_TELEMETRY | false | true o false, sin distinguir mayúsculas; cualquier otra cosa avisa y cuenta como falso | Ambos | --telemetry (ambos) | Exporta trazas, métricas y registros por OTLP. OTEL_SDK_DISABLED=true lo veta |
GITLAB_MCP_TELEMETRY_IDENTITY | none | none, pseudonymous, full, sin distinguir mayúsculas | Ambos | --telemetry-identity (ambos) | Qué registra la telemetría sobre quién hizo una llamada: nadie, un resumen con clave que correlaciona las llamadas de quien llama sin nombrarlo, o el id y el nombre de usuario de GitLab. La identidad nunca llega a una métrica. Un valor no reconocido se registra en ERROR, y no se registra nada sobre quién llama (Registrar quién hizo la llamada) |
GITLAB_MCP_TELEMETRY_IDENTITY_KEY | Vacío | Cualquier secreto | Ambos | Ninguno, a propósito | El secreto del que la política pseudonymous deriva sus claves (HKDF-SHA256). Vacío genera uno por proceso, así que un resumen solo significa algo dentro de un proceso; defínelo cuando varias réplicas deban coincidir o un recuento tenga que sobrevivir a un reinicio, y mantenlo lejos de donde acabe la telemetría. No tiene flag porque los argumentos de un proceso se pueden leer a través de /proc |
GITLAB_MCP_TELEMETRY_IDENTITY_ROTATION | Vacío | Duración; vacío o 0 conserva la clave toda la vida del proceso; como mucho 30 días (720h) | Ambos | --telemetry-identity-rotation (ambos) | Cuánto vive una clave generada. Se ignora, con un WARN, cuando está definida GITLAB_MCP_TELEMETRY_IDENTITY_KEY. Un valor no interpretable o fuera de rango se registra en ERROR, y no se registra nada sobre quién llama |
GITLAB_MCP_TELEMETRY_TOOL_NAME | auto | auto, on, off, sin distinguir mayúsculas; cualquier otra cosa se registra en ERROR y se lee como auto | Ambos | --telemetry-tool-name (ambos) | Si gen_ai.tool.name es una dimensión de las métricas. auto la mantiene en las superficies dinámica y meta y la quita en individual, donde un millar de herramientas agotaría el límite de cardinalidad del SDK y plegaría la cola larga en una única serie de desbordamiento |
Las variables OTEL_*
Sección titulada «Las variables OTEL_*»Las variables estándar conservan sus nombres, y casi todas las leen los propios exportadores y el SDK de OpenTelemetry, nunca el código de este servidor. Unas pocas las lee también este servidor, por el motivo de la última columna.
| Variable | La lee | Qué hace este servidor con ella |
|---|---|---|
OTEL_SDK_DISABLED | Solo este servidor | true (sin distinguir mayúsculas) veta la telemetría aunque la pidan GITLAB_MCP_TELEMETRY o --telemetry. Nada en el SDK de Go implementa la variable, así que lo hace el servidor |
OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_TRACES_PROTOCOL, ..._METRICS_PROTOCOL, ..._LOGS_PROTOCOL | Este servidor | Elige el exportador de cada señal, primero la variable propia de la señal: http/protobuf (el predeterminado, también escrito http) o grpc. http/json y cualquier otra cosa detienen la telemetría al arrancar con una línea ERROR, y el servidor sigue sirviendo sin ella |
OTEL_EXPORTER_OTLP_ENDPOINT y sus formas por señal | Los exportadores; también este servidor | Se nombra en la línea de arranque y en la server card, sin el usuario ni la contraseña que lleve, y se contrasta con las cabeceras para el aviso de texto plano |
OTEL_EXPORTER_OTLP_HEADERS y sus formas por señal | Los exportadores; también este servidor | Una credencial del colector: el servidor avisa una vez cuando una cruzaría la red en claro hacia otro host, y la elimina de sus propias líneas de log (Autenticarse ante tu colector) |
OTEL_EXPORTER_OTLP_INSECURE y sus formas por señal | Los exportadores; también este servidor | Solo se lee para decidir qué señales nombra ese aviso, porque los exportadores de trazas y métricas de Go le dejan anular un endpoint https |
OTEL_EXPORTER_OTLP_CERTIFICATE, ..._CLIENT_CERTIFICATE, ..._CLIENT_KEY y sus formas por señal | Los exportadores; este servidor las comprueba antes | Un fichero de CA que no se puede leer o que no contiene ningún certificado, o un certificado de cliente sin su clave bajo el mismo prefijo, detiene la telemetría al arrancar con un ERROR que nombra la variable, en lugar de dejar que los exportadores recurran a otra cosa en silencio |
OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES | El SDK; este servidor las comprueba | Cuando ninguna nombra el servicio, el servidor se llama a sí mismo gitlab-mcp-server; cuando alguna lo hace, se mantiene ese nombre. Cualquier otro atributo de recurso pasa sin tocar |
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT | El SDK; este servidor comprueba si está definida | Sin definir, el servidor limita cada valor de atributo de span a 4096 caracteres en lugar de dejarlo sin límite |
OTEL_TRACES_SAMPLER | El SDK; este servidor comprueba si está definida | Sin definir, el span HTTP ignora la petición de quien llama de no ser muestreado, así que quien llama de forma anónima no puede apagar el registro de su propio rechazo. Definida, decide el muestreador que elegiste |
Cualquier otra variable OTEL_* (plazos, compresión, lotes, intervalos de exportación) | Solo los exportadores y el SDK | Nada. Sus duraciones son milisegundos enteros |
Leídas por el runtime de Go
Sección titulada «Leídas por el runtime de Go»Otros dos grupos de variables los lee la biblioteca estándar de Go, no código escrito por este proyecto:
- Las variables de proxy
HTTPS_PROXY,HTTP_PROXYyNO_PROXY(y sus grafías en minúsculas), leídas una vez por proceso para las conexiones con GitLab. Tras un proxy la conexión es con el proxy, y el destino que hay detrás se juzga como describe Conexiones salientes; los hosts que deban alcanzarse directamente van enNO_PROXY. SSL_CERT_FILEen Linux y en los demás sistemas Unix salvo macOS, que indica a Go un paquete de certificados raíz. Sustituye las raíces predeterminadas para todo el proceso, así que dale un paquete y no un único certificado. Es la respuesta en contenedores a una CA privada, y no necesitaGITLAB_MCP_SKIP_TLS_VERIFY.
Nombres retirados
Sección titulada «Nombres retirados»Los ajustes que define este proyecto ganaron el prefijo GITLAB_MCP_ en la 2.8.0, porque un servidor stdio se ejecuta en la shell desde la que arrancó su cliente, junto a todas las demás herramientas de esa shell, y un nombre tan genérico como LOG_LEVEL o AUTH_MODE puede pertenecer ya a una de ellas. Las grafías antiguas respondieron junto a las nuevas hasta la 3.1.0, que las eliminó. Se retrasaron una versión a propósito: la 2.7.5 incluye un autoactualizador y la 3.0.0 no, así que un despliegue 2.7.5 se actualizó solo a la 3.0.0 sin que nadie leyera una nota de versión, y la 3.1.0 es la primera versión a la que nadie llega arrastrado.
Ya nada lee una grafía antigua. El servidor conoce la grafía antigua de 32 ajustes, y al arrancar, después de cargar los ficheros dotenv, busca cada una: el sufijo sin prefijo (LOG_LEVEL para GITLAB_MCP_LOG_LEVEL) o, para cinco de ellos, el nombre con prefijo GITLAB_ que tenían (GITLAB_TIER, GITLAB_READ_ONLY, GITLAB_SAFE_MODE, GITLAB_IGNORE_SCOPES, GITLAB_SKIP_TLS_VERIFY). YOLO_MODE es la grafía antigua de GITLAB_MCP_YOLO_MODE. Los otros 26 nombres sin prefijo son ACTION_TIMEOUT, AUTH_DISTINCT_TOKEN_LIMIT, AUTH_DISTINCT_TOKEN_WINDOW, AUTH_FAILURE_LIMIT, AUTH_FAILURE_WINDOW, AUTH_MODE, CAPABILITY_SURFACE, CLIENT_COMPAT, DRAIN_DELAY, EMBEDDED_RESOURCES, EXCLUDE_TOOLS, LOG_LEVEL, MAX_HTTP_CLIENTS, META_PARAM_SCHEMA, OAUTH_CACHE_TTL, OAUTH_CLIENT_UID, POOL_IDLE_TIMEOUT, PPROF_ADDR, PUBLIC_URL, RATE_LIMIT_BURST, RATE_LIMIT_RPS, SESSION_REVALIDATE_INTERVAL, SESSION_TIMEOUT, TOOL_SURFACE, TRUSTED_ORIGINS y UPLOAD_MAX_FILE_SIZE. Cada una que encuentra se informa en ambos transportes:
GITLAB_TIER is no longer read (removed in 3.1.0): rename it to GITLAB_MCP_TIER| Nombre antiguo | Qué pasa ahora |
|---|---|
GITLAB_READ_ONLY | Impide el arranque: la línea de arriba en ERROR, seguida de “and this deployment will not be started under a capability it did not ask for”, y estado de salida 1 |
GITLAB_SAFE_MODE | Impide el arranque, del mismo modo |
EXCLUDE_TOOLS | Impide el arranque, del mismo modo. Es el único nombre sin prefijo de los tres y puede pertenecer a otra herramienta de la misma shell; el servidor no puede saberlo, así que renómbralo a GITLAB_MCP_EXCLUDE_TOOLS, o quítalo del entorno de este servidor |
| Los otros 29 | Una línea WARN, y el servidor arranca con el ajuste en su valor predeterminado |
Los tres que impiden el arranque son la forma en que un operador retira parte de lo que sirve un despliegue, así que una versión que ignorase uno en silencio serviría escrituras, o las acciones que el operador quitó, en un despliegue que no pidió ninguna de las dos cosas. La comprobación mira el nombre y nunca su valor, así que GITLAB_READ_ONLY=false también lo impide, y un nombre definido en un fichero dotenv que carga el servidor cuenta igual que uno exportado en la shell. Como solo se leen nombres, un LOG_LEVEL sin prefijo que pertenezca a otra herramienta de la misma shell también se informa; solo genera un aviso.
Dos nombres se eliminaron antes, en la 3.0.0, y se ignoran sin decir nada: META_TOOLS (con su grafía GITLAB_MCP_META_TOOLS y el flag --meta-tools, que ahora es un flag desconocido), sustituido por GITLAB_MCP_TOOL_SURFACE; y GITLAB_ENTERPRISE, sustituido por GITLAB_MCP_TIER. A un despliegue que aún define GITLAB_ENTERPRISE se le detecta el tier, como a uno que no define nada.
Algunos nombres siguen sin prefijo a propósito: GITLAB_URL y GITLAB_TOKEN, la convención de GitLab, que define toda configuración existente; AUTOPILOT, una convención de otras herramientas de agentes; y OTEL_*, que pertenecen a la especificación de OpenTelemetry y que leen los propios exportadores, así que nunca verían una grafía con prefijo. Las variables MODELEVAL_*, GITLAB_MCP_TEST_INVENTORY_DIR y GITLAB_MCP_TEST_SNAPSHOT_PARITY configuran los arneses de pruebas y de evaluación de este repositorio; el servidor nunca las lee.
Ficheros dotenv
Sección titulada «Ficheros dotenv»Además de su entorno, el servidor lee dos ficheros dotenv, en ambos transportes, antes de que nada lea la configuración:
~/.gitlab-mcp-server.enven tu directorio personal, si existe.- El único fichero que nombre
GITLAB_MCP_ENV_FILE, o--env-file, que fija lo mismo y gana a la variable.
Precedencia, de mayor a menor:
- Un flag pasado de forma explícita. En ambos transportes son
--env-file, los siete flags que escriben su variable (--log-level,--client-compat,--upload-max-file-size,--yolo-mode,--description-substitutions,--allow-private-instances,--pprof-addr) y los cuatro flags de telemetría; en modo HTTP, todos los flags. - El entorno del proceso, que es lo que pasó el cliente MCP o exportó la shell.
- El fichero que nombra
GITLAB_MCP_ENV_FILE. - El fichero personal.
Un fichero nunca sobrescribe una variable que ya está definida. Eso incluye una variable exportada vacía: oculta el valor del fichero, y después el servidor la lee como no definida.
GITLAB_MCP_ENV_FILE se resuelve una sola vez, desde el entorno del proceso, antes de cargar ningún fichero, así que un fichero que carga el servidor no puede nombrar a otro. Dale una ruta absoluta. Una relativa se resuelve contra el directorio de trabajo, que el cliente cambia con cada espacio de trabajo que abre, así que una línea relativa en una configuración de cliente a nivel de usuario nombra un fichero distinto en cada repositorio; el servidor avisa cuando ve una. La carga del fichero nombrado se anuncia en WARN con su ruta, y un fichero que no se puede leer también es un WARN, no un rechazo.
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxxGITLAB_URL=https://gitlab.example.comGITLAB_MCP_TOOL_SURFACE=dynamicGITLAB_MCP_UPLOAD_MAX_FILE_SIZE=500MBGITLAB_MCP_LOG_LEVEL=infoNo subas nunca a un repositorio un fichero que contenga un token, y restríngelo a su propietario (chmod 600 en Linux y macOS).
El directorio de trabajo no es una fuente de configuración
Sección titulada «El directorio de trabajo no es una fuente de configuración»Un .env en el directorio de trabajo no se carga. Un servidor stdio hereda su directorio de trabajo del cliente, y todo cliente que abre un espacio de trabajo lo fija en ese espacio, así que el fichero llega con un repositorio clonado o un archivo descomprimido, escrito por quien los escribió. Cuando ese fichero se cargaba el primero, dos líneas en un repositorio podían enviar tu token a otro host, desactivar la verificación de certificados para que nada se quejara, activar la telemetría hacia un colector de su elección y reescribir las descripciones de herramientas que lee el modelo, todo antes de cualquier llamada a una herramienta: la comprobación de arranque entregaba el token. Las variables que lo hacen posible son justo las que ningún cliente define, así que siempre estaban libres para el primer fichero encontrado.
Ahora un fichero dotenv configura el servidor solo cuando alguien lo puso donde el servidor mira o lo nombró. Estar en el directorio de trabajo no es una decisión que haya tomado nadie, que es la misma conclusión a la que llegaron safe.directory de Git, direnv allow de direnv y la confianza en el espacio de trabajo de VS Code.
El fichero se sigue buscando. Uno que existe y no está vacío se nombra en WARN con su ruta absoluta, el número de claves que quería definir y hasta diez de sus nombres, nunca sus valores, para que un fichero que dejó de surtir efecto aparezca en el log y no en una tarde de depuración. Para seguir usándolo, nómbralo por ruta absoluta en GITLAB_MCP_ENV_FILE: el fichero que nombra se carga a propósito, aunque sea ese mismo .env.
Equivalencias en modo HTTP
Sección titulada «Equivalencias en modo HTTP»En modo HTTP, la configuración se resuelve en tres capas, de mayor a menor:
- Un flag pasado de forma explícita en la línea de comandos. Pasar un flag cuyo valor coincide con el predeterminado también cuenta como elegirlo:
--rate-limit-rps=10gana aGITLAB_MCP_RATE_LIMIT_RPS=2. - La variable con el mismo significado, cuando no se pasó su flag.
- El valor predeterminado.
Una variable solo se tiene en cuenta cuando está definida y no está vacía, y pasa por el mismo intérprete y los mismos límites que en stdio, así que un valor no válido detiene el arranque con loading environment configuration: ... en lugar de recurrir en silencio a otro valor. Las filas de arriba que avisan en lugar de eso lo dicen.
Un servidor stdio lee las variables y, de los flags, solo --http, --transport, --env-file, los siete que escriben una variable y los cuatro de telemetría. Nada de esta tabla se puede alcanzar desde una petición: un cliente solo controla su propio token y, donde el despliegue lo permite, la cabecera GITLAB-URL, y una cabecera de petición con el nombre de cualquier otro ajuste se ignora y se registra (Servidor HTTP).
| Variable | Flag | Notas |
|---|---|---|
GITLAB_MCP_ENV_FILE | --env-file | Ambos transportes; gana el flag |
| Ninguna | --http, --transport | El transporte solo se elige en la línea de comandos |
GITLAB_URL | --gitlab-url | Un valor separado por comas equivale a la lista de un flag repetido |
| Ninguna | --allow-any-gitlab-url | Sin variable a propósito: deja que quien llama elija el host al que se envía su token, así que pertenece a la línea de comandos que arrancó el proceso |
GITLAB_TOKEN | Ninguno | Solo stdio. En modo HTTP cada petición trae su propio token |
GITLAB_MCP_SKIP_TLS_VERIFY | --skip-tls-verify | |
GITLAB_MCP_ALLOW_PRIVATE_INSTANCES | --allow-private-instances | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_TOOL_SURFACE | --tool-surface | |
GITLAB_MCP_CAPABILITY_SURFACE | --capability-surface | |
GITLAB_MCP_META_PARAM_SCHEMA | --meta-param-schema | |
GITLAB_MCP_TIER | --tier | Sin ninguno de los dos, el tier se detecta por credencial |
GITLAB_MCP_READ_ONLY | --read-only | |
GITLAB_MCP_SAFE_MODE | --safe-mode | |
GITLAB_MCP_EMBEDDED_RESOURCES | --embedded-resources | |
GITLAB_MCP_EXCLUDE_TOOLS | --exclude-tools | |
GITLAB_MCP_IGNORE_SCOPES | --ignore-scopes | |
GITLAB_MCP_CLIENT_COMPAT | --client-compat | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS | --description-substitutions | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_YOLO_MODE | --yolo-mode | Ambos transportes; el flag escribe la variable |
AUTOPILOT | Ninguno | Ambos transportes; pierde frente a una GITLAB_MCP_YOLO_MODE no vacía |
GITLAB_MCP_UPLOAD_MAX_FILE_SIZE | --upload-max-file-size | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_ACTION_TIMEOUT | --action-timeout | Ambos transportes; stdio solo lee la variable |
GITLAB_MCP_ALLOWED_UPLOAD_DIRS, GITLAB_MCP_ALLOWED_DOWNLOAD_DIRS, GITLAB_MCP_ALLOWED_IMPORT_DIRS | Ninguno | Solo stdio: el modo HTTP rechaza toda ruta local digan lo que digan |
GITLAB_MCP_STDIO_MAX_LINE_BYTES | Ninguno | Solo stdio. Su equivalente HTTP es --max-request-body-bytes, que no tiene variable |
GITLAB_MCP_MAX_LISTEN_STREAMS | Ninguno | Ambos transportes; solo en el entorno |
GITLAB_MCP_LOG_LEVEL | --log-level | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_PPROF_ADDR | --pprof-addr | Ambos transportes; el flag escribe la variable |
GITLAB_MCP_MAX_HTTP_CLIENTS | --max-http-clients | |
GITLAB_MCP_SESSION_TIMEOUT | --session-timeout | Solo el flag acepta 0 |
GITLAB_MCP_POOL_IDLE_TIMEOUT | --pool-idle-timeout | |
GITLAB_MCP_SESSION_REVALIDATE_INTERVAL | --revalidate-interval | La única pareja cuyos nombres difieren |
GITLAB_MCP_DRAIN_DELAY | --drain-delay | |
GITLAB_MCP_AUTH_MODE | --auth-mode | |
GITLAB_MCP_PUBLIC_URL | --public-url | |
GITLAB_MCP_TRUSTED_ORIGINS | --trusted-origins | |
GITLAB_MCP_OAUTH_CACHE_TTL | --oauth-cache-ttl | |
GITLAB_MCP_OAUTH_CLIENT_UID | --oauth-client-uid | |
| Ninguna | --resource-documentation, --resource-policy-uri, --resource-tos-uri | Los enlaces de los metadatos RFC 9728; solo flags |
GITLAB_MCP_RATE_LIMIT_RPS | --rate-limit-rps | Los valores predeterminados difieren: 10 en modo HTTP, 0 en stdio, que ignora el flag |
GITLAB_MCP_RATE_LIMIT_BURST | --rate-limit-burst | |
GITLAB_MCP_AUTH_FAILURE_LIMIT | --auth-failure-limit | |
GITLAB_MCP_AUTH_FAILURE_WINDOW | --auth-failure-window | |
GITLAB_MCP_AUTH_DISTINCT_TOKEN_LIMIT | --auth-distinct-token-limit | |
GITLAB_MCP_AUTH_DISTINCT_TOKEN_WINDOW | --auth-distinct-token-window | |
| Ninguna | --trusted-proxies, --trusted-proxy-header | Solo flags, y cada uno exige el otro |
| Ninguna | --http-addr, --http-socket-mode, --tls-cert, --tls-key | El listener; solo flags |
| Ninguna | --stateless, --json-response, --max-request-body-bytes, --http-idle-timeout | El transporte HTTP streamable; solo flags |
GITLAB_MCP_TELEMETRY | --telemetry | Ambos transportes |
GITLAB_MCP_TELEMETRY_IDENTITY | --telemetry-identity | Ambos transportes |
GITLAB_MCP_TELEMETRY_IDENTITY_KEY | Ninguno | Solo en el entorno, a propósito: los argumentos de un proceso se pueden leer a través de /proc |
GITLAB_MCP_TELEMETRY_IDENTITY_ROTATION | --telemetry-identity-rotation | Ambos transportes |
GITLAB_MCP_TELEMETRY_TOOL_NAME | --telemetry-tool-name | Ambos transportes |
Los flags que se ejecutan una vez y terminan (--tool-search, --probe, --shutdown, --version, -h y --help) no tienen variable; --tool-search lee GITLAB_MCP_TOOL_SURFACE, GITLAB_MCP_TIER y los ficheros dotenv, así que un despliegue stdio busca en lo que sirve. La referencia de la línea de comandos cubre cada flag.
Rutas locales en modo HTTP
Sección titulada «Rutas locales en modo HTTP»Un servidor al que se llega por HTTP rechaza toda ruta local que nombre quien llama: un file_path o un directory_path que leer, un output_path en el que escribir y un archivo de importación local. El llamante no tiene ficheros en la máquina en la que corre el servidor, así que cualquier ruta que pueda nombrar pertenece a otra persona. El rechazo no depende de las tres variables GITLAB_MCP_ALLOWED_*_DIRS, que no tienen efecto en modo HTTP, y sigue al transporte que el proceso sirve de verdad, --transport=auto incluido.
El error lo dice y, para file_path, nombra la entrada que lleva los bytes en la propia petición:
file_path is disabled when the server is reached over HTTP: the file would be read from the server's own disk, not yours; send the bytes with content_base64 insteadcontent_base64 es la forma remota de una subida, y uno de los motivos por los que el límite del cuerpo de petición HTTP se queda por defecto en los 4 MiB del SDK.