gitlab-mcp-server is configured through environment variables. A .env file in the current directory is loaded automatically (via godotenv), and the server also loads ~/.gitlab-mcp-server.env as a fallback for secrets written by the Setup Wizard.
Diátaxis type: Reference Audience: 👤🔧 All users Prerequisites: A running GitLab instance with a Personal Access Token 📖 User documentation: See the Configuration on the documentation site for a user-friendly version.
Using in CI/CD? See the CI/CD Usage guide for pipeline-specific setup with Project Access Tokens.
These are the settings every user needs to get started.
| Variable | Description | Example |
|---|---|---|
GITLAB_TOKEN |
Personal Access Token with api scope |
glpat-xxxxxxxxxxxxxxxxxxxx |
| Variable | Default | Description |
|---|---|---|
GITLAB_URL |
https://gitlab.com |
GitLab instance base URL. Set this for self-managed instances |
GITLAB_SKIP_TLS_VERIFY |
false |
Skip TLS certificate verification for self-signed certs |
TOOL_SURFACE |
dynamic |
Canonical tool catalog selector: dynamic, meta, or individual |
META_TOOLS |
(legacy) | Deprecated compatibility selector. Accepted values map to TOOL_SURFACE: true -> meta, false -> individual, and dynamic -> dynamic. Ignored when TOOL_SURFACE is set |
CAPABILITY_SURFACE |
full |
Resource and prompt catalog selector: full preserves all resources, workflow guides, prompts, and the surface-aware gitlab://tools manifest; minimal keeps the gitlab://tools manifest only |
META_PARAM_SCHEMA |
opaque |
Meta-tool input-schema strategy: opaque (compact envelope), compact, or full. Applies to meta-tool tools/list schemas only. See Environment Variables |
GITLAB_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_ENTERPRISE |
(unset) | Deprecated — use GITLAB_TIER. Honored only when GITLAB_TIER is unset: true → ultimate, false → free. Emits a deprecation warning |
GITLAB_READ_ONLY |
false |
Read-only mode: disables all mutating tools at startup |
GITLAB_SAFE_MODE |
false |
Safe mode: intercepts mutating tools and returns a JSON preview instead of executing. Read-only tools work normally. If GITLAB_READ_ONLY=true, it takes precedence |
EMBEDDED_RESOURCES |
true |
Embed canonical gitlab:// MCP resource URIs as EmbeddedResource content blocks in gitlab_*_get tool results. Set false to disable for clients that don't tolerate duplicate content blocks |
EXCLUDE_TOOLS |
(empty) | Comma-separated list of tool names to exclude from registration |
GITLAB_IGNORE_SCOPES |
false |
Skip PAT scope detection and register all tools regardless of token permissions |
UPLOAD_MAX_FILE_SIZE |
2GB |
Maximum file size for upload and file tools. Supports human-friendly suffixes (KB, MB, GB, case-insensitive). Upper bound: 1 TB |
LOG_LEVEL |
info |
Logging verbosity: debug, info, warn, error |
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
GITLAB_SKIP_TLS_VERIFY=false
TOOL_SURFACE=dynamic
GITLAB_READ_ONLY=false
GITLAB_SAFE_MODE=false
EMBEDDED_RESOURCES=true
UPLOAD_MAX_FILE_SIZE=2GB
LOG_LEVEL=infoFor self-managed GitLab, add GITLAB_URL=https://gitlab.example.com.
Security: The
.envfile is gitignored. Never commit tokens or credentials.
The easiest way to configure gitlab-mcp-server is through the built-in Setup Wizard. It installs the binary, configures your GitLab connection, and writes MCP client config files — all in one step.
# Run the wizard (auto-detects best UI: web → TUI → CLI)
gitlab-mcp-server --setup
# Or force a specific UI mode
gitlab-mcp-server --setup --setup-mode web # Opens browser-based UI
gitlab-mcp-server --setup --setup-mode tui # Terminal UI (Bubble Tea)
gitlab-mcp-server --setup --setup-mode cli # Plain text fallbackOn Windows, double-click the .exe — if no GITLAB_TOKEN is set, the wizard starts automatically.
The wizard supports 10 MCP clients: VS Code (GitHub Copilot), Claude Desktop, Claude Code (CLI), Cursor, Windsurf (Codeium), JetBrains IDEs, Copilot CLI, OpenCode, Crush (Charm), and Zed.
Stdio only: The wizard configures the stdio MCP server only — it does not configure the long-running HTTP server (OAuth mode, session timeout, max HTTP clients, etc.). For shared or remote HTTP deployments, use HTTP Server Mode instead.
Pre-loading existing configuration: If ~/.gitlab-mcp-server.env already exists, every UI mode (web, TUI, CLI) loads it before showing the form. Saved values for GitLab URL, token, catalog mode, safety flags, auto-update, rate limits, log level, and other advanced options are pre-selected. Leave the token field blank to keep the stored token; enter a new value only to rotate it. This makes re-running --setup a way to tweak one or two fields without re-typing everything.
Inline help (Web UI only): The Web UI attaches a tooltip to every advanced option explaining what the setting does, its default, and the trade-off. Hover or focus the ? button next to any label to see it.
Secure secret storage: The wizard writes the stdio server configuration, including GITLAB_URL, GITLAB_TOKEN, TLS, catalog, safety, upload, rate-limit, and auto-update options, to ~/.gitlab-mcp-server.env (with 0600 permissions on Unix). Most client config files only contain non-secret launch preferences and references to that env file where supported. GenerateEntry(ClientJetBrains, ...) is the compatibility exception: JetBrains cannot reference the shared env file, so the display-only JSON snippet includes the full env map, including secrets. Prefer an auto-written client config when possible; if you use the JetBrains snippet, store it with local-only permissions and rotate the token if the snippet is exposed.
For per-client setup instructions (VS Code, Claude Desktop, Cursor, Claude Code, Windsurf, JetBrains, Zed, Kiro), see Getting Started.
For HTTP mode (remote/multi-user), see HTTP Server Mode.
Instead of hardcoding GITLAB_TOKEN directly in the MCP client JSON configuration, you can use the secure mechanisms provided by each client.
VS Code input variables prompt you for the token on first server start and store the value securely. Use ${input:variable-id} in any env value:
VS Code supports loading all environment variables from a file on disk via the envFile property. This keeps secrets out of the JSON entirely:
{
"servers": {
"gitlab": {
"type": "stdio",
"command": "/usr/local/bin/gitlab-mcp-server",
"envFile": "${userHome}/.gitlab-mcp-server.env"
}
}
}Where ~/.gitlab-mcp-server.env (or any path you choose) contains:
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
GITLAB_SKIP_TLS_VERIFY=true
TOOL_SURFACE=metaAdd GITLAB_URL=https://gitlab.example.com for self-managed GitLab.
Tip: You can combine
envFilewithenv— values inenvoverride those fromenvFile.
Copilot CLI reads MCP server configuration from environment variables. Set the token at the OS level:
Linux / macOS — add to ~/.bashrc, ~/.zshrc, or equivalent:
export GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"Windows — set via PowerShell (persistent, user-level):
[Environment]::SetEnvironmentVariable('GITLAB_TOKEN', 'glpat-xxxxxxxxxxxxxxxxxxxx', 'User')Then restart your terminal. The MCP server inherits system environment variables.
OpenCode uses its own MCP configuration file. Add the server with environment variables inline, or set the token as a system environment variable (see above) to keep it out of the config file.
Cursor uses the mcpServers configuration format. Set the token as a system environment variable (see above) and omit it from .cursor/mcp.json, or keep it hardcoded for local-only use.
See Security for additional token management best practices.
These settings are for operators deploying the server for a team or managing advanced behaviors. Most users can skip this section entirely.
This table summarizes the most common operational variables. For the complete source-of-truth list, see Environment Variable Reference; for HTTP flags, see CLI Reference.
| Variable | Default | Description |
|---|---|---|
AUTO_UPDATE |
true |
Enable automatic binary updates (true/check/false) |
AUTO_UPDATE_REPO |
jmrplens/gitlab-mcp-server |
GitHub repository for release assets |
AUTO_UPDATE_INTERVAL |
1h |
Interval between periodic update checks (HTTP mode background checks only) |
AUTO_UPDATE_TIMEOUT |
60s |
Timeout for startup/background update checks (range: 5s–10m) |
YOLO_MODE |
false |
Skip destructive action confirmation prompts |
AUTOPILOT |
false |
Same as YOLO_MODE — skip confirmation prompts |
AUTH_MODE |
legacy |
HTTP mode authentication: legacy (per-request header) or oauth (RFC 9728 Bearer token verification) |
OAUTH_CACHE_TTL |
15m |
TTL for verified OAuth token identity cache (min 1m, max 2h) |
RATE_LIMIT_RPS |
0 |
Per-server tools/call rate limit in requests/second (0 = disabled) |
RATE_LIMIT_BURST |
40 |
Token-bucket burst size when RATE_LIMIT_RPS > 0 |
See Auto-Update for detailed documentation on update modes, MCP tools, release requirements, and troubleshooting.
| Mode | Variable | Tools Exposed | Best For |
|---|---|---|---|
| Dynamic toolset (default) | TOOL_SURFACE=dynamic |
gitlab_find_action, gitlab_execute_action |
Most users — lowest startup context while retaining full catalog reachability |
| Meta-tools | TOOL_SURFACE=meta |
32 base / 48 self-managed enterprise / 49 GitLab.com Enterprise | Clients that prefer consolidated domain dispatchers with action parameters |
| Individual tools | TOOL_SURFACE=individual |
893 CE / 1061 self-managed enterprise / 1067 GitLab.com Enterprise | Clients that need granular tool selection |
Use the default dynamic surface for normal low-token deployments. Set TOOL_SURFACE=meta only when a client or workflow prefers domain meta-tools. META_TOOLS remains accepted for compatibility only and should appear only in migration guidance.
See Meta-Tools for the complete domain-action mapping and Dynamic Toolset for the low-token find/execute workflow.
META_PARAM_SCHEMA controls only the visible inputSchema of meta-tool dispatchers in tools/list. It does not change handler validation, execution, dynamic find output, or the gitlab://tools manifest contents.
| Tool surface | Visible tool schema impact | Tool manifest availability | Dynamic describe behavior | Token impact | Recommended use |
|---|---|---|---|---|---|
meta |
Applies to every visible domain meta-tool. opaque shows {action, params}; compact and full inline per-action oneOf schemas |
gitlab://tools and gitlab://tools/{id} in full or minimal |
Not applicable | full is 11.9x larger than opaque; compact is 6.5x larger |
Keep opaque; use gitlab://tools for exact params |
dynamic |
Does not change the two dynamic tool schemas | gitlab://tools and gitlab://tools/{id} in full or minimal |
gitlab_find_action returns discovery and schema details inline |
No practical startup benefit for Dynamic tool schemas | Keep opaque; use find or gitlab://tools |
individual |
Ignored because individual tools expose one operation per tool with direct typed schemas | gitlab://tools and gitlab://tools/{id} in full or minimal |
Not applicable | None | Leave unset |
The evaluated modes remain opaque, compact, and full. The setting name remains valid for the final architecture because it describes the meta-tool dispatcher envelope, while the action catalog remains the source of the underlying per-action schemas.
CAPABILITY_SURFACE=full is the default and preserves the existing MCP resources and prompts catalog. CAPABILITY_SURFACE=minimal is a non-default low-token mode: it keeps gitlab://tools for surface-aware action discovery, and omits static GitLab data resources, workflow guide resources, and prompt templates. Dynamic execution still works without reading resources because gitlab_find_action returns exact action schemas inline.
Measured startup context is the reason this setting keeps only two modes for now: full resources plus prompts cost about 18.2k tokens, while minimal keeps the shared capability overhead low by advertising only the unified tool manifest. Candidate intermediate modes such as schemas, resources, or docs would add another configuration axis without beating the existing low-token workflows. Reconsider an intermediate mode only if future audits show a concrete client that needs more resources but cannot tolerate prompts or static resources.
When running the server for multiple users, use HTTP mode. Configuration comes from CLI flags instead of environment variables:
| Flag | Default | Description |
|---|---|---|
--http |
(off) | Enable HTTP transport mode |
--http-addr |
:8080 |
HTTP listen address |
--gitlab-url |
(optional) | Fixed GitLab instance URL. Omit it to require each client to send GITLAB-URL per request |
--skip-tls-verify |
false |
Skip TLS certificate verification |
--tool-surface |
dynamic |
Canonical tool catalog selector: dynamic, meta, or individual |
--meta-tools |
(unset) | Deprecated compatibility flag. Use --tool-surface=individual instead of --meta-tools=false |
--capability-surface |
full |
Resource and prompt catalog selector: full or minimal |
--meta-param-schema |
opaque |
Meta-tool input-schema strategy: opaque, compact, or full |
--tier |
(detected) | Force the licensing tier: free, ce, premium, or ultimate. When set, used verbatim with no license check. When omitted, HTTP mode detects the tier per token+URL pool entry from the instance license (fallback free) |
--max-http-clients |
100 |
Maximum concurrent client sessions |
--session-timeout |
30m |
Idle session timeout |
--http-idle-timeout |
0 (disabled) |
HTTP server idle connection timeout. Default 0 disables idle connection closure, so --session-timeout is the effective session lifetime; set a positive duration to recycle idle connections sooner |
--auth-mode |
legacy |
Authentication mode: legacy (per-request header) or oauth (RFC 9728 Bearer token verification) |
--oauth-cache-ttl |
15m |
TTL for verified OAuth token cache (1m–2h) |
--revalidate-interval |
15m |
Interval for OAuth token re-validation against GitLab (0 disables; upper bound 24h) |
--trusted-proxy-header |
(empty) | Header containing the real client IP when behind a reverse proxy (e.g. Fly-Client-IP, X-Real-IP, X-Forwarded-For). Used by the per-IP auth rate limiter |
--auto-update |
true |
Enable automatic binary updates |
--auto-update-repo |
jmrplens/gitlab-mcp-server |
GitHub repository for release assets |
--auto-update-interval |
1h |
Interval between periodic update checks |
--auto-update-timeout |
60s |
Timeout for startup/background update checks (range: 5s–10m) |
--read-only |
false |
Expose only read-only tools |
--safe-mode |
false |
Intercept mutating tools, return preview |
--embedded-resources |
true |
Embed canonical gitlab:// MCP resource URIs as EmbeddedResource content blocks in gitlab_*_get tool results |
--rate-limit-rps |
0 |
Per-server tools/call rate limit in req/s (0 = disabled) |
--rate-limit-burst |
40 |
Token-bucket burst size when --rate-limit-rps > 0 |
--exclude-tools |
(empty) | Comma-separated tool names to exclude |
--ignore-scopes |
false |
Skip PAT scope detection |
No GITLAB_TOKEN is needed at startup — each client provides its own token per-request via PRIVATE-TOKEN header or Authorization: Bearer. Clients can specify a GITLAB-URL header only when the server starts without --gitlab-url; when --gitlab-url is configured, it is authoritative and client-provided GITLAB-URL values are ignored and logged.
To enable server-side token verification, set --auth-mode=oauth:
gitlab-mcp-server --http \
--gitlab-url=https://gitlab.com \
--auth-mode=oauth \
--oauth-cache-ttl=15mReplace https://gitlab.com with your self-managed GitLab URL when needed.
With OAuth mode:
- All tokens are verified against GitLab's
/api/v4/userendpoint before reaching the MCP handler - Verified tokens are cached (SHA-256 hashed) for
--oauth-cache-ttlduration (default 15m, range 1m–2h) - An RFC 9728 metadata endpoint is served at
/.well-known/oauth-protected-resource, enabling MCP clients with OAuth 2.1 support to discover the GitLab authorization server automatically PRIVATE-TOKENheaders are auto-converted toAuthorization: Bearerfor compatibility
For a complete guide on creating GitLab OAuth applications for your MCP clients, see OAuth App Setup.
See HTTP Server Mode for architecture and deployment details.
These features are always active and require no configuration:
| Feature | Description |
|---|---|
| Content annotations | All Markdown content is annotated with audience and priority — ContentList (priority 0.4), ContentDetail (0.6), ContentMutate (0.8). This helps MCP clients optimize display and prevents raw Markdown from duplicating the JSON output |
| Clickable links | List results in 14 domains include [text](url) links to GitLab entities (MRs, issues, pipelines, etc.) |
| Next-step hints | Every list/detail/mutation response includes 💡 Next steps suggestions. In meta-tool mode, these are also injected into the JSON structuredContent as a next_steps array |
| Formatted dates | All timestamps are displayed in readable format (2025-01-15 10:30) instead of raw ISO 8601 |
See Output Format for details.
Configuration is loaded by internal/config/ in this order:
.envfile in the current directory (if present) viagodotenv~/.gitlab-mcp-server.envin the user's home directory (fallback for wizard-managed secrets)- Environment variables (override both
.envfiles) - Command-line flags (
--http,--http-addr)
Note:
godotenvdoes not overwrite existing variables, so values from step 1 take precedence over step 2, and explicit environment variables (step 3) override both.
The config.Load() function validates that GITLAB_TOKEN is set and defaults GITLAB_URL to https://gitlab.com when it is omitted (stdio mode only). In HTTP mode, configuration comes from CLI flags and no token is required at startup — each client provides its own token per-request via PRIVATE-TOKEN or Authorization: Bearer headers. Clients can provide GITLAB-URL only in multi-instance mode, when the server starts without --gitlab-url; all other MCP server settings are process policy and cannot be overridden per request. When --auth-mode=oauth, the server validates tokens against the GitLab /api/v4/user endpoint and caches verified identities with a configurable TTL (see HTTP Server Mode — OAuth Mode).
{ "inputs": [ { "type": "promptString", "id": "gitlab-token", "description": "GitLab Personal Access Token", "password": true } ], "servers": { "gitlab": { "type": "stdio", "command": "/usr/local/bin/gitlab-mcp-server", "env": { "GITLAB_TOKEN": "${input:gitlab-token}", "TOOL_SURFACE": "meta" } } } }