@zereight/mcp-gitlab 2.0.35 → 2.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/README.md CHANGED
@@ -6,89 +6,60 @@
6
6
 
7
7
  ## @zereight/mcp-gitlab
8
8
 
9
- GitLab MCP(Model Context Protocol) Server. **Includes bug fixes and improvements over the original GitLab MCP server.**
9
+ A comprehensive GitLab MCP server for AI clients. Manage projects, merge requests, issues, pipelines, wiki, releases, milestones, and more through stdio, SSE, and Streamable HTTP.
10
10
 
11
- ## Usage
11
+ Supports PAT, OAuth, read-only mode, dynamic API URLs, and remote authorization for VS Code, Claude, Cursor, Copilot, and other MCP clients.
12
12
 
13
- ### Using with Claude Code, Codex, Antigravity, OpenCode, Copilot, Cline, Roo Code, Cursor, Kilo Code, Amp Code
13
+ ### Why use this GitLab MCP?
14
14
 
15
- When using with the Claude App, you need to set up your API key and URLs directly.
15
+ - Broad GitLab coverage projects, repository browsing, merge requests, issues, pipelines, wiki, releases, labels, milestones, and more
16
+ - Flexible auth — Personal Access Token, local OAuth2 browser flow, MCP OAuth proxy, and per-request remote authorization
17
+ - Multiple transports — stdio for local clients, SSE for legacy clients, and Streamable HTTP for modern remote deployments
18
+ - Client-friendly setup — examples for Claude Code, Codex, Antigravity, OpenCode, Copilot, Cline, Roo Code, Cursor, Kilo Code, and Amp Code
19
+ - Self-hosted ready — works with custom GitLab instances, proxy settings, and dynamic API URL routing
16
20
 
17
- #### Authentication Methods
21
+ Quick start: choose either Personal Access Token or OAuth2 setup below and use `@zereight/mcp-gitlab` in your MCP client configuration.
18
22
 
19
- The server supports two authentication methods:
23
+ ### Client Setup Guides
20
24
 
21
- 1. **Personal Access Token** (traditional method)
22
- 2. **OAuth2** (recommended for better security)
25
+ - [Claude Code Setup Guide](./docs/claude-code-setup.md)
26
+ - [VS Code Setup Guide](./docs/vscode-setup.md)
27
+ - [GitHub Copilot Setup Guide](./docs/copilot-setup.md)
28
+ - [Codex Setup Guide](./docs/codex-setup.md)
29
+ - [Cursor Setup Guide](./docs/cursor-setup.md)
30
+ - [JSON-Based MCP Clients Setup Guide](./docs/json-mcp-clients-setup.md) - for Factory AI Droid, OpenClaw, and OpenCode style clients
31
+ - [OAuth2 Authentication Setup Guide](./docs/oauth-setup.md)
32
+ - [Environment Variables Reference](./docs/environment-variables.md)
23
33
 
24
- #### Using OAuth2 Authentication
34
+ ## Usage
25
35
 
26
- OAuth2 provides a more secure authentication flow using browser-based authentication. When enabled, the server will:
36
+ ### Setup Overview
27
37
 
28
- 1. Open your browser to GitLab's authorization page
29
- 2. Wait for you to approve the access
30
- 3. Store the token securely for future use
31
- 4. Automatically refresh the token when it expires
38
+ #### Authentication Methods
32
39
 
33
- For detailed OAuth2 setup instructions, see [OAuth Setup Guide](./docs/oauth-setup.md).
40
+ The server supports four authentication methods:
34
41
 
35
- Quick setup - first create a GitLab OAuth application:
42
+ **For local/desktop use** (most common):
36
43
 
37
- 1. Go to your GitLab instance: `Admin area` `Applications`
38
- 2. Create a new application with:
39
- - **Name**: `GitLab MCP Server` (or any name you prefer)
40
- - **Redirect URI**: `http://127.0.0.1:8888/callback`
41
- - **Scopes**: Select `api` (provides complete read/write access to the API)
42
- 3. Copy the **Application ID** (this is your Client ID)
44
+ 1. **Personal Access Token** (`GITLAB_PERSONAL_ACCESS_TOKEN`) simplest setup
45
+ 2. **OAuth2 Local Browser** (`GITLAB_USE_OAUTH`) — recommended for better security
43
46
 
44
- Then configure the MCP server with OAuth:
47
+ **For server/remote deployments**:
45
48
 
46
- ```json
47
- {
48
- "mcpServers": {
49
- "gitlab": {
50
- "command": "npx",
51
- "args": ["-y", "@zereight/mcp-gitlab"],
52
- "env": {
53
- "GITLAB_USE_OAUTH": "true",
54
- "GITLAB_OAUTH_CLIENT_ID": "your_oauth_client_id",
55
- "GITLAB_OAUTH_CLIENT_SECRET": "your_oauth_client_secret", // Required for Confidential apps only
56
- "GITLAB_OAUTH_REDIRECT_URI": "http://127.0.0.1:8888/callback",
57
- "GITLAB_API_URL": "your_gitlab_api_url",
58
- "GITLAB_PROJECT_ID": "your_project_id", // Optional: default project
59
- "GITLAB_ALLOWED_PROJECT_IDS": "", // Optional: comma-separated list of allowed project IDs
60
- "GITLAB_READ_ONLY_MODE": "false",
61
- "USE_GITLAB_WIKI": "false", // use wiki api?
62
- "USE_MILESTONE": "false", // use milestone api?
63
- "USE_PIPELINE": "false" // use pipeline api?
64
- }
65
- }
66
- }
67
- }
68
- ```
49
+ 3. **OAuth2 — MCP Proxy** (`GITLAB_MCP_OAUTH`) — for remote MCP clients such as Claude.ai
50
+ 4. **Remote Authorization** (`REMOTE_AUTHORIZATION`) — multi-user deployments where each caller provides their own token
69
51
 
70
- #### Using Personal Access Token (traditional)
52
+ #### Quick setup paths
71
53
 
72
- ```json
73
- {
74
- "mcpServers": {
75
- "gitlab": {
76
- "command": "npx",
77
- "args": ["-y", "@zereight/mcp-gitlab"],
78
- "env": {
79
- "GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
80
- "GITLAB_API_URL": "your_gitlab_api_url",
81
- "GITLAB_PROJECT_ID": "your_project_id", // Optional: default project
82
- "GITLAB_ALLOWED_PROJECT_IDS": "", // Optional: comma-separated list of allowed project IDs
83
- "GITLAB_READ_ONLY_MODE": "false",
84
- "USE_GITLAB_WIKI": "false", // use wiki api?
85
- "USE_MILESTONE": "false", // use milestone api?
86
- "USE_PIPELINE": "false" // use pipeline api?
87
- }
88
- }
89
- }
90
- }
91
- ```
54
+ - **Claude Code**: see [Claude Code Setup Guide](./docs/claude-code-setup.md)
55
+ - **VS Code**: see [VS Code Setup Guide](./docs/vscode-setup.md)
56
+ - **GitHub Copilot**: see [GitHub Copilot Setup Guide](./docs/copilot-setup.md)
57
+ - **Codex**: see [Codex Setup Guide](./docs/codex-setup.md)
58
+ - **Cursor**: see [Cursor Setup Guide](./docs/cursor-setup.md)
59
+ - **Factory AI Droid / OpenClaw / OpenCode style clients**: see [JSON-Based MCP Clients Setup Guide](./docs/json-mcp-clients-setup.md)
60
+ - **OAuth browser flow details**: see [OAuth2 Authentication Setup Guide](./docs/oauth-setup.md)
61
+
62
+ For the simplest local setup, start with a Personal Access Token. For browser-based local auth, use OAuth2. For remote or multi-user deployments, continue to the MCP OAuth and Remote Authorization sections later in this README.
92
63
 
93
64
  #### Using CLI Arguments (for clients with env var issues)
94
65
 
@@ -122,155 +93,6 @@ Some MCP clients (like GitHub Copilot CLI) have issues with environment variable
122
93
 
123
94
  CLI arguments take precedence over environment variables.
124
95
 
125
- #### vscode .vscode/mcp.json
126
-
127
- **Using OAuth2 (Non-Confidential - Recommended):**
128
-
129
- ```json
130
- {
131
- "servers": {
132
- "GitLab-MCP": {
133
- "type": "stdio",
134
- "command": "npx",
135
- "args": ["-y", "@zereight/mcp-gitlab"],
136
- "env": {
137
- "GITLAB_USE_OAUTH": "true",
138
- "GITLAB_OAUTH_CLIENT_ID": "your_oauth_client_id",
139
- "GITLAB_OAUTH_REDIRECT_URI": "http://127.0.0.1:8888/callback",
140
- "GITLAB_API_URL": "https://gitlab.com/api/v4",
141
- "GITLAB_READ_ONLY_MODE": "false",
142
- "USE_GITLAB_WIKI": "false",
143
- "USE_MILESTONE": "false",
144
- "USE_PIPELINE": "false"
145
- }
146
- }
147
- }
148
- }
149
- ```
150
-
151
- **Using OAuth2 (Confidential):**
152
-
153
- ```json
154
- {
155
- "inputs": [
156
- {
157
- "type": "promptString",
158
- "id": "gitlab-oauth-secret",
159
- "description": "GitLab OAuth Client Secret",
160
- "password": true
161
- }
162
- ],
163
- "servers": {
164
- "GitLab-MCP": {
165
- "type": "stdio",
166
- "command": "npx",
167
- "args": ["-y", "@zereight/mcp-gitlab"],
168
- "env": {
169
- "GITLAB_USE_OAUTH": "true",
170
- "GITLAB_OAUTH_CLIENT_ID": "your_oauth_client_id",
171
- "GITLAB_OAUTH_CLIENT_SECRET": "${input:gitlab-oauth-secret}",
172
- "GITLAB_OAUTH_REDIRECT_URI": "http://127.0.0.1:8888/callback",
173
- "GITLAB_API_URL": "https://gitlab.com/api/v4",
174
- "GITLAB_READ_ONLY_MODE": "false"
175
- }
176
- }
177
- }
178
- }
179
- ```
180
-
181
- **Using Personal Access Token:**
182
-
183
- ```json
184
- {
185
- "inputs": [
186
- {
187
- "type": "promptString",
188
- "id": "gitlab-token",
189
- "description": "GitLab Personal Access Token",
190
- "password": true
191
- }
192
- ],
193
- "servers": {
194
- "GitLab-MCP": {
195
- "type": "stdio",
196
- "command": "npx",
197
- "args": ["-y", "@zereight/mcp-gitlab"],
198
- "env": {
199
- "GITLAB_PERSONAL_ACCESS_TOKEN": "${input:gitlab-token}",
200
- "GITLAB_API_URL": "https://gitlab.com/api/v4",
201
- "GITLAB_READ_ONLY_MODE": "false",
202
- "USE_GITLAB_WIKI": "false",
203
- "USE_MILESTONE": "false",
204
- "USE_PIPELINE": "false"
205
- }
206
- }
207
- }
208
- }
209
- ```
210
-
211
- #### Strands Agents SDK (MCP Tools)
212
-
213
- ```python
214
- env_vars = {
215
- "GITLAB_PERSONAL_ACCESS_TOKEN": gitlab_access_token,
216
- "GITLAB_API_URL": gitlab_api_url,
217
- "USE_GITLAB_WIKI": use_gitlab_wiki
218
- # ......the rest of the optional parameters
219
- }
220
-
221
- stdio_gitlab_mcp_client = MCPClient(
222
- lambda: stdio_client(
223
- StdioServerParameters(
224
- command="npx",
225
- args=["-y", "@zereight/mcp-gitlab"],
226
- env=env_vars,
227
- )
228
- )
229
- )
230
- ```
231
-
232
- #### Docker
233
-
234
- > **Note**: For Docker deployments, **Personal Access Token is recommended**. OAuth requires browser-based authentication and a local callback server, which does not work properly in containerized environments.
235
-
236
- **Using Personal Access Token (stdio) - Recommended:**
237
-
238
- ```json
239
- {
240
- "mcpServers": {
241
- "gitlab": {
242
- "command": "docker",
243
- "args": [
244
- "run",
245
- "-i",
246
- "--rm",
247
- "-e",
248
- "GITLAB_PERSONAL_ACCESS_TOKEN",
249
- "-e",
250
- "GITLAB_API_URL",
251
- "-e",
252
- "GITLAB_READ_ONLY_MODE",
253
- "-e",
254
- "USE_GITLAB_WIKI",
255
- "-e",
256
- "USE_MILESTONE",
257
- "-e",
258
- "USE_PIPELINE",
259
- "zereight050/gitlab-mcp"
260
- ],
261
- "env": {
262
- "GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
263
- "GITLAB_API_URL": "https://gitlab.com/api/v4",
264
- "GITLAB_READ_ONLY_MODE": "false",
265
- "USE_GITLAB_WIKI": "true",
266
- "USE_MILESTONE": "true",
267
- "USE_PIPELINE": "true"
268
- }
269
- }
270
- }
271
- }
272
- ```
273
-
274
96
  - sse
275
97
 
276
98
  ```shell
@@ -325,114 +147,117 @@ docker run -i --rm \
325
147
  }
326
148
  ```
327
149
 
150
+ #### Using MCP OAuth Proxy (`GITLAB_MCP_OAUTH`)
151
+
152
+ > **For server/remote deployments only.** This mode requires the MCP server to be deployed with a publicly accessible HTTPS URL. For local/desktop use, see `GITLAB_USE_OAUTH` above.
153
+
154
+ For remote MCP clients that support the MCP OAuth specification (e.g. Claude.ai).
155
+ The server acts as a full OAuth 2.0 authorization server — unauthenticated requests
156
+ receive a `401 + WWW-Authenticate` response, which triggers the OAuth browser flow
157
+ automatically on the client side.
158
+
159
+ **How it works**: You deploy this MCP server somewhere with a public HTTPS URL. MCP
160
+ clients connect to `{MCP_SERVER_URL}/mcp`. The server handles the OAuth 2.0 flow,
161
+ exchanging credentials with GitLab on behalf of the client.
162
+
163
+ **Prerequisites**:
164
+
165
+ 1. A publicly accessible HTTPS server URL (`MCP_SERVER_URL`) — use [ngrok](https://ngrok.com) for local testing
166
+ 2. A pre-registered GitLab OAuth application with `api` (or `read_api`) scopes
167
+ — Go to `Admin area` → `Applications`, set Redirect URI to `{MCP_SERVER_URL}/callback`
168
+
169
+ | Environment Variable | Required | Description |
170
+ | --------------------- | -------- | ---------------------------------------------------------- |
171
+ | `GITLAB_MCP_OAUTH` | ✅ | Set to `true` to enable |
172
+ | `GITLAB_API_URL` | ✅ | GitLab API base URL |
173
+ | `GITLAB_OAUTH_APP_ID` | ✅ | GitLab OAuth Application ID |
174
+ | `MCP_SERVER_URL` | ✅ | Public HTTPS URL of this MCP server |
175
+ | `STREAMABLE_HTTP` | ✅ | Must be `true` |
176
+ | `GITLAB_OAUTH_SCOPES` | optional | Comma-separated scopes (default: `api,read_api,read_user`) |
177
+
178
+ ```shell
179
+ docker run -i --rm \
180
+ -e HOST=0.0.0.0 \
181
+ -e GITLAB_MCP_OAUTH=true \
182
+ -e STREAMABLE_HTTP=true \
183
+ -e MCP_SERVER_URL=https://your-server.example.com \
184
+ -e GITLAB_API_URL="https://gitlab.com/api/v4" \
185
+ -e GITLAB_OAUTH_APP_ID=your_app_id \
186
+ -p 3000:3002 \
187
+ zereight050/gitlab-mcp
188
+ ```
189
+
190
+ MCP client configuration:
191
+
192
+ ```json
193
+ {
194
+ "mcpServers": {
195
+ "gitlab": {
196
+ "type": "http",
197
+ "url": "https://your-server.example.com/mcp"
198
+ }
199
+ }
200
+ }
201
+ ```
202
+
203
+ #### Using Remote Authorization (`REMOTE_AUTHORIZATION`)
204
+
205
+ > **For server/remote deployments only.** Each HTTP caller provides their own GitLab token directly in request headers — no OAuth flow involved.
206
+
207
+ For multi-user or multi-tenant deployments where each caller provides their own
208
+ GitLab token in the HTTP request header. No OAuth flow — the MCP server forwards
209
+ the token to GitLab on behalf of the caller.
210
+
211
+ **Header priority**: `Private-Token` > `JOB-TOKEN` > `Authorization: Bearer`
212
+
213
+ | Environment Variable | Required | Description |
214
+ | ------------------------ | -------- | ---------------------------------------------------------- |
215
+ | `REMOTE_AUTHORIZATION` | ✅ | Set to `true` to enable |
216
+ | `STREAMABLE_HTTP` | ✅ | Must be `true` |
217
+ | `ENABLE_DYNAMIC_API_URL` | optional | Allow per-request GitLab URL via `X-GitLab-API-URL` header |
218
+
219
+ **Example request headers**:
220
+
221
+ ```http
222
+ Private-Token: glpat-xxxxxxxxxxxxxxxxxxxx
223
+ ```
224
+
225
+ or using a Bearer token:
226
+
227
+ ```http
228
+ Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx
229
+ ```
230
+
231
+ > ⚠️ `REMOTE_AUTHORIZATION` is **not compatible** with SSE transport. `STREAMABLE_HTTP=true` is required.
232
+
328
233
  ### Environment Variables
329
234
 
330
- #### Authentication Configuration
331
-
332
- - `GITLAB_PERSONAL_ACCESS_TOKEN`: Your GitLab personal access token. **Required in standard mode**; not used when `REMOTE_AUTHORIZATION=true` or when using OAuth.
333
- - `GITLAB_USE_OAUTH`: Set to `true` to enable OAuth2 authentication instead of personal access token.
334
- - `GITLAB_OAUTH_CLIENT_ID`: The Client ID from your GitLab OAuth application. Required when using OAuth.
335
- - `GITLAB_OAUTH_CLIENT_SECRET`: The Client Secret from your GitLab OAuth application. Required only for Confidential applications.
336
- - `GITLAB_OAUTH_REDIRECT_URI`: The OAuth callback URL. Default: `http://127.0.0.1:8888/callback`
337
- - `GITLAB_OAUTH_TOKEN_PATH`: Custom path to store the OAuth token. Default: `~/.gitlab-mcp-token.json`
338
- - `REMOTE_AUTHORIZATION`: When set to 'true', enables remote per-session authorization via HTTP headers. In this mode:
339
- - The server accepts GitLab PAT tokens from HTTP headers (`Authorization: Bearer <token>`, `Private-Token: <token>` or `Job-Token: <token>`) on a per-session basis
340
- - `GITLAB_PERSONAL_ACCESS_TOKEN` environment variable is **not required** and ignored
341
- - Only works with **Streamable HTTP transport** (`STREAMABLE_HTTP=true`) because session management was already handled by the transport layer
342
- - **SSE transport is disabled** - attempting to use SSE with remote authorization will cause the server to exit with an error
343
- - Each client session can use a different token, enabling multi-user support with secure session isolation
344
- - Tokens are stored per session and automatically cleaned up when sessions close or timeout
345
- - `SESSION_TIMEOUT_SECONDS`: Session auth token timeout in seconds. Default: `3600` (1 hour). Valid range: 1-86400 seconds (recommended: 60+). After this period of inactivity, the auth token is removed but the transport session remains active. The client must provide auth headers again on the next request. Only applies when `REMOTE_AUTHORIZATION=true`.
346
-
347
- #### General Configuration
348
-
349
- - `GITLAB_API_URL`: Your GitLab API URL. (Default: `https://gitlab.com/api/v4`)
350
- - `GITLAB_PROJECT_ID`: Default project ID. If set, Overwrite this value when making an API request.
351
- - `GITLAB_ALLOWED_PROJECT_IDS`: Optional comma-separated list of allowed project IDs. When set with a single value, acts as a default project (like the old "lock" mode). When set with multiple values, restricts access to only those projects. Examples:
352
- - Single value `123`: MCP server can only access project 123 and uses it as default
353
- - Multiple values `123,456,789`: MCP server can access projects 123, 456, and 789 but requires explicit project ID in requests
354
- - `GITLAB_READ_ONLY_MODE`: When set to 'true', restricts the server to only expose read-only operations. Useful for enhanced security or when write access is not needed. Also useful for using with Cursor and it's 40 tool limit.
355
- - `GITLAB_DENIED_TOOLS_REGEX`: When set as a regular expression, it excludes the matching tools.
356
- - `USE_GITLAB_WIKI`: Legacy flag. Wiki features are now enabled by default. When set to 'true', ensures wiki-related tools are included even if the `wiki` toolset is not explicitly listed in `GITLAB_TOOLSETS`.
357
- - `USE_MILESTONE`: Legacy flag. Milestone features are now enabled by default. When set to 'true', ensures milestone-related tools are included even if the `milestones` toolset is not explicitly listed in `GITLAB_TOOLSETS`.
358
- - `USE_PIPELINE`: Legacy flag. Pipeline features are now enabled by default. When set to 'true', ensures pipeline-related tools are included even if the `pipelines` toolset is not explicitly listed in `GITLAB_TOOLSETS`.
359
- - `GITLAB_TOOLSETS`: Comma-separated list of toolset IDs to enable. When empty or unset, default toolsets are used. Set to `"all"` to enable every toolset. Available toolsets (default toolsets marked with `*`):
360
- - `merge_requests`\* — MR operations, notes, discussions, draft notes, threads, versions, file diffs, conflicts (34 tools)
361
- - `issues`\* — Issue CRUD, notes, links, discussions (14 tools)
362
- - `repositories`\* — Search, create, file contents, push, fork, tree (7 tools)
363
- - `branches`\* — Branch creation, commits, diffs (4 tools)
364
- - `projects`\* — Project/namespace info, group projects, iterations (8 tools)
365
- - `labels`\* — Label CRUD (5 tools)
366
- - `pipelines`\* — Pipeline, job, deployment, environment, and artifact operations (19 tools)
367
- - `milestones`\* — Milestone CRUD, issues, MRs, burndown (9 tools)
368
- - `wiki`\* — Wiki page CRUD for projects and groups (10 tools)
369
- - `releases`\* — Release CRUD, evidence, asset download (7 tools)
370
- - `users`\* — User info, events, markdown upload, attachments (5 tools)
371
- - `workitems` — Work item CRUD via GraphQL, type conversion, statuses, custom fields, notes, timeline events (12 tools, opt-in)
372
- - `webhooks` — Webhook listing and event inspection (3 tools, opt-in)
373
- - `search` — Code search across projects, groups, or globally (3 tools, requires advanced search or exact code search enabled)
374
-
375
- Note: `execute_graphql` is not in any toolset and must be added individually via `GITLAB_TOOLS` if needed.
376
- Exposing arbitrary GraphQL would allow bypassing toolset boundaries (e.g. querying data that the user intentionally disabled via toolsets like wiki or pipelines), which is a security and permission-containment concern. Keeping `execute_graphql` out of all toolsets and requiring explicit opt-in via `GITLAB_TOOLS=execute_graphql` is intentional, to align with that principle rather than for backward compatibility.
377
- CLI arg: `--toolsets`
378
- - `GITLAB_TOOLS`: Comma-separated list of individual tool names to add on top of the enabled toolsets (additive). Useful for cherry-picking specific tools without enabling an entire toolset. Example: `GITLAB_TOOLS="list_pipelines,execute_graphql"`. CLI arg: `--tools`
379
-
380
- Combined logic: `final tools = (tools from enabled toolsets) ∪ (GITLAB_TOOLS) ∪ (legacy flag overrides)`
381
-
382
- Examples:
383
- ```bash
384
- # Default behavior (unchanged)
385
- GITLAB_PERSONAL_ACCESS_TOKEN=xxx npx @zereight/mcp-gitlab
386
-
387
- # Only issues and repositories
388
- GITLAB_TOOLSETS="issues,repositories" npx @zereight/mcp-gitlab
389
-
390
- # All toolsets
391
- GITLAB_TOOLSETS="all" npx @zereight/mcp-gitlab
392
-
393
- # Default toolsets + one extra pipeline tool
394
- GITLAB_TOOLS="list_pipelines" npx @zereight/mcp-gitlab
395
-
396
- # Specific toolsets + individual tools
397
- GITLAB_TOOLSETS="issues,merge_requests" GITLAB_TOOLS="list_pipelines,get_pipeline" npx @zereight/mcp-gitlab
398
-
399
- # Legacy flags still work (backward compatible)
400
- USE_PIPELINE=true npx @zereight/mcp-gitlab
401
- ```
402
- - `GITLAB_AUTH_COOKIE_PATH`: Path to an authentication cookie file for GitLab instances that require cookie-based authentication. When provided, the cookie will be included in all GitLab API requests.
403
- - `SSE`: When set to 'true', enables the Server-Sent Events transport.
404
- - `STREAMABLE_HTTP`: When set to 'true', enables the Streamable HTTP transport. If both **SSE** and **STREAMABLE_HTTP** are set to 'true', the server will prioritize Streamable HTTP over SSE transport.
405
- - `GITLAB_COMMIT_FILES_PER_PAGE`: The number of files per page that GitLab returns for commit diffs. This value should match the server-side GitLab setting. Adjust this if your GitLab instance uses a custom per-page value for commit diffs.
406
- - `GITLAB_REPO_FILE_ENCODING`: Encoding for repository file create/update and related commit payloads sent to the GitLab API. Use `text` (default) or `base64`. Equivalent CLI: `--repo-file-encoding=text|base64`.
407
-
408
- #### Performance & Security Configuration
409
-
410
- - `HOST`: Server host address. Default: `127.0.0.1` (localhost only). Set to `0.0.0.0` to allow external connections (required for Docker with port forwarding).
411
- - `MAX_SESSIONS`: Maximum number of concurrent sessions allowed. Default: `1000`. Valid range: 1-10000. When limit is reached, new connections are rejected with HTTP 503.
412
- - `MAX_REQUESTS_PER_MINUTE`: Rate limit per session in requests per minute. Default: `60`. Valid range: 1-1000. Exceeded requests return HTTP 429.
413
- - `PORT`: Server port. Default: `3002`. Valid range: 1-65535.
414
- - `HTTP_PROXY`: HTTP proxy server URL for outgoing requests. Example: `http://proxy.example.com:8080`. Supports HTTP/HTTPS and SOCKS proxies (URLs starting with `socks://` or `socks5://`). CLI arg: `--http-proxy`
415
- - `HTTPS_PROXY`: HTTPS proxy server URL for outgoing requests. Example: `https://proxy.example.com:8080`. Supports HTTP/HTTPS and SOCKS proxies. CLI arg: `--https-proxy`
416
- - `NO_PROXY`: Comma-separated list of hosts that should bypass the proxy. Supports:
417
- - Exact hostname matches (e.g., `localhost`, `gitlab.internal.com`)
418
- - Domain suffix matches (e.g., `.internal.com` matches any subdomain)
419
- - IP addresses (e.g., `127.0.0.1`, `192.168.1.1`)
420
- - Port-specific matches (e.g., `example.com:443`)
421
- - Wildcard `*` to bypass proxy for all hosts
422
- - Example: `NO_PROXY=localhost,127.0.0.1,.internal.com`
423
- - CLI arg: `--no-proxy`
424
-
425
- #### Monitoring Endpoints
426
-
427
- When using Streamable HTTP transport, the following endpoints are available:
428
-
429
- - `/health`: Health check endpoint returning server status, active sessions count, and uptime.
430
- - `/metrics`: Detailed metrics including:
431
- - Active and total session counts
432
- - Authentication metrics (failures, expirations)
433
- - Rate limiting statistics
434
- - Resource usage (memory, uptime)
435
- - Configuration summary
235
+ Use the dedicated reference for the full environment variable list:
236
+
237
+ - [Environment Variables Reference](./docs/environment-variables.md)
238
+
239
+ Most users only need one of these starting sets:
240
+
241
+ - **Local PAT**: `GITLAB_PERSONAL_ACCESS_TOKEN`, `GITLAB_API_URL`
242
+ - **Local OAuth**: `GITLAB_USE_OAUTH=true`, `GITLAB_OAUTH_CLIENT_ID`, `GITLAB_OAUTH_REDIRECT_URI`, `GITLAB_API_URL`
243
+ - **Remote multi-user HTTP**: `STREAMABLE_HTTP=true`, `REMOTE_AUTHORIZATION=true`, `HOST`, `PORT`
244
+
245
+ Commonly referenced variables:
246
+
247
+ - `GITLAB_API_URL`
248
+ - `GITLAB_PERSONAL_ACCESS_TOKEN`
249
+ - `GITLAB_USE_OAUTH`
250
+ - `REMOTE_AUTHORIZATION`
251
+ - `GITLAB_MCP_OAUTH`
252
+
253
+ The reference document also covers:
254
+
255
+ - auth and OAuth variables
256
+ - MCP OAuth proxy variables
257
+ - project and tool filtering variables
258
+ - dynamic tool discovery via `discover_tools` (on-demand toolset activation)
259
+ - transport and session variables
260
+ - proxy and TLS variables
436
261
 
437
262
  ### Remote Authorization Setup (Multi-User Support)
438
263
 
@@ -512,7 +337,7 @@ calls (need `api` or `read_api`).
512
337
  1. Go to your GitLab instance → **Admin Area > Applications** (instance-wide) or **User Settings > Applications** (personal)
513
338
  2. Create a new application with:
514
339
  - **Confidential**: unchecked
515
- - **Scopes**: `api`, `read_api`, `read_user`
340
+ - **Scopes**: `api`, `read_api`, `read_user` (or whichever scopes you intend to request via `GITLAB_OAUTH_SCOPES`)
516
341
  3. Save and copy the **Application ID** — this is your `GITLAB_OAUTH_APP_ID`
517
342
 
518
343
  **How it works:**
@@ -566,14 +391,15 @@ No `headers` field is needed — Claude.ai obtains the token via OAuth automatic
566
391
 
567
392
  **Environment variables:**
568
393
 
569
- | Variable | Required | Description |
570
- |---|---|---|
571
- | `GITLAB_MCP_OAUTH` | Yes | Set to `true` to enable |
572
- | `GITLAB_OAUTH_APP_ID` | Yes | Client ID of the pre-registered GitLab OAuth application |
573
- | `MCP_SERVER_URL` | Yes | Public HTTPS URL of your MCP server |
574
- | `GITLAB_API_URL` | Yes | Your GitLab instance API URL (e.g. `https://gitlab.com/api/v4`) |
575
- | `STREAMABLE_HTTP` | Yes | Must be `true` (SSE is not supported) |
576
- | `MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL` | No | Set `true` for local HTTP dev only |
394
+ | Variable | Required | Description |
395
+ | ------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
396
+ | `GITLAB_MCP_OAUTH` | Yes | Set to `true` to enable |
397
+ | `GITLAB_OAUTH_APP_ID` | Yes | Client ID of the pre-registered GitLab OAuth application |
398
+ | `MCP_SERVER_URL` | Yes | Public HTTPS URL of your MCP server |
399
+ | `GITLAB_API_URL` | Yes | Your GitLab instance API URL (e.g. `https://gitlab.com/api/v4`) |
400
+ | `STREAMABLE_HTTP` | Yes | Must be `true` (SSE is not supported) |
401
+ | `GITLAB_OAUTH_SCOPES` | No | Comma-separated GitLab scopes to request (e.g. `api,read_user`). Defaults to `api` (or `read_api` when `GITLAB_READ_ONLY_MODE=true`). The pre-registered application must be configured with at least these scopes. |
402
+ | `MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL` | No | Set `true` for local HTTP dev only |
577
403
 
578
404
  **Important Notes:**
579
405
 
@@ -582,6 +408,20 @@ No `headers` field is needed — Claude.ai obtains the token via OAuth automatic
582
408
  - Session timeout, rate limiting, and capacity limits apply identically to the
583
409
  `REMOTE_AUTHORIZATION` mode (`SESSION_TIMEOUT_SECONDS`, `MAX_REQUESTS_PER_MINUTE`,
584
410
  `MAX_SESSIONS`)
411
+ - **Header auth fallback:** when `Private-Token` or `JOB-TOKEN` request headers are
412
+ present, OAuth validation is skipped and the raw token is used directly for that
413
+ session. This allows PATs and CI job tokens to be used alongside the OAuth flow on
414
+ the same server instance. `Authorization: Bearer` is always treated as an OAuth
415
+ token — use `Private-Token` for PAT-based header auth.
416
+
417
+ ## Agent Skill Files
418
+
419
+ Pre-built skill files are available in [`skills/gitlab-mcp/`](./skills/gitlab-mcp/) for AI agents that support skill/instruction loading (Claude Code, GitHub Copilot, Cursor, etc.).
420
+
421
+ - **[SKILL.md](./skills/gitlab-mcp/SKILL.md)** — Core guide (~800 tokens) with toolset overview, key workflows, and parameter hints
422
+ - **[reference/](./skills/gitlab-mcp/reference/)** — Detailed workflow docs for code review, merge requests, issues, and pipelines
423
+
424
+ Register the skill directory in your AI client to get optimal tool usage guidance without relying solely on the full ListTools response.
585
425
 
586
426
  ## Tools 🛠️
587
427
 
@@ -0,0 +1,75 @@
1
+ // Parse CLI arguments before anything else
2
+ const args = process.argv.slice(2);
3
+ export const cliArgs = {};
4
+ for (let i = 0; i < args.length; i++) {
5
+ const arg = args[i];
6
+ if (arg.startsWith("--")) {
7
+ const [key, value] = arg.slice(2).split("=");
8
+ if (value) {
9
+ cliArgs[key] = value;
10
+ }
11
+ else if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
12
+ cliArgs[key] = args[++i];
13
+ }
14
+ }
15
+ }
16
+ export function getConfig(cliKey, envKey, defaultValue) {
17
+ return cliArgs[cliKey] || process.env[envKey] || defaultValue;
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Authentication
21
+ // ---------------------------------------------------------------------------
22
+ export const GITLAB_PERSONAL_ACCESS_TOKEN = getConfig("token", "GITLAB_PERSONAL_ACCESS_TOKEN");
23
+ export const GITLAB_JOB_TOKEN = getConfig("job-token", "GITLAB_JOB_TOKEN");
24
+ export const GITLAB_AUTH_COOKIE_PATH = getConfig("cookie-path", "GITLAB_AUTH_COOKIE_PATH");
25
+ export const USE_OAUTH = getConfig("use-oauth", "GITLAB_USE_OAUTH") === "true";
26
+ export const IS_OLD = getConfig("is-old", "GITLAB_IS_OLD") === "true";
27
+ // ---------------------------------------------------------------------------
28
+ // Behavior flags
29
+ // ---------------------------------------------------------------------------
30
+ export const GITLAB_READ_ONLY_MODE = getConfig("read-only", "GITLAB_READ_ONLY_MODE") === "true";
31
+ export const USE_GITLAB_WIKI = getConfig("use-wiki", "USE_GITLAB_WIKI") === "true";
32
+ export const USE_MILESTONE = getConfig("use-milestone", "USE_MILESTONE") === "true";
33
+ export const USE_PIPELINE = getConfig("use-pipeline", "USE_PIPELINE") === "true";
34
+ // ---------------------------------------------------------------------------
35
+ // Tool filtering
36
+ // ---------------------------------------------------------------------------
37
+ export const GITLAB_TOOLSETS_RAW = getConfig("toolsets", "GITLAB_TOOLSETS");
38
+ export const GITLAB_TOOLS_RAW = getConfig("tools", "GITLAB_TOOLS");
39
+ // Tool policy: comma-separated tool names
40
+ // approve = exposed but requires confirmation; hidden = not exposed at all
41
+ export const GITLAB_TOOL_POLICY_APPROVE_RAW = getConfig("tool-policy-approve", "GITLAB_TOOL_POLICY_APPROVE");
42
+ export const GITLAB_TOOL_POLICY_HIDDEN_RAW = getConfig("tool-policy-hidden", "GITLAB_TOOL_POLICY_HIDDEN");
43
+ // ---------------------------------------------------------------------------
44
+ // Transport
45
+ // ---------------------------------------------------------------------------
46
+ export const SSE = getConfig("sse", "SSE") === "true";
47
+ export const STREAMABLE_HTTP = getConfig("streamable-http", "STREAMABLE_HTTP") === "true";
48
+ export const REMOTE_AUTHORIZATION = getConfig("remote-auth", "REMOTE_AUTHORIZATION") === "true";
49
+ export const GITLAB_MCP_OAUTH = getConfig("mcp-oauth", "GITLAB_MCP_OAUTH") === "true";
50
+ // ---------------------------------------------------------------------------
51
+ // OAuth / MCP OAuth
52
+ // ---------------------------------------------------------------------------
53
+ export const MCP_SERVER_URL = getConfig("mcp-server-url", "MCP_SERVER_URL");
54
+ export const GITLAB_OAUTH_APP_ID = getConfig("oauth-app-id", "GITLAB_OAUTH_APP_ID");
55
+ export const GITLAB_OAUTH_SCOPES_RAW = getConfig("oauth-scopes", "GITLAB_OAUTH_SCOPES");
56
+ export const GITLAB_OAUTH_SCOPES = GITLAB_OAUTH_SCOPES_RAW
57
+ ? GITLAB_OAUTH_SCOPES_RAW.split(",").map((s) => s.trim()).filter(Boolean)
58
+ : undefined;
59
+ export const ENABLE_DYNAMIC_API_URL = getConfig("enable-dynamic-api-url", "ENABLE_DYNAMIC_API_URL") === "true";
60
+ // ---------------------------------------------------------------------------
61
+ // Session / server settings
62
+ // ---------------------------------------------------------------------------
63
+ export const SESSION_TIMEOUT_SECONDS = Number.parseInt(getConfig("session-timeout", "SESSION_TIMEOUT_SECONDS", "3600"), 10);
64
+ export const HOST = getConfig("host", "HOST") || "127.0.0.1";
65
+ export const PORT = Number.parseInt(getConfig("port", "PORT", "3002"), 10);
66
+ // ---------------------------------------------------------------------------
67
+ // Proxy configuration
68
+ // ---------------------------------------------------------------------------
69
+ export const HTTP_PROXY = getConfig("http-proxy", "HTTP_PROXY");
70
+ export const HTTPS_PROXY = getConfig("https-proxy", "HTTPS_PROXY");
71
+ export const NO_PROXY = getConfig("no-proxy", "NO_PROXY");
72
+ export const NODE_TLS_REJECT_UNAUTHORIZED = getConfig("tls-reject-unauthorized", "NODE_TLS_REJECT_UNAUTHORIZED");
73
+ export const GITLAB_CA_CERT_PATH = getConfig("ca-cert-path", "GITLAB_CA_CERT_PATH");
74
+ const _poolMaxSizeRaw = getConfig("pool-max-size", "GITLAB_POOL_MAX_SIZE");
75
+ export const GITLAB_POOL_MAX_SIZE = _poolMaxSizeRaw ? Number.parseInt(_poolMaxSizeRaw, 10) : 100;