@structured-world/gitlab-mcp 6.8.0 → 6.10.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.
Files changed (112) hide show
  1. package/LICENSE +202 -21
  2. package/LICENSE.MIT +21 -0
  3. package/README.md +169 -1
  4. package/dist/src/cli/list-tools.d.ts +2 -0
  5. package/dist/src/cli/list-tools.js +768 -0
  6. package/dist/src/cli/list-tools.js.map +1 -0
  7. package/dist/src/config.d.ts +7 -0
  8. package/dist/src/config.js +96 -1
  9. package/dist/src/config.js.map +1 -1
  10. package/dist/src/entities/core/registry.js +68 -63
  11. package/dist/src/entities/core/registry.js.map +1 -1
  12. package/dist/src/entities/core/schema-readonly.d.ts +93 -36
  13. package/dist/src/entities/core/schema-readonly.js +146 -121
  14. package/dist/src/entities/core/schema-readonly.js.map +1 -1
  15. package/dist/src/entities/core/schema.d.ts +33 -23
  16. package/dist/src/entities/core/schema.js +65 -60
  17. package/dist/src/entities/core/schema.js.map +1 -1
  18. package/dist/src/entities/files/registry.js +14 -21
  19. package/dist/src/entities/files/registry.js.map +1 -1
  20. package/dist/src/entities/files/schema-readonly.d.ts +8 -7
  21. package/dist/src/entities/files/schema-readonly.js +20 -25
  22. package/dist/src/entities/files/schema-readonly.js.map +1 -1
  23. package/dist/src/entities/files/schema.d.ts +22 -15
  24. package/dist/src/entities/files/schema.js +32 -73
  25. package/dist/src/entities/files/schema.js.map +1 -1
  26. package/dist/src/entities/integrations/registry.js +3 -0
  27. package/dist/src/entities/integrations/registry.js.map +1 -1
  28. package/dist/src/entities/integrations/schema.d.ts +114 -8
  29. package/dist/src/entities/integrations/schema.js +27 -9
  30. package/dist/src/entities/integrations/schema.js.map +1 -1
  31. package/dist/src/entities/labels/registry.js +8 -7
  32. package/dist/src/entities/labels/registry.js.map +1 -1
  33. package/dist/src/entities/labels/schema-readonly.d.ts +8 -7
  34. package/dist/src/entities/labels/schema-readonly.js +20 -18
  35. package/dist/src/entities/labels/schema-readonly.js.map +1 -1
  36. package/dist/src/entities/labels/schema.d.ts +15 -8
  37. package/dist/src/entities/labels/schema.js +36 -27
  38. package/dist/src/entities/labels/schema.js.map +1 -1
  39. package/dist/src/entities/milestones/registry.js +7 -8
  40. package/dist/src/entities/milestones/registry.js.map +1 -1
  41. package/dist/src/entities/milestones/schema-readonly.d.ts +25 -10
  42. package/dist/src/entities/milestones/schema-readonly.js +47 -26
  43. package/dist/src/entities/milestones/schema-readonly.js.map +1 -1
  44. package/dist/src/entities/milestones/schema.d.ts +19 -9
  45. package/dist/src/entities/milestones/schema.js +31 -20
  46. package/dist/src/entities/milestones/schema.js.map +1 -1
  47. package/dist/src/entities/mrs/registry.js +75 -79
  48. package/dist/src/entities/mrs/registry.js.map +1 -1
  49. package/dist/src/entities/mrs/schema-readonly.d.ts +36 -23
  50. package/dist/src/entities/mrs/schema-readonly.js +197 -338
  51. package/dist/src/entities/mrs/schema-readonly.js.map +1 -1
  52. package/dist/src/entities/mrs/schema.d.ts +113 -37
  53. package/dist/src/entities/mrs/schema.js +140 -258
  54. package/dist/src/entities/mrs/schema.js.map +1 -1
  55. package/dist/src/entities/pipelines/registry.js +10 -4
  56. package/dist/src/entities/pipelines/registry.js.map +1 -1
  57. package/dist/src/entities/pipelines/schema-readonly.d.ts +30 -14
  58. package/dist/src/entities/pipelines/schema-readonly.js +62 -52
  59. package/dist/src/entities/pipelines/schema-readonly.js.map +1 -1
  60. package/dist/src/entities/pipelines/schema.d.ts +23 -16
  61. package/dist/src/entities/pipelines/schema.js +44 -26
  62. package/dist/src/entities/pipelines/schema.js.map +1 -1
  63. package/dist/src/entities/snippets/registry.js +79 -67
  64. package/dist/src/entities/snippets/registry.js.map +1 -1
  65. package/dist/src/entities/snippets/schema-readonly.d.ts +8 -9
  66. package/dist/src/entities/snippets/schema-readonly.js +30 -35
  67. package/dist/src/entities/snippets/schema-readonly.js.map +1 -1
  68. package/dist/src/entities/snippets/schema.d.ts +7 -11
  69. package/dist/src/entities/snippets/schema.js +31 -65
  70. package/dist/src/entities/snippets/schema.js.map +1 -1
  71. package/dist/src/entities/variables/registry.js +9 -5
  72. package/dist/src/entities/variables/registry.js.map +1 -1
  73. package/dist/src/entities/variables/schema-readonly.d.ts +9 -9
  74. package/dist/src/entities/variables/schema-readonly.js +22 -18
  75. package/dist/src/entities/variables/schema-readonly.js.map +1 -1
  76. package/dist/src/entities/variables/schema.d.ts +24 -7
  77. package/dist/src/entities/variables/schema.js +67 -38
  78. package/dist/src/entities/variables/schema.js.map +1 -1
  79. package/dist/src/entities/webhooks/registry.js +48 -46
  80. package/dist/src/entities/webhooks/registry.js.map +1 -1
  81. package/dist/src/entities/webhooks/schema-readonly.d.ts +9 -8
  82. package/dist/src/entities/webhooks/schema-readonly.js +14 -9
  83. package/dist/src/entities/webhooks/schema-readonly.js.map +1 -1
  84. package/dist/src/entities/webhooks/schema.d.ts +79 -26
  85. package/dist/src/entities/webhooks/schema.js +70 -61
  86. package/dist/src/entities/webhooks/schema.js.map +1 -1
  87. package/dist/src/entities/wiki/registry.js +7 -4
  88. package/dist/src/entities/wiki/registry.js.map +1 -1
  89. package/dist/src/entities/wiki/schema-readonly.d.ts +7 -7
  90. package/dist/src/entities/wiki/schema-readonly.js +11 -15
  91. package/dist/src/entities/wiki/schema-readonly.js.map +1 -1
  92. package/dist/src/entities/wiki/schema.d.ts +19 -8
  93. package/dist/src/entities/wiki/schema.js +32 -29
  94. package/dist/src/entities/wiki/schema.js.map +1 -1
  95. package/dist/src/entities/workitems/registry.js +7 -8
  96. package/dist/src/entities/workitems/registry.js.map +1 -1
  97. package/dist/src/entities/workitems/schema-readonly.d.ts +7 -8
  98. package/dist/src/entities/workitems/schema-readonly.js +12 -14
  99. package/dist/src/entities/workitems/schema-readonly.js.map +1 -1
  100. package/dist/src/entities/workitems/schema.d.ts +17 -11
  101. package/dist/src/entities/workitems/schema.js +25 -25
  102. package/dist/src/entities/workitems/schema.js.map +1 -1
  103. package/dist/src/registry-manager.d.ts +1 -0
  104. package/dist/src/registry-manager.js +45 -11
  105. package/dist/src/registry-manager.js.map +1 -1
  106. package/dist/src/utils/schema-utils.d.ts +28 -0
  107. package/dist/src/utils/schema-utils.js +240 -0
  108. package/dist/src/utils/schema-utils.js.map +1 -0
  109. package/dist/structured-world-gitlab-mcp-6.10.0.tgz +0 -0
  110. package/dist/tsconfig.build.tsbuildinfo +1 -1
  111. package/package.json +4 -4
  112. package/dist/structured-world-gitlab-mcp-6.8.0.tgz +0 -0
@@ -0,0 +1,768 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.main = main;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const registry_manager_1 = require("../registry-manager");
41
+ const ToolAvailability_1 = require("../services/ToolAvailability");
42
+ function parseArgs() {
43
+ const args = process.argv.slice(2);
44
+ const options = {
45
+ format: "markdown",
46
+ showEnv: false,
47
+ verbose: false,
48
+ detail: false,
49
+ noExamples: false,
50
+ toc: false,
51
+ };
52
+ for (let i = 0; i < args.length; i++) {
53
+ const arg = args[i];
54
+ switch (arg) {
55
+ case "--json":
56
+ options.format = "json";
57
+ break;
58
+ case "--simple":
59
+ options.format = "simple";
60
+ break;
61
+ case "--export":
62
+ options.format = "export";
63
+ break;
64
+ case "--entity":
65
+ if (i + 1 >= args.length) {
66
+ console.error("Error: --entity flag requires a value.");
67
+ console.error("Usage: yarn list-tools --entity <entity_name>");
68
+ process.exit(1);
69
+ }
70
+ options.entity = args[++i];
71
+ break;
72
+ case "--tool":
73
+ if (i + 1 >= args.length) {
74
+ console.error("Error: --tool flag requires a value.");
75
+ console.error("Usage: yarn list-tools --tool <tool_name>");
76
+ process.exit(1);
77
+ }
78
+ options.tool = args[++i];
79
+ break;
80
+ case "--env":
81
+ options.showEnv = true;
82
+ break;
83
+ case "--verbose":
84
+ case "-v":
85
+ options.verbose = true;
86
+ break;
87
+ case "--detail":
88
+ options.detail = true;
89
+ break;
90
+ case "--no-examples":
91
+ options.noExamples = true;
92
+ break;
93
+ case "--toc":
94
+ options.toc = true;
95
+ break;
96
+ case "--help":
97
+ case "-h":
98
+ printHelp();
99
+ process.exit(0);
100
+ break;
101
+ default:
102
+ if (arg.startsWith("-")) {
103
+ console.error(`Error: Unrecognized option '${arg}'.`);
104
+ console.error("Use '--help' to see available options.");
105
+ process.exit(1);
106
+ }
107
+ break;
108
+ }
109
+ }
110
+ return options;
111
+ }
112
+ function printHelp() {
113
+ console.log(`
114
+ GitLab MCP Tool Lister
115
+
116
+ Usage: yarn list-tools [options]
117
+
118
+ Options:
119
+ --json Output in JSON format
120
+ --simple Simple list of tool names
121
+ --export Generate complete TOOLS.md documentation
122
+ --entity <name> Filter by entity (e.g., workitems, labels, mrs)
123
+ --tool <name> Show details for specific tool
124
+ --env Show environment configuration
125
+ --verbose, -v Show additional details
126
+ --detail Show all tools with their input schemas
127
+ --no-examples Skip example JSON blocks (for --export)
128
+ --toc Include table of contents (for --export)
129
+ --help, -h Show this help
130
+
131
+ Examples:
132
+ yarn list-tools # List all tools in markdown
133
+ yarn list-tools --json # JSON output
134
+ yarn list-tools --export # Generate TOOLS.md to stdout
135
+ yarn list-tools --export > docs/TOOLS.md # Generate TOOLS.md to file
136
+ yarn list-tools --export --toc # With table of contents
137
+ yarn list-tools --export --no-examples # Skip example JSON blocks
138
+ yarn list-tools --entity workitems # Only work items tools
139
+ yarn list-tools --tool list_work_items # Specific tool details
140
+ GITLAB_READONLY=true yarn list-tools # Show read-only tools
141
+ GITLAB_DENIED_TOOLS_REGEX="^create" yarn list-tools # Test filtering
142
+
143
+ Environment Variables:
144
+ GITLAB_READONLY Show only read-only tools
145
+ GITLAB_DENIED_TOOLS_REGEX Regex pattern to exclude tools
146
+ GITLAB_ALLOWED_TOOLS_REGEX Regex pattern to include tools
147
+ `);
148
+ }
149
+ function resolveJsonSchemaType(prop, schema) {
150
+ if (prop.$ref) {
151
+ const refPath = prop.$ref.replace("#/properties/", "");
152
+ const referencedProp = schema.properties?.[refPath];
153
+ if (referencedProp) {
154
+ return resolveJsonSchemaType(referencedProp, schema);
155
+ }
156
+ return "reference";
157
+ }
158
+ if (prop.type) {
159
+ if (prop.type === "array" && prop.items) {
160
+ const itemType = resolveJsonSchemaType(prop.items, schema);
161
+ return `${itemType}[]`;
162
+ }
163
+ return prop.type;
164
+ }
165
+ if (prop.enum) {
166
+ return "enum";
167
+ }
168
+ if (prop.oneOf ?? prop.anyOf) {
169
+ const unionTypes = (prop.oneOf ?? prop.anyOf)?.map(option => resolveJsonSchemaType(option, schema)) ?? [];
170
+ return unionTypes.join(" | ");
171
+ }
172
+ return "unknown";
173
+ }
174
+ function getParameterDescription(schema) {
175
+ const params = [];
176
+ if (schema.properties) {
177
+ for (const [key, value] of Object.entries(schema.properties)) {
178
+ const prop = value;
179
+ const required = schema.required?.includes(key) ?? false;
180
+ const type = resolveJsonSchemaType(prop, schema);
181
+ const description = prop.description ?? "";
182
+ let paramStr = ` - \`${key}\` (${type}${required ? ", required" : ", optional"})`;
183
+ if (description) {
184
+ paramStr += `: ${description}`;
185
+ }
186
+ params.push(paramStr);
187
+ }
188
+ }
189
+ if (schema._def?.schema?._def?.checks) {
190
+ const checks = schema._def.schema._def.checks;
191
+ for (const check of checks) {
192
+ if (check.message) {
193
+ params.push(` - **Validation**: ${check.message}`);
194
+ }
195
+ }
196
+ }
197
+ return params;
198
+ }
199
+ function printEnvironmentInfo() {
200
+ console.log("=== Environment Configuration ===\n");
201
+ console.log(`GITLAB_READONLY: ${process.env.GITLAB_READONLY ?? "false"}`);
202
+ console.log(`GITLAB_DENIED_TOOLS_REGEX: ${process.env.GITLAB_DENIED_TOOLS_REGEX ?? "(not set)"}`);
203
+ console.log(`GITLAB_ALLOWED_TOOLS_REGEX: ${process.env.GITLAB_ALLOWED_TOOLS_REGEX ?? "(not set)"}`);
204
+ console.log(`GITLAB_API_URL: ${process.env.GITLAB_API_URL ?? "https://gitlab.com"}`);
205
+ console.log();
206
+ }
207
+ function getToolTierInfo(toolName) {
208
+ const requirement = ToolAvailability_1.ToolAvailability.getToolRequirement(toolName);
209
+ if (!requirement)
210
+ return "";
211
+ const tierBadge = {
212
+ free: "Free",
213
+ premium: "Premium",
214
+ ultimate: "Ultimate",
215
+ }[requirement.requiredTier] ?? requirement.requiredTier;
216
+ return `[tier: ${tierBadge}]`;
217
+ }
218
+ const ENTITY_TOOLS = {
219
+ Core: [
220
+ "browse_projects",
221
+ "browse_namespaces",
222
+ "browse_commits",
223
+ "browse_events",
224
+ "create_branch",
225
+ "create_group",
226
+ "manage_repository",
227
+ "list_project_members",
228
+ "list_group_iterations",
229
+ "download_attachment",
230
+ "get_users",
231
+ ],
232
+ "Work Items": ["browse_work_items", "manage_work_item"],
233
+ "Merge Requests": [
234
+ "browse_merge_requests",
235
+ "browse_mr_discussions",
236
+ "manage_merge_request",
237
+ "manage_mr_discussion",
238
+ "manage_draft_notes",
239
+ ],
240
+ Labels: ["browse_labels", "manage_label"],
241
+ Wiki: ["browse_wiki", "manage_wiki"],
242
+ Pipelines: ["browse_pipelines", "manage_pipeline", "manage_pipeline_job"],
243
+ Variables: ["browse_variables", "manage_variable"],
244
+ Milestones: ["browse_milestones", "manage_milestone"],
245
+ Files: ["browse_files", "manage_files"],
246
+ Snippets: ["browse_snippets", "manage_snippet"],
247
+ Webhooks: ["list_webhooks", "manage_webhook"],
248
+ Integrations: ["list_integrations", "manage_integration"],
249
+ Todos: ["list_todos", "manage_todos"],
250
+ };
251
+ function groupToolsByEntity(tools) {
252
+ const grouped = new Map();
253
+ const toolToEntity = new Map();
254
+ for (const [entity, toolNames] of Object.entries(ENTITY_TOOLS)) {
255
+ for (const toolName of toolNames) {
256
+ toolToEntity.set(toolName, entity);
257
+ }
258
+ }
259
+ for (const tool of tools) {
260
+ const entity = toolToEntity.get(tool.name) ?? "Other";
261
+ if (!grouped.has(entity)) {
262
+ grouped.set(entity, []);
263
+ }
264
+ grouped.get(entity).push(tool);
265
+ }
266
+ const entityOrder = [
267
+ "Core",
268
+ "Work Items",
269
+ "Merge Requests",
270
+ "Labels",
271
+ "Milestones",
272
+ "Pipelines",
273
+ "Variables",
274
+ "Files",
275
+ "Wiki",
276
+ "Snippets",
277
+ "Webhooks",
278
+ "Integrations",
279
+ "Todos",
280
+ "Other",
281
+ ];
282
+ const sortedGrouped = new Map();
283
+ for (const entity of entityOrder) {
284
+ if (grouped.has(entity)) {
285
+ sortedGrouped.set(entity, grouped.get(entity));
286
+ }
287
+ }
288
+ return sortedGrouped;
289
+ }
290
+ const ACTION_DESCRIPTIONS = {
291
+ list: "List items with filtering and pagination",
292
+ get: "Get a single item by ID",
293
+ create: "Create a new item",
294
+ update: "Update an existing item",
295
+ delete: "Delete an item",
296
+ search: "Search for items",
297
+ diffs: "Get file changes/diffs",
298
+ compare: "Compare two branches or commits",
299
+ merge: "Merge a merge request",
300
+ approve: "Approve a merge request",
301
+ unapprove: "Remove approval from a merge request",
302
+ rebase: "Rebase a merge request",
303
+ cancel: "Cancel a running operation",
304
+ retry: "Retry a failed operation",
305
+ play: "Run a manual job",
306
+ publish: "Publish draft notes",
307
+ drafts: "List draft notes",
308
+ draft: "Get a single draft note",
309
+ resolve: "Resolve a discussion thread",
310
+ unresolve: "Unresolve a discussion thread",
311
+ note: "Add a note/comment",
312
+ mark_done: "Mark as done",
313
+ mark_pending: "Mark as pending",
314
+ disable: "Disable the integration",
315
+ test: "Test a webhook",
316
+ read: "Read item details",
317
+ };
318
+ function extractActions(schema) {
319
+ const actions = [];
320
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
321
+ for (const branch of schema.oneOf) {
322
+ const actionProp = branch.properties?.action;
323
+ const actionName = actionProp?.const;
324
+ if (actionName) {
325
+ const description = actionProp?.description ??
326
+ ACTION_DESCRIPTIONS[actionName] ??
327
+ `Perform ${actionName} operation`;
328
+ actions.push({ name: actionName, description });
329
+ }
330
+ }
331
+ return actions;
332
+ }
333
+ const actionProp = schema.properties?.action;
334
+ if (actionProp?.enum && Array.isArray(actionProp.enum)) {
335
+ for (const actionName of actionProp.enum) {
336
+ if (typeof actionName === "string") {
337
+ const description = ACTION_DESCRIPTIONS[actionName] ?? `Perform ${actionName} operation`;
338
+ actions.push({ name: actionName, description });
339
+ }
340
+ }
341
+ }
342
+ return actions;
343
+ }
344
+ function extractParameters(schema) {
345
+ if (!schema.properties)
346
+ return [];
347
+ const requiredFields = schema.required ?? [];
348
+ const params = [];
349
+ for (const [name, prop] of Object.entries(schema.properties)) {
350
+ params.push({
351
+ name,
352
+ type: resolveJsonSchemaType(prop, schema),
353
+ required: requiredFields.includes(name),
354
+ description: prop.description ?? "",
355
+ });
356
+ }
357
+ return sortParameters(params);
358
+ }
359
+ function sortParameters(params) {
360
+ return params.sort((a, b) => {
361
+ if (a.required && !b.required)
362
+ return -1;
363
+ if (!a.required && b.required)
364
+ return 1;
365
+ if (a.name === "action")
366
+ return -1;
367
+ if (b.name === "action")
368
+ return 1;
369
+ return a.name.localeCompare(b.name);
370
+ });
371
+ }
372
+ function extractParametersGrouped(schema) {
373
+ const result = {
374
+ common: [],
375
+ byAction: new Map(),
376
+ };
377
+ if (!schema.oneOf || !Array.isArray(schema.oneOf)) {
378
+ result.common = extractParameters(schema);
379
+ return result;
380
+ }
381
+ const totalActions = schema.oneOf.length;
382
+ const paramOccurrences = new Map();
383
+ for (const branch of schema.oneOf) {
384
+ const actionName = branch.properties?.action?.const;
385
+ if (!actionName || !branch.properties)
386
+ continue;
387
+ const requiredFields = branch.required ?? [];
388
+ for (const [name, prop] of Object.entries(branch.properties)) {
389
+ if (name === "action")
390
+ continue;
391
+ const type = resolveJsonSchemaType(prop, branch);
392
+ const required = requiredFields.includes(name);
393
+ const description = prop.description ?? "";
394
+ if (!paramOccurrences.has(name)) {
395
+ paramOccurrences.set(name, {
396
+ actions: new Map(),
397
+ type,
398
+ description,
399
+ });
400
+ }
401
+ const occurrence = paramOccurrences.get(name);
402
+ occurrence.actions.set(actionName, { required, type, description });
403
+ if (description.length > occurrence.description.length) {
404
+ occurrence.description = description;
405
+ }
406
+ }
407
+ }
408
+ for (const [name, data] of paramOccurrences) {
409
+ if (data.actions.size === totalActions) {
410
+ const requiredInAll = Array.from(data.actions.values()).every(a => a.required);
411
+ result.common.push({
412
+ name,
413
+ type: data.type,
414
+ required: requiredInAll,
415
+ description: data.description,
416
+ });
417
+ }
418
+ else {
419
+ for (const [actionName, actionData] of data.actions) {
420
+ if (!result.byAction.has(actionName)) {
421
+ result.byAction.set(actionName, []);
422
+ }
423
+ result.byAction.get(actionName).push({
424
+ name,
425
+ type: actionData.type,
426
+ required: actionData.required,
427
+ requiredForAction: actionData.required,
428
+ description: actionData.description || data.description,
429
+ });
430
+ }
431
+ }
432
+ }
433
+ result.common = sortParameters(result.common);
434
+ for (const [action, params] of result.byAction) {
435
+ result.byAction.set(action, params.sort((a, b) => {
436
+ if (a.requiredForAction && !b.requiredForAction)
437
+ return -1;
438
+ if (!a.requiredForAction && b.requiredForAction)
439
+ return 1;
440
+ return a.name.localeCompare(b.name);
441
+ }));
442
+ }
443
+ return result;
444
+ }
445
+ function generateExample(schema) {
446
+ const example = {};
447
+ const actions = extractActions(schema);
448
+ if (actions.length > 0) {
449
+ example.action = actions[0].name;
450
+ }
451
+ let targetSchema = schema;
452
+ let requiredFields = [];
453
+ if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
454
+ targetSchema = schema.oneOf[0];
455
+ requiredFields = targetSchema.required ?? [];
456
+ }
457
+ else if (schema.properties) {
458
+ requiredFields = schema.required ?? [];
459
+ }
460
+ else {
461
+ return example;
462
+ }
463
+ if (!targetSchema.properties)
464
+ return example;
465
+ for (const [name, prop] of Object.entries(targetSchema.properties)) {
466
+ if (name === "action")
467
+ continue;
468
+ const isRequired = requiredFields.includes(name);
469
+ const description = (prop.description ?? "").toLowerCase();
470
+ if (!isRequired)
471
+ continue;
472
+ if (prop.enum && Array.isArray(prop.enum) && prop.enum.length > 0) {
473
+ example[name] = prop.enum[0];
474
+ }
475
+ else if (name.includes("project_id") || name === "projectId") {
476
+ example[name] = "my-group/my-project";
477
+ }
478
+ else if (name.includes("group_id") || name === "groupId") {
479
+ example[name] = "my-group";
480
+ }
481
+ else if (name.includes("namespace")) {
482
+ example[name] = "my-group/my-project";
483
+ }
484
+ else if (name.includes("_iid") || name === "iid") {
485
+ example[name] = "1";
486
+ }
487
+ else if (name.includes("_id") || name === "id") {
488
+ example[name] = "123";
489
+ }
490
+ else if (name === "title") {
491
+ example[name] = "Example title";
492
+ }
493
+ else if (name === "description") {
494
+ example[name] = "Example description";
495
+ }
496
+ else if (name === "url") {
497
+ example[name] = "https://example.com/webhook";
498
+ }
499
+ else if (name === "content") {
500
+ example[name] = "File content here";
501
+ }
502
+ else if (name === "file_path" || name === "path") {
503
+ example[name] = "path/to/file.txt";
504
+ }
505
+ else if (name === "ref" || name === "branch") {
506
+ example[name] = "main";
507
+ }
508
+ else if (name === "from" || name === "to") {
509
+ example[name] = name === "from" ? "main" : "feature-branch";
510
+ }
511
+ else if (description.includes("boolean") || prop.type === "boolean") {
512
+ example[name] = true;
513
+ }
514
+ else if (prop.type === "number" || prop.type === "integer") {
515
+ example[name] = 10;
516
+ }
517
+ else if (prop.type === "array") {
518
+ example[name] = [];
519
+ }
520
+ else {
521
+ example[name] = `example_${name}`;
522
+ }
523
+ }
524
+ return example;
525
+ }
526
+ function getPackageVersion() {
527
+ try {
528
+ let dir = process.cwd();
529
+ let fallbackVersion = null;
530
+ for (let i = 0; i < 5; i++) {
531
+ const pkgPath = path.join(dir, "package.json");
532
+ if (fs.existsSync(pkgPath)) {
533
+ const content = fs.readFileSync(pkgPath, "utf8");
534
+ const pkg = JSON.parse(content);
535
+ if (fallbackVersion === null && pkg.version) {
536
+ fallbackVersion = pkg.version;
537
+ }
538
+ if (pkg.name === "@structured-world/gitlab-mcp") {
539
+ return pkg.version ?? "unknown";
540
+ }
541
+ }
542
+ const parent = path.dirname(dir);
543
+ if (parent === dir)
544
+ break;
545
+ dir = parent;
546
+ }
547
+ return fallbackVersion ?? "unknown";
548
+ }
549
+ catch {
550
+ return "unknown";
551
+ }
552
+ }
553
+ function generateExportMarkdown(tools, options) {
554
+ const lines = [];
555
+ const version = getPackageVersion();
556
+ const timestamp = new Date().toISOString().split("T")[0];
557
+ lines.push("# GitLab MCP Tools Reference");
558
+ lines.push("");
559
+ lines.push("> Auto-generated from source code. Do not edit manually.");
560
+ lines.push(`> Generated: ${timestamp} | Tools: ${tools.length} | Version: ${version}`);
561
+ lines.push("");
562
+ const grouped = groupToolsByEntity(tools);
563
+ if (options.toc) {
564
+ lines.push("## Table of Contents");
565
+ lines.push("");
566
+ for (const [entity, entityTools] of grouped) {
567
+ const anchor = entity.toLowerCase().replace(/\s+/g, "-");
568
+ lines.push(`- [${entity} (${entityTools.length})](#${anchor})`);
569
+ }
570
+ lines.push("");
571
+ lines.push("---");
572
+ lines.push("");
573
+ }
574
+ for (const [entity, entityTools] of grouped) {
575
+ lines.push(`## ${entity}`);
576
+ lines.push("");
577
+ for (const tool of entityTools) {
578
+ const tierInfo = getToolTierInfo(tool.name);
579
+ const tierDisplay = tierInfo ? ` ${tierInfo}` : "";
580
+ lines.push(`### ${tool.name}${tierDisplay}`);
581
+ lines.push("");
582
+ lines.push(tool.description);
583
+ lines.push("");
584
+ const actions = extractActions(tool.inputSchema);
585
+ if (actions.length > 0) {
586
+ lines.push("#### Actions");
587
+ lines.push("");
588
+ lines.push("| Action | Description |");
589
+ lines.push("|--------|-------------|");
590
+ for (const action of actions) {
591
+ lines.push(`| \`${action.name}\` | ${action.description} |`);
592
+ }
593
+ lines.push("");
594
+ }
595
+ const groupedParams = extractParametersGrouped(tool.inputSchema);
596
+ const hasParams = groupedParams.common.length > 0 || groupedParams.byAction.size > 0;
597
+ if (hasParams) {
598
+ lines.push("#### Parameters");
599
+ lines.push("");
600
+ if (groupedParams.common.length > 0) {
601
+ if (groupedParams.byAction.size > 0) {
602
+ lines.push("**Common** (all actions):");
603
+ lines.push("");
604
+ }
605
+ lines.push("| Parameter | Type | Required | Description |");
606
+ lines.push("|-----------|------|----------|-------------|");
607
+ for (const param of groupedParams.common) {
608
+ const req = param.required ? "Yes" : "No";
609
+ const desc = param.description || "-";
610
+ lines.push(`| \`${param.name}\` | ${param.type} | ${req} | ${desc} |`);
611
+ }
612
+ lines.push("");
613
+ }
614
+ if (groupedParams.byAction.size > 0) {
615
+ const sortedActions = Array.from(groupedParams.byAction.keys()).sort();
616
+ for (const actionName of sortedActions) {
617
+ const actionParams = groupedParams.byAction.get(actionName);
618
+ if (actionParams.length === 0)
619
+ continue;
620
+ lines.push(`**Action \`${actionName}\`**:`);
621
+ lines.push("");
622
+ lines.push("| Parameter | Type | Required | Description |");
623
+ lines.push("|-----------|------|----------|-------------|");
624
+ for (const param of actionParams) {
625
+ const req = param.requiredForAction ? "Yes" : "No";
626
+ const desc = param.description || "-";
627
+ lines.push(`| \`${param.name}\` | ${param.type} | ${req} | ${desc} |`);
628
+ }
629
+ lines.push("");
630
+ }
631
+ }
632
+ }
633
+ if (!options.noExamples && tool.inputSchema) {
634
+ const example = generateExample(tool.inputSchema);
635
+ if (Object.keys(example).length > 0) {
636
+ lines.push("#### Example");
637
+ lines.push("");
638
+ lines.push("```json");
639
+ lines.push(JSON.stringify(example, null, 2));
640
+ lines.push("```");
641
+ lines.push("");
642
+ }
643
+ }
644
+ lines.push("---");
645
+ lines.push("");
646
+ }
647
+ }
648
+ return lines.join("\n");
649
+ }
650
+ async function main() {
651
+ const options = parseArgs();
652
+ if (options.showEnv) {
653
+ printEnvironmentInfo();
654
+ }
655
+ const registryManager = registry_manager_1.RegistryManager.getInstance();
656
+ const toolDefinitions = options.format === "export"
657
+ ? registryManager.getAllToolDefinitionsUnfiltered()
658
+ : registryManager.getAllToolDefinitionsTierless();
659
+ const tools = toolDefinitions.map(def => ({
660
+ name: def.name,
661
+ description: def.description,
662
+ inputSchema: def.inputSchema,
663
+ }));
664
+ let filteredTools = tools;
665
+ if (options.entity) {
666
+ const grouped = groupToolsByEntity(tools);
667
+ const entityKey = Array.from(grouped.keys()).find(k => k.toLowerCase().replace(/ /g, "") === options.entity.toLowerCase().replace(/ /g, ""));
668
+ filteredTools = entityKey ? (grouped.get(entityKey) ?? []) : [];
669
+ if (filteredTools.length === 0) {
670
+ console.error(`No tools found for entity: ${options.entity}`);
671
+ process.exit(1);
672
+ }
673
+ }
674
+ if (options.tool) {
675
+ filteredTools = filteredTools.filter(t => t.name === options.tool);
676
+ if (filteredTools.length === 0) {
677
+ console.error(`Tool not found: ${options.tool}`);
678
+ process.exit(1);
679
+ }
680
+ }
681
+ switch (options.format) {
682
+ case "json":
683
+ const output = filteredTools.map(tool => ({
684
+ name: tool.name,
685
+ description: tool.description,
686
+ tier: ToolAvailability_1.ToolAvailability.getToolRequirement(tool.name)?.requiredTier ?? "unknown",
687
+ minVersion: ToolAvailability_1.ToolAvailability.getToolRequirement(tool.name)?.minVersion,
688
+ parameters: tool.inputSchema,
689
+ }));
690
+ console.log(JSON.stringify(output, null, 2));
691
+ break;
692
+ case "simple":
693
+ filteredTools.forEach(tool => {
694
+ console.log(tool.name);
695
+ });
696
+ break;
697
+ case "export":
698
+ const markdown = generateExportMarkdown(filteredTools, {
699
+ noExamples: options.noExamples,
700
+ toc: options.toc,
701
+ });
702
+ console.log(markdown);
703
+ break;
704
+ case "markdown":
705
+ default:
706
+ if (!options.entity && !options.tool) {
707
+ console.log("# GitLab MCP Tools\n");
708
+ console.log(`Total tools available: ${filteredTools.length}\n`);
709
+ const grouped = groupToolsByEntity(filteredTools);
710
+ console.log("## Categories\n");
711
+ for (const [entity, entityTools] of grouped) {
712
+ console.log(`- **${entity}**: ${entityTools.length} tools`);
713
+ }
714
+ console.log();
715
+ for (const [entity, entityTools] of grouped) {
716
+ console.log(`## ${entity}\n`);
717
+ for (const tool of entityTools) {
718
+ const tierInfo = getToolTierInfo(tool.name);
719
+ const tierDisplay = tierInfo ? ` ${tierInfo}` : "";
720
+ console.log(`### ${tool.name}${tierDisplay}`);
721
+ console.log(`**Description**: ${tool.description}\n`);
722
+ if ((options.verbose || options.detail) && tool.inputSchema) {
723
+ console.log("**Parameters**:");
724
+ const params = getParameterDescription(tool.inputSchema);
725
+ if (params.length > 0) {
726
+ params.forEach(p => console.log(p));
727
+ }
728
+ else {
729
+ console.log(" (no parameters)");
730
+ }
731
+ console.log();
732
+ }
733
+ }
734
+ }
735
+ }
736
+ else {
737
+ for (const tool of filteredTools) {
738
+ const tierInfo = getToolTierInfo(tool.name);
739
+ const tierDisplay = tierInfo ? ` ${tierInfo}` : "";
740
+ console.log(`## ${tool.name}${tierDisplay}\n`);
741
+ console.log(`**Description**: ${tool.description}\n`);
742
+ if (tool.inputSchema) {
743
+ console.log("**Parameters**:\n");
744
+ const params = getParameterDescription(tool.inputSchema);
745
+ if (params.length > 0) {
746
+ params.forEach(p => console.log(p));
747
+ }
748
+ else {
749
+ console.log("(no parameters)");
750
+ }
751
+ }
752
+ console.log();
753
+ }
754
+ }
755
+ break;
756
+ }
757
+ if (options.showEnv && options.format === "markdown") {
758
+ console.log("\n---\n");
759
+ console.log("*Note: Tool availability may be affected by environment variables shown above.*");
760
+ }
761
+ }
762
+ if (!process.env.NODE_ENV || process.env.NODE_ENV !== "test") {
763
+ main().catch(error => {
764
+ console.error("Error:", error);
765
+ process.exit(1);
766
+ });
767
+ }
768
+ //# sourceMappingURL=list-tools.js.map