gitlab-mcp 0.1.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.dockerignore +7 -0
  2. package/.editorconfig +9 -0
  3. package/.env.example +75 -0
  4. package/.github/workflows/nodejs.yml +31 -0
  5. package/.github/workflows/npm-publish.yml +31 -0
  6. package/.husky/pre-commit +1 -0
  7. package/.nvmrc +1 -0
  8. package/.prettierrc.json +6 -0
  9. package/Dockerfile +20 -0
  10. package/README.md +416 -251
  11. package/docker-compose.yml +10 -0
  12. package/docs/architecture.md +310 -0
  13. package/docs/authentication.md +299 -0
  14. package/docs/configuration.md +149 -0
  15. package/docs/deployment.md +336 -0
  16. package/docs/tools.md +294 -0
  17. package/eslint.config.js +23 -0
  18. package/package.json +78 -32
  19. package/scripts/get-oauth-token.example.sh +15 -0
  20. package/src/config/env.ts +171 -0
  21. package/src/http.ts +620 -0
  22. package/src/index.ts +77 -0
  23. package/src/lib/auth-context.ts +19 -0
  24. package/src/lib/gitlab-client.ts +1810 -0
  25. package/src/lib/logger.ts +17 -0
  26. package/src/lib/network.ts +45 -0
  27. package/src/lib/oauth.ts +287 -0
  28. package/src/lib/output.ts +51 -0
  29. package/src/lib/policy.ts +78 -0
  30. package/src/lib/request-runtime.ts +376 -0
  31. package/src/lib/sanitize.ts +25 -0
  32. package/src/lib/session-capacity.ts +14 -0
  33. package/src/server/build-server.ts +17 -0
  34. package/src/tools/gitlab.ts +3135 -0
  35. package/src/tools/health.ts +27 -0
  36. package/src/tools/mr-code-context.ts +473 -0
  37. package/src/types/context.ts +13 -0
  38. package/tests/auth-context.test.ts +102 -0
  39. package/tests/gitlab-client.test.ts +672 -0
  40. package/tests/graphql-guard.test.ts +121 -0
  41. package/tests/integration/agent-loop.integration.test.ts +558 -0
  42. package/tests/integration/server.integration.test.ts +543 -0
  43. package/tests/mr-code-context.test.ts +600 -0
  44. package/tests/oauth.test.ts +43 -0
  45. package/tests/output.test.ts +186 -0
  46. package/tests/policy.test.ts +324 -0
  47. package/tests/request-runtime.test.ts +252 -0
  48. package/tests/sanitize.test.ts +123 -0
  49. package/tests/session-capacity.test.ts +49 -0
  50. package/tests/upload-reference.test.ts +88 -0
  51. package/tsconfig.build.json +11 -0
  52. package/tsconfig.json +21 -0
  53. package/vitest.config.ts +12 -0
  54. package/LICENSE +0 -21
  55. package/build/index.js +0 -1642
  56. package/build/schemas.js +0 -684
  57. package/build/test-note.js +0 -54
@@ -0,0 +1,149 @@
1
+ # Configuration Reference
2
+
3
+ All configuration is done through environment variables. The server validates all values at startup using [Zod](https://zod.dev/) schemas and will fail fast with descriptive errors if any value is invalid.
4
+
5
+ You can set variables in a `.env` file (loaded automatically via `dotenv`) or pass them directly as environment variables.
6
+
7
+ ## Core Settings
8
+
9
+ | Variable | Type | Default | Description |
10
+ | -------------------- | ------------------------------------------------------------------------ | ------------- | -------------------------------------------------------- |
11
+ | `NODE_ENV` | `development` \| `test` \| `production` | `development` | Runtime environment. Affects error detail mode defaults. |
12
+ | `LOG_LEVEL` | `fatal` \| `error` \| `warn` \| `info` \| `debug` \| `trace` \| `silent` | `info` | Pino log level. |
13
+ | `MCP_SERVER_NAME` | string | `gitlab-mcp` | Server name reported in MCP handshake. |
14
+ | `MCP_SERVER_VERSION` | string | `0.1.0` | Server version reported in MCP handshake. |
15
+
16
+ ## GitLab API
17
+
18
+ | Variable | Type | Default | Description |
19
+ | ------------------------------ | ------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
20
+ | `GITLAB_API_URL` | string | `https://gitlab.com/api/v4` | Base API URL. Supports **comma-separated** URLs for multi-instance rotation. Each URL is automatically normalized to end with `/api/v4`. |
21
+ | `GITLAB_PERSONAL_ACCESS_TOKEN` | string | — | Static default token for requests in default mode (`REMOTE_AUTHORIZATION=false`). If omitted, runtime can still resolve OAuth/script/file tokens. |
22
+
23
+ ### Multi-Instance Example
24
+
25
+ ```bash
26
+ GITLAB_API_URL=https://gitlab.example.com,https://gitlab-mirror.example.com
27
+ ```
28
+
29
+ The client will normalize each entry and rotate across them for load distribution.
30
+
31
+ ## Authentication
32
+
33
+ ### Personal Access Token
34
+
35
+ | Variable | Type | Default | Description |
36
+ | ------------------------------ | ------ | ------- | ------------------------------------------------------------------- |
37
+ | `GITLAB_PERSONAL_ACCESS_TOKEN` | string | — | Token with `api` scope. Used as the default request token when set. |
38
+
39
+ ### OAuth 2.0 PKCE
40
+
41
+ | Variable | Type | Default | Description |
42
+ | -------------------------------- | ------------ | -------------------------------- | ------------------------------------------------------------------------------ |
43
+ | `GITLAB_USE_OAUTH` | boolean | `false` | Enable OAuth PKCE flow. |
44
+ | `GITLAB_OAUTH_CLIENT_ID` | string | — | **Required** when OAuth is enabled. Application ID from GitLab OAuth settings. |
45
+ | `GITLAB_OAUTH_CLIENT_SECRET` | string | — | Optional. Required only for confidential OAuth applications. |
46
+ | `GITLAB_OAUTH_GITLAB_URL` | string | derived from `GITLAB_API_URL` | GitLab base URL for OAuth endpoints (e.g. `https://gitlab.com`). |
47
+ | `GITLAB_OAUTH_REDIRECT_URI` | string (URL) | `http://127.0.0.1:8765/callback` | Local callback URL for the OAuth flow. |
48
+ | `GITLAB_OAUTH_SCOPES` | string | `api` | Space or comma-separated OAuth scopes. |
49
+ | `GITLAB_OAUTH_TOKEN_PATH` | string | `~/.gitlab-mcp-oauth-token.json` | File path for persisting OAuth tokens. Stored with `chmod 600`. |
50
+ | `GITLAB_OAUTH_AUTO_OPEN_BROWSER` | boolean | `true` | Automatically open the browser for authorization. |
51
+
52
+ ### External Token Script
53
+
54
+ | Variable | Type | Default | Description |
55
+ | -------------------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
56
+ | `GITLAB_TOKEN_SCRIPT` | string | — | Shell command to execute for obtaining a token. Must output either a raw token string or JSON (`{"access_token":"..."}`, `{"token":"..."}`, or `{"private_token":"..."}`). |
57
+ | `GITLAB_TOKEN_SCRIPT_TIMEOUT_MS` | number | `10000` | Script execution timeout (500ms–120s). |
58
+ | `GITLAB_TOKEN_CACHE_SECONDS` | number | `300` | How long to cache the resolved token (0–86400s). |
59
+
60
+ ### Token File
61
+
62
+ | Variable | Type | Default | Description |
63
+ | ---------------------------------- | ------- | ------- | ---------------------------------------------------------------------------------------------- |
64
+ | `GITLAB_TOKEN_FILE` | string | — | Path to a file containing a token. Supports `~/` prefix. |
65
+ | `GITLAB_ALLOW_INSECURE_TOKEN_FILE` | boolean | `false` | Allow token files with group/other read permissions. By default, the file must be `chmod 600`. |
66
+
67
+ ### Cookie-Based Auth
68
+
69
+ | Variable | Type | Default | Description |
70
+ | --------------------------- | ------ | ------- | -------------------------------------------------------------------- |
71
+ | `GITLAB_AUTH_COOKIE_PATH` | string | — | Path to a Netscape-format cookie file. Auto-reloads on file changes. |
72
+ | `GITLAB_COOKIE_WARMUP_PATH` | string | `/user` | API path used for session warmup when cookies are loaded. |
73
+
74
+ ### Remote Authorization (HTTP Mode)
75
+
76
+ | Variable | Type | Default | Description |
77
+ | ------------------------ | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |
78
+ | `REMOTE_AUTHORIZATION` | boolean | `false` | Require per-request tokens via `Authorization` (Bearer) or `Private-Token` headers for HTTP requests. Disables fallback auth chain. |
79
+ | `ENABLE_DYNAMIC_API_URL` | boolean | `false` | Require per-request API URL via `X-GitLab-API-URL` header. Requires `REMOTE_AUTHORIZATION=true`. |
80
+
81
+ ## Policy
82
+
83
+ | Variable | Type | Default | Description |
84
+ | ----------------------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
85
+ | `GITLAB_READ_ONLY_MODE` | boolean | `false` | Disable all mutating tools (create, update, delete, merge, etc.). |
86
+ | `GITLAB_ALLOWED_PROJECT_IDS` | string | — | Comma-separated project IDs. If set, only these projects can be accessed. Empty = no restriction. |
87
+ | `GITLAB_ALLOWED_TOOLS` | string | — | Comma-separated tool allowlist. Accepts names with or without `gitlab_` prefix (e.g. `get_project` or `gitlab_get_project`). Empty = all tools enabled. |
88
+ | `GITLAB_DENIED_TOOLS_REGEX` | string | — | Regex pattern to deny tools by name (example: `^gitlab_delete_`). |
89
+ | `GITLAB_ALLOW_GRAPHQL_WITH_PROJECT_SCOPE` | boolean | `false` | Keep GraphQL tools enabled when `GITLAB_ALLOWED_PROJECT_IDS` is set. By default, GraphQL tools are disabled in project-scoped mode. |
90
+
91
+ ## Feature Toggles
92
+
93
+ | Variable | Type | Default | Description |
94
+ | ----------------- | ------- | ------- | ------------------------------- |
95
+ | `USE_GITLAB_WIKI` | boolean | `true` | Enable wiki-related tools. |
96
+ | `USE_MILESTONE` | boolean | `true` | Enable milestone-related tools. |
97
+ | `USE_PIPELINE` | boolean | `true` | Enable pipeline and job tools. |
98
+ | `USE_RELEASE` | boolean | `true` | Enable release-related tools. |
99
+
100
+ ## Output
101
+
102
+ | Variable | Type | Default | Description |
103
+ | --------------------------- | ---------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
104
+ | `GITLAB_RESPONSE_MODE` | `json` \| `compact-json` \| `yaml` | `json` | Response serialization format. `compact-json` omits indentation. |
105
+ | `GITLAB_MAX_RESPONSE_BYTES` | number | `200000` | Maximum response size in bytes (1,024–2,000,000). Responses exceeding this limit are truncated with a `[truncated N bytes]` suffix. |
106
+ | `GITLAB_HTTP_TIMEOUT_MS` | number | `20000` | GitLab API request timeout in milliseconds (1,000–120,000). |
107
+ | `GITLAB_ERROR_DETAIL_MODE` | `safe` \| `full` | `safe` in production, `full` otherwise | Controls error response verbosity. `safe` returns only the error message; `full` includes upstream details. |
108
+
109
+ ## Network
110
+
111
+ | Variable | Type | Default | Description |
112
+ | ------------------------------ | ------- | ---------------- | ----------------------------------------------------------------------------------------------------------------- |
113
+ | `HTTP_PROXY` | string | — | HTTP proxy URL. |
114
+ | `HTTPS_PROXY` | string | — | HTTPS proxy URL. Takes precedence over `HTTP_PROXY` for HTTPS requests. |
115
+ | `GITLAB_CA_CERT_PATH` | string | — | Path to a custom CA certificate file (PEM format). |
116
+ | `NODE_TLS_REJECT_UNAUTHORIZED` | string | — | Set to `0` to disable TLS verification. **Requires** `GITLAB_ALLOW_INSECURE_TLS=true` as explicit acknowledgment. |
117
+ | `GITLAB_ALLOW_INSECURE_TLS` | boolean | `false` | Acknowledge insecure TLS. Required when `NODE_TLS_REJECT_UNAUTHORIZED=0`. |
118
+ | `GITLAB_CLOUDFLARE_BYPASS` | boolean | `false` | Add browser-like headers (User-Agent, Accept-Language, Cache-Control) to bypass Cloudflare protection. |
119
+ | `GITLAB_USER_AGENT` | string | — | Custom User-Agent header. If not set and `GITLAB_CLOUDFLARE_BYPASS` is enabled, a Chrome-like UA is used. |
120
+ | `GITLAB_ACCEPT_LANGUAGE` | string | `en-US,en;q=0.9` | Accept-Language header (used with Cloudflare bypass). |
121
+
122
+ ## HTTP Server
123
+
124
+ These settings apply only to the HTTP transport (`dist/http.js`).
125
+
126
+ | Variable | Type | Default | Description |
127
+ | ---------------- | ------- | ----------- | ------------------------------------------------------------------------------------------------------------ |
128
+ | `HTTP_HOST` | string | `127.0.0.1` | Bind address. Use `0.0.0.0` to listen on all interfaces. |
129
+ | `HTTP_PORT` | number | `3333` | Listen port (1–65535). |
130
+ | `HTTP_JSON_ONLY` | boolean | `false` | Force JSON-only responses (disable streaming). |
131
+ | `SSE` | boolean | `false` | Enable legacy SSE transport (`GET /sse`, `POST /messages`). Cannot be used with `REMOTE_AUTHORIZATION=true`. |
132
+
133
+ ## Session Management (HTTP Mode)
134
+
135
+ | Variable | Type | Default | Description |
136
+ | ------------------------- | ------ | ------- | -------------------------------------------------------------------------------- |
137
+ | `SESSION_TIMEOUT_SECONDS` | number | `3600` | Idle session TTL in seconds (1–86400). Sessions are garbage-collected every 30s. |
138
+ | `MAX_SESSIONS` | number | `1000` | Maximum concurrent sessions (1–10000). Returns HTTP 503 when exceeded. |
139
+ | `MAX_REQUESTS_PER_MINUTE` | number | `300` | Per-session rate limit (1–10000). Returns HTTP 429 when exceeded. |
140
+
141
+ ## Validation Rules
142
+
143
+ The server enforces these cross-field constraints at startup:
144
+
145
+ - `GITLAB_API_URL` must contain at least one valid URL
146
+ - `GITLAB_USE_OAUTH=true` requires `GITLAB_OAUTH_CLIENT_ID`
147
+ - `ENABLE_DYNAMIC_API_URL=true` requires `REMOTE_AUTHORIZATION=true`
148
+ - `SSE=true` is not compatible with `REMOTE_AUTHORIZATION=true`
149
+ - `NODE_TLS_REJECT_UNAUTHORIZED=0` requires `GITLAB_ALLOW_INSECURE_TLS=true`
@@ -0,0 +1,336 @@
1
+ # Deployment Guide
2
+
3
+ gitlab-mcp can be deployed in several configurations depending on your use case.
4
+
5
+ ## Transport Modes
6
+
7
+ | Mode | Entry Point | Best For |
8
+ | ------------------- | ----------------------------------- | ----------------------------------------------------- |
9
+ | **stdio** | `node dist/index.js` | Local CLI tools (Claude Desktop, Claude Code, Cursor) |
10
+ | **Streamable HTTP** | `node dist/http.js` | Remote deployments, multi-user, shared servers |
11
+ | **SSE** (legacy) | `node dist/http.js` with `SSE=true` | Legacy SSE-only clients |
12
+
13
+ ---
14
+
15
+ ## Local / stdio Mode
16
+
17
+ ### Claude Desktop
18
+
19
+ Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "gitlab": {
25
+ "command": "node",
26
+ "args": ["/absolute/path/to/gitlab-mcp/dist/index.js"],
27
+ "env": {
28
+ "GITLAB_API_URL": "https://gitlab.com/api/v4",
29
+ "GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx"
30
+ }
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ ### Claude Code
37
+
38
+ Add to your Claude Code MCP settings:
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "gitlab": {
44
+ "command": "node",
45
+ "args": ["/absolute/path/to/gitlab-mcp/dist/index.js"],
46
+ "env": {
47
+ "GITLAB_API_URL": "https://gitlab.com/api/v4",
48
+ "GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Cursor / Other MCP Clients
56
+
57
+ Most MCP clients support stdio transport. Use the same configuration pattern — set the command to `node`, args to the dist entry point, and pass environment variables.
58
+
59
+ ---
60
+
61
+ ## HTTP Server Mode
62
+
63
+ ### Basic Setup
64
+
65
+ ```bash
66
+ # Build
67
+ pnpm build
68
+
69
+ # Start HTTP server
70
+ HTTP_HOST=127.0.0.1 HTTP_PORT=3333 node dist/http.js
71
+ ```
72
+
73
+ ### With Remote Authorization
74
+
75
+ For multi-user deployments where each client provides their own GitLab token:
76
+
77
+ ```bash
78
+ REMOTE_AUTHORIZATION=true
79
+ HTTP_HOST=0.0.0.0
80
+ HTTP_PORT=3333
81
+ node dist/http.js
82
+ ```
83
+
84
+ Clients connect with their credentials:
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "gitlab": {
90
+ "url": "http://your-server:3333/mcp",
91
+ "headers": {
92
+ "Authorization": "Bearer glpat-xxxxxxxxxxxxxxxxxxxx"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### Endpoints
100
+
101
+ | Endpoint | Method | Description |
102
+ | ----------- | ----------------- | -------------------------------------- |
103
+ | `/mcp` | POST, GET, DELETE | Streamable HTTP MCP endpoint |
104
+ | `/healthz` | GET | Health check (session count, status) |
105
+ | `/sse` | GET | SSE connection (when `SSE=true`) |
106
+ | `/messages` | POST | SSE message endpoint (when `SSE=true`) |
107
+
108
+ ### Health Check Response
109
+
110
+ ```json
111
+ {
112
+ "status": "ok",
113
+ "server": "gitlab-mcp",
114
+ "activeSessions": 3,
115
+ "activeSseSessions": 0,
116
+ "pendingSessions": 0,
117
+ "maxSessions": 1000,
118
+ "remoteAuthorization": true,
119
+ "readOnlyMode": false,
120
+ "sseEnabled": false
121
+ }
122
+ ```
123
+
124
+ Status is `"degraded"` when session count reaches `MAX_SESSIONS`.
125
+
126
+ ---
127
+
128
+ ## Docker
129
+
130
+ ### Using Docker Compose
131
+
132
+ 1. Create your `.env` file:
133
+
134
+ ```bash
135
+ cp .env.example .env
136
+ # Edit .env with your settings
137
+ ```
138
+
139
+ 2. Start the service:
140
+
141
+ ```bash
142
+ docker compose up --build -d
143
+ ```
144
+
145
+ The HTTP server will be available at `http://127.0.0.1:3333`.
146
+
147
+ ### Using Dockerfile Directly
148
+
149
+ ```bash
150
+ # Build
151
+ docker build -t gitlab-mcp .
152
+
153
+ # Run with environment variables
154
+ docker run -d \
155
+ --name gitlab-mcp \
156
+ -p 3333:3333 \
157
+ -e GITLAB_API_URL=https://gitlab.com/api/v4 \
158
+ -e GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxx \
159
+ -e NODE_ENV=production \
160
+ gitlab-mcp
161
+
162
+ # Or with .env file
163
+ docker run -d \
164
+ --name gitlab-mcp \
165
+ -p 3333:3333 \
166
+ --env-file .env \
167
+ gitlab-mcp
168
+ ```
169
+
170
+ ### Docker Image Details
171
+
172
+ The Dockerfile uses a multi-stage build:
173
+
174
+ 1. **deps** — Install all dependencies
175
+ 2. **build** — Compile TypeScript
176
+ 3. **runtime** — Production image with only production dependencies
177
+
178
+ Base image: `node:22-alpine`
179
+ Exposed port: `3333`
180
+ Entry point: `node dist/http.js`
181
+
182
+ ---
183
+
184
+ ## Production Considerations
185
+
186
+ ### Session Management
187
+
188
+ The HTTP server manages sessions with the following controls:
189
+
190
+ | Setting | Default | Description |
191
+ | ------------------------- | ------- | ---------------------------------------------------------------------- |
192
+ | `SESSION_TIMEOUT_SECONDS` | `3600` | Idle session timeout. Sessions are garbage-collected every 30 seconds. |
193
+ | `MAX_SESSIONS` | `1000` | Maximum concurrent sessions. Returns HTTP 503 when exceeded. |
194
+ | `MAX_REQUESTS_PER_MINUTE` | `300` | Per-session rate limit. Returns HTTP 429 when exceeded. |
195
+
196
+ ### Request Serialization
197
+
198
+ Each session queues requests serially to prevent race conditions. Concurrent requests to the same session are processed in order.
199
+
200
+ ### Error Handling
201
+
202
+ In production, set error detail mode to `safe` to prevent leaking upstream error details:
203
+
204
+ ```bash
205
+ NODE_ENV=production
206
+ # Or explicitly:
207
+ GITLAB_ERROR_DETAIL_MODE=safe
208
+ ```
209
+
210
+ ### Response Size Limits
211
+
212
+ Control response sizes to prevent memory issues:
213
+
214
+ ```bash
215
+ GITLAB_MAX_RESPONSE_BYTES=200000 # 200KB default, range: 1KB–2MB
216
+ ```
217
+
218
+ Responses exceeding this limit are truncated with a `[truncated N bytes]` suffix.
219
+
220
+ ### Logging
221
+
222
+ The server uses [Pino](https://getpino.io/) for structured JSON logging:
223
+
224
+ ```bash
225
+ LOG_LEVEL=info # Options: fatal, error, warn, info, debug, trace, silent
226
+ ```
227
+
228
+ ### Read-Only Mode
229
+
230
+ For safety in production environments:
231
+
232
+ ```bash
233
+ GITLAB_READ_ONLY_MODE=true
234
+ ```
235
+
236
+ This disables all mutating tools (create, update, delete, merge, etc.) at registration time.
237
+
238
+ ### Tool Restrictions
239
+
240
+ Limit the available tools:
241
+
242
+ ```bash
243
+ # Only expose specific tools
244
+ GITLAB_ALLOWED_TOOLS=get_project,list_merge_requests,get_merge_request
245
+
246
+ # Or block tools by pattern
247
+ GITLAB_DENIED_TOOLS_REGEX=^gitlab_(delete|create)_
248
+
249
+ # Restrict to specific projects
250
+ GITLAB_ALLOWED_PROJECT_IDS=123,456
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Multi-Instance Deployment
256
+
257
+ ### Multiple GitLab Instances
258
+
259
+ The server can rotate across multiple GitLab API URLs:
260
+
261
+ ```bash
262
+ GITLAB_API_URL=https://gitlab-primary.example.com,https://gitlab-secondary.example.com
263
+ ```
264
+
265
+ URLs are normalized to `/api/v4` automatically. The client rotates across them for load distribution.
266
+
267
+ ### Dynamic API URL (Per-Request)
268
+
269
+ For serving multiple GitLab instances from a single server:
270
+
271
+ ```bash
272
+ REMOTE_AUTHORIZATION=true
273
+ ENABLE_DYNAMIC_API_URL=true
274
+ ```
275
+
276
+ Clients specify the target GitLab instance via header:
277
+
278
+ ```
279
+ X-GitLab-API-URL: https://other-gitlab.example.com/api/v4
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Reverse Proxy Setup
285
+
286
+ When deploying behind a reverse proxy (nginx, Caddy, etc.):
287
+
288
+ 1. Ensure the proxy passes through `Mcp-Session-Id` headers
289
+ 2. Configure appropriate timeouts for long-running requests
290
+ 3. If using SSE, ensure the proxy supports streaming responses
291
+
292
+ ### nginx Example
293
+
294
+ ```nginx
295
+ location /mcp {
296
+ proxy_pass http://127.0.0.1:3333;
297
+ proxy_set_header Host $host;
298
+ proxy_set_header X-Real-IP $remote_addr;
299
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
300
+ proxy_set_header X-Forwarded-Proto $scheme;
301
+ proxy_read_timeout 120s;
302
+ proxy_buffering off;
303
+ }
304
+
305
+ location /healthz {
306
+ proxy_pass http://127.0.0.1:3333;
307
+ }
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Network Configuration
313
+
314
+ ### Proxy
315
+
316
+ ```bash
317
+ HTTP_PROXY=http://proxy.example.com:8080
318
+ HTTPS_PROXY=http://proxy.example.com:8080
319
+ ```
320
+
321
+ ### Custom CA Certificate
322
+
323
+ For internal PKI or self-signed certificates:
324
+
325
+ ```bash
326
+ GITLAB_CA_CERT_PATH=/etc/ssl/certs/internal-ca.pem
327
+ ```
328
+
329
+ ### Insecure TLS
330
+
331
+ Not recommended for production. Requires explicit acknowledgment:
332
+
333
+ ```bash
334
+ NODE_TLS_REJECT_UNAUTHORIZED=0
335
+ GITLAB_ALLOW_INSECURE_TLS=true
336
+ ```