Skip to content

Latest commit

 

History

History
287 lines (215 loc) · 82 KB

File metadata and controls

287 lines (215 loc) · 82 KB

Environment Variable Reference

Diátaxis type: Reference Audience: 👤🔧 All users Prerequisites: gitlab-mcp-server binary installed

Complete environment variable reference for gitlab-mcp-server stdio mode.


Variable naming

Settings this project defines are read as GITLAB_MCP_<NAME> from 2.8.0.

A stdio MCP server runs in whatever shell its client was started from, next to every other tool that person uses. Names as generic as LOG_LEVEL, AUTH_MODE or RATE_LIMIT_RPS may already be owned by something else there, and the collision is silent: the server reads a value nobody gave it and behaves in a way nobody configured.

The unprefixed spelling was removed in 3.1.0 and is read by nothing. One left set is named at startup, with the variable to rename it to.

The switches that already began with GITLAB_ were renamed as well, so that every variable of this server reads alike: GITLAB_TIER, GITLAB_READ_ONLY, GITLAB_SAFE_MODE, GITLAB_IGNORE_SCOPES and GITLAB_SKIP_TLS_VERIFY are now GITLAB_MCP_TIER, GITLAB_MCP_READ_ONLY, GITLAB_MCP_SAFE_MODE, GITLAB_MCP_IGNORE_SCOPES and GITLAB_MCP_SKIP_TLS_VERIFY, and YOLO_MODE is GITLAB_MCP_YOLO_MODE. The old spellings stopped working in 3.1.0. One left in the environment is reported at startup naming its replacement, and for GITLAB_READ_ONLY and GITLAB_SAFE_MODE the server refuses to start rather than serve writes on a deployment that asked to be read-only.

Two names are gone rather than renamed, both deprecated in 2.7.5 and removed in 3.0.0: META_TOOLS, whose replacement is GITLAB_MCP_TOOL_SURFACE, and GITLAB_ENTERPRISE, whose replacement is GITLAB_MCP_TIER.

Some names stay bare on purpose:

Names Why they were not renamed
GITLAB_URL, GITLAB_TOKEN GitLab's own convention. Every existing configuration sets them, and they are the two most likely to be written into a client configuration from memory
OTEL_* Owned by the OpenTelemetry specification. The exporters read those names themselves and would never see a prefixed spelling
AUTOPILOT A convention other agent tooling sets, honored as an alias of GITLAB_MCP_YOLO_MODE and never warned about. The setting itself is ours and carries the prefix; its old spelling YOLO_MODE was removed in 3.1.0
MODELEVAL_* The model evaluation's own variables, set by make targets in this repository. They configure a test harness that cmd/server never links, so they never appear beside another tool's variables in a user's shell

The tables below always give the name to set, so read the name rather than deriving it. The renamed set is internal/config.PrefixedEnvNames(); a name outside it is read verbatim.


Required

Variable Description Example
GITLAB_TOKEN Personal Access Token with api scope glpat-xxxxxxxxxxxxxxxxxxxx

Optional — Connection

Variable Default Description
GITLAB_URL https://gitlab.com GitLab instance base URL (must use http:// or https:// scheme). Set this for self-managed instances
GITLAB_MCP_SKIP_TLS_VERIFY false Skip TLS certificate verification (true/false). Use for self-signed certs

Optional — Server Behavior

Variable Default Description
GITLAB_MCP_TOOL_SURFACE dynamic Canonical tool catalog selector: dynamic, meta, or individual. dynamic exposes find/execute
GITLAB_MCP_CAPABILITY_SURFACE full Resource and prompt catalog selector: full keeps the complete catalog; minimal keeps the surface-aware gitlab://tools manifest and disables optional GitLab data resources, workflow guides, prompts, and resource subscriptionsresources/subscribe is only advertised on full. Dynamic describe/find still returns action schemas inline with minimal
GITLAB_MCP_META_PARAM_SCHEMA opaque Meta-tool input-schema strategy: opaque (compact {action, params:any} envelope, default), compact (oneOf with property names + types only, 8.7x opaque size) or full (oneOf with full per-action JSON Schemas, 18.3x opaque size). Applies to visible meta-tool schemas in meta; has no practical effect on dynamic or individual tool schemas. Per-action call shapes and JSON Schemas are discoverable through gitlab://tools and gitlab://tools/{id} for every surface
GITLAB_MCP_TIER (detected) Licensing tier: free/ce, premium, or ultimate. When set, used verbatim with no license check. When unset, detected from the instance license (GET /license → plan), fallback free. In HTTP mode use --tier; when omitted the tier is detected per token+URL pool entry. Enterprise/Premium tools are gated when the resolved tier is Premium or Ultimate
GITLAB_MCP_LOG_LEVEL info Logging verbosity: debug, info, warn, error. The --log-level flag sets the same variable and wins over it
GITLAB_MCP_PPROF_ADDR (empty) Serve Go's profiling handlers (net/http/pprof) on this address, on a listener of their own that starts before the transport and stops with the process. The host must be loopback (127.0.0.1:6060, [::1]:6060 or localhost:6060); any other host is refused at startup, since a heap profile is a copy of the process's memory and the handlers take no credential. Empty serves nothing. Both transports; the --pprof-addr flag sets the same variable. Used by cmd/bench_resources to profile the concurrency series
GITLAB_MCP_ALLOW_PRIVATE_INSTANCES false Permit a private, loopback, CGNAT 100.64.0.0/10, link-local, unique-local or unspecified address as a destination this server's operator did not choose. Two destinations are not the operator's choice: an instance a caller named in the GITLAB-URL header under --allow-any-gitlab-url, and a redirect hop that left the configured instance's own host (which is how GitLab answers artifact, trace and package downloads when object storage is configured). An address --gitlab-url or GITLAB_URL named is exempt whatever it resolves to, so a GitLab on localhost, on 10.x or behind a VPN needs nothing set; and a redirect to a private address is allowed anyway when the configured instance itself resolves private. The cloud metadata addresses (169.254.169.254, 169.254.170.2, fd00:ec2::254, 100.100.100.200) are refused on every hop for every deployment and this does not permit them. Enforced at the dialer, after DNS resolution. Both transports; the --allow-private-instances flag sets the same variable. See ADR-0022
GITLAB_MCP_READ_ONLY false Read-only mode: mutating operations are removed per action, not per tool, so reads keep working on every surface — gitlab_issue survives with its read actions and gitlab_execute_action stays available (annotated read-only) for the reads it can route. On the individual surface, where one tool is one action, this is simply the removal of the mutating tools (true/false)
GITLAB_MCP_SAFE_MODE false Safe mode: intercepts mutating operations per action and returns a preview card naming that action and echoing its arguments instead of executing, so issue.create previews while issue.list executes. If GITLAB_MCP_READ_ONLY=true, it takes precedence (true/false)
GITLAB_MCP_EMBEDDED_RESOURCES true Embed the canonical gitlab:// MCP resource URI as an EmbeddedResource content block in the get results that carry one (twenty-two actions, listed in Output Format). Set to false to disable for clients that don't tolerate duplicate content blocks (true/false)
GITLAB_MCP_EXCLUDE_TOOLS (empty) Comma-separated list of tool names, group names or canonical action IDs to exclude (e.g. gitlab_admin,gitlab_runner). They are excluded from the tool surface and from the resources, subscriptions, prompts and argument completions that return the same objects, so the removal holds on every request path
GITLAB_MCP_IGNORE_SCOPES false Skip PAT scope detection and register all tools regardless of token permissions (true/false)
GITLAB_MCP_CLIENT_COMPAT auto Per-client response compatibility. On auto, a session identifying itself as OpenAI Codex gets the float priority in content and resource annotations rounded to 0 or 1 — the Codex builds bundled with ChatGPT.app reject a fractional value and mark the call as an unexpected response type. Every other field, and every other client, is delivered unchanged. Set off to disable the rewriting. Read from the process environment in both stdio and HTTP modes; the --client-compat flag sets the same variable. See Client Compatibility
GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS (empty) Rewrite listed catalog text for strict MCP gateway validators: comma-separated old=new pairs applied in order to every listed description and title (backslash escapes \, \= \\). Covers tools on every surface (schema-embedded descriptions included), prompts, resources and resource templates; never names, URIs, pattern, const, enum values or tool-call payloads. A malformed value refuses startup; an active configuration is announced at WARN once. Both transports; the --description-substitutions flag sets the same variable. See Client Compatibility

Optional — Destructive Action Confirmation

Variable Default Description
GITLAB_MCP_YOLO_MODE false Skip confirmation prompts for destructive actions (delete, force-push)
AUTOPILOT false Same as GITLAB_MCP_YOLO_MODE — skip all confirmation prompts

These are checked by the elicitation subsystem. When the MCP client supports elicitation, destructive tools ask for user confirmation unless one of these is true. A non-empty GITLAB_MCP_YOLO_MODE takes precedence over AUTOPILOT, and the --yolo-mode flag sets GITLAB_MCP_YOLO_MODE.


Optional — Upload

Variable Default Description
GITLAB_MCP_UPLOAD_MAX_FILE_SIZE 2GB Maximum file size for upload and file-read tools. Supports human-friendly suffixes: KB, MB, GB (case-insensitive). Upper bound: 1 TB. Both transports; the --upload-max-file-size flag sets the same variable

Optional — Local File Paths

Variable Default Description
GITLAB_MCP_ALLOWED_IMPORT_DIRS (empty) Additional OS path-list-separated directories allowed for file_path/file project and group import archives. The current working directory (unless it is the filesystem root or the user's home directory, which are dropped as implicit roots) and the OS temp directory are always allowed. Import archives must resolve inside an allowed directory after symlink resolution and must use the .tar.gz extension
GITLAB_MCP_ALLOWED_UPLOAD_DIRS (empty) Additional OS path-list-separated directories a tool may read a local file from (every file_path and directory_path input: uploads, secure files, avatars, package publish). The current working directory (unless it is the filesystem root or the user's home directory, which are dropped as implicit roots) and the OS temp directory are always allowed, and a path is resolved through symlinks first
GITLAB_MCP_ALLOWED_DOWNLOAD_DIRS (empty) Additional OS path-list-separated directories a tool may write a downloaded file into (output_path). Same syntax and same always-allowed roots. The destination is resolved twice, before its parent directories are created and again after, so the second check sees the directory being written to

A server reached over HTTP refuses every caller-supplied local path whatever these say, since the caller has no files on the machine the server runs on. content_base64 is the remote form.


Optional telemetry

Off by default, in both transports. Telemetry goes to a collector the operator configures, never to the maintainer: the endpoint, credentials, sampling and batching come from the standard OTEL_EXPORTER_OTLP_* variables, which the exporters read themselves under their own names, and OTEL_SDK_DISABLED=true vetoes the export regardless of what is set here. Each of these has a flag of the same name except the key, which stays environment-only because process arguments are readable through /proc. See Telemetry.

Variable Default Description
GITLAB_MCP_TELEMETRY false Export OpenTelemetry traces, metrics and logs over OTLP. Flag --telemetry
GITLAB_MCP_TELEMETRY_IDENTITY none How much telemetry records about who made a call: none records nobody, pseudonymous a per-process HMAC digest that correlates one caller's calls without naming them, full the GitLab user id and username. Identity never reaches a metric under any policy. Flag --telemetry-identity
GITLAB_MCP_TELEMETRY_IDENTITY_KEY (empty) Secret the pseudonymous policy derives its keys from (HKDF-SHA256). Empty generates one per process, so a digest identifies a caller within one process and nowhere else; set it when several replicas must agree or a distinct-user count has to survive a restart, and keep it away from wherever the telemetry lands. No flag on purpose
GITLAB_MCP_TELEMETRY_IDENTITY_ROTATION (empty) How long a generated pseudonymisation key lives, e.g. 24h; empty or 0 keeps it for the life of the process, 30 days is the ceiling. Ignored, with a warning at startup, when GITLAB_MCP_TELEMETRY_IDENTITY_KEY is set. Flag --telemetry-identity-rotation
GITLAB_MCP_TELEMETRY_TOOL_NAME auto Whether gen_ai.tool.name is a metric dimension: auto keeps it on the dynamic and meta surfaces and drops it on individual, where about a thousand tools would exhaust the SDK's cardinality limit and collapse the long tail into one overflow bucket; on and off force it. Flag --telemetry-tool-name

Optional — Transport Limits

These apply whichever transport carries the call, so the tool surface makes no difference to them: GITLAB_MCP_ACTION_TIMEOUT bounds the action handler, GITLAB_MCP_STDIO_MAX_LINE_BYTES caps each stdio input message, and GITLAB_MCP_MAX_LISTEN_STREAMS caps the concurrent subscriptions/listen streams one credential may hold open.

Variable Default Description
GITLAB_MCP_ACTION_TIMEOUT 65m Cancel an action still running after this long, in both transports; 0 disables it. Upper bound: 24h. Above the longest wait any action offers (a pipeline wait caps itself at 3600 s), so it ends a handler nobody else bounds, not a legitimate call. HTTP mode also has --action-timeout
GITLAB_MCP_STDIO_MAX_LINE_BYTES 4 MiB Longest stdio message accepted, in bytes. A longer line is refused and answered, not buffered, so a client cannot grow the process by sending one. It matches the SDK's own default for an HTTP request body, so both transports refuse the same messages. Raise it only for a client that inlines large base64 payloads. A missing, unparseable or non-positive value warns and keeps the default
GITLAB_MCP_MAX_LISTEN_STREAMS 64 Concurrent subscriptions/listen streams one credential may hold open; 0 removes that ceiling and nothing else, so a credential holding one open is still counted as busy and is not idle-swept from the pool. A listen is a request the client leaves open, costing a blocked goroutine and a file descriptor each, and a real client opens a handful. A second ceiling of 512 per process is not configurable, because the per-credential one multiplies by however many tokens a caller holds. Both transports

Optional — HTTP Mode (Server Pool)

These variables configure the HTTP server pool. Each has a CLI flag counterpart, and the flag wins when it is passed explicitly — see HTTP Mode Equivalents below. In stdio mode they are parsed but unused, since stdio runs a single server with no pool, with one exception: the two rate-limit variables at the end of the table meter stdio's single server as well, where the limiter is off unless they turn it on.

Variable Default Description
GITLAB_MCP_MAX_HTTP_CLIENTS 100 Maximum unique (token, GitLab URL) server entries kept in the pool; it bounds pooled entries, not sessions or concurrent requests. Upper bound: 10,000
GITLAB_MCP_SESSION_TIMEOUT 30m Idle MCP session timeout; applies to --stateless=false only, since under the default stateless transport each POST's session ends with its response. Upper bound: 24h
GITLAB_MCP_DRAIN_DELAY 0 After SIGTERM, keep the listener open and answer /health with 503 draining for this long before closing it, so a balancer that polls /health removes the instance before the close. Upper bound: 5m. 0 closes at once. Set it to at least one probe interval
GITLAB_MCP_POOL_IDLE_TIMEOUT 1h Reclaim a pooled per-token-and-URL credential entry after this long unused; 0 keeps entries until the pool size bound evicts them. Upper bound: 24h. An entry with a live subscription is never idle by this measure
GITLAB_MCP_SESSION_REVALIDATE_INTERVAL 15m Token re-validation interval for pooled entries. 0 stops the periodic check, but an entry whose credential is older than 1h is still rebuilt, which re-runs the probe. Upper bound: 24h
GITLAB_MCP_AUTH_MODE legacy Authentication mode: legacy (PRIVATE-TOKEN header passthrough) or oauth (RFC 9728 Bearer token verification via GitLab API)
GITLAB_MCP_OAUTH_CACHE_TTL 15m TTL for verified OAuth token identity cache. Range: 1m–2h
GITLAB_MCP_OAUTH_CLIENT_UID (empty) Comma-separated GitLab OAuth application uids whose tokens are admitted. Empty admits any credential the instance accepts; setting it refuses personal access tokens, which belong to no application. Flag --oauth-client-uid; see ADR-0019
GITLAB_MCP_PUBLIC_URL (empty) Externally reachable origin of this deployment. Required with GITLAB_MCP_AUTH_MODE=oauth (RFC 9728 resource identifier); in legacy mode its origin seeds the trusted-origins list
GITLAB_MCP_TRUSTED_ORIGINS (empty) Comma-separated absolute origins (scheme://host[:port]) allowed to make cross-origin browser requests. * accepts any origin and disables the protection; empty adds none, though a configured GITLAB_MCP_PUBLIC_URL origin is trusted regardless
GITLAB_MCP_RATE_LIMIT_RPS 0 Per-credential rate limit, in requests/second, on every call that reaches GitLab (tools/call, resources/read, resources/subscribe, subscriptions/listen, prompts/get), plus tools/list on a bucket of its own refilled a tenth as fast: that one reaches no GitLab and spends the processor every tenant shares instead. Its burst is the configured one, undivided, so a fleet of clients on one credential can still all discover at once. 0 disables the limiter. The default is 0 in stdio and 10 in HTTP mode, where --rate-limit-rps overrides it. See Security — Rate Limiting Model
GITLAB_MCP_RATE_LIMIT_BURST 40 Token-bucket burst size when GITLAB_MCP_RATE_LIMIT_RPS > 0. Must be ≥ 1

Configuration Loading Order

Configuration is loaded by internal/config/ in this precedence order (higher wins):

  1. The process environment, which is what the MCP client passed to the server
  2. The file GITLAB_MCP_ENV_FILE names, when the process environment names one
  3. ~/.gitlab-mcp-server.env in the user's home directory

Note: godotenv never overwrites a variable that is already set, so an earlier step always wins over a later one.

A .env in the current working directory is not on that list. See The working directory is not a configuration source below.

Variable Default Description
GITLAB_MCP_ENV_FILE (empty) Path of one dotenv file to load in addition to the home file; the --env-file flag sets the same thing and wins over it. Read from the process environment only, which is what makes it an opt-in: a file this server loads cannot nominate another, so the working-directory .env cannot name itself. Give an absolute path. A relative one is resolved against the working directory the client chose, which is the load this replaced under another name, so startup warns when it sees one

The working directory is not a configuration source

A stdio server inherits its working directory from the MCP client, and every client that opens a workspace sets it to that workspace. Its contents therefore arrive with a cloned repository or an unpacked archive, chosen by whoever wrote them rather than by whoever runs the server.

The ./.env load used to come first, so two lines in a cloned repository could redirect your token to another host, turn off certificate verification so that redirection raised no error, and rewrite the tool descriptions the model reads. None of it needed a tool call or a model turn: the startup probe delivered the token. The variables that make it work are exactly the ones no MCP client sets, so they are always free for whichever file is read first.

A dotenv file now configures this server only when someone put it where the server looks (~/.gitlab-mcp-server.env) or named it (GITLAB_MCP_ENV_FILE). Being in the working directory is not a decision anyone made, which is the same conclusion Git's safe.directory, direnv's direnv allow and VS Code Workspace Trust reached.

A working-directory .env is still looked for, and reported at WARN with its absolute path and the names of the keys it wanted to set, so a repository-local file that stopped taking effect is a line in the startup log rather than an afternoon of debugging. Nothing in it reaches the environment.


Dotenv File Example

# Required
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx

# Optional
GITLAB_MCP_SKIP_TLS_VERIFY=false
GITLAB_MCP_TOOL_SURFACE=dynamic
GITLAB_MCP_LOG_LEVEL=info
GITLAB_MCP_UPLOAD_MAX_FILE_SIZE=500MB

Write that to ~/.gitlab-mcp-server.env, or to any path you then name in GITLAB_MCP_ENV_FILE. For self-managed GitLab, add GITLAB_URL=https://gitlab.example.com.

Security: Never commit tokens or credentials. Whichever file holds the token, restrict it to its owner (chmod 600 on Unix).


HTTP Mode Equivalents

In HTTP mode, configuration resolves in three layers, highest first:

  1. A CLI flag passed explicitly on the command line. Always wins.
  2. The environment variable, when the corresponding flag was not passed.
  3. The built-in default.

Passing a flag whose value happens to equal the default still counts as choosing it, so the environment cannot override it. See CLI Reference for the full flag list.

The rows marked (none) in the variable column are flags with no environment counterpart at all, the transport and listener flags in particular. A deployment that configures everything else through the environment must still pass those on the command line. The rows marked (none) in the flag column are the reverse: settings that exist only in the environment, because the flag would put a secret on a command line.

Nothing in this table is reachable from a request. Clients control only their GitLab token and the GITLAB-URL header, and what that header may do follows how many instances the deployment published: with none it selects the instance freely; with exactly one it is ignored and logged, because that instance is authoritative; with several it selects among them, and a value naming anything else is refused rather than quietly served the default. Every other configuration header is ignored and reported in the ignored_options log field. See Configuration Precedence.

Environment Variable CLI Flag Notes
GITLAB_MCP_ENV_FILE --env-file Dotenv file loaded besides ~/.gitlab-mcp-server.env; the flag wins over the variable. Both transports
(none) --transport CLI-only; stdio, http or auto. Empty defers to --http, and auto reads file descriptor 0 (HTTP only when stdin is the null device)
GITLAB_URL --gitlab-url Optional in stdio mode; defaults to https://gitlab.com. Required in HTTP mode unless --allow-any-gitlab-url is passed. When set in HTTP mode it fixes the GitLab instance; with the escape hatch and no instance, GITLAB-URL selects per request and a request without it is refused. A comma-separated value (or a repeated --gitlab-url) publishes several instances: GITLAB-URL is then required and selects among them, refusing anything else
(none) --allow-any-gitlab-url CLI-only, and deliberately so: this is the flag that lets a caller choose the host this server sends their token to, so it belongs in the command line that started the process rather than in an environment nobody reads back. Start with no instance published and let GITLAB-URL name any host. For a single-user local deployment where the operator is the caller; it warns at startup and must not be used on a listener anyone else can reach
GITLAB_TOKEN (none) Not needed in HTTP mode — clients provide tokens per-request
GITLAB_MCP_SKIP_TLS_VERIFY --skip-tls-verify
GITLAB_MCP_TOOL_SURFACE --tool-surface Canonical selector: meta, individual, or dynamic
GITLAB_MCP_CAPABILITY_SURFACE --capability-surface Explicit selector: full or minimal
GITLAB_MCP_META_PARAM_SCHEMA --meta-param-schema
GITLAB_MCP_MAX_HTTP_CLIENTS --max-http-clients
GITLAB_MCP_SESSION_TIMEOUT --session-timeout
(none) --http-idle-timeout CLI-only; HTTP server idle connection timeout. Default 0 disables idle closure so --session-timeout is the effective lifetime
(none) --http-addr CLI-only; listen address. host:port binds TCP; a value containing a path separator binds a unix socket instead
(none) --http-socket-mode CLI-only; octal permission mode for a unix socket named by --http-addr (default 0660)
(none) --tls-cert, --tls-key CLI-only; PEM certificate and key that terminate HTTPS on the listener itself. Both or neither
(none) --stateless CLI-only; sessionless streamable HTTP (default true). --stateless=false restores legacy stateful sessions
(none) --json-response CLI-only; return application/json response bodies instead of text/event-stream
(none) --max-request-body-bytes CLI-only; maximum streamable HTTP request body size in bytes; 0 uses the SDK default (4 MiB)
GITLAB_MCP_ACTION_TIMEOUT --action-timeout Both transports; the flag is the HTTP spelling
GITLAB_MCP_DRAIN_DELAY --drain-delay HTTP mode only: stdio has no listener to hold open
GITLAB_MCP_POOL_IDLE_TIMEOUT --pool-idle-timeout
GITLAB_MCP_SESSION_REVALIDATE_INTERVAL --revalidate-interval 0 stops the periodic check; an entry whose credential is older than 1h is still rebuilt
GITLAB_MCP_AUTH_MODE --auth-mode
GITLAB_MCP_OAUTH_CLIENT_UID --oauth-client-uid Comma-separated GitLab OAuth application uids whose tokens are admitted; empty admits any credential the instance accepts
(none) --resource-documentation CLI-only; https URL published as RFC 9728 resource_documentation. Empty publishes this project's HTTP server mode page
(none) --resource-policy-uri CLI-only; https URL published as RFC 9728 resource_policy_uri. Empty omits the field
(none) --resource-tos-uri CLI-only; https URL published as RFC 9728 resource_tos_uri. Empty omits the field
GITLAB_MCP_OAUTH_CACHE_TTL --oauth-cache-ttl
GITLAB_MCP_PUBLIC_URL --public-url
GITLAB_MCP_RATE_LIMIT_RPS --rate-limit-rps
GITLAB_MCP_RATE_LIMIT_BURST --rate-limit-burst
(none) --trusted-proxies CLI-only; addresses or CIDR ranges of the proxies whose --trusted-proxy-header is believed, required with it
(none) --trusted-proxy-header CLI-only; HTTP header with real client IP for rate limiting behind proxies, believed only from --trusted-proxies
GITLAB_MCP_TRUSTED_ORIGINS --trusted-origins
GITLAB_MCP_TIER --tier In HTTP mode, an explicit flag forces the tier; when omitted, the tier is detected from the instance license per token+URL pool entry (fallback free)
GITLAB_MCP_READ_ONLY --read-only
GITLAB_MCP_SAFE_MODE --safe-mode
GITLAB_MCP_EMBEDDED_RESOURCES --embedded-resources
GITLAB_MCP_EXCLUDE_TOOLS --exclude-tools Comma-separated list
GITLAB_MCP_IGNORE_SCOPES --ignore-scopes
GITLAB_MCP_LOG_LEVEL --log-level Both transports. The flag writes the variable, so the one reader stays
GITLAB_MCP_CLIENT_COMPAT --client-compat Both transports; same mechanism
GITLAB_MCP_UPLOAD_MAX_FILE_SIZE --upload-max-file-size Both transports; same mechanism
GITLAB_MCP_YOLO_MODE --yolo-mode Both transports; same mechanism. AUTOPILOT has no flag and loses to a non-empty GITLAB_MCP_YOLO_MODE
GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS --description-substitutions Both transports; same mechanism
GITLAB_MCP_PPROF_ADDR --pprof-addr Both transports; same mechanism. Loopback only
GITLAB_MCP_ALLOW_PRIVATE_INSTANCES --allow-private-instances Both transports; same mechanism. Never permits a cloud metadata address
GITLAB_MCP_TELEMETRY --telemetry Both transports
GITLAB_MCP_TELEMETRY_IDENTITY --telemetry-identity Both transports
GITLAB_MCP_TELEMETRY_IDENTITY_KEY (none) Environment only, on purpose: process arguments are readable through /proc
GITLAB_MCP_TELEMETRY_IDENTITY_ROTATION --telemetry-identity-rotation Both transports
GITLAB_MCP_TELEMETRY_TOOL_NAME --telemetry-tool-name Both transports
GITLAB_MCP_STDIO_MAX_LINE_BYTES (none) stdio only; the HTTP counterpart of the same ceiling is --max-request-body-bytes
GITLAB_MCP_MAX_LISTEN_STREAMS (none) Both transports; environment only
GITLAB_MCP_ALLOWED_UPLOAD_DIRS, GITLAB_MCP_ALLOWED_DOWNLOAD_DIRS, GITLAB_MCP_ALLOWED_IMPORT_DIRS (none) stdio only; a server reached over HTTP refuses every caller-supplied local path whatever these say

See Also