@zereight/mcp-gitlab 1.0.75 → 2.0.0-beta.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 +81 -67
- package/build/customSchemas.js +13 -4
- package/build/index.js +673 -38
- package/build/schemas.js +553 -100
- package/build/src/argon2wrapper.js +68 -0
- package/build/src/authentication.js +78 -0
- package/build/src/authhelpers.js +44 -0
- package/build/src/config.js +99 -0
- package/build/src/customSchemas.js +21 -0
- package/build/src/gitlabhandler.js +1649 -0
- package/build/src/gitlabsession.js +103 -0
- package/build/src/logger.js +11 -0
- package/build/src/mcpserver.js +1331 -0
- package/build/src/oauth.js +389 -0
- package/build/src/schemas.js +1678 -0
- package/package.json +3 -2
- package/build/utils.js +0 -9
package/build/schemas.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { flexibleBoolean } from "./customSchemas.js";
|
|
2
|
+
import { flexibleBoolean, flexibleBooleanNullable } from "./customSchemas.js";
|
|
3
3
|
// Base schemas for common types
|
|
4
4
|
export const GitLabAuthorSchema = z.object({
|
|
5
5
|
name: z.string(),
|
|
@@ -91,6 +91,72 @@ export const GitLabPipelineJobSchema = z.object({
|
|
|
91
91
|
.optional(),
|
|
92
92
|
web_url: z.string().optional(),
|
|
93
93
|
});
|
|
94
|
+
// Pipeline trigger job (bridge) schema
|
|
95
|
+
export const GitLabPipelineTriggerJobSchema = z.object({
|
|
96
|
+
id: z.coerce.string(),
|
|
97
|
+
status: z.string(),
|
|
98
|
+
stage: z.string(),
|
|
99
|
+
name: z.string(),
|
|
100
|
+
ref: z.string(),
|
|
101
|
+
tag: flexibleBoolean,
|
|
102
|
+
coverage: z.number().nullable().optional(),
|
|
103
|
+
created_at: z.string(),
|
|
104
|
+
started_at: z.string().nullable().optional(),
|
|
105
|
+
finished_at: z.string().nullable().optional(),
|
|
106
|
+
duration: z.number().nullable().optional(),
|
|
107
|
+
queued_duration: z.number().nullable().optional(),
|
|
108
|
+
user: z
|
|
109
|
+
.object({
|
|
110
|
+
id: z.coerce.string(),
|
|
111
|
+
name: z.string(),
|
|
112
|
+
username: z.string(),
|
|
113
|
+
avatar_url: z.string().nullable().optional(),
|
|
114
|
+
})
|
|
115
|
+
.optional(),
|
|
116
|
+
commit: z
|
|
117
|
+
.object({
|
|
118
|
+
id: z.string(),
|
|
119
|
+
short_id: z.string(),
|
|
120
|
+
title: z.string(),
|
|
121
|
+
author_name: z.string(),
|
|
122
|
+
author_email: z.string(),
|
|
123
|
+
})
|
|
124
|
+
.optional(),
|
|
125
|
+
pipeline: z
|
|
126
|
+
.object({
|
|
127
|
+
id: z.coerce.string(),
|
|
128
|
+
project_id: z.coerce.string(),
|
|
129
|
+
status: z.string(),
|
|
130
|
+
ref: z.string(),
|
|
131
|
+
sha: z.string(),
|
|
132
|
+
created_at: z.string().optional(),
|
|
133
|
+
updated_at: z.string().optional(),
|
|
134
|
+
web_url: z.string().optional(),
|
|
135
|
+
})
|
|
136
|
+
.optional(),
|
|
137
|
+
web_url: z.string().optional(),
|
|
138
|
+
allow_failure: flexibleBoolean.optional(),
|
|
139
|
+
archived: flexibleBoolean.optional(),
|
|
140
|
+
source: z.string().optional(),
|
|
141
|
+
erased_at: z.string().nullable().optional(),
|
|
142
|
+
project: z
|
|
143
|
+
.object({
|
|
144
|
+
ci_job_token_scope_enabled: flexibleBoolean.optional(),
|
|
145
|
+
})
|
|
146
|
+
.optional(),
|
|
147
|
+
downstream_pipeline: z
|
|
148
|
+
.object({
|
|
149
|
+
id: z.coerce.string(),
|
|
150
|
+
sha: z.string(),
|
|
151
|
+
ref: z.string(),
|
|
152
|
+
status: z.string(),
|
|
153
|
+
created_at: z.string(),
|
|
154
|
+
updated_at: z.string(),
|
|
155
|
+
web_url: z.string(),
|
|
156
|
+
})
|
|
157
|
+
.nullable()
|
|
158
|
+
.optional(),
|
|
159
|
+
});
|
|
94
160
|
// Shared base schema for various pagination options
|
|
95
161
|
// See https://docs.gitlab.com/api/rest/#pagination
|
|
96
162
|
export const PaginationOptionsSchema = z.object({
|
|
@@ -98,7 +164,8 @@ export const PaginationOptionsSchema = z.object({
|
|
|
98
164
|
per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
|
|
99
165
|
});
|
|
100
166
|
// Schema for listing pipelines
|
|
101
|
-
export const ListPipelinesSchema = z
|
|
167
|
+
export const ListPipelinesSchema = z
|
|
168
|
+
.object({
|
|
102
169
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
103
170
|
scope: z
|
|
104
171
|
.enum(["running", "pending", "finished", "branches", "tags"])
|
|
@@ -122,7 +189,9 @@ export const ListPipelinesSchema = z.object({
|
|
|
122
189
|
.describe("The status of pipelines"),
|
|
123
190
|
ref: z.string().optional().describe("The ref of pipelines"),
|
|
124
191
|
sha: z.string().optional().describe("The SHA of pipelines"),
|
|
125
|
-
yaml_errors: flexibleBoolean
|
|
192
|
+
yaml_errors: flexibleBoolean
|
|
193
|
+
.optional()
|
|
194
|
+
.describe("Returns pipelines with invalid configurations"),
|
|
126
195
|
username: z.string().optional().describe("The username of the user who triggered pipelines"),
|
|
127
196
|
updated_after: z
|
|
128
197
|
.string()
|
|
@@ -137,14 +206,16 @@ export const ListPipelinesSchema = z.object({
|
|
|
137
206
|
.optional()
|
|
138
207
|
.describe("Order pipelines by"),
|
|
139
208
|
sort: z.enum(["asc", "desc"]).optional().describe("Sort pipelines"),
|
|
140
|
-
})
|
|
209
|
+
})
|
|
210
|
+
.merge(PaginationOptionsSchema);
|
|
141
211
|
// Schema for getting a specific pipeline
|
|
142
212
|
export const GetPipelineSchema = z.object({
|
|
143
213
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
144
214
|
pipeline_id: z.coerce.string().describe("The ID of the pipeline"),
|
|
145
215
|
});
|
|
146
216
|
// Schema for listing jobs in a pipeline
|
|
147
|
-
export const ListPipelineJobsSchema = z
|
|
217
|
+
export const ListPipelineJobsSchema = z
|
|
218
|
+
.object({
|
|
148
219
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
149
220
|
pipeline_id: z.coerce.string().describe("The ID of the pipeline"),
|
|
150
221
|
scope: z
|
|
@@ -152,7 +223,33 @@ export const ListPipelineJobsSchema = z.object({
|
|
|
152
223
|
.optional()
|
|
153
224
|
.describe("The scope of jobs to show"),
|
|
154
225
|
include_retried: flexibleBoolean.optional().describe("Whether to include retried jobs"),
|
|
155
|
-
})
|
|
226
|
+
})
|
|
227
|
+
.merge(PaginationOptionsSchema);
|
|
228
|
+
// Schema for listing trigger jobs (bridges) in a pipeline
|
|
229
|
+
export const ListPipelineTriggerJobsSchema = z
|
|
230
|
+
.object({
|
|
231
|
+
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
232
|
+
pipeline_id: z.coerce.string().describe("The ID of the pipeline"),
|
|
233
|
+
scope: z
|
|
234
|
+
// https://docs.gitlab.com/api/jobs/#job-status-values
|
|
235
|
+
.enum([
|
|
236
|
+
"canceled",
|
|
237
|
+
"canceling",
|
|
238
|
+
"created",
|
|
239
|
+
"failed",
|
|
240
|
+
"manual",
|
|
241
|
+
"pending",
|
|
242
|
+
"preparing",
|
|
243
|
+
"running",
|
|
244
|
+
"scheduled",
|
|
245
|
+
"skipped",
|
|
246
|
+
"success",
|
|
247
|
+
"waiting_for_resource",
|
|
248
|
+
])
|
|
249
|
+
.optional()
|
|
250
|
+
.describe("The scope of trigger jobs to show"),
|
|
251
|
+
})
|
|
252
|
+
.merge(PaginationOptionsSchema);
|
|
156
253
|
// Schema for creating a new pipeline
|
|
157
254
|
export const CreatePipelineSchema = z.object({
|
|
158
255
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
@@ -176,27 +273,35 @@ export const CancelPipelineSchema = RetryPipelineSchema;
|
|
|
176
273
|
export const GetPipelineJobOutputSchema = z.object({
|
|
177
274
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
178
275
|
job_id: z.coerce.string().describe("The ID of the job"),
|
|
179
|
-
limit: z
|
|
180
|
-
|
|
276
|
+
limit: z
|
|
277
|
+
.number()
|
|
278
|
+
.optional()
|
|
279
|
+
.describe("Maximum number of lines to return from the end of the log (default: 1000)"),
|
|
280
|
+
offset: z
|
|
281
|
+
.number()
|
|
282
|
+
.optional()
|
|
283
|
+
.describe("Number of lines to skip from the end of the log (default: 0)"),
|
|
181
284
|
});
|
|
182
285
|
// User schemas
|
|
183
286
|
export const GitLabUserSchema = z.object({
|
|
184
|
-
username: z.string(), // Changed from login to match GitLab API
|
|
287
|
+
username: z.string().optional(), // Changed from login to match GitLab API
|
|
185
288
|
id: z.coerce.string(),
|
|
186
|
-
name: z.string(),
|
|
187
|
-
avatar_url: z.string().nullable(),
|
|
188
|
-
web_url: z.string(), // Changed from html_url to match GitLab API
|
|
289
|
+
name: z.string().optional(),
|
|
290
|
+
avatar_url: z.string().nullable().optional(),
|
|
291
|
+
web_url: z.string().optional(), // Changed from html_url to match GitLab API
|
|
189
292
|
});
|
|
190
293
|
export const GetUsersSchema = z.object({
|
|
191
294
|
usernames: z.array(z.string()).describe("Array of usernames to search for"),
|
|
192
295
|
});
|
|
193
|
-
export const GitLabUsersResponseSchema = z.record(z.string(), z
|
|
296
|
+
export const GitLabUsersResponseSchema = z.record(z.string(), z
|
|
297
|
+
.object({
|
|
194
298
|
id: z.coerce.string(),
|
|
195
299
|
username: z.string(),
|
|
196
300
|
name: z.string(),
|
|
197
301
|
avatar_url: z.string().nullable(),
|
|
198
302
|
web_url: z.string(),
|
|
199
|
-
})
|
|
303
|
+
})
|
|
304
|
+
.nullable());
|
|
200
305
|
// Namespace related schemas
|
|
201
306
|
// Base schema for project-related operations
|
|
202
307
|
const ProjectParamsSchema = z.object({
|
|
@@ -294,7 +399,7 @@ export const GitLabRepositorySchema = z.object({
|
|
|
294
399
|
jobs_enabled: flexibleBoolean.optional(),
|
|
295
400
|
snippets_enabled: flexibleBoolean.optional(),
|
|
296
401
|
can_create_merge_request_in: flexibleBoolean.optional(),
|
|
297
|
-
resolve_outdated_diff_discussions:
|
|
402
|
+
resolve_outdated_diff_discussions: flexibleBooleanNullable.optional(),
|
|
298
403
|
shared_runners_enabled: flexibleBoolean.optional(),
|
|
299
404
|
shared_with_groups: z
|
|
300
405
|
.array(z.object({
|
|
@@ -376,11 +481,13 @@ export const GitLabCommitSchema = z.object({
|
|
|
376
481
|
message: z.string().optional(), // Add full message field
|
|
377
482
|
web_url: z.string(), // Changed from html_url to match GitLab API
|
|
378
483
|
parent_ids: z.array(z.string()), // Changed from parents to match GitLab API
|
|
379
|
-
stats: z
|
|
484
|
+
stats: z
|
|
485
|
+
.object({
|
|
380
486
|
additions: z.number().optional().nullable(),
|
|
381
487
|
deletions: z.number().optional().nullable(),
|
|
382
488
|
total: z.number().optional().nullable(),
|
|
383
|
-
})
|
|
489
|
+
})
|
|
490
|
+
.optional(), // Only present when with_stats=true
|
|
384
491
|
trailers: z.record(z.string()).optional().default({}), // Git trailers, may be empty object
|
|
385
492
|
extended_trailers: z.record(z.array(z.string())).optional().default({}), // Extended trailers, may be empty object
|
|
386
493
|
});
|
|
@@ -450,14 +557,16 @@ export const CreateBranchOptionsSchema = z.object({
|
|
|
450
557
|
ref: z.string(), // The source branch/commit for the new branch
|
|
451
558
|
});
|
|
452
559
|
export const GitLabCompareResultSchema = z.object({
|
|
453
|
-
commit: z
|
|
560
|
+
commit: z
|
|
561
|
+
.object({
|
|
454
562
|
id: z.string().optional(),
|
|
455
563
|
short_id: z.string().optional(),
|
|
456
564
|
title: z.string().optional(),
|
|
457
565
|
author_name: z.string().optional(),
|
|
458
566
|
author_email: z.string().optional(),
|
|
459
567
|
created_at: z.string().optional(),
|
|
460
|
-
})
|
|
568
|
+
})
|
|
569
|
+
.optional(),
|
|
461
570
|
commits: z.array(GitLabCommitSchema),
|
|
462
571
|
diffs: z.array(GitLabDiffSchema),
|
|
463
572
|
compare_timeout: flexibleBoolean.optional(),
|
|
@@ -518,8 +627,9 @@ export const GitLabIssueSchema = z.object({
|
|
|
518
627
|
.optional(),
|
|
519
628
|
confidential: flexibleBoolean.optional(),
|
|
520
629
|
due_date: z.string().nullable().optional(),
|
|
521
|
-
discussion_locked:
|
|
630
|
+
discussion_locked: flexibleBooleanNullable.optional(),
|
|
522
631
|
weight: z.number().nullable().optional(),
|
|
632
|
+
issue_type: z.string().describe("the type of issue.").nullish(),
|
|
523
633
|
});
|
|
524
634
|
// NEW SCHEMA: For issue with link details (used in listing issue links)
|
|
525
635
|
export const GitLabIssueWithLinkDetailsSchema = GitLabIssueSchema.extend({
|
|
@@ -576,8 +686,8 @@ export const GitLabMergeRequestSchema = z.object({
|
|
|
576
686
|
merge_error: z.string().nullable().optional(),
|
|
577
687
|
work_in_progress: flexibleBoolean.optional(),
|
|
578
688
|
blocking_discussions_resolved: flexibleBoolean.optional(),
|
|
579
|
-
should_remove_source_branch:
|
|
580
|
-
force_remove_source_branch:
|
|
689
|
+
should_remove_source_branch: flexibleBooleanNullable.optional(),
|
|
690
|
+
force_remove_source_branch: flexibleBooleanNullable.optional(),
|
|
581
691
|
allow_collaboration: flexibleBoolean.optional(),
|
|
582
692
|
allow_maintainer_to_push: flexibleBoolean.optional(),
|
|
583
693
|
changes_count: z.string().nullable().optional(),
|
|
@@ -585,32 +695,70 @@ export const GitLabMergeRequestSchema = z.object({
|
|
|
585
695
|
squash: flexibleBoolean.optional(),
|
|
586
696
|
labels: z.array(z.string()).optional(),
|
|
587
697
|
});
|
|
588
|
-
export const LineRangeSchema = z
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
type: z
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
698
|
+
export const LineRangeSchema = z
|
|
699
|
+
.object({
|
|
700
|
+
start: z
|
|
701
|
+
.object({
|
|
702
|
+
line_code: z
|
|
703
|
+
.string()
|
|
704
|
+
.nullable()
|
|
705
|
+
.optional()
|
|
706
|
+
.describe("CRITICAL: Line identifier in format '{file_path_sha1_hash}_{old_line_number}_{new_line_number}'. USUALLY REQUIRED for GitLab diff comments despite being optional in schema. Example: 'a1b2c3d4e5f6_10_15'. Get this from GitLab diff API response, never fabricate."),
|
|
707
|
+
type: z
|
|
708
|
+
.enum(["new", "old", "expanded"])
|
|
709
|
+
.nullable()
|
|
710
|
+
.optional()
|
|
711
|
+
.describe("Line type: 'old' = deleted/original line, 'new' = added/modified line, null = unchanged context. MUST match the line_code format and old_line/new_line values."),
|
|
712
|
+
old_line: z
|
|
713
|
+
.number()
|
|
714
|
+
.nullable()
|
|
715
|
+
.optional()
|
|
716
|
+
.describe("Line number in original file (before changes). REQUIRED when type='old', NULL when type='new' (for purely added lines), can be present for context lines."),
|
|
717
|
+
new_line: z
|
|
718
|
+
.number()
|
|
719
|
+
.nullable()
|
|
720
|
+
.optional()
|
|
721
|
+
.describe("Line number in modified file (after changes). REQUIRED when type='new', NULL when type='old' (for purely deleted lines), can be present for context lines."),
|
|
722
|
+
})
|
|
723
|
+
.describe("Start line position for multiline comment range. MUST specify either old_line OR new_line (or both for context), never neither."),
|
|
724
|
+
end: z
|
|
725
|
+
.object({
|
|
726
|
+
line_code: z
|
|
727
|
+
.string()
|
|
728
|
+
.nullable()
|
|
729
|
+
.optional()
|
|
730
|
+
.describe("CRITICAL: Line identifier in format '{file_path_sha1_hash}_{old_line_number}_{new_line_number}'. USUALLY REQUIRED for GitLab diff comments despite being optional in schema. Example: 'a1b2c3d4e5f6_12_17'. Must be from same file as start.line_code."),
|
|
731
|
+
type: z
|
|
732
|
+
.enum(["new", "old", "expanded"])
|
|
733
|
+
.nullable()
|
|
734
|
+
.optional()
|
|
735
|
+
.describe("Line type: 'old' = deleted/original line, 'new' = added/modified line, null = unchanged context. SHOULD MATCH start.type for consistent ranges (don't mix old/new types)."),
|
|
736
|
+
old_line: z
|
|
737
|
+
.number()
|
|
738
|
+
.nullable()
|
|
739
|
+
.optional()
|
|
740
|
+
.describe("Line number in original file (before changes). REQUIRED when type='old', NULL when type='new' (for purely added lines), can be present for context lines. MUST be >= start.old_line if both specified."),
|
|
741
|
+
new_line: z
|
|
742
|
+
.number()
|
|
743
|
+
.nullable()
|
|
744
|
+
.optional()
|
|
745
|
+
.describe("Line number in modified file (after changes). REQUIRED when type='new', NULL when type='old' (for purely deleted lines), can be present for context lines. MUST be >= start.new_line if both specified."),
|
|
746
|
+
})
|
|
747
|
+
.describe("End line position for multiline comment range. MUST specify either old_line OR new_line (or both for context), never neither. Range must be valid (end >= start)."),
|
|
748
|
+
})
|
|
749
|
+
.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.");
|
|
602
750
|
// Discussion related schemas
|
|
603
751
|
export const GitLabDiscussionNoteSchema = z.object({
|
|
604
752
|
id: z.coerce.string(),
|
|
605
|
-
type: z.enum(["DiscussionNote", "DiffNote", "Note"]).nullable(), // Allow null type for regular notes
|
|
606
|
-
body: z.string(),
|
|
607
|
-
attachment: z.any().nullable(), // Can be string or object, handle appropriately
|
|
608
|
-
author: GitLabUserSchema,
|
|
609
|
-
created_at: z.string(),
|
|
610
|
-
updated_at: z.string(),
|
|
611
|
-
system: flexibleBoolean,
|
|
612
|
-
noteable_id: z.coerce.string(),
|
|
613
|
-
noteable_type: z.enum(["Issue", "MergeRequest", "Snippet", "Commit", "Epic"]),
|
|
753
|
+
type: z.enum(["DiscussionNote", "DiffNote", "Note"]).nullable().optional(), // Allow null type for regular notes
|
|
754
|
+
body: z.string().optional(),
|
|
755
|
+
attachment: z.any().nullable().optional(), // Can be string or object, handle appropriately
|
|
756
|
+
author: GitLabUserSchema.optional(),
|
|
757
|
+
created_at: z.string().optional(),
|
|
758
|
+
updated_at: z.string().optional(),
|
|
759
|
+
system: flexibleBoolean.optional(),
|
|
760
|
+
noteable_id: z.coerce.string().optional(),
|
|
761
|
+
noteable_type: z.enum(["Issue", "MergeRequest", "Snippet", "Commit", "Epic"]).optional(),
|
|
614
762
|
project_id: z.coerce.string().optional(),
|
|
615
763
|
noteable_iid: z.coerce.string().nullable().optional(),
|
|
616
764
|
resolvable: flexibleBoolean.optional(),
|
|
@@ -620,22 +768,31 @@ export const GitLabDiscussionNoteSchema = z.object({
|
|
|
620
768
|
position: z
|
|
621
769
|
.object({
|
|
622
770
|
// Only present for DiffNote
|
|
623
|
-
base_sha: z.string(),
|
|
624
|
-
start_sha: z.string(),
|
|
625
|
-
head_sha: z.string(),
|
|
771
|
+
base_sha: z.string().optional(),
|
|
772
|
+
start_sha: z.string().optional(),
|
|
773
|
+
head_sha: z.string().optional(),
|
|
626
774
|
old_path: z.string().nullable().optional().describe("File path before change"),
|
|
627
775
|
new_path: z.string().nullable().optional().describe("File path after change"),
|
|
628
|
-
position_type: z.enum(["text", "image", "file"]),
|
|
629
|
-
new_line: z
|
|
630
|
-
|
|
776
|
+
position_type: z.enum(["text", "image", "file"]).optional(),
|
|
777
|
+
new_line: z
|
|
778
|
+
.number()
|
|
779
|
+
.nullable()
|
|
780
|
+
.optional()
|
|
781
|
+
.describe("Line number in the modified file (after changes). Used for added lines and context lines. Null for deleted lines."),
|
|
782
|
+
old_line: z
|
|
783
|
+
.number()
|
|
784
|
+
.nullable()
|
|
785
|
+
.optional()
|
|
786
|
+
.describe("Line number in the original file (before changes). Used for deleted lines and context lines. Null for newly added lines."),
|
|
631
787
|
line_range: LineRangeSchema.nullable().optional(), // For multi-line diff notes
|
|
632
788
|
width: z.number().optional(), // For image diff notes
|
|
633
789
|
height: z.number().optional(), // For image diff notes
|
|
634
790
|
x: z.number().optional(), // For image diff notes
|
|
635
791
|
y: z.number().optional(), // For image diff notes
|
|
636
792
|
})
|
|
793
|
+
.passthrough() // Allow additional fields
|
|
637
794
|
.optional(),
|
|
638
|
-
});
|
|
795
|
+
}).passthrough(); // Allow additional fields that GitLab might return
|
|
639
796
|
// Reusable pagination schema for GitLab API responses.
|
|
640
797
|
// See https://docs.gitlab.com/api/rest/#pagination
|
|
641
798
|
export const GitLabPaginationSchema = z.object({
|
|
@@ -661,10 +818,12 @@ export const PaginatedDiscussionsResponseSchema = z.object({
|
|
|
661
818
|
items: z.array(GitLabDiscussionSchema),
|
|
662
819
|
pagination: GitLabPaginationSchema,
|
|
663
820
|
});
|
|
664
|
-
export const ListIssueDiscussionsSchema = z
|
|
821
|
+
export const ListIssueDiscussionsSchema = z
|
|
822
|
+
.object({
|
|
665
823
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
666
824
|
issue_iid: z.coerce.string().describe("The internal ID of the project issue"),
|
|
667
|
-
})
|
|
825
|
+
})
|
|
826
|
+
.merge(PaginationOptionsSchema);
|
|
668
827
|
// Input schema for listing merge request discussions
|
|
669
828
|
export const ListMergeRequestDiscussionsSchema = ProjectParamsSchema.extend({
|
|
670
829
|
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
@@ -714,9 +873,11 @@ export const CreateOrUpdateFileSchema = ProjectParamsSchema.extend({
|
|
|
714
873
|
last_commit_id: z.string().optional().describe("Last known file commit ID"),
|
|
715
874
|
commit_id: z.string().optional().describe("Current file commit ID (for update operations)"),
|
|
716
875
|
});
|
|
717
|
-
export const SearchRepositoriesSchema = z
|
|
876
|
+
export const SearchRepositoriesSchema = z
|
|
877
|
+
.object({
|
|
718
878
|
search: z.string().describe("Search query"), // Changed from query to match GitLab API
|
|
719
|
-
})
|
|
879
|
+
})
|
|
880
|
+
.merge(PaginationOptionsSchema);
|
|
720
881
|
export const CreateRepositorySchema = z.object({
|
|
721
882
|
name: z.string().describe("Repository name"),
|
|
722
883
|
description: z.string().optional().describe("Repository description"),
|
|
@@ -746,6 +907,7 @@ export const CreateIssueSchema = ProjectParamsSchema.extend({
|
|
|
746
907
|
assignee_ids: z.array(z.number()).optional().describe("Array of user IDs to assign"),
|
|
747
908
|
labels: z.array(z.string()).optional().describe("Array of label names"),
|
|
748
909
|
milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
|
|
910
|
+
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"),
|
|
749
911
|
});
|
|
750
912
|
const MergeRequestOptionsSchema = {
|
|
751
913
|
title: z.string().describe("Merge request title"),
|
|
@@ -753,22 +915,20 @@ const MergeRequestOptionsSchema = {
|
|
|
753
915
|
source_branch: z.string().describe("Branch containing changes"),
|
|
754
916
|
target_branch: z.string().describe("Branch to merge into"),
|
|
755
917
|
target_project_id: z.coerce.string().optional().describe("Numeric ID of the target project."),
|
|
756
|
-
assignee_ids: z
|
|
757
|
-
.array(z.number())
|
|
758
|
-
.optional()
|
|
759
|
-
.describe("The ID of the users to assign the MR to"),
|
|
918
|
+
assignee_ids: z.array(z.number()).optional().describe("The ID of the users to assign the MR to"),
|
|
760
919
|
reviewer_ids: z
|
|
761
920
|
.array(z.number())
|
|
762
921
|
.optional()
|
|
763
922
|
.describe("The ID of the users to assign as reviewers of the MR"),
|
|
764
923
|
labels: z.array(z.string()).optional().describe("Labels for the MR"),
|
|
765
924
|
draft: flexibleBoolean.optional().describe("Create as draft merge request"),
|
|
766
|
-
allow_collaboration: z
|
|
767
|
-
|
|
925
|
+
allow_collaboration: z.boolean().optional().describe("Allow commits from upstream members"),
|
|
926
|
+
remove_source_branch: flexibleBooleanNullable
|
|
768
927
|
.optional()
|
|
769
|
-
.describe("
|
|
770
|
-
|
|
771
|
-
|
|
928
|
+
.describe("Flag indicating if a merge request should remove the source branch when merging."),
|
|
929
|
+
squash: flexibleBooleanNullable
|
|
930
|
+
.optional()
|
|
931
|
+
.describe("If true, squash all commits into a single commit on merge."),
|
|
772
932
|
};
|
|
773
933
|
export const CreateMergeRequestOptionsSchema = z.object(MergeRequestOptionsSchema);
|
|
774
934
|
export const CreateMergeRequestSchema = ProjectParamsSchema.extend(MergeRequestOptionsSchema);
|
|
@@ -783,8 +943,13 @@ export const CreateBranchSchema = ProjectParamsSchema.extend({
|
|
|
783
943
|
export const GetBranchDiffsSchema = ProjectParamsSchema.extend({
|
|
784
944
|
from: z.string().describe("The base branch or commit SHA to compare from"),
|
|
785
945
|
to: z.string().describe("The target branch or commit SHA to compare to"),
|
|
786
|
-
straight: flexibleBoolean
|
|
787
|
-
|
|
946
|
+
straight: flexibleBoolean
|
|
947
|
+
.optional()
|
|
948
|
+
.describe("Comparison method: false for '...' (default), true for '--'"),
|
|
949
|
+
excluded_file_patterns: z
|
|
950
|
+
.array(z.string())
|
|
951
|
+
.optional()
|
|
952
|
+
.describe('Array of regex patterns to exclude files from the diff results. Each pattern is a JavaScript-compatible regular expression that matches file paths to ignore. Examples: ["^test/mocks/", "\\.spec\\.ts$", "package-lock\\.json"]'),
|
|
788
953
|
});
|
|
789
954
|
export const GetMergeRequestSchema = ProjectParamsSchema.extend({
|
|
790
955
|
merge_request_iid: z.coerce.string().optional().describe("The IID of a merge request"),
|
|
@@ -794,10 +959,7 @@ export const UpdateMergeRequestSchema = GetMergeRequestSchema.extend({
|
|
|
794
959
|
title: z.string().optional().describe("The title of the merge request"),
|
|
795
960
|
description: z.string().optional().describe("The description of the merge request"),
|
|
796
961
|
target_branch: z.string().optional().describe("The target branch"),
|
|
797
|
-
assignee_ids: z
|
|
798
|
-
.array(z.number())
|
|
799
|
-
.optional()
|
|
800
|
-
.describe("The ID of the users to assign the MR to"),
|
|
962
|
+
assignee_ids: z.array(z.number()).optional().describe("The ID of the users to assign the MR to"),
|
|
801
963
|
reviewer_ids: z
|
|
802
964
|
.array(z.number())
|
|
803
965
|
.optional()
|
|
@@ -814,13 +976,24 @@ export const UpdateMergeRequestSchema = GetMergeRequestSchema.extend({
|
|
|
814
976
|
squash: flexibleBoolean.optional().describe("Squash commits into a single commit when merging"),
|
|
815
977
|
draft: flexibleBoolean.optional().describe("Work in progress merge request"),
|
|
816
978
|
});
|
|
979
|
+
export const MergeMergeRequestSchema = ProjectParamsSchema.extend({
|
|
980
|
+
merge_request_iid: z.coerce.string().optional().describe("The IID of a merge request"),
|
|
981
|
+
auto_merge: flexibleBoolean.optional().default(false).describe("If true, the merge request merges when the pipeline succeeds."),
|
|
982
|
+
merge_commit_message: z.string().optional().describe("Custom merge commit message"),
|
|
983
|
+
merge_when_pipeline_succeeds: flexibleBoolean.optional().default(false).describe("If true, the merge request merges when the pipeline succeeds.in GitLab 17.11. Use"),
|
|
984
|
+
should_remove_source_branch: flexibleBoolean.optional().default(false).describe("Remove source branch after merge"),
|
|
985
|
+
squash_commit_message: z.string().optional().describe("Custom squash commit message"),
|
|
986
|
+
squash: flexibleBoolean.optional().default(false).describe("Squash commits into a single commit when merging"),
|
|
987
|
+
});
|
|
817
988
|
export const GetMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
|
|
818
989
|
view: z.enum(["inline", "parallel"]).optional().describe("Diff view type"),
|
|
819
990
|
});
|
|
820
991
|
export const ListMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
|
|
821
992
|
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
822
993
|
per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
|
|
823
|
-
unidiff: flexibleBoolean
|
|
994
|
+
unidiff: flexibleBoolean
|
|
995
|
+
.optional()
|
|
996
|
+
.describe("Present diffs in the unified diff format. Default is false. Introduced in GitLab 16.5."),
|
|
824
997
|
});
|
|
825
998
|
export const CreateNoteSchema = z.object({
|
|
826
999
|
project_id: z.coerce.string().describe("Project ID or namespace/project_path"),
|
|
@@ -831,10 +1004,20 @@ export const CreateNoteSchema = z.object({
|
|
|
831
1004
|
body: z.string().describe("Note content"),
|
|
832
1005
|
});
|
|
833
1006
|
// Issues API operation schemas
|
|
834
|
-
export const ListIssuesSchema = z
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1007
|
+
export const ListIssuesSchema = z
|
|
1008
|
+
.object({
|
|
1009
|
+
project_id: z.coerce
|
|
1010
|
+
.string()
|
|
1011
|
+
.optional()
|
|
1012
|
+
.describe("Project ID or URL-encoded path (optional - if not provided, lists issues across all accessible projects)"),
|
|
1013
|
+
assignee_id: z.coerce
|
|
1014
|
+
.string()
|
|
1015
|
+
.optional()
|
|
1016
|
+
.describe("Return issues assigned to the given user ID. user id or none or any"),
|
|
1017
|
+
assignee_username: z
|
|
1018
|
+
.array(z.string())
|
|
1019
|
+
.optional()
|
|
1020
|
+
.describe("Return issues assigned to the given username"),
|
|
838
1021
|
author_id: z.coerce.string().optional().describe("Return issues created by the given user ID"),
|
|
839
1022
|
author_username: z.string().optional().describe("Return issues created by the given username"),
|
|
840
1023
|
confidential: flexibleBoolean.optional().describe("Filter confidential or public issues"),
|
|
@@ -843,6 +1026,16 @@ export const ListIssuesSchema = z.object({
|
|
|
843
1026
|
due_date: z.string().optional().describe("Return issues that have the due date"),
|
|
844
1027
|
labels: z.array(z.string()).optional().describe("Array of label names"),
|
|
845
1028
|
milestone: z.string().optional().describe("Milestone title"),
|
|
1029
|
+
issue_type: z
|
|
1030
|
+
.string()
|
|
1031
|
+
.optional()
|
|
1032
|
+
.nullable()
|
|
1033
|
+
.describe("Filter to a given type of issue. One of issue, incident, test_case or task"),
|
|
1034
|
+
iteration_id: z.coerce
|
|
1035
|
+
.string()
|
|
1036
|
+
.optional()
|
|
1037
|
+
.nullable()
|
|
1038
|
+
.describe("Return issues assigned to the given iteration ID. None returns issues that do not belong to an iteration. Any returns issues that belong to an iteration. "),
|
|
846
1039
|
scope: z
|
|
847
1040
|
.enum(["created_by_me", "assigned_to_me", "all"])
|
|
848
1041
|
.optional()
|
|
@@ -855,21 +1048,30 @@ export const ListIssuesSchema = z.object({
|
|
|
855
1048
|
updated_after: z.string().optional().describe("Return issues updated after the given time"),
|
|
856
1049
|
updated_before: z.string().optional().describe("Return issues updated before the given time"),
|
|
857
1050
|
with_labels_details: flexibleBoolean.optional().describe("Return more details for each label"),
|
|
858
|
-
})
|
|
1051
|
+
})
|
|
1052
|
+
.merge(PaginationOptionsSchema);
|
|
859
1053
|
// Merge Requests API operation schemas
|
|
860
|
-
export const ListMergeRequestsSchema = z
|
|
1054
|
+
export const ListMergeRequestsSchema = z
|
|
1055
|
+
.object({
|
|
861
1056
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
862
|
-
assignee_id: z.coerce
|
|
1057
|
+
assignee_id: z.coerce
|
|
1058
|
+
.string()
|
|
1059
|
+
.optional()
|
|
1060
|
+
.describe("Return issues assigned to the given user ID. user id or none or any"),
|
|
863
1061
|
assignee_username: z
|
|
864
1062
|
.string()
|
|
865
1063
|
.optional()
|
|
866
1064
|
.describe("Returns merge requests assigned to the given username"),
|
|
867
|
-
author_id: z.coerce
|
|
1065
|
+
author_id: z.coerce
|
|
1066
|
+
.string()
|
|
1067
|
+
.optional()
|
|
1068
|
+
.describe("Returns merge requests created by the given user ID"),
|
|
868
1069
|
author_username: z
|
|
869
1070
|
.string()
|
|
870
1071
|
.optional()
|
|
871
1072
|
.describe("Returns merge requests created by the given username"),
|
|
872
|
-
reviewer_id: z.coerce
|
|
1073
|
+
reviewer_id: z.coerce
|
|
1074
|
+
.string()
|
|
873
1075
|
.optional()
|
|
874
1076
|
.describe("Returns merge requests which have the user as a reviewer. user id or none or any"),
|
|
875
1077
|
reviewer_username: z
|
|
@@ -904,7 +1106,14 @@ export const ListMergeRequestsSchema = z.object({
|
|
|
904
1106
|
.optional()
|
|
905
1107
|
.describe("Return merge requests with a specific state"),
|
|
906
1108
|
order_by: z
|
|
907
|
-
.enum([
|
|
1109
|
+
.enum([
|
|
1110
|
+
"created_at",
|
|
1111
|
+
"updated_at",
|
|
1112
|
+
"priority",
|
|
1113
|
+
"label_priority",
|
|
1114
|
+
"milestone_due",
|
|
1115
|
+
"popularity",
|
|
1116
|
+
])
|
|
908
1117
|
.optional()
|
|
909
1118
|
.describe("Return merge requests ordered by the given field"),
|
|
910
1119
|
sort: z
|
|
@@ -919,9 +1128,13 @@ export const ListMergeRequestsSchema = z.object({
|
|
|
919
1128
|
.string()
|
|
920
1129
|
.optional()
|
|
921
1130
|
.describe("Return merge requests from a specific source branch"),
|
|
922
|
-
wip: z
|
|
1131
|
+
wip: z
|
|
1132
|
+
.enum(["yes", "no"])
|
|
1133
|
+
.optional()
|
|
1134
|
+
.describe("Filter merge requests against their wip status"),
|
|
923
1135
|
with_labels_details: flexibleBoolean.optional().describe("Return more details for each label"),
|
|
924
|
-
})
|
|
1136
|
+
})
|
|
1137
|
+
.merge(PaginationOptionsSchema);
|
|
925
1138
|
export const GetIssueSchema = z.object({
|
|
926
1139
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
927
1140
|
issue_iid: z.coerce.string().describe("The internal ID of the project issue"),
|
|
@@ -939,6 +1152,7 @@ export const UpdateIssueSchema = z.object({
|
|
|
939
1152
|
milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
|
|
940
1153
|
state_event: z.enum(["close", "reopen"]).optional().describe("Update issue state (close/reopen)"),
|
|
941
1154
|
weight: z.number().optional().describe("Weight of the issue (0-9)"),
|
|
1155
|
+
issue_type: z.enum(["issue", "incident", "test_case", "task"]).describe("the type of issue. One of issue, incident, test_case or task."),
|
|
942
1156
|
});
|
|
943
1157
|
export const DeleteIssueSchema = z.object({
|
|
944
1158
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
@@ -975,10 +1189,12 @@ export const DeleteIssueLinkSchema = z.object({
|
|
|
975
1189
|
issue_link_id: z.coerce.string().describe("The ID of an issue relationship"),
|
|
976
1190
|
});
|
|
977
1191
|
// Namespace API operation schemas
|
|
978
|
-
export const ListNamespacesSchema = z
|
|
1192
|
+
export const ListNamespacesSchema = z
|
|
1193
|
+
.object({
|
|
979
1194
|
search: z.string().optional().describe("Search term for namespaces"),
|
|
980
1195
|
owned: flexibleBoolean.optional().describe("Filter for namespaces owned by current user"),
|
|
981
|
-
})
|
|
1196
|
+
})
|
|
1197
|
+
.merge(PaginationOptionsSchema);
|
|
982
1198
|
export const GetNamespaceSchema = z.object({
|
|
983
1199
|
namespace_id: z.coerce.string().describe("Namespace ID or full path"),
|
|
984
1200
|
});
|
|
@@ -989,11 +1205,16 @@ export const VerifyNamespaceSchema = z.object({
|
|
|
989
1205
|
export const GetProjectSchema = z.object({
|
|
990
1206
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
991
1207
|
});
|
|
992
|
-
export const ListProjectsSchema = z
|
|
1208
|
+
export const ListProjectsSchema = z
|
|
1209
|
+
.object({
|
|
993
1210
|
search: z.string().optional().describe("Search term for projects"),
|
|
994
|
-
search_namespaces: flexibleBoolean
|
|
1211
|
+
search_namespaces: flexibleBoolean
|
|
1212
|
+
.optional()
|
|
1213
|
+
.describe("Needs to be true if search is full path"),
|
|
995
1214
|
owned: flexibleBoolean.optional().describe("Filter for projects owned by current user"),
|
|
996
|
-
membership: flexibleBoolean
|
|
1215
|
+
membership: flexibleBoolean
|
|
1216
|
+
.optional()
|
|
1217
|
+
.describe("Filter for projects where current user is a member"),
|
|
997
1218
|
simple: flexibleBoolean.optional().describe("Return only limited fields"),
|
|
998
1219
|
archived: flexibleBoolean.optional().describe("Filter for archived projects"),
|
|
999
1220
|
visibility: z
|
|
@@ -1017,7 +1238,8 @@ export const ListProjectsSchema = z.object({
|
|
|
1017
1238
|
.optional()
|
|
1018
1239
|
.describe("Filter projects with merge requests feature enabled"),
|
|
1019
1240
|
min_access_level: z.number().optional().describe("Filter by minimum access level"),
|
|
1020
|
-
})
|
|
1241
|
+
})
|
|
1242
|
+
.merge(PaginationOptionsSchema);
|
|
1021
1243
|
// Label operation schemas
|
|
1022
1244
|
export const ListLabelsSchema = z.object({
|
|
1023
1245
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
@@ -1058,7 +1280,8 @@ export const DeleteLabelSchema = z.object({
|
|
|
1058
1280
|
label_id: z.coerce.string().describe("The ID or title of a project's label"),
|
|
1059
1281
|
});
|
|
1060
1282
|
// Group projects schema
|
|
1061
|
-
export const ListGroupProjectsSchema = z
|
|
1283
|
+
export const ListGroupProjectsSchema = z
|
|
1284
|
+
.object({
|
|
1062
1285
|
group_id: z.coerce.string().describe("Group ID or path"),
|
|
1063
1286
|
include_subgroups: flexibleBoolean.optional().describe("Include projects from subgroups"),
|
|
1064
1287
|
search: z.string().optional().describe("Search term to filter projects"),
|
|
@@ -1086,12 +1309,15 @@ export const ListGroupProjectsSchema = z.object({
|
|
|
1086
1309
|
statistics: flexibleBoolean.optional().describe("Include project statistics"),
|
|
1087
1310
|
with_custom_attributes: flexibleBoolean.optional().describe("Include custom attributes"),
|
|
1088
1311
|
with_security_reports: flexibleBoolean.optional().describe("Include security reports"),
|
|
1089
|
-
})
|
|
1312
|
+
})
|
|
1313
|
+
.merge(PaginationOptionsSchema);
|
|
1090
1314
|
// Add wiki operation schemas
|
|
1091
|
-
export const ListWikiPagesSchema = z
|
|
1315
|
+
export const ListWikiPagesSchema = z
|
|
1316
|
+
.object({
|
|
1092
1317
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
1093
1318
|
with_content: flexibleBoolean.optional().describe("Include content of the wiki pages"),
|
|
1094
|
-
})
|
|
1319
|
+
})
|
|
1320
|
+
.merge(PaginationOptionsSchema);
|
|
1095
1321
|
export const GetWikiPageSchema = z.object({
|
|
1096
1322
|
project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
|
|
1097
1323
|
slug: z.string().describe("URL-encoded slug of the wiki page"),
|
|
@@ -1123,7 +1349,9 @@ export const GitLabWikiPageSchema = z.object({
|
|
|
1123
1349
|
updated_at: z.string().optional(),
|
|
1124
1350
|
});
|
|
1125
1351
|
// Merge Request Thread position schema - used for diff notes
|
|
1126
|
-
|
|
1352
|
+
// Extremely flexible position schema for API responses - accepts any structure
|
|
1353
|
+
// Strict position schema for creating draft notes and merge request threads
|
|
1354
|
+
export const MergeRequestThreadPositionCreateSchema = z.object({
|
|
1127
1355
|
base_sha: z.string().describe("REQUIRED: Base commit SHA in the source branch. Get this from merge request diff_refs.base_sha."),
|
|
1128
1356
|
head_sha: z.string().describe("REQUIRED: SHA referencing HEAD of the source branch. Get this from merge request diff_refs.head_sha."),
|
|
1129
1357
|
start_sha: z.string().describe("REQUIRED: SHA referencing the start commit of the source branch. Get this from merge request diff_refs.start_sha."),
|
|
@@ -1138,6 +1366,115 @@ export const MergeRequestThreadPositionSchema = z.object({
|
|
|
1138
1366
|
x: z.number().optional().describe("IMAGE DIFFS ONLY: X coordinate on the image (for position_type='image')."),
|
|
1139
1367
|
y: z.number().optional().describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
|
|
1140
1368
|
});
|
|
1369
|
+
export const MergeRequestThreadPositionSchema = z.object({
|
|
1370
|
+
base_sha: z
|
|
1371
|
+
.string()
|
|
1372
|
+
.describe("REQUIRED: Base commit SHA in the source branch. Get this from merge request diff_refs.base_sha."),
|
|
1373
|
+
head_sha: z
|
|
1374
|
+
.string()
|
|
1375
|
+
.describe("REQUIRED: SHA referencing HEAD of the source branch. Get this from merge request diff_refs.head_sha."),
|
|
1376
|
+
start_sha: z
|
|
1377
|
+
.string()
|
|
1378
|
+
.describe("REQUIRED: SHA referencing the start commit of the source branch. Get this from merge request diff_refs.start_sha."),
|
|
1379
|
+
position_type: z
|
|
1380
|
+
.enum(["text", "image", "file"])
|
|
1381
|
+
.describe("REQUIRED: Position type. Use 'text' for code diffs, 'image' for image diffs, 'file' for file-level comments."),
|
|
1382
|
+
new_path: z
|
|
1383
|
+
.string()
|
|
1384
|
+
.nullable()
|
|
1385
|
+
.optional()
|
|
1386
|
+
.describe("File path after changes. REQUIRED for most diff comments. Use same as old_path if file wasn't renamed."),
|
|
1387
|
+
old_path: z
|
|
1388
|
+
.string()
|
|
1389
|
+
.nullable()
|
|
1390
|
+
.optional()
|
|
1391
|
+
.describe("File path before changes. REQUIRED for most diff comments. Use same as new_path if file wasn't renamed."),
|
|
1392
|
+
new_line: z
|
|
1393
|
+
.number()
|
|
1394
|
+
.nullable()
|
|
1395
|
+
.optional()
|
|
1396
|
+
.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."),
|
|
1397
|
+
old_line: z
|
|
1398
|
+
.number()
|
|
1399
|
+
.nullable()
|
|
1400
|
+
.optional()
|
|
1401
|
+
.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."),
|
|
1402
|
+
line_range: LineRangeSchema.optional().describe("MULTILINE COMMENTS: Specify start/end line positions for commenting on multiple lines. Alternative to single old_line/new_line."),
|
|
1403
|
+
width: z
|
|
1404
|
+
.number()
|
|
1405
|
+
.optional()
|
|
1406
|
+
.describe("IMAGE DIFFS ONLY: Width of the image (for position_type='image')."),
|
|
1407
|
+
height: z
|
|
1408
|
+
.number()
|
|
1409
|
+
.optional()
|
|
1410
|
+
.describe("IMAGE DIFFS ONLY: Height of the image (for position_type='image')."),
|
|
1411
|
+
x: z
|
|
1412
|
+
.number()
|
|
1413
|
+
.optional()
|
|
1414
|
+
.describe("IMAGE DIFFS ONLY: X coordinate on the image (for position_type='image')."),
|
|
1415
|
+
y: z
|
|
1416
|
+
.number()
|
|
1417
|
+
.optional()
|
|
1418
|
+
.describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
|
|
1419
|
+
});
|
|
1420
|
+
// Draft Notes API schemas
|
|
1421
|
+
export const GitLabDraftNoteSchema = z.object({
|
|
1422
|
+
id: z.coerce.string(),
|
|
1423
|
+
author: GitLabUserSchema.optional(),
|
|
1424
|
+
body: z.string().optional(),
|
|
1425
|
+
note: z.string().optional(), // Some APIs might use 'note' instead of 'body'
|
|
1426
|
+
created_at: z.string().optional(),
|
|
1427
|
+
updated_at: z.string().optional(),
|
|
1428
|
+
position: MergeRequestThreadPositionSchema.nullable().optional(),
|
|
1429
|
+
resolve_discussion: flexibleBoolean.optional(),
|
|
1430
|
+
}).transform((data) => ({
|
|
1431
|
+
// Normalize the response to always have consistent field names
|
|
1432
|
+
id: data.id,
|
|
1433
|
+
author: data.author,
|
|
1434
|
+
body: data.body || data.note || "",
|
|
1435
|
+
created_at: data.created_at || "",
|
|
1436
|
+
updated_at: data.updated_at || "",
|
|
1437
|
+
position: data.position,
|
|
1438
|
+
resolve_discussion: data.resolve_discussion,
|
|
1439
|
+
}));
|
|
1440
|
+
// Get draft note schema
|
|
1441
|
+
export const GetDraftNoteSchema = ProjectParamsSchema.extend({
|
|
1442
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1443
|
+
draft_note_id: z.coerce.string().describe("The ID of the draft note"),
|
|
1444
|
+
});
|
|
1445
|
+
// List draft notes schema
|
|
1446
|
+
export const ListDraftNotesSchema = ProjectParamsSchema.extend({
|
|
1447
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1448
|
+
});
|
|
1449
|
+
// Create draft note schema
|
|
1450
|
+
export const CreateDraftNoteSchema = ProjectParamsSchema.extend({
|
|
1451
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1452
|
+
body: z.string().describe("The content of the draft note"),
|
|
1453
|
+
position: MergeRequestThreadPositionCreateSchema.optional().describe("Position when creating a diff note"),
|
|
1454
|
+
resolve_discussion: flexibleBoolean.optional().describe("Whether to resolve the discussion when publishing"),
|
|
1455
|
+
});
|
|
1456
|
+
// Update draft note schema
|
|
1457
|
+
export const UpdateDraftNoteSchema = ProjectParamsSchema.extend({
|
|
1458
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1459
|
+
draft_note_id: z.coerce.string().describe("The ID of the draft note"),
|
|
1460
|
+
body: z.string().optional().describe("The content of the draft note"),
|
|
1461
|
+
position: MergeRequestThreadPositionCreateSchema.optional().describe("Position when creating a diff note"),
|
|
1462
|
+
resolve_discussion: flexibleBoolean.optional().describe("Whether to resolve the discussion when publishing"),
|
|
1463
|
+
});
|
|
1464
|
+
// Delete draft note schema
|
|
1465
|
+
export const DeleteDraftNoteSchema = ProjectParamsSchema.extend({
|
|
1466
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1467
|
+
draft_note_id: z.coerce.string().describe("The ID of the draft note"),
|
|
1468
|
+
});
|
|
1469
|
+
// Publish draft note schema
|
|
1470
|
+
export const PublishDraftNoteSchema = ProjectParamsSchema.extend({
|
|
1471
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1472
|
+
draft_note_id: z.coerce.string().describe("The ID of the draft note"),
|
|
1473
|
+
});
|
|
1474
|
+
// Bulk publish draft notes schema
|
|
1475
|
+
export const BulkPublishDraftNotesSchema = ProjectParamsSchema.extend({
|
|
1476
|
+
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
1477
|
+
});
|
|
1141
1478
|
// Schema for creating a new merge request thread
|
|
1142
1479
|
export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
|
|
1143
1480
|
merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
|
|
@@ -1206,14 +1543,27 @@ export const GetMilestoneBurndownEventsSchema = GetProjectMilestoneSchema.merge(
|
|
|
1206
1543
|
// Add schemas for commit operations
|
|
1207
1544
|
export const ListCommitsSchema = z.object({
|
|
1208
1545
|
project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
|
|
1209
|
-
ref_name: z
|
|
1210
|
-
|
|
1211
|
-
|
|
1546
|
+
ref_name: z
|
|
1547
|
+
.string()
|
|
1548
|
+
.optional()
|
|
1549
|
+
.describe("The name of a repository branch, tag or revision range, or if not given the default branch"),
|
|
1550
|
+
since: z
|
|
1551
|
+
.string()
|
|
1552
|
+
.optional()
|
|
1553
|
+
.describe("Only commits after or on this date are returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ"),
|
|
1554
|
+
until: z
|
|
1555
|
+
.string()
|
|
1556
|
+
.optional()
|
|
1557
|
+
.describe("Only commits before or on this date are returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ"),
|
|
1212
1558
|
path: z.string().optional().describe("The file path"),
|
|
1213
1559
|
author: z.string().optional().describe("Search commits by commit author"),
|
|
1214
1560
|
all: flexibleBoolean.optional().describe("Retrieve every commit from the repository"),
|
|
1215
|
-
with_stats: flexibleBoolean
|
|
1216
|
-
|
|
1561
|
+
with_stats: flexibleBoolean
|
|
1562
|
+
.optional()
|
|
1563
|
+
.describe("Stats about each commit are added to the response"),
|
|
1564
|
+
first_parent: flexibleBoolean
|
|
1565
|
+
.optional()
|
|
1566
|
+
.describe("Follow only the first parent commit upon seeing a merge commit"),
|
|
1217
1567
|
order: z.enum(["default", "topo"]).optional().describe("List commits in order"),
|
|
1218
1568
|
trailers: flexibleBoolean.optional().describe("Parse and include Git trailers for every commit"),
|
|
1219
1569
|
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
@@ -1228,3 +1578,106 @@ export const GetCommitDiffSchema = z.object({
|
|
|
1228
1578
|
project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
|
|
1229
1579
|
sha: z.string().describe("The commit hash or name of a repository branch or tag"),
|
|
1230
1580
|
});
|
|
1581
|
+
// Schema for listing issues assigned to the current user
|
|
1582
|
+
export const MyIssuesSchema = z.object({
|
|
1583
|
+
project_id: z.string().optional().describe("Project ID or URL-encoded path (optional when GITLAB_PROJECT_ID is set)"),
|
|
1584
|
+
state: z
|
|
1585
|
+
.enum(["opened", "closed", "all"])
|
|
1586
|
+
.optional()
|
|
1587
|
+
.describe("Return issues with a specific state (default: opened)"),
|
|
1588
|
+
labels: z.array(z.string()).optional().describe("Array of label names to filter by"),
|
|
1589
|
+
milestone: z.string().optional().describe("Milestone title to filter by"),
|
|
1590
|
+
search: z.string().optional().describe("Search for specific terms in title and description"),
|
|
1591
|
+
created_after: z.string().optional().describe("Return issues created after the given time (ISO 8601)"),
|
|
1592
|
+
created_before: z.string().optional().describe("Return issues created before the given time (ISO 8601)"),
|
|
1593
|
+
updated_after: z.string().optional().describe("Return issues updated after the given time (ISO 8601)"),
|
|
1594
|
+
updated_before: z.string().optional().describe("Return issues updated before the given time (ISO 8601)"),
|
|
1595
|
+
per_page: z.number().optional().describe("Number of items per page (default: 20, max: 100)"),
|
|
1596
|
+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
1597
|
+
});
|
|
1598
|
+
// Schema for listing project members
|
|
1599
|
+
export const ListProjectMembersSchema = z.object({
|
|
1600
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
1601
|
+
query: z.string().optional().describe("Search for members by name or username"),
|
|
1602
|
+
user_ids: z.array(z.number()).optional().describe("Filter by user IDs"),
|
|
1603
|
+
skip_users: z.array(z.number()).optional().describe("User IDs to exclude"),
|
|
1604
|
+
per_page: z.number().optional().describe("Number of items per page (default: 20, max: 100)"),
|
|
1605
|
+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
1606
|
+
});
|
|
1607
|
+
// Schema for GitLab project member
|
|
1608
|
+
export const GitLabProjectMemberSchema = z.object({
|
|
1609
|
+
id: z.number(),
|
|
1610
|
+
username: z.string(),
|
|
1611
|
+
name: z.string(),
|
|
1612
|
+
state: z.string(),
|
|
1613
|
+
avatar_url: z.string().nullable(),
|
|
1614
|
+
web_url: z.string(),
|
|
1615
|
+
access_level: z.number(),
|
|
1616
|
+
access_level_description: z.string().optional(),
|
|
1617
|
+
created_at: z.string(),
|
|
1618
|
+
expires_at: z.string().nullable().optional(),
|
|
1619
|
+
email: z.string().optional(),
|
|
1620
|
+
});
|
|
1621
|
+
// Markdown upload schemas
|
|
1622
|
+
export const GitLabMarkdownUploadSchema = z.object({
|
|
1623
|
+
id: z.number(),
|
|
1624
|
+
alt: z.string(),
|
|
1625
|
+
url: z.string(),
|
|
1626
|
+
full_path: z.string(),
|
|
1627
|
+
markdown: z.string(),
|
|
1628
|
+
});
|
|
1629
|
+
export const MarkdownUploadSchema = z.object({
|
|
1630
|
+
project_id: z.string().describe("Project ID or URL-encoded path of the project"),
|
|
1631
|
+
file_path: z.string().describe("Path to the file to upload"),
|
|
1632
|
+
});
|
|
1633
|
+
export const DownloadAttachmentSchema = z.object({
|
|
1634
|
+
project_id: z.string().describe("Project ID or URL-encoded path of the project"),
|
|
1635
|
+
secret: z.string().describe("The 32-character secret of the upload"),
|
|
1636
|
+
filename: z.string().describe("The filename of the upload"),
|
|
1637
|
+
local_path: z.string().optional().describe("Local path to save the file (optional, defaults to current directory)"),
|
|
1638
|
+
});
|
|
1639
|
+
export const GroupIteration = z.object({
|
|
1640
|
+
id: z.coerce.string(),
|
|
1641
|
+
iid: z.coerce.string(),
|
|
1642
|
+
sequence: z.number(),
|
|
1643
|
+
group_id: z.coerce.string(),
|
|
1644
|
+
title: z.string().optional().nullable(),
|
|
1645
|
+
description: z.string().optional().nullable(),
|
|
1646
|
+
state: z.number(),
|
|
1647
|
+
created_at: z.string(),
|
|
1648
|
+
updated_at: z.string(),
|
|
1649
|
+
due_date: z.string().optional().nullable(),
|
|
1650
|
+
start_date: z.string().optional().nullable(),
|
|
1651
|
+
web_url: z.string().optional().nullable(),
|
|
1652
|
+
});
|
|
1653
|
+
export const ListGroupIterationsSchema = z
|
|
1654
|
+
.object({
|
|
1655
|
+
group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
|
|
1656
|
+
state: z
|
|
1657
|
+
.enum(["opened", "upcoming", "current", "closed", "all"])
|
|
1658
|
+
.optional()
|
|
1659
|
+
.describe("Return opened, upcoming, current, closed, or all iterations."),
|
|
1660
|
+
search: z
|
|
1661
|
+
.string()
|
|
1662
|
+
.optional()
|
|
1663
|
+
.describe("Return only iterations with a title matching the provided string."),
|
|
1664
|
+
in: z
|
|
1665
|
+
.array(z.enum(["title", "cadence_title"]))
|
|
1666
|
+
.optional()
|
|
1667
|
+
.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]."),
|
|
1668
|
+
include_ancestors: flexibleBoolean
|
|
1669
|
+
.optional()
|
|
1670
|
+
.describe("Include iterations for group and its ancestors. Defaults to true."),
|
|
1671
|
+
include_descendants: flexibleBoolean
|
|
1672
|
+
.optional()
|
|
1673
|
+
.describe("Include iterations for group and its descendants. Defaults to false."),
|
|
1674
|
+
updated_before: z
|
|
1675
|
+
.string()
|
|
1676
|
+
.optional()
|
|
1677
|
+
.describe("Return only iterations updated before the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z)."),
|
|
1678
|
+
updated_after: z
|
|
1679
|
+
.string()
|
|
1680
|
+
.optional()
|
|
1681
|
+
.describe("Return only iterations updated after the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z)."),
|
|
1682
|
+
})
|
|
1683
|
+
.merge(PaginationOptionsSchema);
|