Skip to content

Commit 2ecb70d

Browse files
authored
feat(mcp): MCP Ecosystem Compatibility - Graceful Startup, Static Manifest, and Release Pipeline Improvements (#212)
* feat(mcp): add MCP ecosystem compatibility with graceful startup - Enable server startup without GITLAB_TOKEN - tools/list works, tool calls require token - Add static MCP manifest to package.json with tools metadata, transports, feature flags - Create scripts/update-mcp-manifest.js to auto-generate tools list during release - Enhance /health endpoint with MCP protocol info (version, transports, toolCount, authMode) - Update prepare-release.sh to regenerate manifest on release - Add isStaticTokenConfigured() and isAuthenticationConfigured() helpers Closes #210 * test(health): verify auth mode detection in healthHandler - Test oauth authMode when isOAuthEnabled returns true - Test token authMode when static token configured - Test none authMode when no authentication configured - Test error response when isAuthenticationConfigured returns false * docs(server): clarify rate limiting scope for health endpoint Global rateLimiterMiddleware is applied before registerOAuthEndpoints, protecting all routes including /health. * refactor(mcp): extract MCP protocol version to constant - Define MCP_PROTOCOL_VERSION constant in metadata.ts - Use constant in OAuth metadata and health endpoint - Import constant in tests to avoid duplication - Clarify authentication.required: false for server startup - Normalize tier: "unknown" to "free" in manifest generator * fix(health): read tool count from package.json instead of hardcoded value - Replace magic number 44 with dynamic read from package.json mcp.tools - Keeps in sync with manifest updates via scripts/update-mcp-manifest.js - Falls back to 0 if package.json unavailable (bundled environments) * docs(server): use function reference instead of line number in comment Avoid stale line number reference - point to function name instead.
1 parent 2fa9de0 commit 2ecb70d

File tree

12 files changed

+843
-28
lines changed

12 files changed

+843
-28
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ scripts/
3030
!scripts/deploy.sh
3131
!scripts/build-mcpb.sh
3232
!scripts/prepare-release.sh
33+
!scripts/update-mcp-manifest.js
3334

3435
# MCPB bundles (built artifacts)
3536
*.mcpb

package.json

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,380 @@
1010
},
1111
"version": "6.47.1",
1212
"description": "MCP server for using the GitLab API",
13+
"mcp": {
14+
"name": "GitLab MCP Server",
15+
"description": "Model Context Protocol server for GitLab API - 44 tools across 13 entity types with CQRS architecture, OAuth 2.1, and multiple transport modes",
16+
"repository": "https://github.com/structured-world/gitlab-mcp",
17+
"homepage": "https://gitlab-mcp.sw.foundation",
18+
"author": "Dmitry Prudnikov",
19+
"license": "Apache-2.0",
20+
"runtime": "node",
21+
"minNodeVersion": "24.0.0",
22+
"transports": [
23+
"stdio",
24+
"sse",
25+
"streamable-http"
26+
],
27+
"authentication": {
28+
"required": false,
29+
"requiredForToolExecution": true,
30+
"methods": [
31+
"token",
32+
"oauth2"
33+
],
34+
"envVars": [
35+
"GITLAB_TOKEN",
36+
"GITLAB_PERSONAL_ACCESS_TOKEN"
37+
],
38+
"note": "Server starts without token (tools/list works), but tool execution requires authentication"
39+
},
40+
"meta": {
41+
"avatar": "https://gitlab-mcp.sw.foundation/logo.png",
42+
"tags": [
43+
"gitlab",
44+
"devops",
45+
"ci-cd",
46+
"merge-requests",
47+
"issues",
48+
"pipelines",
49+
"developer-tools"
50+
],
51+
"categories": [
52+
"Developer Tools",
53+
"Version Control",
54+
"CI/CD"
55+
]
56+
},
57+
"featureFlags": {
58+
"USE_PIPELINE": "Enable pipeline and CI/CD tools",
59+
"USE_MILESTONE": "Enable milestone management tools",
60+
"USE_GITLAB_WIKI": "Enable wiki page tools",
61+
"USE_WORKITEMS": "Enable work items (issues/epics) tools",
62+
"USE_LABELS": "Enable label management tools",
63+
"USE_MRS": "Enable merge request tools",
64+
"USE_FILES": "Enable file management tools",
65+
"USE_VARIABLES": "Enable CI/CD variables tools",
66+
"USE_SNIPPETS": "Enable snippet tools",
67+
"USE_WEBHOOKS": "Enable webhook tools",
68+
"USE_INTEGRATIONS": "Enable integration tools",
69+
"USE_RELEASES": "Enable release management tools",
70+
"USE_REFS": "Enable refs (branches/tags) tools",
71+
"USE_MEMBERS": "Enable member management tools",
72+
"USE_SEARCH": "Enable search tools",
73+
"USE_ITERATIONS": "Enable iteration tools",
74+
"GITLAB_READ_ONLY_MODE": "Restrict to read-only operations"
75+
},
76+
"tools": [
77+
{
78+
"name": "browse_projects",
79+
"description": "Find, list, or inspect GitLab projects.",
80+
"category": "Projects",
81+
"tier": "free",
82+
"readOnly": true
83+
},
84+
{
85+
"name": "browse_namespaces",
86+
"description": "Explore GitLab groups and user namespaces.",
87+
"category": "Projects",
88+
"tier": "free",
89+
"readOnly": true
90+
},
91+
{
92+
"name": "browse_commits",
93+
"description": "Explore repository commit history and diffs.",
94+
"category": "Repository",
95+
"tier": "free",
96+
"readOnly": true
97+
},
98+
{
99+
"name": "browse_events",
100+
"description": "Track GitLab activity and events.",
101+
"category": "Activity",
102+
"tier": "free",
103+
"readOnly": true
104+
},
105+
{
106+
"name": "browse_users",
107+
"description": "Find GitLab users with smart pattern detection.",
108+
"category": "Users",
109+
"tier": "free",
110+
"readOnly": true
111+
},
112+
{
113+
"name": "browse_todos",
114+
"description": "View your GitLab todo queue (notifications requiring action).",
115+
"category": "Activity",
116+
"tier": "free",
117+
"readOnly": true
118+
},
119+
{
120+
"name": "manage_project",
121+
"description": "Create, update, or manage GitLab projects.",
122+
"category": "Projects",
123+
"tier": "free",
124+
"readOnly": false
125+
},
126+
{
127+
"name": "manage_namespace",
128+
"description": "Create, update, or delete GitLab groups/namespaces.",
129+
"category": "Projects",
130+
"tier": "free",
131+
"readOnly": false
132+
},
133+
{
134+
"name": "manage_todos",
135+
"description": "Manage your GitLab todo queue.",
136+
"category": "Activity",
137+
"tier": "free",
138+
"readOnly": false
139+
},
140+
{
141+
"name": "manage_context",
142+
"description": "View and manage runtime session configuration.",
143+
"category": "Session",
144+
"tier": "free",
145+
"readOnly": true
146+
},
147+
{
148+
"name": "browse_labels",
149+
"description": "List and inspect project or group labels.",
150+
"category": "Planning",
151+
"tier": "free",
152+
"readOnly": true
153+
},
154+
{
155+
"name": "manage_label",
156+
"description": "Create, update, or delete project/group labels.",
157+
"category": "Planning",
158+
"tier": "free",
159+
"readOnly": false
160+
},
161+
{
162+
"name": "browse_merge_requests",
163+
"description": "Find and inspect merge requests.",
164+
"category": "Merge Requests",
165+
"tier": "free",
166+
"readOnly": true
167+
},
168+
{
169+
"name": "browse_mr_discussions",
170+
"description": "Read discussion threads and draft review notes on merge requests.",
171+
"category": "Merge Requests",
172+
"tier": "free",
173+
"readOnly": true
174+
},
175+
{
176+
"name": "manage_merge_request",
177+
"description": "Create, update, merge, or approve merge requests.",
178+
"category": "Merge Requests",
179+
"tier": "free",
180+
"readOnly": false
181+
},
182+
{
183+
"name": "manage_mr_discussion",
184+
"description": "Post comments, start threads, and suggest code changes on merge requests.",
185+
"category": "Merge Requests",
186+
"tier": "free",
187+
"readOnly": false
188+
},
189+
{
190+
"name": "manage_draft_notes",
191+
"description": "Create and manage unpublished review comments on merge requests.",
192+
"category": "Merge Requests",
193+
"tier": "free",
194+
"readOnly": false
195+
},
196+
{
197+
"name": "browse_files",
198+
"description": "Explore project file structure and read source code.",
199+
"category": "Repository",
200+
"tier": "free",
201+
"readOnly": true
202+
},
203+
{
204+
"name": "manage_files",
205+
"description": "Create, update, or upload repository files.",
206+
"category": "Repository",
207+
"tier": "free",
208+
"readOnly": false
209+
},
210+
{
211+
"name": "browse_milestones",
212+
"description": "Track milestone progress with associated issues and MRs.",
213+
"category": "Planning",
214+
"tier": "free",
215+
"readOnly": true
216+
},
217+
{
218+
"name": "manage_milestone",
219+
"description": "Create, update, or delete project/group milestones.",
220+
"category": "Planning",
221+
"tier": "free",
222+
"readOnly": false
223+
},
224+
{
225+
"name": "browse_pipelines",
226+
"description": "Monitor CI/CD pipelines and read job logs.",
227+
"category": "CI/CD",
228+
"tier": "free",
229+
"readOnly": true
230+
},
231+
{
232+
"name": "manage_pipeline",
233+
"description": "Trigger, retry, or cancel CI/CD pipelines.",
234+
"category": "CI/CD",
235+
"tier": "free",
236+
"readOnly": false
237+
},
238+
{
239+
"name": "manage_pipeline_job",
240+
"description": "Control individual CI/CD jobs within a pipeline.",
241+
"category": "CI/CD",
242+
"tier": "free",
243+
"readOnly": false
244+
},
245+
{
246+
"name": "browse_variables",
247+
"description": "List and inspect CI/CD variables for projects or groups.",
248+
"category": "CI/CD",
249+
"tier": "free",
250+
"readOnly": true
251+
},
252+
{
253+
"name": "manage_variable",
254+
"description": "Create, update, or delete CI/CD variables with environment scoping.",
255+
"category": "CI/CD",
256+
"tier": "free",
257+
"readOnly": false
258+
},
259+
{
260+
"name": "browse_wiki",
261+
"description": "Read wiki pages in projects or groups.",
262+
"category": "Content",
263+
"tier": "free",
264+
"readOnly": true
265+
},
266+
{
267+
"name": "manage_wiki",
268+
"description": "Create, update, or delete wiki pages.",
269+
"category": "Content",
270+
"tier": "free",
271+
"readOnly": false
272+
},
273+
{
274+
"name": "browse_work_items",
275+
"description": "Find and inspect issues, epics, tasks, and other work items.",
276+
"category": "Planning",
277+
"tier": "free",
278+
"readOnly": true
279+
},
280+
{
281+
"name": "manage_work_item",
282+
"description": "Create, update, delete, or link work items (issues, epics, tasks).",
283+
"category": "Planning",
284+
"tier": "free",
285+
"readOnly": false
286+
},
287+
{
288+
"name": "browse_snippets",
289+
"description": "Find and read code snippets with versioning support.",
290+
"category": "Content",
291+
"tier": "free",
292+
"readOnly": true
293+
},
294+
{
295+
"name": "manage_snippet",
296+
"description": "Create, update, or delete code snippets with multi-file support.",
297+
"category": "Content",
298+
"tier": "free",
299+
"readOnly": false
300+
},
301+
{
302+
"name": "browse_webhooks",
303+
"description": "List and inspect webhook configurations for projects or groups.",
304+
"category": "Integrations",
305+
"tier": "free",
306+
"readOnly": true
307+
},
308+
{
309+
"name": "manage_webhook",
310+
"description": "Create, update, delete, or test webhooks for event-driven automation.",
311+
"category": "Integrations",
312+
"tier": "free",
313+
"readOnly": false
314+
},
315+
{
316+
"name": "browse_integrations",
317+
"description": "Discover active project integrations and their configuration.",
318+
"category": "Integrations",
319+
"tier": "free",
320+
"readOnly": true
321+
},
322+
{
323+
"name": "manage_integration",
324+
"description": "Configure or disable project integrations (50+ supported).",
325+
"category": "Integrations",
326+
"tier": "free",
327+
"readOnly": false
328+
},
329+
{
330+
"name": "browse_releases",
331+
"description": "View project releases and asset download links.",
332+
"category": "Releases",
333+
"tier": "free",
334+
"readOnly": true
335+
},
336+
{
337+
"name": "manage_release",
338+
"description": "Create, update, or delete project releases with asset management.",
339+
"category": "Releases",
340+
"tier": "free",
341+
"readOnly": false
342+
},
343+
{
344+
"name": "browse_refs",
345+
"description": "Inspect branches, tags, and their protection rules.",
346+
"category": "Repository",
347+
"tier": "free",
348+
"readOnly": true
349+
},
350+
{
351+
"name": "manage_ref",
352+
"description": "Create, delete, and protect branches and tags.",
353+
"category": "Repository",
354+
"tier": "free",
355+
"readOnly": false
356+
},
357+
{
358+
"name": "browse_members",
359+
"description": "View team members and access levels in projects or groups.",
360+
"category": "Access",
361+
"tier": "free",
362+
"readOnly": true
363+
},
364+
{
365+
"name": "manage_member",
366+
"description": "Add, remove, or update access levels for project/group members.",
367+
"category": "Access",
368+
"tier": "free",
369+
"readOnly": false
370+
},
371+
{
372+
"name": "browse_search",
373+
"description": "Search across GitLab resources globally or within a scope.",
374+
"category": "Discovery",
375+
"tier": "free",
376+
"readOnly": true
377+
},
378+
{
379+
"name": "browse_iterations",
380+
"description": "View group iterations for agile sprint planning.",
381+
"category": "Planning",
382+
"tier": "premium",
383+
"readOnly": true
384+
}
385+
]
386+
},
13387
"license": "Apache-2.0",
14388
"author": "Dmitry Prudnikov <[email protected]>",
15389
"packageManager": "[email protected]",

0 commit comments

Comments
 (0)