@zereight/mcp-gitlab 1.0.76 → 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/build/schemas.js CHANGED
@@ -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.object({
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.optional().describe("Returns pipelines with invalid configurations"),
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
- }).merge(PaginationOptionsSchema);
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.object({
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
- }).merge(PaginationOptionsSchema);
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.number().optional().describe("Maximum number of lines to return from the end of the log (default: 1000)"),
180
- offset: z.number().optional().describe("Number of lines to skip from the end of the log (default: 0)"),
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.object({
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
- }).nullable());
303
+ })
304
+ .nullable());
200
305
  // Namespace related schemas
201
306
  // Base schema for project-related operations
202
307
  const ProjectParamsSchema = 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.object({
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
- }).optional(), // Only present when with_stats=true
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.object({
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
- }).optional(),
568
+ })
569
+ .optional(),
461
570
  commits: z.array(GitLabCommitSchema),
462
571
  diffs: z.array(GitLabDiffSchema),
463
572
  compare_timeout: flexibleBoolean.optional(),
@@ -520,6 +629,7 @@ export const GitLabIssueSchema = z.object({
520
629
  due_date: z.string().nullable().optional(),
521
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({
@@ -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.object({
589
- start: z.object({
590
- line_code: z.string().nullable().optional().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."),
591
- type: z.enum(["new", "old", "expanded"]).nullable().optional().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."),
592
- old_line: z.number().nullable().optional().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."),
593
- new_line: z.number().nullable().optional().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."),
594
- }).describe("Start line position for multiline comment range. MUST specify either old_line OR new_line (or both for context), never neither."),
595
- end: z.object({
596
- line_code: z.string().nullable().optional().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."),
597
- type: z.enum(["new", "old", "expanded"]).nullable().optional().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)."),
598
- old_line: z.number().nullable().optional().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."),
599
- new_line: z.number().nullable().optional().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."),
600
- }).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)."),
601
- }).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.");
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.number().nullable().optional().describe("Line number in the modified file (after changes). Used for added lines and context lines. Null for deleted lines."),
630
- old_line: z.number().nullable().optional().describe("Line number in the original file (before changes). Used for deleted lines and context lines. Null for newly added lines."),
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.object({
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
- }).merge(PaginationOptionsSchema);
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.object({
876
+ export const SearchRepositoriesSchema = z
877
+ .object({
718
878
  search: z.string().describe("Search query"), // Changed from query to match GitLab API
719
- }).merge(PaginationOptionsSchema);
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
- .boolean()
925
+ allow_collaboration: z.boolean().optional().describe("Allow commits from upstream members"),
926
+ remove_source_branch: flexibleBooleanNullable
768
927
  .optional()
769
- .describe("Allow commits from upstream members"),
770
- remove_source_branch: flexibleBooleanNullable.optional().describe("Flag indicating if a merge request should remove the source branch when merging."),
771
- squash: flexibleBooleanNullable.optional().describe("If true, squash all commits into a single commit on merge."),
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.optional().describe("Comparison method: false for '...' (default), true for '--'"),
787
- excluded_file_patterns: z.array(z.string()).optional().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\"]"),
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.optional().describe("Present diffs in the unified diff format. Default is false. Introduced in GitLab 16.5."),
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.object({
835
- project_id: z.coerce.string().optional().describe("Project ID or URL-encoded path (optional - if not provided, lists issues across all accessible projects)"),
836
- assignee_id: z.coerce.string().optional().describe("Return issues assigned to the given user ID. user id or none or any"),
837
- assignee_username: z.array(z.string()).optional().describe("Return issues assigned to the given username"),
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,8 +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"),
846
- issue_type: z.string().optional().nullable().describe("Filter to a given type of issue. One of issue, incident, test_case or task"),
847
- iteration_id: z.coerce.string().optional().nullable().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. "),
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. "),
848
1039
  scope: z
849
1040
  .enum(["created_by_me", "assigned_to_me", "all"])
850
1041
  .optional()
@@ -857,21 +1048,30 @@ export const ListIssuesSchema = z.object({
857
1048
  updated_after: z.string().optional().describe("Return issues updated after the given time"),
858
1049
  updated_before: z.string().optional().describe("Return issues updated before the given time"),
859
1050
  with_labels_details: flexibleBoolean.optional().describe("Return more details for each label"),
860
- }).merge(PaginationOptionsSchema);
1051
+ })
1052
+ .merge(PaginationOptionsSchema);
861
1053
  // Merge Requests API operation schemas
862
- export const ListMergeRequestsSchema = z.object({
1054
+ export const ListMergeRequestsSchema = z
1055
+ .object({
863
1056
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
864
- assignee_id: z.coerce.string().optional().describe("Return issues assigned to the given user ID. user id or none or any"),
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"),
865
1061
  assignee_username: z
866
1062
  .string()
867
1063
  .optional()
868
1064
  .describe("Returns merge requests assigned to the given username"),
869
- author_id: z.coerce.string().optional().describe("Returns merge requests created by the given user ID"),
1065
+ author_id: z.coerce
1066
+ .string()
1067
+ .optional()
1068
+ .describe("Returns merge requests created by the given user ID"),
870
1069
  author_username: z
871
1070
  .string()
872
1071
  .optional()
873
1072
  .describe("Returns merge requests created by the given username"),
874
- reviewer_id: z.coerce.string()
1073
+ reviewer_id: z.coerce
1074
+ .string()
875
1075
  .optional()
876
1076
  .describe("Returns merge requests which have the user as a reviewer. user id or none or any"),
877
1077
  reviewer_username: z
@@ -906,7 +1106,14 @@ export const ListMergeRequestsSchema = z.object({
906
1106
  .optional()
907
1107
  .describe("Return merge requests with a specific state"),
908
1108
  order_by: z
909
- .enum(["created_at", "updated_at", "priority", "label_priority", "milestone_due", "popularity"])
1109
+ .enum([
1110
+ "created_at",
1111
+ "updated_at",
1112
+ "priority",
1113
+ "label_priority",
1114
+ "milestone_due",
1115
+ "popularity",
1116
+ ])
910
1117
  .optional()
911
1118
  .describe("Return merge requests ordered by the given field"),
912
1119
  sort: z
@@ -921,9 +1128,13 @@ export const ListMergeRequestsSchema = z.object({
921
1128
  .string()
922
1129
  .optional()
923
1130
  .describe("Return merge requests from a specific source branch"),
924
- wip: z.enum(["yes", "no"]).optional().describe("Filter merge requests against their wip status"),
1131
+ wip: z
1132
+ .enum(["yes", "no"])
1133
+ .optional()
1134
+ .describe("Filter merge requests against their wip status"),
925
1135
  with_labels_details: flexibleBoolean.optional().describe("Return more details for each label"),
926
- }).merge(PaginationOptionsSchema);
1136
+ })
1137
+ .merge(PaginationOptionsSchema);
927
1138
  export const GetIssueSchema = z.object({
928
1139
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
929
1140
  issue_iid: z.coerce.string().describe("The internal ID of the project issue"),
@@ -941,6 +1152,7 @@ export const UpdateIssueSchema = z.object({
941
1152
  milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
942
1153
  state_event: z.enum(["close", "reopen"]).optional().describe("Update issue state (close/reopen)"),
943
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."),
944
1156
  });
945
1157
  export const DeleteIssueSchema = z.object({
946
1158
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -977,10 +1189,12 @@ export const DeleteIssueLinkSchema = z.object({
977
1189
  issue_link_id: z.coerce.string().describe("The ID of an issue relationship"),
978
1190
  });
979
1191
  // Namespace API operation schemas
980
- export const ListNamespacesSchema = z.object({
1192
+ export const ListNamespacesSchema = z
1193
+ .object({
981
1194
  search: z.string().optional().describe("Search term for namespaces"),
982
1195
  owned: flexibleBoolean.optional().describe("Filter for namespaces owned by current user"),
983
- }).merge(PaginationOptionsSchema);
1196
+ })
1197
+ .merge(PaginationOptionsSchema);
984
1198
  export const GetNamespaceSchema = z.object({
985
1199
  namespace_id: z.coerce.string().describe("Namespace ID or full path"),
986
1200
  });
@@ -991,11 +1205,16 @@ export const VerifyNamespaceSchema = z.object({
991
1205
  export const GetProjectSchema = z.object({
992
1206
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
993
1207
  });
994
- export const ListProjectsSchema = z.object({
1208
+ export const ListProjectsSchema = z
1209
+ .object({
995
1210
  search: z.string().optional().describe("Search term for projects"),
996
- search_namespaces: flexibleBoolean.optional().describe("Needs to be true if search is full path"),
1211
+ search_namespaces: flexibleBoolean
1212
+ .optional()
1213
+ .describe("Needs to be true if search is full path"),
997
1214
  owned: flexibleBoolean.optional().describe("Filter for projects owned by current user"),
998
- membership: flexibleBoolean.optional().describe("Filter for projects where current user is a member"),
1215
+ membership: flexibleBoolean
1216
+ .optional()
1217
+ .describe("Filter for projects where current user is a member"),
999
1218
  simple: flexibleBoolean.optional().describe("Return only limited fields"),
1000
1219
  archived: flexibleBoolean.optional().describe("Filter for archived projects"),
1001
1220
  visibility: z
@@ -1019,7 +1238,8 @@ export const ListProjectsSchema = z.object({
1019
1238
  .optional()
1020
1239
  .describe("Filter projects with merge requests feature enabled"),
1021
1240
  min_access_level: z.number().optional().describe("Filter by minimum access level"),
1022
- }).merge(PaginationOptionsSchema);
1241
+ })
1242
+ .merge(PaginationOptionsSchema);
1023
1243
  // Label operation schemas
1024
1244
  export const ListLabelsSchema = z.object({
1025
1245
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1060,7 +1280,8 @@ export const DeleteLabelSchema = z.object({
1060
1280
  label_id: z.coerce.string().describe("The ID or title of a project's label"),
1061
1281
  });
1062
1282
  // Group projects schema
1063
- export const ListGroupProjectsSchema = z.object({
1283
+ export const ListGroupProjectsSchema = z
1284
+ .object({
1064
1285
  group_id: z.coerce.string().describe("Group ID or path"),
1065
1286
  include_subgroups: flexibleBoolean.optional().describe("Include projects from subgroups"),
1066
1287
  search: z.string().optional().describe("Search term to filter projects"),
@@ -1088,12 +1309,15 @@ export const ListGroupProjectsSchema = z.object({
1088
1309
  statistics: flexibleBoolean.optional().describe("Include project statistics"),
1089
1310
  with_custom_attributes: flexibleBoolean.optional().describe("Include custom attributes"),
1090
1311
  with_security_reports: flexibleBoolean.optional().describe("Include security reports"),
1091
- }).merge(PaginationOptionsSchema);
1312
+ })
1313
+ .merge(PaginationOptionsSchema);
1092
1314
  // Add wiki operation schemas
1093
- export const ListWikiPagesSchema = z.object({
1315
+ export const ListWikiPagesSchema = z
1316
+ .object({
1094
1317
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1095
1318
  with_content: flexibleBoolean.optional().describe("Include content of the wiki pages"),
1096
- }).merge(PaginationOptionsSchema);
1319
+ })
1320
+ .merge(PaginationOptionsSchema);
1097
1321
  export const GetWikiPageSchema = z.object({
1098
1322
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1099
1323
  slug: z.string().describe("URL-encoded slug of the wiki page"),
@@ -1125,7 +1349,9 @@ export const GitLabWikiPageSchema = z.object({
1125
1349
  updated_at: z.string().optional(),
1126
1350
  });
1127
1351
  // Merge Request Thread position schema - used for diff notes
1128
- export const MergeRequestThreadPositionSchema = z.object({
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({
1129
1355
  base_sha: z.string().describe("REQUIRED: Base commit SHA in the source branch. Get this from merge request diff_refs.base_sha."),
1130
1356
  head_sha: z.string().describe("REQUIRED: SHA referencing HEAD of the source branch. Get this from merge request diff_refs.head_sha."),
1131
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."),
@@ -1140,6 +1366,115 @@ export const MergeRequestThreadPositionSchema = z.object({
1140
1366
  x: z.number().optional().describe("IMAGE DIFFS ONLY: X coordinate on the image (for position_type='image')."),
1141
1367
  y: z.number().optional().describe("IMAGE DIFFS ONLY: Y coordinate on the image (for position_type='image')."),
1142
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
+ });
1143
1478
  // Schema for creating a new merge request thread
1144
1479
  export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
1145
1480
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
@@ -1208,14 +1543,27 @@ export const GetMilestoneBurndownEventsSchema = GetProjectMilestoneSchema.merge(
1208
1543
  // Add schemas for commit operations
1209
1544
  export const ListCommitsSchema = z.object({
1210
1545
  project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
1211
- ref_name: z.string().optional().describe("The name of a repository branch, tag or revision range, or if not given the default branch"),
1212
- since: z.string().optional().describe("Only commits after or on this date are returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ"),
1213
- until: z.string().optional().describe("Only commits before or on this date are returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ"),
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"),
1214
1558
  path: z.string().optional().describe("The file path"),
1215
1559
  author: z.string().optional().describe("Search commits by commit author"),
1216
1560
  all: flexibleBoolean.optional().describe("Retrieve every commit from the repository"),
1217
- with_stats: flexibleBoolean.optional().describe("Stats about each commit are added to the response"),
1218
- first_parent: flexibleBoolean.optional().describe("Follow only the first parent commit upon seeing a merge commit"),
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"),
1219
1567
  order: z.enum(["default", "topo"]).optional().describe("List commits in order"),
1220
1568
  trailers: flexibleBoolean.optional().describe("Parse and include Git trailers for every commit"),
1221
1569
  page: z.number().optional().describe("Page number for pagination (default: 1)"),
@@ -1230,6 +1578,64 @@ export const GetCommitDiffSchema = z.object({
1230
1578
  project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
1231
1579
  sha: z.string().describe("The commit hash or name of a repository branch or tag"),
1232
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
+ });
1233
1639
  export const GroupIteration = z.object({
1234
1640
  id: z.coerce.string(),
1235
1641
  iid: z.coerce.string(),
@@ -1244,13 +1650,34 @@ export const GroupIteration = z.object({
1244
1650
  start_date: z.string().optional().nullable(),
1245
1651
  web_url: z.string().optional().nullable(),
1246
1652
  });
1247
- export const ListGroupIterationsSchema = z.object({
1653
+ export const ListGroupIterationsSchema = z
1654
+ .object({
1248
1655
  group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1249
- state: z.enum(["opened", "upcoming", "current", "closed", "all"]).optional().describe("Return opened, upcoming, current, closed, or all iterations."),
1250
- search: z.string().optional().describe("Return only iterations with a title matching the provided string."),
1251
- in: z.array(z.enum(["title", "cadence_title"])).optional().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]."),
1252
- include_ancestors: flexibleBoolean.optional().describe("Include iterations for group and its ancestors. Defaults to true."),
1253
- include_descendants: flexibleBoolean.optional().describe("Include iterations for group and its descendants. Defaults to false."),
1254
- updated_before: z.string().optional().describe("Return only iterations updated before the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z)."),
1255
- updated_after: z.string().optional().describe("Return only iterations updated after the given datetime. Expected in ISO 8601 format (2019-03-15T08:00:00Z)."),
1256
- }).merge(PaginationOptionsSchema);
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);