@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 +171 -331
- package/build/config.js +75 -0
- package/build/customSchemas.js +0 -12
- package/build/gitlab-client-pool.js +0 -1
- package/build/index.js +357 -1687
- package/build/oauth-proxy.js +11 -4
- package/build/schemas.js +66 -48
- package/build/test/mcp-oauth-tests.js +109 -0
- package/build/test/schema-tests.js +77 -3
- package/build/test/test-token-optimizations.js +688 -0
- package/build/test/test-toolset-filtering.js +30 -30
- package/build/tools/registry.js +1172 -0
- package/build/utils/helpers.js +57 -0
- package/build/utils/schema.js +49 -0
- package/build/utils/url.js +19 -0
- package/package.json +21 -2
package/README.md
CHANGED
|
@@ -6,89 +6,60 @@
|
|
|
6
6
|
|
|
7
7
|
## @zereight/mcp-gitlab
|
|
8
8
|
|
|
9
|
-
GitLab MCP
|
|
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
|
-
|
|
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
|
-
###
|
|
13
|
+
### Why use this GitLab MCP?
|
|
14
14
|
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23
|
+
### Client Setup Guides
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
34
|
+
## Usage
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
### Setup Overview
|
|
27
37
|
|
|
28
|
-
|
|
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
|
-
|
|
40
|
+
The server supports four authentication methods:
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
**For local/desktop use** (most common):
|
|
36
43
|
|
|
37
|
-
1.
|
|
38
|
-
2.
|
|
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
|
-
|
|
47
|
+
**For server/remote deployments**:
|
|
45
48
|
|
|
46
|
-
|
|
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
|
-
####
|
|
52
|
+
#### Quick setup paths
|
|
71
53
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
-
|
|
337
|
-
-
|
|
338
|
-
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
- `
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
-
|
|
351
|
-
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
-
|
|
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
|
|
570
|
-
|
|
571
|
-
| `GITLAB_MCP_OAUTH`
|
|
572
|
-
| `GITLAB_OAUTH_APP_ID`
|
|
573
|
-
| `MCP_SERVER_URL`
|
|
574
|
-
| `GITLAB_API_URL`
|
|
575
|
-
| `STREAMABLE_HTTP`
|
|
576
|
-
| `
|
|
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
|
|
package/build/config.js
ADDED
|
@@ -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;
|