@zereight/mcp-gitlab 2.0.5 → 2.0.7
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 +1 -0
- package/build/index.js +197 -100
- package/build/schemas.js +106 -100
- package/build/test/readonly-mcp-tests.js +381 -0
- package/package.json +5 -1
package/build/index.js
CHANGED
|
@@ -29,7 +29,7 @@ GitLabDiscussionNoteSchema, // Added
|
|
|
29
29
|
GitLabDiscussionSchema,
|
|
30
30
|
// Draft Notes Schemas
|
|
31
31
|
GitLabDraftNoteSchema, GitLabForkSchema, GitLabIssueLinkSchema, GitLabIssueSchema, GitLabIssueWithLinkDetailsSchema, GitLabMarkdownUploadSchema, GitLabMergeRequestSchema, GitLabMilestonesSchema, GitLabNamespaceExistsResponseSchema, GitLabNamespaceSchema, GitLabPipelineJobSchema, GitLabPipelineSchema, GitLabPipelineTriggerJobSchema, GitLabProjectMemberSchema, GitLabProjectSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabSearchResponseSchema, GitLabTreeItemSchema, GitLabTreeSchema, GitLabUserSchema, GitLabUsersResponseSchema, GitLabWikiPageSchema, GroupIteration, ListCommitsSchema, ListDraftNotesSchema, ListGroupIterationsSchema, ListGroupProjectsSchema, ListIssueDiscussionsSchema, ListIssueLinksSchema, ListIssuesSchema, ListLabelsSchema, ListMergeRequestDiffsSchema, // Added
|
|
32
|
-
ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListPipelineTriggerJobsSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, MarkdownUploadSchema, DownloadAttachmentSchema, MergeMergeRequestSchema, MyIssuesSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema } from "./schemas.js";
|
|
32
|
+
ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListPipelineTriggerJobsSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, MarkdownUploadSchema, DownloadAttachmentSchema, MergeMergeRequestSchema, MyIssuesSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema, ExecuteGraphQLSchema } from "./schemas.js";
|
|
33
33
|
import { randomUUID } from "crypto";
|
|
34
34
|
import { pino } from "pino";
|
|
35
35
|
const logger = pino({
|
|
@@ -213,452 +213,459 @@ const DEFAULT_FETCH_CONFIG = {
|
|
|
213
213
|
return httpAgent;
|
|
214
214
|
},
|
|
215
215
|
};
|
|
216
|
+
const toJSONSchema = (schema) => zodToJsonSchema(schema, { $refStrategy: 'none' });
|
|
216
217
|
// Define all available tools
|
|
217
218
|
const allTools = [
|
|
218
219
|
{
|
|
219
220
|
name: "merge_merge_request",
|
|
220
221
|
description: "Merge a merge request in a GitLab project",
|
|
221
|
-
inputSchema:
|
|
222
|
+
inputSchema: toJSONSchema(MergeMergeRequestSchema),
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "execute_graphql",
|
|
226
|
+
description: "Execute a GitLab GraphQL query",
|
|
227
|
+
inputSchema: zodToJsonSchema(ExecuteGraphQLSchema),
|
|
222
228
|
},
|
|
223
229
|
{
|
|
224
230
|
name: "create_or_update_file",
|
|
225
231
|
description: "Create or update a single file in a GitLab project",
|
|
226
|
-
inputSchema:
|
|
232
|
+
inputSchema: toJSONSchema(CreateOrUpdateFileSchema),
|
|
227
233
|
},
|
|
228
234
|
{
|
|
229
235
|
name: "search_repositories",
|
|
230
236
|
description: "Search for GitLab projects",
|
|
231
|
-
inputSchema:
|
|
237
|
+
inputSchema: toJSONSchema(SearchRepositoriesSchema),
|
|
232
238
|
},
|
|
233
239
|
{
|
|
234
240
|
name: "create_repository",
|
|
235
241
|
description: "Create a new GitLab project",
|
|
236
|
-
inputSchema:
|
|
242
|
+
inputSchema: toJSONSchema(CreateRepositorySchema),
|
|
237
243
|
},
|
|
238
244
|
{
|
|
239
245
|
name: "get_file_contents",
|
|
240
246
|
description: "Get the contents of a file or directory from a GitLab project",
|
|
241
|
-
inputSchema:
|
|
247
|
+
inputSchema: toJSONSchema(GetFileContentsSchema),
|
|
242
248
|
},
|
|
243
249
|
{
|
|
244
250
|
name: "push_files",
|
|
245
251
|
description: "Push multiple files to a GitLab project in a single commit",
|
|
246
|
-
inputSchema:
|
|
252
|
+
inputSchema: toJSONSchema(PushFilesSchema),
|
|
247
253
|
},
|
|
248
254
|
{
|
|
249
255
|
name: "create_issue",
|
|
250
256
|
description: "Create a new issue in a GitLab project",
|
|
251
|
-
inputSchema:
|
|
257
|
+
inputSchema: toJSONSchema(CreateIssueSchema),
|
|
252
258
|
},
|
|
253
259
|
{
|
|
254
260
|
name: "create_merge_request",
|
|
255
261
|
description: "Create a new merge request in a GitLab project",
|
|
256
|
-
inputSchema:
|
|
262
|
+
inputSchema: toJSONSchema(CreateMergeRequestSchema),
|
|
257
263
|
},
|
|
258
264
|
{
|
|
259
265
|
name: "fork_repository",
|
|
260
266
|
description: "Fork a GitLab project to your account or specified namespace",
|
|
261
|
-
inputSchema:
|
|
267
|
+
inputSchema: toJSONSchema(ForkRepositorySchema),
|
|
262
268
|
},
|
|
263
269
|
{
|
|
264
270
|
name: "create_branch",
|
|
265
271
|
description: "Create a new branch in a GitLab project",
|
|
266
|
-
inputSchema:
|
|
272
|
+
inputSchema: toJSONSchema(CreateBranchSchema),
|
|
267
273
|
},
|
|
268
274
|
{
|
|
269
275
|
name: "get_merge_request",
|
|
270
276
|
description: "Get details of a merge request (Either mergeRequestIid or branchName must be provided)",
|
|
271
|
-
inputSchema:
|
|
277
|
+
inputSchema: toJSONSchema(GetMergeRequestSchema),
|
|
272
278
|
},
|
|
273
279
|
{
|
|
274
280
|
name: "get_merge_request_diffs",
|
|
275
281
|
description: "Get the changes/diffs of a merge request (Either mergeRequestIid or branchName must be provided)",
|
|
276
|
-
inputSchema:
|
|
282
|
+
inputSchema: toJSONSchema(GetMergeRequestDiffsSchema),
|
|
277
283
|
},
|
|
278
284
|
{
|
|
279
285
|
name: "list_merge_request_diffs",
|
|
280
286
|
description: "List merge request diffs with pagination support (Either mergeRequestIid or branchName must be provided)",
|
|
281
|
-
inputSchema:
|
|
287
|
+
inputSchema: toJSONSchema(ListMergeRequestDiffsSchema),
|
|
282
288
|
},
|
|
283
289
|
{
|
|
284
290
|
name: "get_branch_diffs",
|
|
285
291
|
description: "Get the changes/diffs between two branches or commits in a GitLab project",
|
|
286
|
-
inputSchema:
|
|
292
|
+
inputSchema: toJSONSchema(GetBranchDiffsSchema),
|
|
287
293
|
},
|
|
288
294
|
{
|
|
289
295
|
name: "update_merge_request",
|
|
290
296
|
description: "Update a merge request (Either mergeRequestIid or branchName must be provided)",
|
|
291
|
-
inputSchema:
|
|
297
|
+
inputSchema: toJSONSchema(UpdateMergeRequestSchema),
|
|
292
298
|
},
|
|
293
299
|
{
|
|
294
300
|
name: "create_note",
|
|
295
301
|
description: "Create a new note (comment) to an issue or merge request",
|
|
296
|
-
inputSchema:
|
|
302
|
+
inputSchema: toJSONSchema(CreateNoteSchema),
|
|
297
303
|
},
|
|
298
304
|
{
|
|
299
305
|
name: "create_merge_request_thread",
|
|
300
306
|
description: "Create a new thread on a merge request",
|
|
301
|
-
inputSchema:
|
|
307
|
+
inputSchema: toJSONSchema(CreateMergeRequestThreadSchema),
|
|
302
308
|
},
|
|
303
309
|
{
|
|
304
310
|
name: "mr_discussions",
|
|
305
311
|
description: "List discussion items for a merge request",
|
|
306
|
-
inputSchema:
|
|
312
|
+
inputSchema: toJSONSchema(ListMergeRequestDiscussionsSchema),
|
|
307
313
|
},
|
|
308
314
|
{
|
|
309
315
|
name: "update_merge_request_note",
|
|
310
316
|
description: "Modify an existing merge request thread note",
|
|
311
|
-
inputSchema:
|
|
317
|
+
inputSchema: toJSONSchema(UpdateMergeRequestNoteSchema),
|
|
312
318
|
},
|
|
313
319
|
{
|
|
314
320
|
name: "create_merge_request_note",
|
|
315
321
|
description: "Add a new note to an existing merge request thread",
|
|
316
|
-
inputSchema:
|
|
322
|
+
inputSchema: toJSONSchema(CreateMergeRequestNoteSchema),
|
|
317
323
|
},
|
|
318
324
|
{
|
|
319
325
|
name: "get_draft_note",
|
|
320
326
|
description: "Get a single draft note from a merge request",
|
|
321
|
-
inputSchema:
|
|
327
|
+
inputSchema: toJSONSchema(GetDraftNoteSchema),
|
|
322
328
|
},
|
|
323
329
|
{
|
|
324
330
|
name: "list_draft_notes",
|
|
325
331
|
description: "List draft notes for a merge request",
|
|
326
|
-
inputSchema:
|
|
332
|
+
inputSchema: toJSONSchema(ListDraftNotesSchema),
|
|
327
333
|
},
|
|
328
334
|
{
|
|
329
335
|
name: "create_draft_note",
|
|
330
336
|
description: "Create a draft note for a merge request",
|
|
331
|
-
inputSchema:
|
|
337
|
+
inputSchema: toJSONSchema(CreateDraftNoteSchema),
|
|
332
338
|
},
|
|
333
339
|
{
|
|
334
340
|
name: "update_draft_note",
|
|
335
341
|
description: "Update an existing draft note",
|
|
336
|
-
inputSchema:
|
|
342
|
+
inputSchema: toJSONSchema(UpdateDraftNoteSchema),
|
|
337
343
|
},
|
|
338
344
|
{
|
|
339
345
|
name: "delete_draft_note",
|
|
340
346
|
description: "Delete a draft note",
|
|
341
|
-
inputSchema:
|
|
347
|
+
inputSchema: toJSONSchema(DeleteDraftNoteSchema),
|
|
342
348
|
},
|
|
343
349
|
{
|
|
344
350
|
name: "publish_draft_note",
|
|
345
351
|
description: "Publish a single draft note",
|
|
346
|
-
inputSchema:
|
|
352
|
+
inputSchema: toJSONSchema(PublishDraftNoteSchema),
|
|
347
353
|
},
|
|
348
354
|
{
|
|
349
355
|
name: "bulk_publish_draft_notes",
|
|
350
356
|
description: "Publish all draft notes for a merge request",
|
|
351
|
-
inputSchema:
|
|
357
|
+
inputSchema: toJSONSchema(BulkPublishDraftNotesSchema),
|
|
352
358
|
},
|
|
353
359
|
{
|
|
354
360
|
name: "update_issue_note",
|
|
355
361
|
description: "Modify an existing issue thread note",
|
|
356
|
-
inputSchema:
|
|
362
|
+
inputSchema: toJSONSchema(UpdateIssueNoteSchema),
|
|
357
363
|
},
|
|
358
364
|
{
|
|
359
365
|
name: "create_issue_note",
|
|
360
366
|
description: "Add a new note to an existing issue thread",
|
|
361
|
-
inputSchema:
|
|
367
|
+
inputSchema: toJSONSchema(CreateIssueNoteSchema),
|
|
362
368
|
},
|
|
363
369
|
{
|
|
364
370
|
name: "list_issues",
|
|
365
371
|
description: "List issues (default: created by current user only; use scope='all' for all accessible issues)",
|
|
366
|
-
inputSchema:
|
|
372
|
+
inputSchema: toJSONSchema(ListIssuesSchema),
|
|
367
373
|
},
|
|
368
374
|
{
|
|
369
375
|
name: "my_issues",
|
|
370
376
|
description: "List issues assigned to the authenticated user (defaults to open issues)",
|
|
371
|
-
inputSchema:
|
|
377
|
+
inputSchema: toJSONSchema(MyIssuesSchema),
|
|
372
378
|
},
|
|
373
379
|
{
|
|
374
380
|
name: "get_issue",
|
|
375
381
|
description: "Get details of a specific issue in a GitLab project",
|
|
376
|
-
inputSchema:
|
|
382
|
+
inputSchema: toJSONSchema(GetIssueSchema),
|
|
377
383
|
},
|
|
378
384
|
{
|
|
379
385
|
name: "update_issue",
|
|
380
386
|
description: "Update an issue in a GitLab project",
|
|
381
|
-
inputSchema:
|
|
387
|
+
inputSchema: toJSONSchema(UpdateIssueSchema),
|
|
382
388
|
},
|
|
383
389
|
{
|
|
384
390
|
name: "delete_issue",
|
|
385
391
|
description: "Delete an issue from a GitLab project",
|
|
386
|
-
inputSchema:
|
|
392
|
+
inputSchema: toJSONSchema(DeleteIssueSchema),
|
|
387
393
|
},
|
|
388
394
|
{
|
|
389
395
|
name: "list_issue_links",
|
|
390
396
|
description: "List all issue links for a specific issue",
|
|
391
|
-
inputSchema:
|
|
397
|
+
inputSchema: toJSONSchema(ListIssueLinksSchema),
|
|
392
398
|
},
|
|
393
399
|
{
|
|
394
400
|
name: "list_issue_discussions",
|
|
395
401
|
description: "List discussions for an issue in a GitLab project",
|
|
396
|
-
inputSchema:
|
|
402
|
+
inputSchema: toJSONSchema(ListIssueDiscussionsSchema),
|
|
397
403
|
},
|
|
398
404
|
{
|
|
399
405
|
name: "get_issue_link",
|
|
400
406
|
description: "Get a specific issue link",
|
|
401
|
-
inputSchema:
|
|
407
|
+
inputSchema: toJSONSchema(GetIssueLinkSchema),
|
|
402
408
|
},
|
|
403
409
|
{
|
|
404
410
|
name: "create_issue_link",
|
|
405
411
|
description: "Create an issue link between two issues",
|
|
406
|
-
inputSchema:
|
|
412
|
+
inputSchema: toJSONSchema(CreateIssueLinkSchema),
|
|
407
413
|
},
|
|
408
414
|
{
|
|
409
415
|
name: "delete_issue_link",
|
|
410
416
|
description: "Delete an issue link",
|
|
411
|
-
inputSchema:
|
|
417
|
+
inputSchema: toJSONSchema(DeleteIssueLinkSchema),
|
|
412
418
|
},
|
|
413
419
|
{
|
|
414
420
|
name: "list_namespaces",
|
|
415
421
|
description: "List all namespaces available to the current user",
|
|
416
|
-
inputSchema:
|
|
422
|
+
inputSchema: toJSONSchema(ListNamespacesSchema),
|
|
417
423
|
},
|
|
418
424
|
{
|
|
419
425
|
name: "get_namespace",
|
|
420
426
|
description: "Get details of a namespace by ID or path",
|
|
421
|
-
inputSchema:
|
|
427
|
+
inputSchema: toJSONSchema(GetNamespaceSchema),
|
|
422
428
|
},
|
|
423
429
|
{
|
|
424
430
|
name: "verify_namespace",
|
|
425
431
|
description: "Verify if a namespace path exists",
|
|
426
|
-
inputSchema:
|
|
432
|
+
inputSchema: toJSONSchema(VerifyNamespaceSchema),
|
|
427
433
|
},
|
|
428
434
|
{
|
|
429
435
|
name: "get_project",
|
|
430
436
|
description: "Get details of a specific project",
|
|
431
|
-
inputSchema:
|
|
437
|
+
inputSchema: toJSONSchema(GetProjectSchema),
|
|
432
438
|
},
|
|
433
439
|
{
|
|
434
440
|
name: "list_projects",
|
|
435
441
|
description: "List projects accessible by the current user",
|
|
436
|
-
inputSchema:
|
|
442
|
+
inputSchema: toJSONSchema(ListProjectsSchema),
|
|
437
443
|
},
|
|
438
444
|
{
|
|
439
445
|
name: "list_project_members",
|
|
440
446
|
description: "List members of a GitLab project",
|
|
441
|
-
inputSchema:
|
|
447
|
+
inputSchema: toJSONSchema(ListProjectMembersSchema),
|
|
442
448
|
},
|
|
443
449
|
{
|
|
444
450
|
name: "list_labels",
|
|
445
451
|
description: "List labels for a project",
|
|
446
|
-
inputSchema:
|
|
452
|
+
inputSchema: toJSONSchema(ListLabelsSchema),
|
|
447
453
|
},
|
|
448
454
|
{
|
|
449
455
|
name: "get_label",
|
|
450
456
|
description: "Get a single label from a project",
|
|
451
|
-
inputSchema:
|
|
457
|
+
inputSchema: toJSONSchema(GetLabelSchema),
|
|
452
458
|
},
|
|
453
459
|
{
|
|
454
460
|
name: "create_label",
|
|
455
461
|
description: "Create a new label in a project",
|
|
456
|
-
inputSchema:
|
|
462
|
+
inputSchema: toJSONSchema(CreateLabelSchema),
|
|
457
463
|
},
|
|
458
464
|
{
|
|
459
465
|
name: "update_label",
|
|
460
466
|
description: "Update an existing label in a project",
|
|
461
|
-
inputSchema:
|
|
467
|
+
inputSchema: toJSONSchema(UpdateLabelSchema),
|
|
462
468
|
},
|
|
463
469
|
{
|
|
464
470
|
name: "delete_label",
|
|
465
471
|
description: "Delete a label from a project",
|
|
466
|
-
inputSchema:
|
|
472
|
+
inputSchema: toJSONSchema(DeleteLabelSchema),
|
|
467
473
|
},
|
|
468
474
|
{
|
|
469
475
|
name: "list_group_projects",
|
|
470
476
|
description: "List projects in a GitLab group with filtering options",
|
|
471
|
-
inputSchema:
|
|
477
|
+
inputSchema: toJSONSchema(ListGroupProjectsSchema),
|
|
472
478
|
},
|
|
473
479
|
{
|
|
474
480
|
name: "list_wiki_pages",
|
|
475
481
|
description: "List wiki pages in a GitLab project",
|
|
476
|
-
inputSchema:
|
|
482
|
+
inputSchema: toJSONSchema(ListWikiPagesSchema),
|
|
477
483
|
},
|
|
478
484
|
{
|
|
479
485
|
name: "get_wiki_page",
|
|
480
486
|
description: "Get details of a specific wiki page",
|
|
481
|
-
inputSchema:
|
|
487
|
+
inputSchema: toJSONSchema(GetWikiPageSchema),
|
|
482
488
|
},
|
|
483
489
|
{
|
|
484
490
|
name: "create_wiki_page",
|
|
485
491
|
description: "Create a new wiki page in a GitLab project",
|
|
486
|
-
inputSchema:
|
|
492
|
+
inputSchema: toJSONSchema(CreateWikiPageSchema),
|
|
487
493
|
},
|
|
488
494
|
{
|
|
489
495
|
name: "update_wiki_page",
|
|
490
496
|
description: "Update an existing wiki page in a GitLab project",
|
|
491
|
-
inputSchema:
|
|
497
|
+
inputSchema: toJSONSchema(UpdateWikiPageSchema),
|
|
492
498
|
},
|
|
493
499
|
{
|
|
494
500
|
name: "delete_wiki_page",
|
|
495
501
|
description: "Delete a wiki page from a GitLab project",
|
|
496
|
-
inputSchema:
|
|
502
|
+
inputSchema: toJSONSchema(DeleteWikiPageSchema),
|
|
497
503
|
},
|
|
498
504
|
{
|
|
499
505
|
name: "get_repository_tree",
|
|
500
506
|
description: "Get the repository tree for a GitLab project (list files and directories)",
|
|
501
|
-
inputSchema:
|
|
507
|
+
inputSchema: toJSONSchema(GetRepositoryTreeSchema),
|
|
502
508
|
},
|
|
503
509
|
{
|
|
504
510
|
name: "list_pipelines",
|
|
505
511
|
description: "List pipelines in a GitLab project with filtering options",
|
|
506
|
-
inputSchema:
|
|
512
|
+
inputSchema: toJSONSchema(ListPipelinesSchema),
|
|
507
513
|
},
|
|
508
514
|
{
|
|
509
515
|
name: "get_pipeline",
|
|
510
516
|
description: "Get details of a specific pipeline in a GitLab project",
|
|
511
|
-
inputSchema:
|
|
517
|
+
inputSchema: toJSONSchema(GetPipelineSchema),
|
|
512
518
|
},
|
|
513
519
|
{
|
|
514
520
|
name: "list_pipeline_jobs",
|
|
515
521
|
description: "List all jobs in a specific pipeline",
|
|
516
|
-
inputSchema:
|
|
522
|
+
inputSchema: toJSONSchema(ListPipelineJobsSchema),
|
|
517
523
|
},
|
|
518
524
|
{
|
|
519
525
|
name: "list_pipeline_trigger_jobs",
|
|
520
526
|
description: "List all trigger jobs (bridges) in a specific pipeline that trigger downstream pipelines",
|
|
521
|
-
inputSchema:
|
|
527
|
+
inputSchema: toJSONSchema(ListPipelineTriggerJobsSchema),
|
|
522
528
|
},
|
|
523
529
|
{
|
|
524
530
|
name: "get_pipeline_job",
|
|
525
531
|
description: "Get details of a GitLab pipeline job number",
|
|
526
|
-
inputSchema:
|
|
532
|
+
inputSchema: toJSONSchema(GetPipelineJobOutputSchema),
|
|
527
533
|
},
|
|
528
534
|
{
|
|
529
535
|
name: "get_pipeline_job_output",
|
|
530
536
|
description: "Get the output/trace of a GitLab pipeline job with optional pagination to limit context window usage",
|
|
531
|
-
inputSchema:
|
|
537
|
+
inputSchema: toJSONSchema(GetPipelineJobOutputSchema),
|
|
532
538
|
},
|
|
533
539
|
{
|
|
534
540
|
name: "create_pipeline",
|
|
535
541
|
description: "Create a new pipeline for a branch or tag",
|
|
536
|
-
inputSchema:
|
|
542
|
+
inputSchema: toJSONSchema(CreatePipelineSchema),
|
|
537
543
|
},
|
|
538
544
|
{
|
|
539
545
|
name: "retry_pipeline",
|
|
540
546
|
description: "Retry a failed or canceled pipeline",
|
|
541
|
-
inputSchema:
|
|
547
|
+
inputSchema: toJSONSchema(RetryPipelineSchema),
|
|
542
548
|
},
|
|
543
549
|
{
|
|
544
550
|
name: "cancel_pipeline",
|
|
545
551
|
description: "Cancel a running pipeline",
|
|
546
|
-
inputSchema:
|
|
552
|
+
inputSchema: toJSONSchema(CancelPipelineSchema),
|
|
547
553
|
},
|
|
548
554
|
{
|
|
549
555
|
name: "play_pipeline_job",
|
|
550
556
|
description: "Run a manual pipeline job",
|
|
551
|
-
inputSchema:
|
|
557
|
+
inputSchema: toJSONSchema(PlayPipelineJobSchema),
|
|
552
558
|
},
|
|
553
559
|
{
|
|
554
560
|
name: "retry_pipeline_job",
|
|
555
561
|
description: "Retry a failed or canceled pipeline job",
|
|
556
|
-
inputSchema:
|
|
562
|
+
inputSchema: toJSONSchema(RetryPipelineJobSchema),
|
|
557
563
|
},
|
|
558
564
|
{
|
|
559
565
|
name: "cancel_pipeline_job",
|
|
560
566
|
description: "Cancel a running pipeline job",
|
|
561
|
-
inputSchema:
|
|
567
|
+
inputSchema: toJSONSchema(CancelPipelineJobSchema),
|
|
562
568
|
},
|
|
563
569
|
{
|
|
564
570
|
name: "list_merge_requests",
|
|
565
571
|
description: "List merge requests in a GitLab project with filtering options",
|
|
566
|
-
inputSchema:
|
|
572
|
+
inputSchema: toJSONSchema(ListMergeRequestsSchema),
|
|
567
573
|
},
|
|
568
574
|
{
|
|
569
575
|
name: "list_milestones",
|
|
570
576
|
description: "List milestones in a GitLab project with filtering options",
|
|
571
|
-
inputSchema:
|
|
577
|
+
inputSchema: toJSONSchema(ListProjectMilestonesSchema),
|
|
572
578
|
},
|
|
573
579
|
{
|
|
574
580
|
name: "get_milestone",
|
|
575
581
|
description: "Get details of a specific milestone",
|
|
576
|
-
inputSchema:
|
|
582
|
+
inputSchema: toJSONSchema(GetProjectMilestoneSchema),
|
|
577
583
|
},
|
|
578
584
|
{
|
|
579
585
|
name: "create_milestone",
|
|
580
586
|
description: "Create a new milestone in a GitLab project",
|
|
581
|
-
inputSchema:
|
|
587
|
+
inputSchema: toJSONSchema(CreateProjectMilestoneSchema),
|
|
582
588
|
},
|
|
583
589
|
{
|
|
584
590
|
name: "edit_milestone",
|
|
585
591
|
description: "Edit an existing milestone in a GitLab project",
|
|
586
|
-
inputSchema:
|
|
592
|
+
inputSchema: toJSONSchema(EditProjectMilestoneSchema),
|
|
587
593
|
},
|
|
588
594
|
{
|
|
589
595
|
name: "delete_milestone",
|
|
590
596
|
description: "Delete a milestone from a GitLab project",
|
|
591
|
-
inputSchema:
|
|
597
|
+
inputSchema: toJSONSchema(DeleteProjectMilestoneSchema),
|
|
592
598
|
},
|
|
593
599
|
{
|
|
594
600
|
name: "get_milestone_issue",
|
|
595
601
|
description: "Get issues associated with a specific milestone",
|
|
596
|
-
inputSchema:
|
|
602
|
+
inputSchema: toJSONSchema(GetMilestoneIssuesSchema),
|
|
597
603
|
},
|
|
598
604
|
{
|
|
599
605
|
name: "get_milestone_merge_requests",
|
|
600
606
|
description: "Get merge requests associated with a specific milestone",
|
|
601
|
-
inputSchema:
|
|
607
|
+
inputSchema: toJSONSchema(GetMilestoneMergeRequestsSchema),
|
|
602
608
|
},
|
|
603
609
|
{
|
|
604
610
|
name: "promote_milestone",
|
|
605
611
|
description: "Promote a milestone to the next stage",
|
|
606
|
-
inputSchema:
|
|
612
|
+
inputSchema: toJSONSchema(PromoteProjectMilestoneSchema),
|
|
607
613
|
},
|
|
608
614
|
{
|
|
609
615
|
name: "get_milestone_burndown_events",
|
|
610
616
|
description: "Get burndown events for a specific milestone",
|
|
611
|
-
inputSchema:
|
|
617
|
+
inputSchema: toJSONSchema(GetMilestoneBurndownEventsSchema),
|
|
612
618
|
},
|
|
613
619
|
{
|
|
614
620
|
name: "get_users",
|
|
615
621
|
description: "Get GitLab user details by usernames",
|
|
616
|
-
inputSchema:
|
|
622
|
+
inputSchema: toJSONSchema(GetUsersSchema),
|
|
617
623
|
},
|
|
618
624
|
{
|
|
619
625
|
name: "list_commits",
|
|
620
626
|
description: "List repository commits with filtering options",
|
|
621
|
-
inputSchema:
|
|
627
|
+
inputSchema: toJSONSchema(ListCommitsSchema),
|
|
622
628
|
},
|
|
623
629
|
{
|
|
624
630
|
name: "get_commit",
|
|
625
631
|
description: "Get details of a specific commit",
|
|
626
|
-
inputSchema:
|
|
632
|
+
inputSchema: toJSONSchema(GetCommitSchema),
|
|
627
633
|
},
|
|
628
634
|
{
|
|
629
635
|
name: "get_commit_diff",
|
|
630
636
|
description: "Get changes/diffs of a specific commit",
|
|
631
|
-
inputSchema:
|
|
637
|
+
inputSchema: toJSONSchema(GetCommitDiffSchema),
|
|
632
638
|
},
|
|
633
639
|
{
|
|
634
640
|
name: "list_group_iterations",
|
|
635
641
|
description: "List group iterations with filtering options",
|
|
636
|
-
inputSchema:
|
|
642
|
+
inputSchema: toJSONSchema(ListGroupIterationsSchema),
|
|
637
643
|
},
|
|
638
644
|
{
|
|
639
645
|
name: "upload_markdown",
|
|
640
646
|
description: "Upload a file to a GitLab project for use in markdown content",
|
|
641
|
-
inputSchema:
|
|
647
|
+
inputSchema: toJSONSchema(MarkdownUploadSchema),
|
|
642
648
|
},
|
|
643
649
|
{
|
|
644
650
|
name: "download_attachment",
|
|
645
651
|
description: "Download an uploaded file from a GitLab project by secret and filename",
|
|
646
|
-
inputSchema:
|
|
652
|
+
inputSchema: toJSONSchema(DownloadAttachmentSchema),
|
|
647
653
|
},
|
|
648
654
|
{
|
|
649
655
|
name: "list_events",
|
|
650
656
|
description: "List all events for the currently authenticated user. Note: before/after parameters accept date format YYYY-MM-DD only",
|
|
651
|
-
inputSchema:
|
|
657
|
+
inputSchema: toJSONSchema(ListEventsSchema),
|
|
652
658
|
},
|
|
653
659
|
{
|
|
654
660
|
name: "get_project_events",
|
|
655
661
|
description: "List all visible events for a specified project. Note: before/after parameters accept date format YYYY-MM-DD only",
|
|
656
|
-
inputSchema:
|
|
662
|
+
inputSchema: toJSONSchema(GetProjectEventsSchema),
|
|
657
663
|
},
|
|
658
664
|
];
|
|
659
665
|
// Define which tools are read-only
|
|
660
666
|
const readOnlyTools = [
|
|
661
667
|
"search_repositories",
|
|
668
|
+
"execute_graphql",
|
|
662
669
|
"get_file_contents",
|
|
663
670
|
"get_merge_request",
|
|
664
671
|
"get_merge_request_diffs",
|
|
@@ -763,6 +770,7 @@ function normalizeGitLabApiUrl(url) {
|
|
|
763
770
|
const GITLAB_API_URL = normalizeGitLabApiUrl(process.env.GITLAB_API_URL || "");
|
|
764
771
|
const GITLAB_PROJECT_ID = process.env.GITLAB_PROJECT_ID;
|
|
765
772
|
const GITLAB_ALLOWED_PROJECT_IDS = process.env.GITLAB_ALLOWED_PROJECT_IDS?.split(',').map(id => id.trim()).filter(Boolean) || [];
|
|
773
|
+
const GITLAB_COMMIT_FILES_PER_PAGE = process.env.GITLAB_COMMIT_FILES_PER_PAGE ? parseInt(process.env.GITLAB_COMMIT_FILES_PER_PAGE) : 20;
|
|
766
774
|
if (!GITLAB_PERSONAL_ACCESS_TOKEN) {
|
|
767
775
|
logger.error("GITLAB_PERSONAL_ACCESS_TOKEN environment variable is not set");
|
|
768
776
|
process.exit(1);
|
|
@@ -3012,17 +3020,35 @@ async function getCommit(projectId, sha, stats) {
|
|
|
3012
3020
|
*
|
|
3013
3021
|
* @param {string} projectId - Project ID or URL-encoded path
|
|
3014
3022
|
* @param {string} sha - The commit hash or name of a repository branch or tag
|
|
3023
|
+
* @param {boolean} [full_diff] - Whether to return the full diff or only first page
|
|
3015
3024
|
* @returns {Promise<GitLabMergeRequestDiff[]>} The commit diffs
|
|
3016
3025
|
*/
|
|
3017
|
-
async function getCommitDiff(projectId, sha) {
|
|
3026
|
+
async function getCommitDiff(projectId, sha, full_diff) {
|
|
3018
3027
|
projectId = decodeURIComponent(projectId);
|
|
3019
|
-
const
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3028
|
+
const baseUrl = `${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/commits/${encodeURIComponent(sha)}/diff`;
|
|
3029
|
+
let allDiffs = [];
|
|
3030
|
+
let page = 1;
|
|
3031
|
+
while (true) {
|
|
3032
|
+
const url = new URL(baseUrl);
|
|
3033
|
+
if (full_diff) {
|
|
3034
|
+
url.searchParams.append("page", page.toString());
|
|
3035
|
+
}
|
|
3036
|
+
const response = await fetch(url.toString(), {
|
|
3037
|
+
...DEFAULT_FETCH_CONFIG,
|
|
3038
|
+
});
|
|
3039
|
+
await handleGitLabError(response);
|
|
3040
|
+
const data = await response.json();
|
|
3041
|
+
const diffs = z.array(GitLabDiffSchema).parse(data);
|
|
3042
|
+
allDiffs.push(...diffs);
|
|
3043
|
+
if (!full_diff) {
|
|
3044
|
+
break;
|
|
3045
|
+
}
|
|
3046
|
+
if (diffs.length < GITLAB_COMMIT_FILES_PER_PAGE) {
|
|
3047
|
+
break;
|
|
3048
|
+
}
|
|
3049
|
+
page++;
|
|
3050
|
+
}
|
|
3051
|
+
return allDiffs;
|
|
3026
3052
|
}
|
|
3027
3053
|
/**
|
|
3028
3054
|
* Get the current authenticated user
|
|
@@ -3114,8 +3140,8 @@ async function listGroupIterations(groupId, options = {}) {
|
|
|
3114
3140
|
url.searchParams.append("state", options.state);
|
|
3115
3141
|
if (options.search)
|
|
3116
3142
|
url.searchParams.append("search", options.search);
|
|
3117
|
-
if (options.
|
|
3118
|
-
url.searchParams.append("in", options.
|
|
3143
|
+
if (options.search_in)
|
|
3144
|
+
url.searchParams.append("in", options.search_in.join(","));
|
|
3119
3145
|
if (options.include_ancestors !== undefined)
|
|
3120
3146
|
url.searchParams.append("include_ancestors", options.include_ancestors.toString());
|
|
3121
3147
|
if (options.include_descendants !== undefined)
|
|
@@ -3288,6 +3314,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3288
3314
|
}
|
|
3289
3315
|
logger.info(request.params.name);
|
|
3290
3316
|
switch (request.params.name) {
|
|
3317
|
+
case "execute_graphql": {
|
|
3318
|
+
const args = ExecuteGraphQLSchema.parse(request.params.arguments);
|
|
3319
|
+
const apiUrl = new URL(GITLAB_API_URL);
|
|
3320
|
+
// Build GraphQL endpoint preserving any instance subpath (e.g. /gitlab)
|
|
3321
|
+
const restPath = apiUrl.pathname || ""; // e.g. /api/v4 or /gitlab/api/v4
|
|
3322
|
+
const idx = restPath.lastIndexOf("/api/v4");
|
|
3323
|
+
const prefix = idx >= 0 ? restPath.slice(0, idx) : "";
|
|
3324
|
+
const graphqlUrl = process.env.GITLAB_GRAPHQL_URL || `${apiUrl.origin}${prefix}/api/graphql`;
|
|
3325
|
+
// Add timeout to avoid hanging requests
|
|
3326
|
+
const controller = new AbortController();
|
|
3327
|
+
const timeoutMs = 45000;
|
|
3328
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
3329
|
+
logger.info({ endpoint: graphqlUrl }, "execute_graphql request");
|
|
3330
|
+
try {
|
|
3331
|
+
const response = await fetch(graphqlUrl, {
|
|
3332
|
+
...DEFAULT_FETCH_CONFIG,
|
|
3333
|
+
method: "POST",
|
|
3334
|
+
headers: {
|
|
3335
|
+
...DEFAULT_HEADERS,
|
|
3336
|
+
"Content-Type": "application/json",
|
|
3337
|
+
Accept: "application/json",
|
|
3338
|
+
},
|
|
3339
|
+
body: JSON.stringify({ query: args.query, variables: args.variables || {} }),
|
|
3340
|
+
signal: controller.signal,
|
|
3341
|
+
});
|
|
3342
|
+
if (!response.ok) {
|
|
3343
|
+
await handleGitLabError(response);
|
|
3344
|
+
}
|
|
3345
|
+
const json = await response.json();
|
|
3346
|
+
return {
|
|
3347
|
+
content: [{ type: "text", text: JSON.stringify(json, null, 2) }],
|
|
3348
|
+
};
|
|
3349
|
+
}
|
|
3350
|
+
catch (err) {
|
|
3351
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3352
|
+
return {
|
|
3353
|
+
content: [
|
|
3354
|
+
{
|
|
3355
|
+
type: "text",
|
|
3356
|
+
text: JSON.stringify({ error: `GraphQL request failed: ${message}` }, null, 2),
|
|
3357
|
+
},
|
|
3358
|
+
],
|
|
3359
|
+
};
|
|
3360
|
+
}
|
|
3361
|
+
finally {
|
|
3362
|
+
clearTimeout(timeout);
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3291
3365
|
case "fork_repository": {
|
|
3292
3366
|
if (GITLAB_PROJECT_ID) {
|
|
3293
3367
|
throw new Error("Direct project ID is set. So fork_repository is not allowed");
|
|
@@ -4096,7 +4170,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4096
4170
|
}
|
|
4097
4171
|
case "get_commit_diff": {
|
|
4098
4172
|
const args = GetCommitDiffSchema.parse(request.params.arguments);
|
|
4099
|
-
const diff = await getCommitDiff(args.project_id, args.sha);
|
|
4173
|
+
const diff = await getCommitDiff(args.project_id, args.sha, args.full_diff);
|
|
4100
4174
|
return {
|
|
4101
4175
|
content: [{ type: "text", text: JSON.stringify(diff, null, 2) }],
|
|
4102
4176
|
};
|
|
@@ -4269,6 +4343,29 @@ async function startStreamableHTTPServer() {
|
|
|
4269
4343
|
});
|
|
4270
4344
|
}
|
|
4271
4345
|
});
|
|
4346
|
+
// to delete a mcp server session explicitly
|
|
4347
|
+
app.delete("/mcp", async (req, res) => {
|
|
4348
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
4349
|
+
if (!sessionId) {
|
|
4350
|
+
res.status(400).json({ error: "mcp-session-id header is required" });
|
|
4351
|
+
return;
|
|
4352
|
+
}
|
|
4353
|
+
const transport = streamableTransports[sessionId];
|
|
4354
|
+
if (transport) {
|
|
4355
|
+
try {
|
|
4356
|
+
await transport.close();
|
|
4357
|
+
logger.info(`Explicitly closed session via DELETE request: ${sessionId}`);
|
|
4358
|
+
res.status(204).send();
|
|
4359
|
+
}
|
|
4360
|
+
catch (error) {
|
|
4361
|
+
logger.error(`Error closing session ${sessionId}:`, error);
|
|
4362
|
+
res.status(500).json({ error: "Failed to close session" });
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
else {
|
|
4366
|
+
res.status(404).json({ error: "Session not found" });
|
|
4367
|
+
}
|
|
4368
|
+
});
|
|
4272
4369
|
// Health check endpoint
|
|
4273
4370
|
app.get("/health", (_, res) => {
|
|
4274
4371
|
res.status(200).json({
|