@structured-world/gitlab-mcp 6.36.0 → 6.38.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 +4 -4
- package/dist/src/cli/list-tools.js +51 -33
- package/dist/src/cli/list-tools.js.map +1 -1
- package/dist/src/cli/setup/presets.js +30 -17
- package/dist/src/cli/setup/presets.js.map +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.js +3 -2
- package/dist/src/config.js.map +1 -1
- package/dist/src/entities/core/registry.js +234 -204
- package/dist/src/entities/core/registry.js.map +1 -1
- package/dist/src/entities/core/schema-readonly.d.ts +23 -47
- package/dist/src/entities/core/schema-readonly.js +22 -42
- package/dist/src/entities/core/schema-readonly.js.map +1 -1
- package/dist/src/entities/core/schema.d.ts +60 -15
- package/dist/src/entities/core/schema.js +76 -12
- package/dist/src/entities/core/schema.js.map +1 -1
- package/dist/src/entities/files/registry.js +13 -0
- package/dist/src/entities/files/registry.js.map +1 -1
- package/dist/src/entities/files/schema-readonly.d.ts +5 -0
- package/dist/src/entities/files/schema-readonly.js +7 -0
- package/dist/src/entities/files/schema-readonly.js.map +1 -1
- package/dist/src/entities/index.d.ts +1 -0
- package/dist/src/entities/index.js +1 -0
- package/dist/src/entities/index.js.map +1 -1
- package/dist/src/entities/iterations/index.d.ts +2 -0
- package/dist/src/entities/iterations/index.js +19 -0
- package/dist/src/entities/iterations/index.js.map +1 -0
- package/dist/src/entities/iterations/registry.d.ts +5 -0
- package/dist/src/entities/iterations/registry.js +106 -0
- package/dist/src/entities/iterations/registry.js.map +1 -0
- package/dist/src/entities/iterations/schema-readonly.d.ts +21 -0
- package/dist/src/entities/iterations/schema-readonly.js +28 -0
- package/dist/src/entities/iterations/schema-readonly.js.map +1 -0
- package/dist/src/entities/pipelines/schema-readonly.d.ts +1 -1
- package/dist/src/entities/search/schema-readonly.d.ts +7 -7
- package/dist/src/entities/shared.d.ts +2 -2
- package/dist/src/entities/snippets/schema-readonly.d.ts +2 -2
- package/dist/src/entities/snippets/schema.d.ts +4 -4
- package/dist/src/entities/workitems/registry.js +169 -5
- package/dist/src/entities/workitems/registry.js.map +1 -1
- package/dist/src/entities/workitems/schema.d.ts +51 -0
- package/dist/src/entities/workitems/schema.js +125 -0
- package/dist/src/entities/workitems/schema.js.map +1 -1
- package/dist/src/graphql/workItems.d.ts +125 -1
- package/dist/src/graphql/workItems.js +158 -1
- package/dist/src/graphql/workItems.js.map +1 -1
- package/dist/src/profiles/builtin/code-reviewer.yaml +2 -2
- package/dist/src/profiles/builtin/developer.yaml +1 -1
- package/dist/src/registry-manager.js +11 -0
- package/dist/src/registry-manager.js.map +1 -1
- package/dist/src/services/ToolAvailability.d.ts +1 -2
- package/dist/src/services/ToolAvailability.js +38 -384
- package/dist/src/services/ToolAvailability.js.map +1 -1
- package/dist/src/services/WidgetAvailability.js +10 -5
- package/dist/src/services/WidgetAvailability.js.map +1 -1
- package/dist/src/utils/error-handler.js +1 -1
- package/dist/src/utils/error-handler.js.map +1 -1
- package/dist/src/utils/idConversion.d.ts +11 -0
- package/dist/src/utils/idConversion.js +13 -0
- package/dist/src/utils/idConversion.js.map +1 -1
- package/dist/structured-world-gitlab-mcp-6.38.0.tgz +0 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/structured-world-gitlab-mcp-6.36.0.tgz +0 -0
|
@@ -50,7 +50,7 @@ exports.coreToolRegistry = new Map([
|
|
|
50
50
|
"browse_projects",
|
|
51
51
|
{
|
|
52
52
|
name: "browse_projects",
|
|
53
|
-
description: "
|
|
53
|
+
description: "Find, list, or inspect GitLab projects. Actions: search (find by name/topic across GitLab), list (browse accessible projects or group projects), get (retrieve full project details). Related: manage_project to create/update/delete projects.",
|
|
54
54
|
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseProjectsSchema),
|
|
55
55
|
handler: async (args) => {
|
|
56
56
|
const input = schema_readonly_1.BrowseProjectsSchema.parse(args);
|
|
@@ -173,7 +173,7 @@ exports.coreToolRegistry = new Map([
|
|
|
173
173
|
"browse_namespaces",
|
|
174
174
|
{
|
|
175
175
|
name: "browse_namespaces",
|
|
176
|
-
description: "
|
|
176
|
+
description: "Explore GitLab groups and user namespaces. Actions: list (discover available namespaces), get (retrieve details with storage stats), verify (check if path exists). Related: manage_namespace to create/update/delete groups.",
|
|
177
177
|
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseNamespacesSchema),
|
|
178
178
|
handler: async (args) => {
|
|
179
179
|
const input = schema_readonly_1.BrowseNamespacesSchema.parse(args);
|
|
@@ -237,7 +237,7 @@ exports.coreToolRegistry = new Map([
|
|
|
237
237
|
"browse_commits",
|
|
238
238
|
{
|
|
239
239
|
name: "browse_commits",
|
|
240
|
-
description: "
|
|
240
|
+
description: "Explore repository commit history and diffs. Actions: list (browse commits with filters), get (retrieve commit metadata and stats), diff (view code changes). Related: browse_refs for branch/tag info.",
|
|
241
241
|
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseCommitsSchema),
|
|
242
242
|
handler: async (args) => {
|
|
243
243
|
const input = schema_readonly_1.BrowseCommitsSchema.parse(args);
|
|
@@ -317,7 +317,7 @@ exports.coreToolRegistry = new Map([
|
|
|
317
317
|
"browse_events",
|
|
318
318
|
{
|
|
319
319
|
name: "browse_events",
|
|
320
|
-
description: "
|
|
320
|
+
description: "Track GitLab activity and events. Actions: user (your activity across all projects), project (specific project activity feed). Filter by date range, action type, or target type.",
|
|
321
321
|
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseEventsSchema),
|
|
322
322
|
handler: async (args) => {
|
|
323
323
|
const input = schema_readonly_1.BrowseEventsSchema.parse(args);
|
|
@@ -369,15 +369,110 @@ exports.coreToolRegistry = new Map([
|
|
|
369
369
|
},
|
|
370
370
|
],
|
|
371
371
|
[
|
|
372
|
-
"
|
|
372
|
+
"browse_users",
|
|
373
373
|
{
|
|
374
|
-
name: "
|
|
375
|
-
description: "
|
|
376
|
-
inputSchema: z.toJSONSchema(
|
|
374
|
+
name: "browse_users",
|
|
375
|
+
description: "Find GitLab users with smart pattern detection. Actions: search (find users by name/email/username with transliteration support), get (retrieve specific user by ID). Related: browse_members for project/group membership.",
|
|
376
|
+
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseUsersSchema),
|
|
377
377
|
handler: async (args) => {
|
|
378
|
-
const input =
|
|
379
|
-
if ((0, config_1.isActionDenied)("
|
|
380
|
-
throw new Error(`Action '${input.action}' is not allowed for
|
|
378
|
+
const input = schema_readonly_1.BrowseUsersSchema.parse(args);
|
|
379
|
+
if ((0, config_1.isActionDenied)("browse_users", input.action)) {
|
|
380
|
+
throw new Error(`Action '${input.action}' is not allowed for browse_users tool`);
|
|
381
|
+
}
|
|
382
|
+
switch (input.action) {
|
|
383
|
+
case "search": {
|
|
384
|
+
const { smart_search, search, username, public_email, ...otherParams } = input;
|
|
385
|
+
const hasUsernameOrEmail = Boolean(username) || Boolean(public_email);
|
|
386
|
+
const hasOnlySearch = Boolean(search) && !hasUsernameOrEmail;
|
|
387
|
+
const shouldUseSmartSearch = smart_search === false ? false : smart_search === true || hasOnlySearch;
|
|
388
|
+
if (shouldUseSmartSearch && (search || username || public_email)) {
|
|
389
|
+
const query = search ?? username ?? public_email ?? "";
|
|
390
|
+
const additionalParams = {};
|
|
391
|
+
Object.entries(otherParams).forEach(([key, value]) => {
|
|
392
|
+
if (value !== undefined && key !== "smart_search" && key !== "action") {
|
|
393
|
+
additionalParams[key] = value;
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
return await (0, smart_user_search_1.smartUserSearch)(query, additionalParams);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
const queryParams = new URLSearchParams();
|
|
400
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
401
|
+
if (value !== undefined && key !== "smart_search" && key !== "action") {
|
|
402
|
+
queryParams.set(key, String(value));
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/users?${queryParams}`;
|
|
406
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl);
|
|
407
|
+
if (!response.ok) {
|
|
408
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
409
|
+
}
|
|
410
|
+
const users = await response.json();
|
|
411
|
+
return (0, idConversion_1.cleanGidsFromObject)(users);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
case "get": {
|
|
415
|
+
const { user_id } = input;
|
|
416
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/users/${encodeURIComponent(user_id)}`;
|
|
417
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl);
|
|
418
|
+
if (!response.ok) {
|
|
419
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
420
|
+
}
|
|
421
|
+
const user = await response.json();
|
|
422
|
+
return (0, idConversion_1.cleanGidsFromObject)(user);
|
|
423
|
+
}
|
|
424
|
+
default:
|
|
425
|
+
throw new Error(`Unknown action: ${input.action}`);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
],
|
|
430
|
+
[
|
|
431
|
+
"browse_todos",
|
|
432
|
+
{
|
|
433
|
+
name: "browse_todos",
|
|
434
|
+
description: "View your GitLab todo queue (notifications requiring action). Actions: list (filter by state, action type, target type). Todos are auto-created for assignments, mentions, reviews, and pipeline failures. Related: manage_todos to mark done/restore.",
|
|
435
|
+
inputSchema: z.toJSONSchema(schema_readonly_1.BrowseTodosSchema),
|
|
436
|
+
handler: async (args) => {
|
|
437
|
+
const input = schema_readonly_1.BrowseTodosSchema.parse(args);
|
|
438
|
+
if ((0, config_1.isActionDenied)("browse_todos", input.action)) {
|
|
439
|
+
throw new Error(`Action '${input.action}' is not allowed for browse_todos tool`);
|
|
440
|
+
}
|
|
441
|
+
switch (input.action) {
|
|
442
|
+
case "list": {
|
|
443
|
+
const queryParams = new URLSearchParams();
|
|
444
|
+
const { action: _action, todo_action, ...rest } = input;
|
|
445
|
+
if (todo_action)
|
|
446
|
+
queryParams.set("action", todo_action);
|
|
447
|
+
Object.entries(rest).forEach(([key, value]) => {
|
|
448
|
+
if (value !== undefined) {
|
|
449
|
+
queryParams.set(key, String(value));
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/todos?${queryParams}`;
|
|
453
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl);
|
|
454
|
+
if (!response.ok) {
|
|
455
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
456
|
+
}
|
|
457
|
+
const todos = await response.json();
|
|
458
|
+
return (0, idConversion_1.cleanGidsFromObject)(todos);
|
|
459
|
+
}
|
|
460
|
+
default:
|
|
461
|
+
throw new Error(`Unknown action: ${input.action}`);
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
],
|
|
466
|
+
[
|
|
467
|
+
"manage_project",
|
|
468
|
+
{
|
|
469
|
+
name: "manage_project",
|
|
470
|
+
description: "Create, update, or manage GitLab projects. Actions: create (new project with settings), fork (copy existing project), update (modify settings), delete (remove permanently), archive/unarchive (toggle read-only), transfer (move to different namespace). Related: browse_projects for discovery.",
|
|
471
|
+
inputSchema: z.toJSONSchema(schema_1.ManageProjectSchema),
|
|
472
|
+
handler: async (args) => {
|
|
473
|
+
const input = schema_1.ManageProjectSchema.parse(args);
|
|
474
|
+
if ((0, config_1.isActionDenied)("manage_project", input.action)) {
|
|
475
|
+
throw new Error(`Action '${input.action}' is not allowed for manage_project tool`);
|
|
381
476
|
}
|
|
382
477
|
switch (input.action) {
|
|
383
478
|
case "create": {
|
|
@@ -479,6 +574,67 @@ exports.coreToolRegistry = new Map([
|
|
|
479
574
|
}
|
|
480
575
|
return await response.json();
|
|
481
576
|
}
|
|
577
|
+
case "update": {
|
|
578
|
+
const { project_id, action: _action, ...updateParams } = input;
|
|
579
|
+
const body = new URLSearchParams();
|
|
580
|
+
Object.entries(updateParams).forEach(([key, value]) => {
|
|
581
|
+
if (value !== undefined) {
|
|
582
|
+
body.set(key, String(value));
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${(0, projectIdentifier_1.normalizeProjectId)(project_id)}`;
|
|
586
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
587
|
+
method: "PUT",
|
|
588
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
589
|
+
body: body.toString(),
|
|
590
|
+
});
|
|
591
|
+
if (!response.ok) {
|
|
592
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
593
|
+
}
|
|
594
|
+
return await response.json();
|
|
595
|
+
}
|
|
596
|
+
case "delete": {
|
|
597
|
+
const { project_id } = input;
|
|
598
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${(0, projectIdentifier_1.normalizeProjectId)(project_id)}`;
|
|
599
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, { method: "DELETE" });
|
|
600
|
+
if (!response.ok) {
|
|
601
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
602
|
+
}
|
|
603
|
+
return { success: true, message: `Project ${project_id} deleted` };
|
|
604
|
+
}
|
|
605
|
+
case "archive": {
|
|
606
|
+
const { project_id } = input;
|
|
607
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${(0, projectIdentifier_1.normalizeProjectId)(project_id)}/archive`;
|
|
608
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, { method: "POST" });
|
|
609
|
+
if (!response.ok) {
|
|
610
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
611
|
+
}
|
|
612
|
+
return await response.json();
|
|
613
|
+
}
|
|
614
|
+
case "unarchive": {
|
|
615
|
+
const { project_id } = input;
|
|
616
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${(0, projectIdentifier_1.normalizeProjectId)(project_id)}/unarchive`;
|
|
617
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, { method: "POST" });
|
|
618
|
+
if (!response.ok) {
|
|
619
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
620
|
+
}
|
|
621
|
+
return await response.json();
|
|
622
|
+
}
|
|
623
|
+
case "transfer": {
|
|
624
|
+
const { project_id, namespace } = input;
|
|
625
|
+
const body = new URLSearchParams();
|
|
626
|
+
body.set("namespace", namespace);
|
|
627
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${(0, projectIdentifier_1.normalizeProjectId)(project_id)}/transfer`;
|
|
628
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
629
|
+
method: "PUT",
|
|
630
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
631
|
+
body: body.toString(),
|
|
632
|
+
});
|
|
633
|
+
if (!response.ok) {
|
|
634
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
635
|
+
}
|
|
636
|
+
return await response.json();
|
|
637
|
+
}
|
|
482
638
|
default:
|
|
483
639
|
throw new Error(`Unknown action: ${input.action}`);
|
|
484
640
|
}
|
|
@@ -486,200 +642,77 @@ exports.coreToolRegistry = new Map([
|
|
|
486
642
|
},
|
|
487
643
|
],
|
|
488
644
|
[
|
|
489
|
-
"
|
|
645
|
+
"manage_namespace",
|
|
490
646
|
{
|
|
491
|
-
name: "
|
|
492
|
-
description: "
|
|
493
|
-
inputSchema: z.toJSONSchema(
|
|
647
|
+
name: "manage_namespace",
|
|
648
|
+
description: "Create, update, or delete GitLab groups/namespaces. Actions: create (new group with visibility/settings), update (modify group settings), delete (remove permanently). Related: browse_namespaces for discovery.",
|
|
649
|
+
inputSchema: z.toJSONSchema(schema_1.ManageNamespaceSchema),
|
|
494
650
|
handler: async (args) => {
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const hasOnlySearch = Boolean(search) && !hasUsernameOrEmail;
|
|
499
|
-
const shouldUseSmartSearch = smart_search === false ? false : smart_search === true || hasOnlySearch;
|
|
500
|
-
if (shouldUseSmartSearch && (search || username || public_email)) {
|
|
501
|
-
const query = search ?? username ?? public_email ?? "";
|
|
502
|
-
const additionalParams = {};
|
|
503
|
-
Object.entries(otherParams).forEach(([key, value]) => {
|
|
504
|
-
if (value !== undefined && key !== "smart_search") {
|
|
505
|
-
additionalParams[key] = value;
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
return await (0, smart_user_search_1.smartUserSearch)(query, additionalParams);
|
|
651
|
+
const input = schema_1.ManageNamespaceSchema.parse(args);
|
|
652
|
+
if ((0, config_1.isActionDenied)("manage_namespace", input.action)) {
|
|
653
|
+
throw new Error(`Action '${input.action}' is not allowed for manage_namespace tool`);
|
|
509
654
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (value !== undefined && key !== "project_id") {
|
|
540
|
-
queryParams.set(key, String(value));
|
|
655
|
+
switch (input.action) {
|
|
656
|
+
case "create": {
|
|
657
|
+
const body = new URLSearchParams();
|
|
658
|
+
body.set("name", input.name);
|
|
659
|
+
body.set("path", input.path);
|
|
660
|
+
if (input.description)
|
|
661
|
+
body.set("description", input.description);
|
|
662
|
+
if (input.visibility)
|
|
663
|
+
body.set("visibility", input.visibility);
|
|
664
|
+
if (input.parent_id !== undefined)
|
|
665
|
+
body.set("parent_id", String(input.parent_id));
|
|
666
|
+
if (input.lfs_enabled !== undefined)
|
|
667
|
+
body.set("lfs_enabled", String(input.lfs_enabled));
|
|
668
|
+
if (input.request_access_enabled !== undefined)
|
|
669
|
+
body.set("request_access_enabled", String(input.request_access_enabled));
|
|
670
|
+
if (input.default_branch_protection !== undefined)
|
|
671
|
+
body.set("default_branch_protection", String(input.default_branch_protection));
|
|
672
|
+
if (input.avatar)
|
|
673
|
+
body.set("avatar", input.avatar);
|
|
674
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/groups`;
|
|
675
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
676
|
+
method: "POST",
|
|
677
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
678
|
+
body: body.toString(),
|
|
679
|
+
});
|
|
680
|
+
if (!response.ok) {
|
|
681
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
682
|
+
}
|
|
683
|
+
return await response.json();
|
|
541
684
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const options = schema_readonly_1.ListGroupIterationsSchema.parse(args);
|
|
561
|
-
const { group_id } = options;
|
|
562
|
-
const queryParams = new URLSearchParams();
|
|
563
|
-
Object.entries(options).forEach(([key, value]) => {
|
|
564
|
-
if (value !== undefined && key !== "group_id") {
|
|
565
|
-
queryParams.set(key, String(value));
|
|
685
|
+
case "update": {
|
|
686
|
+
const { group_id, action: _action, ...updateParams } = input;
|
|
687
|
+
const body = new URLSearchParams();
|
|
688
|
+
Object.entries(updateParams).forEach(([key, value]) => {
|
|
689
|
+
if (value !== undefined) {
|
|
690
|
+
body.set(key, String(value));
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/groups/${encodeURIComponent(group_id)}`;
|
|
694
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
695
|
+
method: "PUT",
|
|
696
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
697
|
+
body: body.toString(),
|
|
698
|
+
});
|
|
699
|
+
if (!response.ok) {
|
|
700
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
701
|
+
}
|
|
702
|
+
return await response.json();
|
|
566
703
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
},
|
|
576
|
-
],
|
|
577
|
-
[
|
|
578
|
-
"download_attachment",
|
|
579
|
-
{
|
|
580
|
-
name: "download_attachment",
|
|
581
|
-
description: "DOWNLOAD: Retrieve file attachments from issues/MRs. Requires secret token and filename from attachment URL.",
|
|
582
|
-
inputSchema: z.toJSONSchema(schema_readonly_1.DownloadAttachmentSchema),
|
|
583
|
-
handler: async (args) => {
|
|
584
|
-
const options = schema_readonly_1.DownloadAttachmentSchema.parse(args);
|
|
585
|
-
const { project_id, secret, filename } = options;
|
|
586
|
-
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${encodeURIComponent(project_id)}/uploads/${secret}/${filename}`;
|
|
587
|
-
const response = await (0, fetch_1.enhancedFetch)(apiUrl);
|
|
588
|
-
if (!response.ok) {
|
|
589
|
-
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
590
|
-
}
|
|
591
|
-
const attachment = await response.arrayBuffer();
|
|
592
|
-
return {
|
|
593
|
-
filename,
|
|
594
|
-
content: Buffer.from(attachment).toString("base64"),
|
|
595
|
-
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
596
|
-
};
|
|
597
|
-
},
|
|
598
|
-
},
|
|
599
|
-
],
|
|
600
|
-
[
|
|
601
|
-
"create_branch",
|
|
602
|
-
{
|
|
603
|
-
name: "create_branch",
|
|
604
|
-
description: "NEW BRANCH: Create a Git branch from existing ref. Required before creating MRs. Ref can be branch name, tag, or commit SHA.",
|
|
605
|
-
inputSchema: z.toJSONSchema(schema_1.CreateBranchSchema),
|
|
606
|
-
handler: async (args) => {
|
|
607
|
-
const options = schema_1.CreateBranchSchema.parse(args);
|
|
608
|
-
const body = new URLSearchParams();
|
|
609
|
-
body.set("branch", options.branch);
|
|
610
|
-
body.set("ref", options.ref);
|
|
611
|
-
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/projects/${encodeURIComponent(options.project_id)}/repository/branches`;
|
|
612
|
-
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
613
|
-
method: "POST",
|
|
614
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
615
|
-
body: body.toString(),
|
|
616
|
-
});
|
|
617
|
-
if (!response.ok) {
|
|
618
|
-
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
619
|
-
}
|
|
620
|
-
return await response.json();
|
|
621
|
-
},
|
|
622
|
-
},
|
|
623
|
-
],
|
|
624
|
-
[
|
|
625
|
-
"create_group",
|
|
626
|
-
{
|
|
627
|
-
name: "create_group",
|
|
628
|
-
description: "CREATE GROUP: Create a new GitLab group/namespace. Groups organize projects and teams. Can create subgroups with parent_id.",
|
|
629
|
-
inputSchema: z.toJSONSchema(schema_1.CreateGroupSchema),
|
|
630
|
-
handler: async (args) => {
|
|
631
|
-
const options = schema_1.CreateGroupSchema.parse(args);
|
|
632
|
-
const body = new URLSearchParams();
|
|
633
|
-
body.set("name", options.name);
|
|
634
|
-
body.set("path", options.path);
|
|
635
|
-
if (options.description)
|
|
636
|
-
body.set("description", options.description);
|
|
637
|
-
if (options.visibility)
|
|
638
|
-
body.set("visibility", options.visibility);
|
|
639
|
-
if (options.parent_id !== undefined)
|
|
640
|
-
body.set("parent_id", String(options.parent_id));
|
|
641
|
-
if (options.lfs_enabled !== undefined)
|
|
642
|
-
body.set("lfs_enabled", String(options.lfs_enabled));
|
|
643
|
-
if (options.request_access_enabled !== undefined)
|
|
644
|
-
body.set("request_access_enabled", String(options.request_access_enabled));
|
|
645
|
-
if (options.default_branch_protection !== undefined)
|
|
646
|
-
body.set("default_branch_protection", String(options.default_branch_protection));
|
|
647
|
-
if (options.avatar)
|
|
648
|
-
body.set("avatar", options.avatar);
|
|
649
|
-
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/groups`;
|
|
650
|
-
const response = await (0, fetch_1.enhancedFetch)(apiUrl, {
|
|
651
|
-
method: "POST",
|
|
652
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
653
|
-
body: body.toString(),
|
|
654
|
-
});
|
|
655
|
-
if (!response.ok) {
|
|
656
|
-
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
657
|
-
}
|
|
658
|
-
return await response.json();
|
|
659
|
-
},
|
|
660
|
-
},
|
|
661
|
-
],
|
|
662
|
-
[
|
|
663
|
-
"list_todos",
|
|
664
|
-
{
|
|
665
|
-
name: "list_todos",
|
|
666
|
-
description: "TASK QUEUE: View your GitLab todos (notifications requiring action). Todos are auto-created when you're assigned to issues/MRs, @mentioned, requested as reviewer, or CI pipelines fail. Filter by state (pending/done), action type (assigned, mentioned, review_requested), or target type (Issue, MergeRequest).",
|
|
667
|
-
inputSchema: z.toJSONSchema(schema_readonly_1.ListTodosSchema),
|
|
668
|
-
handler: async (args) => {
|
|
669
|
-
const options = schema_readonly_1.ListTodosSchema.parse(args);
|
|
670
|
-
const queryParams = new URLSearchParams();
|
|
671
|
-
Object.entries(options).forEach(([key, value]) => {
|
|
672
|
-
if (value !== undefined) {
|
|
673
|
-
queryParams.set(key, String(value));
|
|
704
|
+
case "delete": {
|
|
705
|
+
const { group_id } = input;
|
|
706
|
+
const apiUrl = `${process.env.GITLAB_API_URL}/api/v4/groups/${encodeURIComponent(group_id)}`;
|
|
707
|
+
const response = await (0, fetch_1.enhancedFetch)(apiUrl, { method: "DELETE" });
|
|
708
|
+
if (!response.ok) {
|
|
709
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
710
|
+
}
|
|
711
|
+
return { success: true, message: `Group ${group_id} deleted` };
|
|
674
712
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
const response = await (0, fetch_1.enhancedFetch)(apiUrl);
|
|
678
|
-
if (!response.ok) {
|
|
679
|
-
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
713
|
+
default:
|
|
714
|
+
throw new Error(`Unknown action: ${input.action}`);
|
|
680
715
|
}
|
|
681
|
-
const todos = await response.json();
|
|
682
|
-
return (0, idConversion_1.cleanGidsFromObject)(todos);
|
|
683
716
|
},
|
|
684
717
|
},
|
|
685
718
|
],
|
|
@@ -687,7 +720,7 @@ exports.coreToolRegistry = new Map([
|
|
|
687
720
|
"manage_todos",
|
|
688
721
|
{
|
|
689
722
|
name: "manage_todos",
|
|
690
|
-
description: "
|
|
723
|
+
description: "Manage your GitLab todo queue. Actions: mark_done (complete a single todo), mark_all_done (clear entire queue), restore (undo completion). Related: browse_todos to view your todo list.",
|
|
691
724
|
inputSchema: z.toJSONSchema(schema_1.ManageTodosSchema),
|
|
692
725
|
handler: async (args) => {
|
|
693
726
|
const input = schema_1.ManageTodosSchema.parse(args);
|
|
@@ -734,11 +767,8 @@ function getCoreReadOnlyToolNames() {
|
|
|
734
767
|
"browse_namespaces",
|
|
735
768
|
"browse_commits",
|
|
736
769
|
"browse_events",
|
|
737
|
-
"
|
|
738
|
-
"
|
|
739
|
-
"list_group_iterations",
|
|
740
|
-
"download_attachment",
|
|
741
|
-
"list_todos",
|
|
770
|
+
"browse_users",
|
|
771
|
+
"browse_todos",
|
|
742
772
|
];
|
|
743
773
|
}
|
|
744
774
|
function getCoreToolDefinitions() {
|