Skip to content

HTTP Server Mode

By default, GitLab MCP Server runs in stdio mode — each AI client spawns its own server process. HTTP mode is an alternative where a single server process serves multiple clients over the network, each authenticating with their own GitLab token.

ScenarioRecommended Mode
Single developer, local AI clientstdio
Team sharing one server instanceHTTP
Remote/headless server deploymentHTTP
CI/CD integration with MCPHTTP
Testing with curl or HTTP clientsHTTP
Terminal window
gitlab-mcp-server --http --gitlab-url=https://your-gitlab.example.com

The server starts listening on port 8080 by default. The MCP endpoint is available at /mcp.

FlagDefaultDescription
--http(off)Enable HTTP transport mode
--http-addr:8080HTTP listen address (host:port)
--gitlab-url(required)GitLab instance base URL
--skip-tls-verifyfalseSkip TLS certificate verification for self-signed certs
--meta-toolstrueEnable domain meta-tools (42 or 57 with —enterprise)
--enterprisefalseEnable Enterprise/Premium tools (35 individual + 15 meta-tools)
--read-onlyfalseRead-only mode: disable all mutating tools
--max-http-clients100Maximum unique tokens in the server pool
--session-timeout30mIdle MCP session timeout
--auto-updatetrueAuto-update mode: true, check, or false
--auto-update-repojmrplens/gitlab-mcp-serverGitHub repository for release assets
--auto-update-interval1hPeriodic update check interval
--auth-modelegacyAuthentication mode: legacy or oauth (RFC 9728)
--oauth-cache-ttl15mOAuth token identity cache TTL (range: 1m–2h)

Clients must provide their GitLab Personal Access Token on every HTTP request using one of two headers:

PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx
Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx

If both headers are present, PRIVATE-TOKEN takes precedence. Requests without a valid token are rejected.

OAuth mode (--auth-mode=oauth) enables RFC 9728–compliant OAuth 2.1 authentication. Instead of managing tokens manually, MCP clients discover the authorization server automatically and handle the OAuth flow:

Terminal window
gitlab-mcp-server --http --gitlab-url=https://gitlab.example.com --auth-mode=oauth

How it works:

  1. The server exposes /.well-known/oauth-protected-resource with metadata pointing to your GitLab instance as the authorization server
  2. MCP clients (VS Code, Claude Code) discover this endpoint and initiate the OAuth 2.1 PKCE flow
  3. Users authorize in the browser — no token copying required
  4. The server validates Bearer tokens against the GitLab API and caches the identity for --oauth-cache-ttl (default: 15 minutes)

Client configuration in OAuth mode:

{
"servers": {
"gitlab": {
"type": "http",
"url": "http://your-server:8080/mcp",
"oauth": {
"clientId": "YOUR_GITLAB_APPLICATION_ID",
"scopes": ["api"]
}
}
}
}
  • clientId: The Application ID from your GitLab OAuth Application (see docs/oauth-app-setup.md)
  • scopes: Must include api for full tool functionality

VS Code handles OAuth discovery and authorization automatically.

The core of HTTP mode is a bounded LRU pool of MCP server instances, keyed by the SHA-256 hash of each client’s token.

graph TD
    subgraph "HTTP Mode Architecture"
        REQ1["Client A<br/>Token: glpat-aaa"] --> HANDLER[StreamableHTTPHandler]
        REQ2["Client B<br/>Token: glpat-bbb"] --> HANDLER
        REQ3["Client C<br/>Token: glpat-aaa"] --> HANDLER

        HANDLER --> POOL[Server Pool]

        POOL --> ENTRY1["hash(glpat-aaa)<br/>MCP Server + GitLab Client"]
        POOL --> ENTRY2["hash(glpat-bbb)<br/>MCP Server + GitLab Client"]
    end

    ENTRY1 --> GL1["GitLab API<br/>as user A"]
    ENTRY2 --> GL2["GitLab API<br/>as user B"]

Key properties:

  • Clients with the same token share the same MCP server instance
  • Clients with different tokens get completely isolated instances
  • Raw tokens are never stored — only SHA-256 hashes are kept in memory
  • When the pool reaches --max-http-clients, the least recently used entry is evicted
  1. First request: Token is extracted, hashed, and a new MCP server + GitLab client is created
  2. Subsequent requests: The existing entry is found and promoted in the LRU list
  3. Idle timeout: After --session-timeout of inactivity, the MCP session is closed (but the pool entry remains)
  4. Pool eviction: When capacity is reached, the oldest entry is removed entirely

Add to .vscode/mcp.json:

{
"servers": {
"gitlab": {
"type": "http",
"url": "http://your-server:8080/mcp",
"headers": {
"PRIVATE-TOKEN": "glpat-your-token"
}
}
}
}
services:
gitlab-mcp:
image: ghcr.io/jmrplens/gitlab-mcp-server:latest
ports:
- "8080:8080"
command:
- "--http"
- "--gitlab-url=https://gitlab.example.com"
- "--http-addr=:8080"
- "--max-http-clients=200"
- "--session-timeout=1h"
restart: unless-stopped

Start the service:

Terminal window
docker compose up -d

You can verify the server is running by sending a tools/list request:

Terminal window
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "PRIVATE-TOKEN: glpat-your-token" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}' | head -c 200

A successful response returns a JSON-RPC result with the list of available tools.