@zereight/mcp-gitlab 2.0.28 → 2.0.32

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/build/schemas.js CHANGED
@@ -62,6 +62,8 @@ export const GitLabPipelineJobSchema = z.object({
62
62
  started_at: z.string().nullable().optional(),
63
63
  finished_at: z.string().nullable().optional(),
64
64
  duration: z.number().nullable().optional(),
65
+ queued_duration: z.number().nullable().optional(),
66
+ failure_reason: z.string().nullable().optional(),
65
67
  user: z
66
68
  .object({
67
69
  id: z.coerce.string(),
@@ -89,6 +91,19 @@ export const GitLabPipelineJobSchema = z.object({
89
91
  })
90
92
  .optional(),
91
93
  web_url: z.string().optional(),
94
+ allow_failure: z.boolean().optional(),
95
+ retried: z.boolean().optional(),
96
+ tag_list: z.array(z.string()).optional(),
97
+ runner: z
98
+ .object({
99
+ id: z.coerce.string().optional(),
100
+ description: z.string().nullable().optional(),
101
+ active: z.boolean().optional(),
102
+ is_shared: z.boolean().optional(),
103
+ runner_type: z.string().optional(),
104
+ })
105
+ .nullable()
106
+ .optional(),
92
107
  });
93
108
  // Pipeline trigger job (bridge) schema
94
109
  export const GitLabPipelineTriggerJobSchema = z.object({
@@ -188,9 +203,7 @@ export const ListPipelinesSchema = z
188
203
  .describe("The status of pipelines"),
189
204
  ref: z.string().optional().describe("The ref of pipelines"),
190
205
  sha: z.string().optional().describe("The SHA of pipelines"),
191
- yaml_errors: z.boolean()
192
- .optional()
193
- .describe("Returns pipelines with invalid configurations"),
206
+ yaml_errors: z.boolean().optional().describe("Returns pipelines with invalid configurations"),
194
207
  username: z.string().optional().describe("The username of the user who triggered pipelines"),
195
208
  updated_after: z
196
209
  .string()
@@ -249,6 +262,126 @@ export const ListPipelineTriggerJobsSchema = z
249
262
  .describe("The scope of trigger jobs to show"),
250
263
  })
251
264
  .merge(PaginationOptionsSchema);
265
+ // Deployment related schemas
266
+ export const GitLabDeploymentSchema = z.object({
267
+ id: z.coerce.string(),
268
+ iid: z.coerce.string().optional(),
269
+ status: z.string(),
270
+ ref: z.string().optional(),
271
+ sha: z.string(),
272
+ created_at: z.string(),
273
+ updated_at: z.string().optional(),
274
+ finished_at: z.string().nullable().optional(),
275
+ environment: z
276
+ .object({
277
+ id: z.coerce.string().optional(),
278
+ name: z.string(),
279
+ slug: z.string().optional(),
280
+ external_url: z.string().nullable().optional(),
281
+ state: z.string().optional(),
282
+ tier: z.string().optional(),
283
+ })
284
+ .optional(),
285
+ deployable: z
286
+ .object({
287
+ id: z.coerce.string().optional(),
288
+ name: z.string().optional(),
289
+ status: z.string().optional(),
290
+ stage: z.string().optional(),
291
+ web_url: z.string().optional(),
292
+ pipeline: z
293
+ .object({
294
+ id: z.coerce.string().optional(),
295
+ status: z.string().optional(),
296
+ ref: z.string().optional(),
297
+ sha: z.string().optional(),
298
+ web_url: z.string().optional(),
299
+ })
300
+ .optional(),
301
+ })
302
+ .nullable()
303
+ .optional(),
304
+ user: z
305
+ .object({
306
+ id: z.coerce.string().optional(),
307
+ username: z.string().optional(),
308
+ name: z.string().optional(),
309
+ avatar_url: z.string().nullable().optional(),
310
+ })
311
+ .optional(),
312
+ web_url: z.string().optional(),
313
+ });
314
+ export const ListDeploymentsSchema = z
315
+ .object({
316
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
317
+ environment: z.string().optional().describe("Filter by environment name"),
318
+ ref: z.string().optional().describe("Filter by ref"),
319
+ sha: z
320
+ .string()
321
+ .optional()
322
+ .describe("Filter by commit SHA (if supported by your GitLab version)"),
323
+ status: z.string().optional().describe("Filter by deployment status"),
324
+ updated_after: z
325
+ .string()
326
+ .optional()
327
+ .describe("Return deployments updated after the specified date"),
328
+ updated_before: z
329
+ .string()
330
+ .optional()
331
+ .describe("Return deployments updated before the specified date"),
332
+ order_by: z
333
+ .enum(["id", "iid", "created_at", "updated_at", "ref", "status", "environment"])
334
+ .optional()
335
+ .describe("Order deployments by"),
336
+ sort: z.enum(["asc", "desc"]).optional().describe("Sort deployments"),
337
+ })
338
+ .merge(PaginationOptionsSchema);
339
+ export const GetDeploymentSchema = z.object({
340
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
341
+ deployment_id: z.coerce.string().describe("The ID of the deployment"),
342
+ });
343
+ // Environment related schemas
344
+ const GitLabEnvironmentLastDeploymentSchema = z.object({
345
+ id: z.coerce.string().optional(),
346
+ iid: z.coerce.string().optional(),
347
+ status: z.string().optional(),
348
+ ref: z.string().optional(),
349
+ sha: z.string().optional(),
350
+ created_at: z.string().optional(),
351
+ updated_at: z.string().optional(),
352
+ web_url: z.string().optional(),
353
+ });
354
+ export const GitLabEnvironmentSchema = z.object({
355
+ id: z.coerce.string(),
356
+ name: z.string(),
357
+ slug: z.string().optional(),
358
+ external_url: z.string().nullable().optional(),
359
+ state: z.string().optional(),
360
+ tier: z.string().optional(),
361
+ environment_type: z.string().optional(),
362
+ created_at: z.string().optional(),
363
+ updated_at: z.string().optional(),
364
+ auto_stop_at: z.string().nullable().optional(),
365
+ enable_advanced_logs_querying: z.boolean().optional(),
366
+ logs_api_path: z.string().optional(),
367
+ web_url: z.string().optional(),
368
+ last_deployment: GitLabEnvironmentLastDeploymentSchema.nullable().optional(),
369
+ });
370
+ export const ListEnvironmentsSchema = z
371
+ .object({
372
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
373
+ name: z.string().optional().describe("Return environments with this exact name"),
374
+ search: z.string().optional().describe("Search environments by name"),
375
+ states: z
376
+ .enum(["available", "stopped"])
377
+ .optional()
378
+ .describe("Filter environments by state"),
379
+ })
380
+ .merge(PaginationOptionsSchema);
381
+ export const GetEnvironmentSchema = z.object({
382
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
383
+ environment_id: z.coerce.string().describe("The ID of the environment"),
384
+ });
252
385
  // Schema for creating a new pipeline
253
386
  export const CreatePipelineSchema = z.object({
254
387
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -260,6 +393,10 @@ export const CreatePipelineSchema = z.object({
260
393
  }))
261
394
  .optional()
262
395
  .describe("An array of variables to use for the pipeline"),
396
+ inputs: z
397
+ .record(z.string(), z.string())
398
+ .optional()
399
+ .describe("Input parameters for the pipeline (key-value pairs for spec:inputs)"),
263
400
  });
264
401
  // Schema for retrying a pipeline
265
402
  export const RetryPipelineSchema = z.object({
@@ -300,7 +437,7 @@ export const PlayPipelineJobSchema = z.object({
300
437
  });
301
438
  // Schema for retrying a job
302
439
  export const RetryPipelineJobSchema = PipelineJobControlSchema;
303
- // Schema for canceling a job
440
+ // Schema for canceling a job
304
441
  export const CancelPipelineJobSchema = z.object({
305
442
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
306
443
  job_id: z.coerce.string().describe("The ID of the job"),
@@ -438,17 +575,17 @@ export const GitLabRepositorySchema = z.object({
438
575
  export const GitLabProjectSchema = GitLabRepositorySchema;
439
576
  // File content schemas
440
577
  export const GitLabFileContentSchema = z.object({
441
- file_name: z.string(), // Changed from name to match GitLab API
442
- file_path: z.string(), // Changed from path to match GitLab API
443
- size: z.number(),
578
+ file_name: z.string().optional(),
579
+ file_path: z.string(),
580
+ size: z.coerce.number().optional(),
444
581
  encoding: z.string(),
445
582
  content: z.string(),
446
- content_sha256: z.string(), // Changed from sha to match GitLab API
447
- ref: z.string(), // Added as GitLab requires branch reference
448
- blob_id: z.string(), // Added to match GitLab API
449
- commit_id: z.string(), // ID of the current file version
450
- last_commit_id: z.string(), // Added to match GitLab API
451
- execute_filemode: z.boolean().optional(), // Added to match GitLab API
583
+ content_sha256: z.string().optional(),
584
+ ref: z.string().optional(),
585
+ blob_id: z.string().optional(),
586
+ commit_id: z.string().optional(),
587
+ last_commit_id: z.string().optional(),
588
+ execute_filemode: z.boolean().optional(),
452
589
  });
453
590
  export const GitLabDirectoryContentSchema = z.object({
454
591
  name: z.string(),
@@ -715,6 +852,15 @@ export const GitLabMergeRequestSchema = z.object({
715
852
  allow_collaboration: z.boolean().optional(),
716
853
  allow_maintainer_to_push: z.boolean().optional(),
717
854
  changes_count: z.string().nullable().optional(),
855
+ diverged_commits_count: z.coerce
856
+ .number()
857
+ .nullable()
858
+ .optional()
859
+ .describe("Number of commits the source branch is behind the target branch"),
860
+ rebase_in_progress: z
861
+ .boolean()
862
+ .optional()
863
+ .describe("Whether rebase is currently in progress for this merge request"),
718
864
  merge_when_pipeline_succeeds: z.boolean().optional(),
719
865
  squash: z.boolean().optional(),
720
866
  labels: z.array(z.string()).optional(),
@@ -772,7 +918,8 @@ export const LineRangeSchema = z
772
918
  })
773
919
  .describe("Line range for multiline comments on GitLab merge request diffs. VALIDATION RULES: 1) line_code is critical for GitLab API success, 2) start/end must have consistent types, 3) line numbers must form valid range, 4) get line_code from GitLab diff API, never generate manually.");
774
920
  // Discussion related schemas
775
- export const GitLabDiscussionNoteSchema = z.object({
921
+ export const GitLabDiscussionNoteSchema = z
922
+ .object({
776
923
  id: z.coerce.string(),
777
924
  type: z.enum(["DiscussionNote", "DiffNote", "Note"]).nullable().optional(), // Allow null type for regular notes
778
925
  body: z.string().optional(),
@@ -816,7 +963,8 @@ export const GitLabDiscussionNoteSchema = z.object({
816
963
  })
817
964
  .passthrough() // Allow additional fields
818
965
  .optional(),
819
- }).passthrough(); // Allow additional fields that GitLab might return
966
+ })
967
+ .passthrough(); // Allow additional fields that GitLab might return
820
968
  // Reusable pagination schema for GitLab API responses.
821
969
  // See https://docs.gitlab.com/api/rest/#pagination
822
970
  export const GitLabPaginationSchema = z.object({
@@ -855,7 +1003,10 @@ export const ListMergeRequestDiscussionsSchema = ProjectParamsSchema.extend({
855
1003
  export const GetMergeRequestNotesSchema = ProjectParamsSchema.extend({
856
1004
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
857
1005
  sort: z.enum(["asc", "desc"]).optional().describe("The sort order of the notes"),
858
- order_by: z.enum(["created_at", "updated_at"]).optional().describe("The field to sort the notes by"),
1006
+ order_by: z
1007
+ .enum(["created_at", "updated_at"])
1008
+ .optional()
1009
+ .describe("The field to sort the notes by"),
859
1010
  per_page: z.coerce.number().optional().describe("Number of items per page"),
860
1011
  page: z.coerce.number().optional().describe("Page number for pagination"),
861
1012
  });
@@ -950,10 +1101,43 @@ export const CreateRepositorySchema = z.object({
950
1101
  .describe("Repository visibility level"),
951
1102
  initialize_with_readme: z.boolean().optional().describe("Initialize with README.md"),
952
1103
  });
953
- export const GetFileContentsSchema = ProjectParamsSchema.extend({
954
- file_path: z.string().describe("Path to the file or directory"),
1104
+ export const GetFileContentsSchema = z
1105
+ .object({
1106
+ project_id: z.coerce
1107
+ .string()
1108
+ .optional()
1109
+ .describe("Project ID or URL-encoded path (optional; falls back to env)"),
1110
+ file_path: z
1111
+ .string()
1112
+ .optional()
1113
+ .describe("Path to the file or directory. Takes precedence over 'path' when both are provided"),
1114
+ path: z.string().optional().describe("Alias of file_path"),
955
1115
  ref: z.string().optional().describe("Branch/tag/commit to get contents from"),
956
- });
1116
+ })
1117
+ .superRefine((data, ctx) => {
1118
+ const fp = data.file_path?.trim();
1119
+ const p = data.path?.trim();
1120
+ if (!fp && !p) {
1121
+ ctx.addIssue({
1122
+ code: z.ZodIssueCode.custom,
1123
+ message: "Either 'file_path' or 'path' must be provided",
1124
+ path: ["file_path"],
1125
+ });
1126
+ }
1127
+ const finalPath = fp && fp.length > 0 ? fp : p ?? "";
1128
+ if (finalPath.trim().length === 0) {
1129
+ ctx.addIssue({
1130
+ code: z.ZodIssueCode.custom,
1131
+ message: "file_path cannot be empty or whitespace",
1132
+ path: ["file_path"],
1133
+ });
1134
+ }
1135
+ })
1136
+ .transform(data => ({
1137
+ project_id: (data.project_id ?? "").trim() || undefined,
1138
+ file_path: ((data.file_path ?? "").trim() || (data.path ?? "").trim()).trim(),
1139
+ ref: (data.ref ?? "").trim() || undefined,
1140
+ }));
957
1141
  export const PushFilesSchema = ProjectParamsSchema.extend({
958
1142
  branch: z.string().describe("Branch to push to"),
959
1143
  files: z
@@ -970,7 +1154,11 @@ export const CreateIssueSchema = ProjectParamsSchema.extend({
970
1154
  assignee_ids: z.array(z.number()).optional().describe("Array of user IDs to assign"),
971
1155
  labels: z.array(z.string()).optional().describe("Array of label names"),
972
1156
  milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
973
- issue_type: z.enum(["issue", "incident", "test_case", "task"]).describe("the type of issue. One of issue, incident, test_case or task.").nullish().default("issue"),
1157
+ issue_type: z
1158
+ .enum(["issue", "incident", "test_case", "task"])
1159
+ .describe("the type of issue. One of issue, incident, test_case or task.")
1160
+ .nullish()
1161
+ .default("issue"),
974
1162
  });
975
1163
  const MergeRequestOptionsSchema = {
976
1164
  title: z.string().describe("Merge request title"),
@@ -986,10 +1174,14 @@ const MergeRequestOptionsSchema = {
986
1174
  labels: z.array(z.string()).optional().describe("Labels for the MR"),
987
1175
  draft: z.boolean().optional().describe("Create as draft merge request"),
988
1176
  allow_collaboration: z.boolean().optional().describe("Allow commits from upstream members"),
989
- remove_source_branch: z.boolean().nullable()
1177
+ remove_source_branch: z
1178
+ .boolean()
1179
+ .nullable()
990
1180
  .optional()
991
1181
  .describe("Flag indicating if a merge request should remove the source branch when merging."),
992
- squash: z.boolean().nullable()
1182
+ squash: z
1183
+ .boolean()
1184
+ .nullable()
993
1185
  .optional()
994
1186
  .describe("If true, squash all commits into a single commit on merge."),
995
1187
  };
@@ -1006,7 +1198,8 @@ export const CreateBranchSchema = ProjectParamsSchema.extend({
1006
1198
  export const GetBranchDiffsSchema = ProjectParamsSchema.extend({
1007
1199
  from: z.string().describe("The base branch or commit SHA to compare from"),
1008
1200
  to: z.string().describe("The target branch or commit SHA to compare to"),
1009
- straight: z.boolean()
1201
+ straight: z
1202
+ .boolean()
1010
1203
  .optional()
1011
1204
  .describe("Comparison method: false for '...' (default), true for '--'"),
1012
1205
  excluded_file_patterns: z
@@ -1041,18 +1234,40 @@ export const UpdateMergeRequestSchema = GetMergeRequestSchema.extend({
1041
1234
  });
1042
1235
  export const MergeMergeRequestSchema = ProjectParamsSchema.extend({
1043
1236
  merge_request_iid: z.coerce.string().optional().describe("The IID of a merge request"),
1044
- auto_merge: z.boolean().optional().default(false).describe("If true, the merge request merges when the pipeline succeeds."),
1237
+ auto_merge: z
1238
+ .boolean()
1239
+ .optional()
1240
+ .default(false)
1241
+ .describe("If true, the merge request merges when the pipeline succeeds."),
1045
1242
  merge_commit_message: z.string().optional().describe("Custom merge commit message"),
1046
- merge_when_pipeline_succeeds: z.boolean().optional().default(false).describe("If true, the merge request merges when the pipeline succeeds.in GitLab 17.11. Use"),
1047
- should_remove_source_branch: z.boolean().optional().default(false).describe("Remove source branch after merge"),
1243
+ merge_when_pipeline_succeeds: z
1244
+ .boolean()
1245
+ .optional()
1246
+ .default(false)
1247
+ .describe("If true, the merge request merges when the pipeline succeeds.in GitLab 17.11. Use"),
1248
+ should_remove_source_branch: z
1249
+ .boolean()
1250
+ .optional()
1251
+ .default(false)
1252
+ .describe("Remove source branch after merge"),
1048
1253
  squash_commit_message: z.string().optional().describe("Custom squash commit message"),
1049
- squash: z.boolean().optional().default(false).describe("Squash commits into a single commit when merging"),
1254
+ squash: z
1255
+ .boolean()
1256
+ .optional()
1257
+ .default(false)
1258
+ .describe("Squash commits into a single commit when merging"),
1050
1259
  });
1051
1260
  // Merge Request Approval schemas
1052
1261
  export const ApproveMergeRequestSchema = ProjectParamsSchema.extend({
1053
1262
  merge_request_iid: z.coerce.string().describe("The IID of the merge request to approve"),
1054
- sha: z.string().optional().describe("The HEAD of the merge request. Optional, but used to ensure the merge request hasn't changed since you last reviewed it"),
1055
- approval_password: z.string().optional().describe("Current user's password. Required if 'Require user re-authentication to approve' is enabled in the project settings"),
1263
+ sha: z
1264
+ .string()
1265
+ .optional()
1266
+ .describe("The HEAD of the merge request. Optional, but used to ensure the merge request hasn't changed since you last reviewed it"),
1267
+ approval_password: z
1268
+ .string()
1269
+ .optional()
1270
+ .describe("Current user's password. Required if 'Require user re-authentication to approve' is enabled in the project settings"),
1056
1271
  });
1057
1272
  export const UnapproveMergeRequestSchema = ProjectParamsSchema.extend({
1058
1273
  merge_request_iid: z.coerce.string().describe("The IID of the merge request to unapprove"),
@@ -1073,26 +1288,47 @@ export const GitLabApprovalRuleSchema = z.object({
1073
1288
  eligible_approvers: z.array(GitLabApprovalUserSchema).optional(),
1074
1289
  approvals_required: z.number(),
1075
1290
  users: z.array(GitLabApprovalUserSchema).optional(),
1076
- groups: z.array(z.object({
1291
+ groups: z
1292
+ .array(z.object({
1077
1293
  id: z.coerce.string(),
1078
1294
  name: z.string(),
1079
1295
  path: z.string(),
1080
1296
  full_path: z.string(),
1081
1297
  avatar_url: z.string().nullable().optional(),
1082
1298
  web_url: z.string(),
1083
- })).optional(),
1299
+ }))
1300
+ .optional(),
1084
1301
  contains_hidden_groups: z.boolean().optional(),
1085
1302
  approved_by: z.array(GitLabApprovalUserSchema).optional(),
1086
- source_rule: z.object({
1303
+ source_rule: z
1304
+ .object({
1087
1305
  id: z.coerce.string().optional(),
1088
1306
  name: z.string().optional(),
1089
1307
  rule_type: z.string().optional(),
1090
- }).nullable().optional(),
1308
+ })
1309
+ .nullable()
1310
+ .optional(),
1311
+ approved: z.boolean().optional(),
1312
+ });
1313
+ export const GitLabMergeRequestApprovalsResponseSchema = z.object({
1091
1314
  approved: z.boolean().optional(),
1315
+ user_has_approved: z.boolean().optional(),
1316
+ user_can_approve: z.boolean().optional(),
1317
+ approved_by: z
1318
+ .array(z.object({
1319
+ user: GitLabApprovalUserSchema,
1320
+ }))
1321
+ .optional(),
1092
1322
  });
1093
1323
  export const GitLabMergeRequestApprovalStateSchema = z.object({
1094
1324
  approval_rules_overwritten: z.boolean().optional(),
1095
1325
  rules: z.array(GitLabApprovalRuleSchema).optional(),
1326
+ approved: z.boolean().optional(),
1327
+ user_has_approved: z.boolean().optional(),
1328
+ user_can_approve: z.boolean().optional(),
1329
+ approved_by: z.array(GitLabApprovalUserSchema).optional(),
1330
+ approved_by_usernames: z.array(z.string()).optional(),
1331
+ source_endpoint: z.enum(["approval_state", "approvals"]).optional(),
1096
1332
  });
1097
1333
  export const GetMergeRequestApprovalStateSchema = ProjectParamsSchema.extend({
1098
1334
  merge_request_iid: z.coerce.string().describe("The IID of the merge request"),
@@ -1107,7 +1343,8 @@ export const GetMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
1107
1343
  export const ListMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
1108
1344
  page: z.number().optional().describe("Page number for pagination (default: 1)"),
1109
1345
  per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
1110
- unidiff: z.boolean()
1346
+ unidiff: z
1347
+ .boolean()
1111
1348
  .optional()
1112
1349
  .describe("Present diffs in the unified diff format. Default is false. Introduced in GitLab 16.5."),
1113
1350
  });
@@ -1117,7 +1354,8 @@ export const ListMergeRequestVersionsSchema = ProjectParamsSchema.extend({
1117
1354
  });
1118
1355
  export const GetMergeRequestVersionSchema = ListMergeRequestVersionsSchema.extend({
1119
1356
  version_id: z.coerce.string().describe("The ID of the merge request diff version"),
1120
- unidiff: z.boolean()
1357
+ unidiff: z
1358
+ .boolean()
1121
1359
  .optional()
1122
1360
  .describe("Present diffs in the unified diff format. Default is false. Introduced in GitLab 16.5."),
1123
1361
  });
@@ -1177,7 +1415,10 @@ export const ListIssuesSchema = z
1177
1415
  // Merge Requests API operation schemas
1178
1416
  export const ListMergeRequestsSchema = z
1179
1417
  .object({
1180
- project_id: z.coerce.string().optional().describe("Project ID or URL-encoded path (optional - if not provided, lists all merge requests the user has access to)"),
1418
+ project_id: z.coerce
1419
+ .string()
1420
+ .optional()
1421
+ .describe("Project ID or URL-encoded path (optional - if not provided, lists all merge requests the user has access to)"),
1181
1422
  assignee_id: z.coerce
1182
1423
  .string()
1183
1424
  .optional()
@@ -1276,7 +1517,9 @@ export const UpdateIssueSchema = z.object({
1276
1517
  milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
1277
1518
  state_event: z.enum(["close", "reopen"]).optional().describe("Update issue state (close/reopen)"),
1278
1519
  weight: z.number().optional().describe("Weight of the issue (0-9)"),
1279
- issue_type: z.enum(["issue", "incident", "test_case", "task"]).describe("the type of issue. One of issue, incident, test_case or task."),
1520
+ issue_type: z
1521
+ .enum(["issue", "incident", "test_case", "task"])
1522
+ .describe("the type of issue. One of issue, incident, test_case or task."),
1280
1523
  });
1281
1524
  export const DeleteIssueSchema = z.object({
1282
1525
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1332,11 +1575,10 @@ export const GetProjectSchema = z.object({
1332
1575
  export const ListProjectsSchema = z
1333
1576
  .object({
1334
1577
  search: z.string().optional().describe("Search term for projects"),
1335
- search_namespaces: z.boolean()
1336
- .optional()
1337
- .describe("Needs to be true if search is full path"),
1578
+ search_namespaces: z.boolean().optional().describe("Needs to be true if search is full path"),
1338
1579
  owned: z.boolean().optional().describe("Filter for projects owned by current user"),
1339
- membership: z.boolean()
1580
+ membership: z
1581
+ .boolean()
1340
1582
  .optional()
1341
1583
  .describe("Filter for projects where current user is a member"),
1342
1584
  simple: z.boolean().optional().describe("Return only limited fields"),
@@ -1476,19 +1718,57 @@ export const GitLabWikiPageSchema = z.object({
1476
1718
  // Extremely flexible position schema for API responses - accepts any structure
1477
1719
  // Strict position schema for creating draft notes and merge request threads
1478
1720
  export const MergeRequestThreadPositionCreateSchema = z.object({
1479
- base_sha: z.string().describe("REQUIRED: Base commit SHA in the source branch. Get this from merge request diff_refs.base_sha."),
1480
- head_sha: z.string().describe("REQUIRED: SHA referencing HEAD of the source branch. Get this from merge request diff_refs.head_sha."),
1481
- start_sha: z.string().describe("REQUIRED: SHA referencing the start commit of the source branch. Get this from merge request diff_refs.start_sha."),
1482
- position_type: z.enum(["text", "image", "file"]).describe("REQUIRED: Position type. Use 'text' for code diffs, 'image' for image diffs, 'file' for file-level comments."),
1483
- new_path: z.string().nullable().optional().describe("File path after changes. REQUIRED for most diff comments. Use same as old_path if file wasn't renamed."),
1484
- old_path: z.string().nullable().optional().describe("File path before changes. REQUIRED for most diff comments. Use same as new_path if file wasn't renamed."),
1485
- new_line: z.number().nullable().optional().describe("Line number in modified file (after changes). Use for added lines or context lines. NULL for deleted lines. For single-line comments on new lines."),
1486
- old_line: z.number().nullable().optional().describe("Line number in original file (before changes). Use for deleted lines or context lines. NULL for added lines. For single-line comments on old lines."),
1487
- line_range: LineRangeSchema.nullable().optional().describe("MULTILINE COMMENTS: Specify start/end line positions for commenting on multiple lines. Alternative to single old_line/new_line."),
1488
- width: z.number().optional().describe("IMAGE DIFFS ONLY: Width of the image (for position_type='image')."),
1489
- height: z.number().optional().describe("IMAGE DIFFS ONLY: Height of the image (for position_type='image')."),
1490
- x: z.number().optional().describe("IMAGE DIFFS ONLY: X coordinate on the image (for position_type='image')."),
1491
- y: z.number().optional().describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
1721
+ base_sha: z
1722
+ .string()
1723
+ .describe("REQUIRED: Base commit SHA in the source branch. Get this from merge request diff_refs.base_sha."),
1724
+ head_sha: z
1725
+ .string()
1726
+ .describe("REQUIRED: SHA referencing HEAD of the source branch. Get this from merge request diff_refs.head_sha."),
1727
+ start_sha: z
1728
+ .string()
1729
+ .describe("REQUIRED: SHA referencing the start commit of the source branch. Get this from merge request diff_refs.start_sha."),
1730
+ position_type: z
1731
+ .enum(["text", "image", "file"])
1732
+ .describe("REQUIRED: Position type. Use 'text' for code diffs, 'image' for image diffs, 'file' for file-level comments."),
1733
+ new_path: z
1734
+ .string()
1735
+ .nullable()
1736
+ .optional()
1737
+ .describe("File path after changes. REQUIRED for most diff comments. Use same as old_path if file wasn't renamed."),
1738
+ old_path: z
1739
+ .string()
1740
+ .nullable()
1741
+ .optional()
1742
+ .describe("File path before changes. REQUIRED for most diff comments. Use same as new_path if file wasn't renamed."),
1743
+ new_line: z
1744
+ .number()
1745
+ .nullable()
1746
+ .optional()
1747
+ .describe("Line number in modified file (after changes). Use for added lines or context lines. NULL for deleted lines. For single-line comments on new lines."),
1748
+ old_line: z
1749
+ .number()
1750
+ .nullable()
1751
+ .optional()
1752
+ .describe("Line number in original file (before changes). Use for deleted lines or context lines. NULL for added lines. For single-line comments on old lines."),
1753
+ line_range: LineRangeSchema.nullable()
1754
+ .optional()
1755
+ .describe("MULTILINE COMMENTS: Specify start/end line positions for commenting on multiple lines. Alternative to single old_line/new_line."),
1756
+ width: z
1757
+ .number()
1758
+ .optional()
1759
+ .describe("IMAGE DIFFS ONLY: Width of the image (for position_type='image')."),
1760
+ height: z
1761
+ .number()
1762
+ .optional()
1763
+ .describe("IMAGE DIFFS ONLY: Height of the image (for position_type='image')."),
1764
+ x: z
1765
+ .number()
1766
+ .optional()
1767
+ .describe("IMAGE DIFFS ONLY: X coordinate on the image (for position_type='image')."),
1768
+ y: z
1769
+ .number()
1770
+ .optional()
1771
+ .describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
1492
1772
  });
1493
1773
  // Schema for creating/sending position to GitLab API (stricter)
1494
1774
  export const MergeRequestThreadPositionSchema = z.object({
@@ -1524,7 +1804,9 @@ export const MergeRequestThreadPositionSchema = z.object({
1524
1804
  .nullable()
1525
1805
  .optional()
1526
1806
  .describe("Line number in original file (before changes). Use for deleted lines or context lines. NULL for added lines. For single-line comments on old lines."),
1527
- line_range: LineRangeSchema.nullable().optional().describe("MULTILINE COMMENTS: Specify start/end line positions for commenting on multiple lines. Alternative to single old_line/new_line."),
1807
+ line_range: LineRangeSchema.nullable()
1808
+ .optional()
1809
+ .describe("MULTILINE COMMENTS: Specify start/end line positions for commenting on multiple lines. Alternative to single old_line/new_line."),
1528
1810
  width: z
1529
1811
  .number()
1530
1812
  .nullable()
@@ -1547,22 +1829,26 @@ export const MergeRequestThreadPositionSchema = z.object({
1547
1829
  .describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
1548
1830
  });
1549
1831
  // Draft Notes API schemas
1550
- export const GitLabDraftNoteSchema = z.object({
1832
+ export const GitLabDraftNoteSchema = z
1833
+ .object({
1551
1834
  id: z.coerce.string(),
1552
1835
  author: GitLabUserSchema.optional(),
1553
1836
  body: z.string().optional(),
1554
1837
  note: z.string().optional(), // Some APIs might use 'note' instead of 'body'
1555
1838
  created_at: z.string().optional(),
1556
1839
  updated_at: z.string().optional(),
1557
- position: MergeRequestThreadPositionSchema.nullable().optional(),
1840
+ discussion_id: z.string().nullable().optional(),
1841
+ position: z.record(z.unknown()).nullable().optional(),
1558
1842
  resolve_discussion: z.boolean().optional(),
1559
- }).transform((data) => ({
1843
+ })
1844
+ .transform(data => ({
1560
1845
  // Normalize the response to always have consistent field names
1561
1846
  id: data.id,
1562
1847
  author: data.author,
1563
1848
  body: data.body || data.note || "",
1564
1849
  created_at: data.created_at || "",
1565
1850
  updated_at: data.updated_at || "",
1851
+ discussion_id: data.discussion_id || null,
1566
1852
  position: data.position,
1567
1853
  resolve_discussion: data.resolve_discussion,
1568
1854
  }));
@@ -1579,8 +1865,15 @@ export const ListDraftNotesSchema = ProjectParamsSchema.extend({
1579
1865
  export const CreateDraftNoteSchema = ProjectParamsSchema.extend({
1580
1866
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
1581
1867
  body: z.string().describe("The content of the draft note"),
1868
+ in_reply_to_discussion_id: z.coerce
1869
+ .string()
1870
+ .optional()
1871
+ .describe("The ID of a discussion the draft note replies to"),
1582
1872
  position: MergeRequestThreadPositionSchema.optional().describe("Position when creating a diff note"),
1583
- resolve_discussion: z.boolean().optional().describe("Whether to resolve the discussion when publishing"),
1873
+ resolve_discussion: z
1874
+ .boolean()
1875
+ .optional()
1876
+ .describe("Whether to resolve the discussion when publishing"),
1584
1877
  });
1585
1878
  // Update draft note schema
1586
1879
  export const UpdateDraftNoteSchema = ProjectParamsSchema.extend({
@@ -1588,7 +1881,10 @@ export const UpdateDraftNoteSchema = ProjectParamsSchema.extend({
1588
1881
  draft_note_id: z.coerce.string().describe("The ID of the draft note"),
1589
1882
  body: z.string().optional().describe("The content of the draft note"),
1590
1883
  position: MergeRequestThreadPositionSchema.optional().describe("Position when creating a diff note"),
1591
- resolve_discussion: z.boolean().optional().describe("Whether to resolve the discussion when publishing"),
1884
+ resolve_discussion: z
1885
+ .boolean()
1886
+ .optional()
1887
+ .describe("Whether to resolve the discussion when publishing"),
1592
1888
  });
1593
1889
  // Delete draft note schema
1594
1890
  export const DeleteDraftNoteSchema = ProjectParamsSchema.extend({
@@ -1692,10 +1988,9 @@ export const ListCommitsSchema = z.object({
1692
1988
  path: z.string().optional().describe("The file path"),
1693
1989
  author: z.string().optional().describe("Search commits by commit author"),
1694
1990
  all: z.boolean().optional().describe("Retrieve every commit from the repository"),
1695
- with_stats: z.boolean()
1696
- .optional()
1697
- .describe("Stats about each commit are added to the response"),
1698
- first_parent: z.boolean()
1991
+ with_stats: z.boolean().optional().describe("Stats about each commit are added to the response"),
1992
+ first_parent: z
1993
+ .boolean()
1699
1994
  .optional()
1700
1995
  .describe("Follow only the first parent commit upon seeing a merge commit"),
1701
1996
  order: z.enum(["default", "topo"]).optional().describe("List commits in order"),
@@ -1711,11 +2006,17 @@ export const GetCommitSchema = z.object({
1711
2006
  export const GetCommitDiffSchema = z.object({
1712
2007
  project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
1713
2008
  sha: z.string().describe("The commit hash or name of a repository branch or tag"),
1714
- full_diff: z.boolean().optional().describe("Whether to return the full diff or only first page (default: false)"),
2009
+ full_diff: z
2010
+ .boolean()
2011
+ .optional()
2012
+ .describe("Whether to return the full diff or only first page (default: false)"),
1715
2013
  });
1716
2014
  // Schema for listing issues assigned to the current user
1717
2015
  export const MyIssuesSchema = z.object({
1718
- project_id: z.string().optional().describe("Project ID or URL-encoded path (optional when GITLAB_PROJECT_ID is set)"),
2016
+ project_id: z
2017
+ .string()
2018
+ .optional()
2019
+ .describe("Project ID or URL-encoded path (optional when GITLAB_PROJECT_ID is set)"),
1719
2020
  state: z
1720
2021
  .enum(["opened", "closed", "all"])
1721
2022
  .optional()
@@ -1723,10 +2024,22 @@ export const MyIssuesSchema = z.object({
1723
2024
  labels: z.array(z.string()).optional().describe("Array of label names to filter by"),
1724
2025
  milestone: z.string().optional().describe("Milestone title to filter by"),
1725
2026
  search: z.string().optional().describe("Search for specific terms in title and description"),
1726
- created_after: z.string().optional().describe("Return issues created after the given time (ISO 8601)"),
1727
- created_before: z.string().optional().describe("Return issues created before the given time (ISO 8601)"),
1728
- updated_after: z.string().optional().describe("Return issues updated after the given time (ISO 8601)"),
1729
- updated_before: z.string().optional().describe("Return issues updated before the given time (ISO 8601)"),
2027
+ created_after: z
2028
+ .string()
2029
+ .optional()
2030
+ .describe("Return issues created after the given time (ISO 8601)"),
2031
+ created_before: z
2032
+ .string()
2033
+ .optional()
2034
+ .describe("Return issues created before the given time (ISO 8601)"),
2035
+ updated_after: z
2036
+ .string()
2037
+ .optional()
2038
+ .describe("Return issues updated after the given time (ISO 8601)"),
2039
+ updated_before: z
2040
+ .string()
2041
+ .optional()
2042
+ .describe("Return issues updated before the given time (ISO 8601)"),
1730
2043
  per_page: z.number().optional().describe("Number of items per page (default: 20, max: 100)"),
1731
2044
  page: z.number().optional().describe("Page number for pagination (default: 1)"),
1732
2045
  });
@@ -1773,7 +2086,10 @@ export const DownloadAttachmentSchema = z.object({
1773
2086
  project_id: z.string().describe("Project ID or URL-encoded path of the project"),
1774
2087
  secret: z.string().describe("The 32-character secret of the upload"),
1775
2088
  filename: z.string().describe("The filename of the upload"),
1776
- local_path: z.string().optional().describe("Local path to save the file (optional, defaults to current directory)"),
2089
+ local_path: z
2090
+ .string()
2091
+ .optional()
2092
+ .describe("Local path to save the file (optional, defaults to current directory)"),
1777
2093
  });
1778
2094
  export const GroupIteration = z.object({
1779
2095
  id: z.coerce.string(),
@@ -1804,10 +2120,12 @@ export const ListGroupIterationsSchema = z
1804
2120
  .array(z.enum(["title", "cadence_title"]))
1805
2121
  .optional()
1806
2122
  .describe("Fields in which fuzzy search should be performed with the query given in the argument search. The available options are title and cadence_title. Default is [title]."),
1807
- include_ancestors: z.boolean()
2123
+ include_ancestors: z
2124
+ .boolean()
1808
2125
  .optional()
1809
2126
  .describe("Include iterations for group and its ancestors. Defaults to true."),
1810
- include_descendants: z.boolean()
2127
+ include_descendants: z
2128
+ .boolean()
1811
2129
  .optional()
1812
2130
  .describe("Include iterations for group and its descendants. Defaults to false."),
1813
2131
  updated_before: z
@@ -1829,7 +2147,8 @@ export const GitLabEventAuthorSchema = z.object({
1829
2147
  avatar_url: z.string().nullable(),
1830
2148
  web_url: z.string(),
1831
2149
  });
1832
- export const GitLabEventSchema = z.object({
2150
+ export const GitLabEventSchema = z
2151
+ .object({
1833
2152
  id: z.coerce.string(),
1834
2153
  project_id: z.coerce.string(),
1835
2154
  action_name: z.string(),
@@ -1843,26 +2162,57 @@ export const GitLabEventSchema = z.object({
1843
2162
  author_username: z.string(),
1844
2163
  imported: z.boolean(),
1845
2164
  imported_from: z.string(),
1846
- }).passthrough(); // Allow additional fields
2165
+ })
2166
+ .passthrough(); // Allow additional fields
1847
2167
  // List events schema
1848
2168
  export const ListEventsSchema = z.object({
1849
- action: z.string().optional().describe("If defined, returns events with the specified action type"),
1850
- target_type: z.enum(["epic", "issue", "merge_request", "milestone", "note", "project", "snippet", "user"]).optional().describe("If defined, returns events with the specified target type"),
1851
- before: z.string().optional().describe("If defined, Returns events created before the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use before=2025-08-30"),
1852
- after: z.string().optional().describe("If defined, Returns events created after the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use after=2025-08-28"),
2169
+ action: z
2170
+ .string()
2171
+ .optional()
2172
+ .describe("If defined, returns events with the specified action type"),
2173
+ target_type: z
2174
+ .enum(["epic", "issue", "merge_request", "milestone", "note", "project", "snippet", "user"])
2175
+ .optional()
2176
+ .describe("If defined, returns events with the specified target type"),
2177
+ before: z
2178
+ .string()
2179
+ .optional()
2180
+ .describe("If defined, Returns events created before the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use before=2025-08-30"),
2181
+ after: z
2182
+ .string()
2183
+ .optional()
2184
+ .describe("If defined, Returns events created after the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use after=2025-08-28"),
1853
2185
  scope: z.string().optional().describe("Include all events across a user's projects"),
1854
- sort: z.enum(["asc", "desc"]).optional().describe("Direction to sort the results by creation date. Default: desc"),
2186
+ sort: z
2187
+ .enum(["asc", "desc"])
2188
+ .optional()
2189
+ .describe("Direction to sort the results by creation date. Default: desc"),
1855
2190
  page: z.number().optional().describe("Returns the specified results page. Default: 1"),
1856
2191
  per_page: z.number().optional().describe("Number of results per page. Default: 20"),
1857
2192
  });
1858
2193
  // Get project events schema
1859
2194
  export const GetProjectEventsSchema = z.object({
1860
2195
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1861
- action: z.string().optional().describe("If defined, returns events with the specified action type"),
1862
- target_type: z.enum(["epic", "issue", "merge_request", "milestone", "note", "project", "snippet", "user"]).optional().describe("If defined, returns events with the specified target type"),
1863
- before: z.string().optional().describe("If defined, Returns events created before the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use before=2025-08-30"),
1864
- after: z.string().optional().describe("If defined, Returns events created after the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use after=2025-08-28"),
1865
- sort: z.enum(["asc", "desc"]).optional().describe("Direction to sort the results by creation date. Default: desc"),
2196
+ action: z
2197
+ .string()
2198
+ .optional()
2199
+ .describe("If defined, returns events with the specified action type"),
2200
+ target_type: z
2201
+ .enum(["epic", "issue", "merge_request", "milestone", "note", "project", "snippet", "user"])
2202
+ .optional()
2203
+ .describe("If defined, returns events with the specified target type"),
2204
+ before: z
2205
+ .string()
2206
+ .optional()
2207
+ .describe("If defined, Returns events created before the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use before=2025-08-30"),
2208
+ after: z
2209
+ .string()
2210
+ .optional()
2211
+ .describe("If defined, Returns events created after the specified date (YYYY-MM-DD format). To include events on 2025-08-29, use after=2025-08-28"),
2212
+ sort: z
2213
+ .enum(["asc", "desc"])
2214
+ .optional()
2215
+ .describe("Direction to sort the results by creation date. Default: desc"),
1866
2216
  page: z.number().optional().describe("Returns the specified results page. Default: 1"),
1867
2217
  per_page: z.number().optional().describe("Number of results per page. Default: 20"),
1868
2218
  });
@@ -1885,10 +2235,7 @@ export const GitLabMergeRequestVersionDetailSchema = GitLabMergeRequestVersionSc
1885
2235
  // GraphQL generic execution schema
1886
2236
  export const ExecuteGraphQLSchema = z.object({
1887
2237
  query: z.string().describe("GraphQL query string"),
1888
- variables: z
1889
- .record(z.any())
1890
- .optional()
1891
- .describe("Variables object for the GraphQL query"),
2238
+ variables: z.record(z.any()).optional().describe("Variables object for the GraphQL query"),
1892
2239
  });
1893
2240
  // Release schemas
1894
2241
  export const GitLabReleaseAssetLinkSchema = z.object({
@@ -1920,15 +2267,18 @@ export const GitLabReleaseSchema = z.object({
1920
2267
  description_html: z.string().nullable().optional(),
1921
2268
  created_at: z.string(),
1922
2269
  released_at: z.string().nullable().optional(),
1923
- author: z.object({
2270
+ author: z
2271
+ .object({
1924
2272
  id: z.number(),
1925
2273
  name: z.string(),
1926
2274
  username: z.string(),
1927
2275
  state: z.string(),
1928
2276
  avatar_url: z.string().nullable().optional(),
1929
2277
  web_url: z.string(),
1930
- }).optional(),
1931
- commit: z.object({
2278
+ })
2279
+ .optional(),
2280
+ commit: z
2281
+ .object({
1932
2282
  id: z.string(),
1933
2283
  short_id: z.string(),
1934
2284
  title: z.string(),
@@ -1941,13 +2291,15 @@ export const GitLabReleaseSchema = z.object({
1941
2291
  committer_name: z.string(),
1942
2292
  committer_email: z.string(),
1943
2293
  committed_date: z.string(),
1944
- }).optional(),
2294
+ })
2295
+ .optional(),
1945
2296
  milestones: z.array(GitLabMilestonesSchema).optional(),
1946
2297
  commit_path: z.string().optional(),
1947
2298
  tag_path: z.string().optional(),
1948
2299
  assets: GitLabReleaseAssetsSchema.optional(),
1949
2300
  evidences: z.array(GitLabReleaseEvidenceSchema).optional(),
1950
- _links: z.object({
2301
+ _links: z
2302
+ .object({
1951
2303
  closed_issues_url: z.string().optional(),
1952
2304
  closed_merge_requests_url: z.string().optional(),
1953
2305
  edit_url: z.string().optional(),
@@ -1955,7 +2307,8 @@ export const GitLabReleaseSchema = z.object({
1955
2307
  opened_issues_url: z.string().optional(),
1956
2308
  opened_merge_requests_url: z.string().optional(),
1957
2309
  self: z.string().optional(),
1958
- }).optional(),
2310
+ })
2311
+ .optional(),
1959
2312
  upcoming_release: z.boolean().optional(),
1960
2313
  historical_release: z.boolean().optional(),
1961
2314
  });
@@ -1989,7 +2342,10 @@ export const CreateReleaseSchema = z.object({
1989
2342
  tag_name: z.string().describe("The tag where the release is created from"),
1990
2343
  name: z.string().optional().describe("The release name"),
1991
2344
  tag_message: z.string().optional().describe("Message to use if creating a new annotated tag"),
1992
- description: z.string().optional().describe("The description of the release. You can use Markdown."),
2345
+ description: z
2346
+ .string()
2347
+ .optional()
2348
+ .describe("The description of the release. You can use Markdown."),
1993
2349
  ref: z
1994
2350
  .string()
1995
2351
  .optional()
@@ -2002,9 +2358,16 @@ export const CreateReleaseSchema = z.object({
2002
2358
  .object({
2003
2359
  links: z
2004
2360
  .array(z.object({
2005
- name: z.string().describe("The name of the link. Link names must be unique within the release."),
2006
- url: z.string().describe("The URL of the link. Link URLs must be unique within the release."),
2007
- direct_asset_path: z.string().optional().describe("Optional path for a direct asset link."),
2361
+ name: z
2362
+ .string()
2363
+ .describe("The name of the link. Link names must be unique within the release."),
2364
+ url: z
2365
+ .string()
2366
+ .describe("The URL of the link. Link URLs must be unique within the release."),
2367
+ direct_asset_path: z
2368
+ .string()
2369
+ .optional()
2370
+ .describe("Optional path for a direct asset link."),
2008
2371
  link_type: z
2009
2372
  .enum(["other", "runbook", "image", "package"])
2010
2373
  .optional()
@@ -2023,7 +2386,10 @@ export const UpdateReleaseSchema = z.object({
2023
2386
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2024
2387
  tag_name: z.string().describe("The Git tag the release is associated with"),
2025
2388
  name: z.string().optional().describe("The release name"),
2026
- description: z.string().optional().describe("The description of the release. You can use Markdown."),
2389
+ description: z
2390
+ .string()
2391
+ .optional()
2392
+ .describe("The description of the release. You can use Markdown."),
2027
2393
  milestones: z
2028
2394
  .array(z.string())
2029
2395
  .optional()
@@ -2041,8 +2407,45 @@ export const CreateReleaseEvidenceSchema = z.object({
2041
2407
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2042
2408
  tag_name: z.string().describe("The Git tag the release is associated with"),
2043
2409
  });
2410
+ // Job Artifacts schemas
2411
+ export const ListJobArtifactsSchema = z.object({
2412
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2413
+ job_id: z.coerce.string().describe("The ID of the job"),
2414
+ path: z
2415
+ .string()
2416
+ .optional()
2417
+ .describe("Directory path within the artifacts archive (defaults to root)"),
2418
+ recursive: z
2419
+ .boolean()
2420
+ .optional()
2421
+ .describe("Whether to list artifacts recursively"),
2422
+ });
2423
+ export const GitLabArtifactEntrySchema = z.object({
2424
+ name: z.string(),
2425
+ path: z.string(),
2426
+ type: z.enum(["file", "directory"]),
2427
+ size: z.number().optional(),
2428
+ mode: z.string().optional(),
2429
+ });
2430
+ export const DownloadJobArtifactsSchema = z.object({
2431
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2432
+ job_id: z.coerce.string().describe("The ID of the job"),
2433
+ local_path: z
2434
+ .string()
2435
+ .optional()
2436
+ .describe("Local directory to save the artifact archive (defaults to current directory)"),
2437
+ });
2438
+ export const GetJobArtifactFileSchema = z.object({
2439
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2440
+ job_id: z.coerce.string().describe("The ID of the job"),
2441
+ artifact_path: z
2442
+ .string()
2443
+ .describe("Path to the file within the artifacts archive"),
2444
+ });
2044
2445
  export const DownloadReleaseAssetSchema = z.object({
2045
2446
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2046
2447
  tag_name: z.string().describe("The Git tag the release is associated with"),
2047
- direct_asset_path: z.string().describe("Path to the release asset file as specified when creating or updating its link"),
2448
+ direct_asset_path: z
2449
+ .string()
2450
+ .describe("Path to the release asset file as specified when creating or updating its link"),
2048
2451
  });