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.
- package/.dockerignore +7 -0
- package/.editorconfig +9 -0
- package/.env.example +75 -0
- package/.github/workflows/nodejs.yml +31 -0
- package/.github/workflows/npm-publish.yml +31 -0
- package/.husky/pre-commit +1 -0
- package/.nvmrc +1 -0
- package/.prettierrc.json +6 -0
- package/Dockerfile +20 -0
- package/README.md +416 -251
- package/docker-compose.yml +10 -0
- package/docs/architecture.md +310 -0
- package/docs/authentication.md +299 -0
- package/docs/configuration.md +149 -0
- package/docs/deployment.md +336 -0
- package/docs/tools.md +294 -0
- package/eslint.config.js +23 -0
- package/package.json +78 -32
- package/scripts/get-oauth-token.example.sh +15 -0
- package/src/config/env.ts +171 -0
- package/src/http.ts +620 -0
- package/src/index.ts +77 -0
- package/src/lib/auth-context.ts +19 -0
- package/src/lib/gitlab-client.ts +1810 -0
- package/src/lib/logger.ts +17 -0
- package/src/lib/network.ts +45 -0
- package/src/lib/oauth.ts +287 -0
- package/src/lib/output.ts +51 -0
- package/src/lib/policy.ts +78 -0
- package/src/lib/request-runtime.ts +376 -0
- package/src/lib/sanitize.ts +25 -0
- package/src/lib/session-capacity.ts +14 -0
- package/src/server/build-server.ts +17 -0
- package/src/tools/gitlab.ts +3135 -0
- package/src/tools/health.ts +27 -0
- package/src/tools/mr-code-context.ts +473 -0
- package/src/types/context.ts +13 -0
- package/tests/auth-context.test.ts +102 -0
- package/tests/gitlab-client.test.ts +672 -0
- package/tests/graphql-guard.test.ts +121 -0
- package/tests/integration/agent-loop.integration.test.ts +558 -0
- package/tests/integration/server.integration.test.ts +543 -0
- package/tests/mr-code-context.test.ts +600 -0
- package/tests/oauth.test.ts +43 -0
- package/tests/output.test.ts +186 -0
- package/tests/policy.test.ts +324 -0
- package/tests/request-runtime.test.ts +252 -0
- package/tests/sanitize.test.ts +123 -0
- package/tests/session-capacity.test.ts +49 -0
- package/tests/upload-reference.test.ts +88 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +12 -0
- package/LICENSE +0 -21
- package/build/index.js +0 -1642
- package/build/schemas.js +0 -684
- 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
|
+
```
|