@zereight/mcp-gitlab 2.0.33 → 2.0.35

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
@@ -16,7 +16,7 @@ export const GitLabPipelineSchema = z.object({
16
16
  created_at: z.string(),
17
17
  updated_at: z.string(),
18
18
  web_url: z.string(),
19
- duration: z.number().nullable().optional(),
19
+ duration: z.coerce.number().nullable().optional(),
20
20
  started_at: z.string().nullable().optional(),
21
21
  finished_at: z.string().nullable().optional(),
22
22
  coverage: z.coerce.number().nullable().optional(),
@@ -35,7 +35,7 @@ export const GitLabPipelineSchema = z.object({
35
35
  label: z.string().optional(),
36
36
  group: z.string().optional(),
37
37
  tooltip: z.string().optional(),
38
- has_details: z.boolean().optional(),
38
+ has_details: z.coerce.boolean().optional(),
39
39
  details_path: z.string().optional(),
40
40
  illustration: z
41
41
  .object({
@@ -56,13 +56,13 @@ export const GitLabPipelineJobSchema = z.object({
56
56
  stage: z.string(),
57
57
  name: z.string(),
58
58
  ref: z.string(),
59
- tag: z.boolean(),
59
+ tag: z.coerce.boolean(),
60
60
  coverage: z.coerce.number().nullable().optional(),
61
61
  created_at: z.string(),
62
62
  started_at: z.string().nullable().optional(),
63
63
  finished_at: z.string().nullable().optional(),
64
- duration: z.number().nullable().optional(),
65
- queued_duration: z.number().nullable().optional(),
64
+ duration: z.coerce.number().nullable().optional(),
65
+ queued_duration: z.coerce.number().nullable().optional(),
66
66
  failure_reason: z.string().nullable().optional(),
67
67
  user: z
68
68
  .object({
@@ -91,15 +91,15 @@ export const GitLabPipelineJobSchema = z.object({
91
91
  })
92
92
  .optional(),
93
93
  web_url: z.string().optional(),
94
- allow_failure: z.boolean().optional(),
95
- retried: z.boolean().optional(),
94
+ allow_failure: z.coerce.boolean().optional(),
95
+ retried: z.coerce.boolean().optional(),
96
96
  tag_list: z.array(z.string()).optional(),
97
97
  runner: z
98
98
  .object({
99
99
  id: z.coerce.string().optional(),
100
100
  description: z.string().nullable().optional(),
101
- active: z.boolean().optional(),
102
- is_shared: z.boolean().optional(),
101
+ active: z.coerce.boolean().optional(),
102
+ is_shared: z.coerce.boolean().optional(),
103
103
  runner_type: z.string().optional(),
104
104
  })
105
105
  .nullable()
@@ -112,13 +112,13 @@ export const GitLabPipelineTriggerJobSchema = z.object({
112
112
  stage: z.string(),
113
113
  name: z.string(),
114
114
  ref: z.string(),
115
- tag: z.boolean(),
116
- coverage: z.number().nullable().optional(),
115
+ tag: z.coerce.boolean(),
116
+ coverage: z.coerce.number().nullable().optional(),
117
117
  created_at: z.string(),
118
118
  started_at: z.string().nullable().optional(),
119
119
  finished_at: z.string().nullable().optional(),
120
- duration: z.number().nullable().optional(),
121
- queued_duration: z.number().nullable().optional(),
120
+ duration: z.coerce.number().nullable().optional(),
121
+ queued_duration: z.coerce.number().nullable().optional(),
122
122
  user: z
123
123
  .object({
124
124
  id: z.coerce.string(),
@@ -149,13 +149,13 @@ export const GitLabPipelineTriggerJobSchema = z.object({
149
149
  })
150
150
  .optional(),
151
151
  web_url: z.string().optional(),
152
- allow_failure: z.boolean().optional(),
153
- archived: z.boolean().optional(),
152
+ allow_failure: z.coerce.boolean().optional(),
153
+ archived: z.coerce.boolean().optional(),
154
154
  source: z.string().optional(),
155
155
  erased_at: z.string().nullable().optional(),
156
156
  project: z
157
157
  .object({
158
- ci_job_token_scope_enabled: z.boolean().optional(),
158
+ ci_job_token_scope_enabled: z.coerce.boolean().optional(),
159
159
  })
160
160
  .optional(),
161
161
  downstream_pipeline: z
@@ -174,8 +174,8 @@ export const GitLabPipelineTriggerJobSchema = z.object({
174
174
  // Shared base schema for various pagination options
175
175
  // See https://docs.gitlab.com/api/rest/#pagination
176
176
  export const PaginationOptionsSchema = z.object({
177
- page: z.number().optional().describe("Page number for pagination (default: 1)"),
178
- per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
177
+ page: z.coerce.number().optional().describe("Page number for pagination (default: 1)"),
178
+ per_page: z.coerce.number().optional().describe("Number of items per page (max: 100, default: 20)"),
179
179
  });
180
180
  // Schema for listing pipelines
181
181
  export const ListPipelinesSchema = z
@@ -203,7 +203,7 @@ export const ListPipelinesSchema = z
203
203
  .describe("The status of pipelines"),
204
204
  ref: z.string().optional().describe("The ref of pipelines"),
205
205
  sha: z.string().optional().describe("The SHA of pipelines"),
206
- yaml_errors: z.boolean().optional().describe("Returns pipelines with invalid configurations"),
206
+ yaml_errors: z.coerce.boolean().optional().describe("Returns pipelines with invalid configurations"),
207
207
  username: z.string().optional().describe("The username of the user who triggered pipelines"),
208
208
  updated_after: z
209
209
  .string()
@@ -234,7 +234,7 @@ export const ListPipelineJobsSchema = z
234
234
  .enum(["created", "pending", "running", "failed", "success", "canceled", "skipped", "manual"])
235
235
  .optional()
236
236
  .describe("The scope of jobs to show"),
237
- include_retried: z.boolean().optional().describe("Whether to include retried jobs"),
237
+ include_retried: z.coerce.boolean().optional().describe("Whether to include retried jobs"),
238
238
  })
239
239
  .merge(PaginationOptionsSchema);
240
240
  // Schema for listing trigger jobs (bridges) in a pipeline
@@ -362,7 +362,7 @@ export const GitLabEnvironmentSchema = z.object({
362
362
  created_at: z.string().optional(),
363
363
  updated_at: z.string().optional(),
364
364
  auto_stop_at: z.string().nullable().optional(),
365
- enable_advanced_logs_querying: z.boolean().optional(),
365
+ enable_advanced_logs_querying: z.coerce.boolean().optional(),
366
366
  logs_api_path: z.string().optional(),
367
367
  web_url: z.string().optional(),
368
368
  last_deployment: GitLabEnvironmentLastDeploymentSchema.nullable().optional(),
@@ -441,7 +441,7 @@ export const RetryPipelineJobSchema = PipelineJobControlSchema;
441
441
  export const CancelPipelineJobSchema = z.object({
442
442
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
443
443
  job_id: z.coerce.string().describe("The ID of the job"),
444
- force: z.boolean().optional().describe("Force cancellation of the job"),
444
+ force: z.coerce.boolean().optional().describe("Force cancellation of the job"),
445
445
  });
446
446
  // User schemas
447
447
  export const GitLabUserSchema = z.object({
@@ -477,19 +477,19 @@ export const GitLabNamespaceSchema = z.object({
477
477
  parent_id: z.coerce.string().nullable(),
478
478
  avatar_url: z.string().nullable(),
479
479
  web_url: z.string(),
480
- members_count_with_descendants: z.number().optional(),
481
- billable_members_count: z.number().optional(),
482
- max_seats_used: z.number().optional(),
483
- seats_in_use: z.number().optional(),
480
+ members_count_with_descendants: z.coerce.number().optional(),
481
+ billable_members_count: z.coerce.number().optional(),
482
+ max_seats_used: z.coerce.number().optional(),
483
+ seats_in_use: z.coerce.number().optional(),
484
484
  plan: z.string().optional(),
485
485
  end_date: z.string().nullable().optional(),
486
486
  trial_ends_on: z.string().nullable().optional(),
487
- trial: z.boolean().optional(),
488
- root_repository_size: z.number().optional(),
489
- projects_count: z.number().optional(),
487
+ trial: z.coerce.boolean().optional(),
488
+ root_repository_size: z.coerce.number().optional(),
489
+ projects_count: z.coerce.number().optional(),
490
490
  });
491
491
  export const GitLabNamespaceExistsResponseSchema = z.object({
492
- exists: z.boolean(),
492
+ exists: z.coerce.boolean(),
493
493
  suggests: z.array(z.string()).optional(),
494
494
  });
495
495
  // Repository related schemas
@@ -509,7 +509,7 @@ export const GitLabRepositorySchema = z.object({
509
509
  owner: GitLabOwnerSchema.optional(),
510
510
  web_url: z.string().optional(),
511
511
  description: z.string().nullable(),
512
- fork: z.boolean().optional(),
512
+ fork: z.coerce.boolean().optional(),
513
513
  ssh_url_to_repo: z.string().optional(),
514
514
  http_url_to_repo: z.string().optional(),
515
515
  created_at: z.string().optional(),
@@ -529,45 +529,45 @@ export const GitLabRepositorySchema = z.object({
529
529
  readme_url: z.string().optional().nullable(),
530
530
  topics: z.array(z.string()).optional(),
531
531
  tag_list: z.array(z.string()).optional(), // deprecated but still present
532
- open_issues_count: z.number().optional(),
533
- archived: z.boolean().optional(),
534
- forks_count: z.number().optional(),
535
- star_count: z.number().optional(),
532
+ open_issues_count: z.coerce.number().optional(),
533
+ archived: z.coerce.boolean().optional(),
534
+ forks_count: z.coerce.number().optional(),
535
+ star_count: z.coerce.number().optional(),
536
536
  permissions: z
537
537
  .object({
538
538
  project_access: z
539
539
  .object({
540
- access_level: z.number(),
541
- notification_level: z.number().nullable().optional(),
540
+ access_level: z.coerce.number(),
541
+ notification_level: z.coerce.number().nullable().optional(),
542
542
  })
543
543
  .optional()
544
544
  .nullable(),
545
545
  group_access: z
546
546
  .object({
547
- access_level: z.number(),
548
- notification_level: z.number().nullable().optional(),
547
+ access_level: z.coerce.number(),
548
+ notification_level: z.coerce.number().nullable().optional(),
549
549
  })
550
550
  .optional()
551
551
  .nullable(),
552
552
  })
553
553
  .optional(),
554
- container_registry_enabled: z.boolean().optional(),
554
+ container_registry_enabled: z.coerce.boolean().optional(),
555
555
  container_registry_access_level: z.string().optional(),
556
- issues_enabled: z.boolean().optional(),
557
- merge_requests_enabled: z.boolean().optional(),
556
+ issues_enabled: z.coerce.boolean().optional(),
557
+ merge_requests_enabled: z.coerce.boolean().optional(),
558
558
  merge_requests_template: z.string().nullable().optional(),
559
- wiki_enabled: z.boolean().optional(),
560
- jobs_enabled: z.boolean().optional(),
561
- snippets_enabled: z.boolean().optional(),
562
- can_create_merge_request_in: z.boolean().optional(),
563
- resolve_outdated_diff_discussions: z.boolean().nullable().optional(),
564
- shared_runners_enabled: z.boolean().optional(),
559
+ wiki_enabled: z.coerce.boolean().optional(),
560
+ jobs_enabled: z.coerce.boolean().optional(),
561
+ snippets_enabled: z.coerce.boolean().optional(),
562
+ can_create_merge_request_in: z.coerce.boolean().optional(),
563
+ resolve_outdated_diff_discussions: z.coerce.boolean().nullable().optional(),
564
+ shared_runners_enabled: z.coerce.boolean().optional(),
565
565
  shared_with_groups: z
566
566
  .array(z.object({
567
567
  group_id: z.coerce.string(),
568
568
  group_name: z.string(),
569
569
  group_full_path: z.string(),
570
- group_access_level: z.number(),
570
+ group_access_level: z.coerce.number(),
571
571
  }))
572
572
  .optional(),
573
573
  });
@@ -585,7 +585,7 @@ export const GitLabFileContentSchema = z.object({
585
585
  blob_id: z.string().optional(),
586
586
  commit_id: z.string().optional(),
587
587
  last_commit_id: z.string().optional(),
588
- execute_filemode: z.boolean().optional(),
588
+ execute_filemode: z.coerce.boolean().optional(),
589
589
  });
590
590
  export const GitLabDirectoryContentSchema = z.object({
591
591
  name: z.string(),
@@ -619,8 +619,8 @@ export const GetRepositoryTreeSchema = z.object({
619
619
  .string()
620
620
  .optional()
621
621
  .describe("The name of a repository branch or tag. Defaults to the default branch."),
622
- recursive: z.boolean().optional().describe("Boolean value to get a recursive tree"),
623
- per_page: z.number().optional().describe("Number of results to show per page"),
622
+ recursive: z.coerce.boolean().optional().describe("Boolean value to get a recursive tree"),
623
+ per_page: z.coerce.number().optional().describe("Number of results to show per page"),
624
624
  page_token: z.string().optional().describe("The tree record ID for pagination"),
625
625
  pagination: z.string().optional().describe("Pagination method (keyset)"),
626
626
  });
@@ -644,9 +644,9 @@ export const GitLabCommitSchema = z.object({
644
644
  parent_ids: z.array(z.string()), // Changed from parents to match GitLab API
645
645
  stats: z
646
646
  .object({
647
- additions: z.number().optional().nullable(),
648
- deletions: z.number().optional().nullable(),
649
- total: z.number().optional().nullable(),
647
+ additions: z.coerce.number().optional().nullable(),
648
+ deletions: z.coerce.number().optional().nullable(),
649
+ total: z.coerce.number().optional().nullable(),
650
650
  })
651
651
  .optional(), // Only present when with_stats=true
652
652
  trailers: z.record(z.string()).optional().default({}), // Git trailers, may be empty object
@@ -672,7 +672,7 @@ export const GitLabMilestonesSchema = z.object({
672
672
  state: z.string(),
673
673
  updated_at: z.string(),
674
674
  created_at: z.string(),
675
- expired: z.boolean(),
675
+ expired: z.coerce.boolean(),
676
676
  web_url: z.string().optional(),
677
677
  });
678
678
  // Input schemas for operations
@@ -680,14 +680,19 @@ export const CreateRepositoryOptionsSchema = z.object({
680
680
  name: z.string(),
681
681
  description: z.string().optional(),
682
682
  visibility: z.enum(["private", "internal", "public"]).optional(), // Changed from private to match GitLab API
683
- initialize_with_readme: z.boolean().optional(), // Changed from auto_init to match GitLab API
683
+ initialize_with_readme: z.coerce.boolean().optional(), // Changed from auto_init to match GitLab API
684
684
  });
685
685
  export const CreateIssueOptionsSchema = z.object({
686
686
  title: z.string(),
687
687
  description: z.string().optional(), // Changed from body to match GitLab API
688
- assignee_ids: z.array(z.number()).optional(), // Changed from assignees to match GitLab API
688
+ assignee_ids: z.array(z.coerce.number()).optional(), // Changed from assignees to match GitLab API
689
689
  milestone_id: z.coerce.string().optional(), // Changed from milestone to match GitLab API
690
690
  labels: z.array(z.string()).optional(),
691
+ issue_type: z
692
+ .enum(["issue", "incident", "test_case", "task"])
693
+ .optional()
694
+ .describe("The type of issue. One of issue, incident, test_case or task."),
695
+ weight: z.coerce.number().optional().describe("Weight of the issue (0-9)"),
691
696
  });
692
697
  export const GitLabDiffSchema = z.object({
693
698
  old_path: z.string(),
@@ -695,9 +700,9 @@ export const GitLabDiffSchema = z.object({
695
700
  a_mode: z.string(),
696
701
  b_mode: z.string(),
697
702
  diff: z.string(),
698
- new_file: z.boolean(),
699
- renamed_file: z.boolean(),
700
- deleted_file: z.boolean(),
703
+ new_file: z.coerce.boolean(),
704
+ renamed_file: z.coerce.boolean(),
705
+ deleted_file: z.coerce.boolean(),
701
706
  });
702
707
  // Response schemas for operations
703
708
  export const GitLabCreateUpdateFileResponseSchema = z.object({
@@ -707,11 +712,52 @@ export const GitLabCreateUpdateFileResponseSchema = z.object({
707
712
  content: GitLabFileContentSchema.optional(),
708
713
  });
709
714
  export const GitLabSearchResponseSchema = z.object({
710
- count: z.number().optional(),
711
- total_pages: z.number().optional(),
712
- current_page: z.number().optional(),
715
+ count: z.coerce.number().optional(),
716
+ total_pages: z.coerce.number().optional(),
717
+ current_page: z.coerce.number().optional(),
713
718
  items: z.array(GitLabRepositorySchema),
714
719
  });
720
+ // Search blobs (code search) schemas
721
+ export const GitLabSearchBlobResultSchema = z.object({
722
+ basename: z.string(),
723
+ data: z.string(),
724
+ path: z.string(),
725
+ filename: z.string(),
726
+ id: z.union([z.string(), z.null()]).optional(),
727
+ ref: z.string(),
728
+ startline: z.coerce.number(),
729
+ project_id: z.coerce.string(),
730
+ });
731
+ const SearchBlobsBaseSchema = z.object({
732
+ search: z
733
+ .string()
734
+ .describe('Code search query string. On instances with exact code search (Zoekt), the query supports rich inline syntax: "class foo" (exact match), foo file:\\.js$ (file pattern), foo lang:ruby (language), sym:foo (symbol search), foo -bar (negation), case:yes (case-sensitive). When using Zoekt inline filters, prefer them over the separate filename/path/extension params which are for basic search.'),
735
+ filename: z
736
+ .string()
737
+ .optional()
738
+ .describe("Filter by filename (supports * wildcard, e.g. '*.ts')"),
739
+ path: z
740
+ .string()
741
+ .optional()
742
+ .describe("Filter by file path (supports * wildcard, e.g. 'src/utils/*')"),
743
+ extension: z
744
+ .string()
745
+ .optional()
746
+ .describe("Filter by file extension without dot (e.g. 'py', 'ts')"),
747
+ });
748
+ export const SearchCodeSchema = SearchBlobsBaseSchema.merge(PaginationOptionsSchema);
749
+ export const SearchProjectCodeSchema = ProjectParamsSchema.extend({
750
+ ...SearchBlobsBaseSchema.shape,
751
+ ref: z.string().optional().describe("Branch or tag to search in (defaults to default branch)"),
752
+ }).merge(PaginationOptionsSchema);
753
+ export const SearchGroupCodeSchema = z
754
+ .object({
755
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
756
+ })
757
+ .extend({
758
+ ...SearchBlobsBaseSchema.shape,
759
+ })
760
+ .merge(PaginationOptionsSchema);
715
761
  // create branch schemas
716
762
  export const CreateBranchOptionsSchema = z.object({
717
763
  name: z.string(), // Changed from ref to match GitLab API
@@ -730,8 +776,8 @@ export const GitLabCompareResultSchema = z.object({
730
776
  .optional(),
731
777
  commits: z.array(GitLabCommitSchema),
732
778
  diffs: z.array(GitLabDiffSchema),
733
- compare_timeout: z.boolean().optional(),
734
- compare_same_ref: z.boolean().optional(),
779
+ compare_timeout: z.coerce.boolean().optional(),
780
+ compare_same_ref: z.coerce.boolean().optional(),
735
781
  });
736
782
  // Issue related schemas
737
783
  export const GitLabLabelSchema = z.object({
@@ -741,12 +787,12 @@ export const GitLabLabelSchema = z.object({
741
787
  text_color: z.string(),
742
788
  description: z.string().nullable(),
743
789
  description_html: z.string().nullable(),
744
- open_issues_count: z.number().optional(),
745
- closed_issues_count: z.number().optional(),
746
- open_merge_requests_count: z.number().optional(),
747
- subscribed: z.boolean().optional(),
748
- priority: z.number().nullable().optional(),
749
- is_project_label: z.boolean().optional(),
790
+ open_issues_count: z.coerce.number().optional(),
791
+ closed_issues_count: z.coerce.number().optional(),
792
+ open_merge_requests_count: z.coerce.number().optional(),
793
+ subscribed: z.coerce.boolean().optional(),
794
+ priority: z.coerce.number().nullable().optional(),
795
+ is_project_label: z.coerce.boolean().optional(),
750
796
  });
751
797
  export const GitLabMilestoneSchema = z.object({
752
798
  id: z.coerce.string(),
@@ -780,16 +826,16 @@ export const GitLabIssueSchema = z.object({
780
826
  .optional(),
781
827
  time_stats: z
782
828
  .object({
783
- time_estimate: z.number(),
784
- total_time_spent: z.number(),
829
+ time_estimate: z.coerce.number(),
830
+ total_time_spent: z.coerce.number(),
785
831
  human_time_estimate: z.string().nullable(),
786
832
  human_total_time_spent: z.string().nullable(),
787
833
  })
788
834
  .optional(),
789
- confidential: z.boolean().optional(),
835
+ confidential: z.coerce.boolean().optional(),
790
836
  due_date: z.string().nullable().optional(),
791
- discussion_locked: z.boolean().nullable().optional(),
792
- weight: z.number().nullable().optional(),
837
+ discussion_locked: z.coerce.boolean().nullable().optional(),
838
+ weight: z.coerce.number().nullable().optional(),
793
839
  issue_type: z.string().describe("the type of issue.").nullish(),
794
840
  });
795
841
  // NEW SCHEMA: For issue with link details (used in listing issue links)
@@ -828,8 +874,8 @@ export const GitLabMergeRequestSchema = z.object({
828
874
  title: z.string(),
829
875
  description: z.string().nullable(),
830
876
  state: z.string(),
831
- merged: z.boolean().optional(),
832
- draft: z.boolean().optional(),
877
+ merged: z.coerce.boolean().optional(),
878
+ draft: z.coerce.boolean().optional(),
833
879
  author: GitLabUserSchema,
834
880
  assignees: z.array(GitLabUserSchema).optional(),
835
881
  reviewers: z.array(GitLabUserSchema).optional(),
@@ -845,12 +891,12 @@ export const GitLabMergeRequestSchema = z.object({
845
891
  detailed_merge_status: z.string().optional(),
846
892
  merge_status: z.string().optional(),
847
893
  merge_error: z.string().nullable().optional(),
848
- work_in_progress: z.boolean().optional(),
849
- blocking_discussions_resolved: z.boolean().optional(),
850
- should_remove_source_branch: z.boolean().nullable().optional(),
851
- force_remove_source_branch: z.boolean().nullable().optional(),
852
- allow_collaboration: z.boolean().optional(),
853
- allow_maintainer_to_push: z.boolean().optional(),
894
+ work_in_progress: z.coerce.boolean().optional(),
895
+ blocking_discussions_resolved: z.coerce.boolean().optional(),
896
+ should_remove_source_branch: z.coerce.boolean().nullable().optional(),
897
+ force_remove_source_branch: z.coerce.boolean().nullable().optional(),
898
+ allow_collaboration: z.coerce.boolean().optional(),
899
+ allow_maintainer_to_push: z.coerce.boolean().optional(),
854
900
  changes_count: z.string().nullable().optional(),
855
901
  diverged_commits_count: z.coerce
856
902
  .number()
@@ -861,8 +907,8 @@ export const GitLabMergeRequestSchema = z.object({
861
907
  .boolean()
862
908
  .optional()
863
909
  .describe("Whether rebase is currently in progress for this merge request"),
864
- merge_when_pipeline_succeeds: z.boolean().optional(),
865
- squash: z.boolean().optional(),
910
+ merge_when_pipeline_succeeds: z.coerce.boolean().optional(),
911
+ squash: z.coerce.boolean().optional(),
866
912
  labels: z.array(z.string()).optional(),
867
913
  });
868
914
  export const LineRangeSchema = z
@@ -927,13 +973,13 @@ export const GitLabDiscussionNoteSchema = z
927
973
  author: GitLabUserSchema.optional(),
928
974
  created_at: z.string().optional(),
929
975
  updated_at: z.string().optional(),
930
- system: z.boolean().optional(),
976
+ system: z.coerce.boolean().optional(),
931
977
  noteable_id: z.coerce.string().optional(),
932
978
  noteable_type: z.enum(["Issue", "MergeRequest", "Snippet", "Commit", "Epic"]).optional(),
933
979
  project_id: z.coerce.string().optional(),
934
980
  noteable_iid: z.coerce.string().nullable().optional(),
935
- resolvable: z.boolean().optional(),
936
- resolved: z.boolean().optional(),
981
+ resolvable: z.coerce.boolean().optional(),
982
+ resolved: z.coerce.boolean().optional(),
937
983
  resolved_by: GitLabUserSchema.nullable().optional(),
938
984
  resolved_at: z.string().nullable().optional(),
939
985
  position: z
@@ -956,10 +1002,10 @@ export const GitLabDiscussionNoteSchema = z
956
1002
  .optional()
957
1003
  .describe("Line number in the original file (before changes). Used for deleted lines and context lines. Null for newly added lines."),
958
1004
  line_range: LineRangeSchema.nullable().optional(), // Accept any value for line_range including null
959
- width: z.number().nullable().optional(), // For image diff notes
960
- height: z.number().nullable().optional(), // For image diff notes
961
- x: z.number().nullable().optional(), // For image diff notes
962
- y: z.number().nullable().optional(), // For image diff notes
1005
+ width: z.coerce.number().nullable().optional(), // For image diff notes
1006
+ height: z.coerce.number().nullable().optional(), // For image diff notes
1007
+ x: z.coerce.number().nullable().optional(), // For image diff notes
1008
+ y: z.coerce.number().nullable().optional(), // For image diff notes
963
1009
  })
964
1010
  .passthrough() // Allow additional fields
965
1011
  .optional(),
@@ -968,12 +1014,12 @@ export const GitLabDiscussionNoteSchema = z
968
1014
  // Reusable pagination schema for GitLab API responses.
969
1015
  // See https://docs.gitlab.com/api/rest/#pagination
970
1016
  export const GitLabPaginationSchema = z.object({
971
- x_next_page: z.number().nullable().optional(),
972
- x_page: z.number().optional(),
973
- x_per_page: z.number().optional(),
974
- x_prev_page: z.number().nullable().optional(),
975
- x_total: z.number().nullable().optional(),
976
- x_total_pages: z.number().nullable().optional(),
1017
+ x_next_page: z.coerce.number().nullable().optional(),
1018
+ x_page: z.coerce.number().optional(),
1019
+ x_per_page: z.coerce.number().optional(),
1020
+ x_prev_page: z.coerce.number().nullable().optional(),
1021
+ x_total: z.coerce.number().nullable().optional(),
1022
+ x_total_pages: z.coerce.number().nullable().optional(),
977
1023
  });
978
1024
  // Base paginated response schema that can be extended.
979
1025
  // See https://docs.gitlab.com/api/rest/#pagination
@@ -982,7 +1028,7 @@ export const PaginatedResponseSchema = z.object({
982
1028
  });
983
1029
  export const GitLabDiscussionSchema = z.object({
984
1030
  id: z.coerce.string(),
985
- individual_note: z.boolean(),
1031
+ individual_note: z.coerce.boolean(),
986
1032
  notes: z.array(GitLabDiscussionNoteSchema),
987
1033
  });
988
1034
  // Create a schema for paginated discussions response
@@ -1041,7 +1087,7 @@ export const UpdateMergeRequestDiscussionNoteSchema = ProjectParamsSchema.extend
1041
1087
  discussion_id: z.coerce.string().describe("The ID of a thread"),
1042
1088
  note_id: z.coerce.string().describe("The ID of a thread note"),
1043
1089
  body: z.string().optional().describe("The content of the note or reply"),
1044
- resolved: z.boolean().optional().describe("Resolve or unresolve the note"),
1090
+ resolved: z.coerce.boolean().optional().describe("Resolve or unresolve the note"),
1045
1091
  })
1046
1092
  .refine(data => data.body !== undefined || data.resolved !== undefined, {
1047
1093
  message: "At least one of 'body' or 'resolved' must be provided",
@@ -1062,7 +1108,7 @@ export const UpdateIssueNoteSchema = ProjectParamsSchema.extend({
1062
1108
  discussion_id: z.coerce.string().describe("The ID of a thread"),
1063
1109
  note_id: z.coerce.string().describe("The ID of a thread note"),
1064
1110
  body: z.string().optional().describe("The content of the note or reply"),
1065
- resolved: z.boolean().optional().describe("Resolve or unresolve the note"),
1111
+ resolved: z.coerce.boolean().optional().describe("Resolve or unresolve the note"),
1066
1112
  })
1067
1113
  .refine(data => data.body !== undefined || data.resolved !== undefined, {
1068
1114
  message: "At least one of 'body' or 'resolved' must be provided",
@@ -1099,7 +1145,7 @@ export const CreateRepositorySchema = z.object({
1099
1145
  .enum(["private", "internal", "public"])
1100
1146
  .optional()
1101
1147
  .describe("Repository visibility level"),
1102
- initialize_with_readme: z.boolean().optional().describe("Initialize with README.md"),
1148
+ initialize_with_readme: z.coerce.boolean().optional().describe("Initialize with README.md"),
1103
1149
  });
1104
1150
  export const GetFileContentsSchema = z
1105
1151
  .object({
@@ -1151,14 +1197,15 @@ export const PushFilesSchema = ProjectParamsSchema.extend({
1151
1197
  export const CreateIssueSchema = ProjectParamsSchema.extend({
1152
1198
  title: z.string().describe("Issue title"),
1153
1199
  description: z.string().optional().describe("Issue description"),
1154
- assignee_ids: z.array(z.number()).optional().describe("Array of user IDs to assign"),
1200
+ assignee_ids: z.array(z.coerce.number()).optional().describe("Array of user IDs to assign"),
1155
1201
  labels: z.array(z.string()).optional().describe("Array of label names"),
1156
1202
  milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
1157
1203
  issue_type: z
1158
1204
  .enum(["issue", "incident", "test_case", "task"])
1159
- .describe("the type of issue. One of issue, incident, test_case or task.")
1160
- .nullish()
1161
- .default("issue"),
1205
+ .optional()
1206
+ .default("issue")
1207
+ .describe("The type of issue. One of issue, incident, test_case or task."),
1208
+ weight: z.coerce.number().optional().describe("Weight of the issue (numeric, typically hours of work)"),
1162
1209
  });
1163
1210
  const MergeRequestOptionsSchema = {
1164
1211
  title: z.string().describe("Merge request title"),
@@ -1166,14 +1213,14 @@ const MergeRequestOptionsSchema = {
1166
1213
  source_branch: z.string().describe("Branch containing changes"),
1167
1214
  target_branch: z.string().describe("Branch to merge into"),
1168
1215
  target_project_id: z.coerce.string().optional().describe("Numeric ID of the target project."),
1169
- assignee_ids: z.array(z.number()).optional().describe("The ID of the users to assign the MR to"),
1216
+ assignee_ids: z.array(z.coerce.number()).optional().describe("The ID of the users to assign the MR to"),
1170
1217
  reviewer_ids: z
1171
- .array(z.number())
1218
+ .array(z.coerce.number())
1172
1219
  .optional()
1173
1220
  .describe("The ID of the users to assign as reviewers of the MR"),
1174
1221
  labels: z.array(z.string()).optional().describe("Labels for the MR"),
1175
- draft: z.boolean().optional().describe("Create as draft merge request"),
1176
- allow_collaboration: z.boolean().optional().describe("Allow commits from upstream members"),
1222
+ draft: z.coerce.boolean().optional().describe("Create as draft merge request"),
1223
+ allow_collaboration: z.coerce.boolean().optional().describe("Allow commits from upstream members"),
1177
1224
  remove_source_branch: z
1178
1225
  .boolean()
1179
1226
  .nullable()
@@ -1215,9 +1262,9 @@ export const UpdateMergeRequestSchema = GetMergeRequestSchema.extend({
1215
1262
  title: z.string().optional().describe("The title of the merge request"),
1216
1263
  description: z.string().optional().describe("The description of the merge request"),
1217
1264
  target_branch: z.string().optional().describe("The target branch"),
1218
- assignee_ids: z.array(z.number()).optional().describe("The ID of the users to assign the MR to"),
1265
+ assignee_ids: z.array(z.coerce.number()).optional().describe("The ID of the users to assign the MR to"),
1219
1266
  reviewer_ids: z
1220
- .array(z.number())
1267
+ .array(z.coerce.number())
1221
1268
  .optional()
1222
1269
  .describe("The ID of the users to assign as reviewers of the MR"),
1223
1270
  labels: z.array(z.string()).optional().describe("Labels for the MR"),
@@ -1229,8 +1276,8 @@ export const UpdateMergeRequestSchema = GetMergeRequestSchema.extend({
1229
1276
  .boolean()
1230
1277
  .optional()
1231
1278
  .describe("Flag indicating if the source branch should be removed"),
1232
- squash: z.boolean().optional().describe("Squash commits into a single commit when merging"),
1233
- draft: z.boolean().optional().describe("Work in progress merge request"),
1279
+ squash: z.coerce.boolean().optional().describe("Squash commits into a single commit when merging"),
1280
+ draft: z.coerce.boolean().optional().describe("Work in progress merge request"),
1234
1281
  });
1235
1282
  export const MergeMergeRequestSchema = ProjectParamsSchema.extend({
1236
1283
  merge_request_iid: z.coerce.string().optional().describe("The IID of a merge request"),
@@ -1286,7 +1333,7 @@ export const GitLabApprovalRuleSchema = z.object({
1286
1333
  name: z.string(),
1287
1334
  rule_type: z.string(),
1288
1335
  eligible_approvers: z.array(GitLabApprovalUserSchema).optional(),
1289
- approvals_required: z.number(),
1336
+ approvals_required: z.coerce.number(),
1290
1337
  users: z.array(GitLabApprovalUserSchema).optional(),
1291
1338
  groups: z
1292
1339
  .array(z.object({
@@ -1298,7 +1345,7 @@ export const GitLabApprovalRuleSchema = z.object({
1298
1345
  web_url: z.string(),
1299
1346
  }))
1300
1347
  .optional(),
1301
- contains_hidden_groups: z.boolean().optional(),
1348
+ contains_hidden_groups: z.coerce.boolean().optional(),
1302
1349
  approved_by: z.array(GitLabApprovalUserSchema).optional(),
1303
1350
  source_rule: z
1304
1351
  .object({
@@ -1308,12 +1355,12 @@ export const GitLabApprovalRuleSchema = z.object({
1308
1355
  })
1309
1356
  .nullable()
1310
1357
  .optional(),
1311
- approved: z.boolean().optional(),
1358
+ approved: z.coerce.boolean().optional(),
1312
1359
  });
1313
1360
  export const GitLabMergeRequestApprovalsResponseSchema = z.object({
1314
- approved: z.boolean().optional(),
1315
- user_has_approved: z.boolean().optional(),
1316
- user_can_approve: z.boolean().optional(),
1361
+ approved: z.coerce.boolean().optional(),
1362
+ user_has_approved: z.coerce.boolean().optional(),
1363
+ user_can_approve: z.coerce.boolean().optional(),
1317
1364
  approved_by: z
1318
1365
  .array(z.object({
1319
1366
  user: GitLabApprovalUserSchema,
@@ -1321,11 +1368,11 @@ export const GitLabMergeRequestApprovalsResponseSchema = z.object({
1321
1368
  .optional(),
1322
1369
  });
1323
1370
  export const GitLabMergeRequestApprovalStateSchema = z.object({
1324
- approval_rules_overwritten: z.boolean().optional(),
1371
+ approval_rules_overwritten: z.coerce.boolean().optional(),
1325
1372
  rules: z.array(GitLabApprovalRuleSchema).optional(),
1326
- approved: z.boolean().optional(),
1327
- user_has_approved: z.boolean().optional(),
1328
- user_can_approve: z.boolean().optional(),
1373
+ approved: z.coerce.boolean().optional(),
1374
+ user_has_approved: z.coerce.boolean().optional(),
1375
+ user_can_approve: z.coerce.boolean().optional(),
1329
1376
  approved_by: z.array(GitLabApprovalUserSchema).optional(),
1330
1377
  approved_by_usernames: z.array(z.string()).optional(),
1331
1378
  source_endpoint: z.enum(["approval_state", "approvals"]).optional(),
@@ -1333,6 +1380,9 @@ export const GitLabMergeRequestApprovalStateSchema = z.object({
1333
1380
  export const GetMergeRequestApprovalStateSchema = ProjectParamsSchema.extend({
1334
1381
  merge_request_iid: z.coerce.string().describe("The IID of the merge request"),
1335
1382
  });
1383
+ export const GetMergeRequestConflictsSchema = ProjectParamsSchema.extend({
1384
+ merge_request_iid: z.coerce.string().describe("The IID of the merge request"),
1385
+ });
1336
1386
  export const GetMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
1337
1387
  view: z.enum(["inline", "parallel"]).optional().describe("Diff view type"),
1338
1388
  excluded_file_patterns: z
@@ -1341,13 +1391,29 @@ export const GetMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
1341
1391
  .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: ["^vendor/", "^test/mocks/", "\\.spec\\.ts$", "package-lock\\.json"]'),
1342
1392
  });
1343
1393
  export const ListMergeRequestDiffsSchema = GetMergeRequestSchema.extend({
1344
- page: z.number().optional().describe("Page number for pagination (default: 1)"),
1345
- per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
1394
+ page: z.coerce.number().optional().describe("Page number for pagination (default: 1)"),
1395
+ per_page: z.coerce.number().optional().describe("Number of items per page (max: 100, default: 20)"),
1346
1396
  unidiff: z
1347
1397
  .boolean()
1348
1398
  .optional()
1349
1399
  .describe("Present diffs in the unified diff format. Default is false. Introduced in GitLab 16.5."),
1350
1400
  });
1401
+ export const ListMergeRequestChangedFilesSchema = GetMergeRequestSchema.extend({
1402
+ excluded_file_patterns: z
1403
+ .array(z.string())
1404
+ .optional()
1405
+ .describe('Array of regex patterns to exclude files. Examples: ["^vendor/", "\\.pb\\.go$"]'),
1406
+ });
1407
+ export const GetMergeRequestFileDiffSchema = GetMergeRequestSchema.extend({
1408
+ file_paths: z
1409
+ .array(z.string())
1410
+ .describe("List of file paths to retrieve diffs for (e.g. ['src/api/users.ts', 'src/repo/user.go']). " +
1411
+ "Call list_merge_request_changed_files first to get the full list of changed paths."),
1412
+ unidiff: z
1413
+ .boolean()
1414
+ .optional()
1415
+ .describe("Present diff in the unified diff format. Default is false."),
1416
+ });
1351
1417
  // Merge Request Versions API operation schemas
1352
1418
  export const ListMergeRequestVersionsSchema = ProjectParamsSchema.extend({
1353
1419
  merge_request_iid: z.coerce.string().describe("The internal ID of the merge request"),
@@ -1384,7 +1450,7 @@ export const ListIssuesSchema = z
1384
1450
  .describe("Return issues assigned to the given username"),
1385
1451
  author_id: z.coerce.string().optional().describe("Return issues created by the given user ID"),
1386
1452
  author_username: z.string().optional().describe("Return issues created by the given username"),
1387
- confidential: z.boolean().optional().describe("Filter confidential or public issues"),
1453
+ confidential: z.coerce.boolean().optional().describe("Filter confidential or public issues"),
1388
1454
  created_after: z.string().optional().describe("Return issues created after the given time"),
1389
1455
  created_before: z.string().optional().describe("Return issues created before the given time"),
1390
1456
  due_date: z.string().optional().describe("Return issues that have the due date"),
@@ -1409,7 +1475,7 @@ export const ListIssuesSchema = z
1409
1475
  .describe("Return issues with a specific state"),
1410
1476
  updated_after: z.string().optional().describe("Return issues updated after the given time"),
1411
1477
  updated_before: z.string().optional().describe("Return issues updated before the given time"),
1412
- with_labels_details: z.boolean().optional().describe("Return more details for each label"),
1478
+ with_labels_details: z.coerce.boolean().optional().describe("Return more details for each label"),
1413
1479
  })
1414
1480
  .merge(PaginationOptionsSchema);
1415
1481
  // Merge Requests API operation schemas
@@ -1422,27 +1488,27 @@ export const ListMergeRequestsSchema = z
1422
1488
  assignee_id: z.coerce
1423
1489
  .string()
1424
1490
  .optional()
1425
- .describe("Return issues assigned to the given user ID. user id or none or any"),
1491
+ .describe("Return MRs assigned to the given user ID (integer), 'none', or 'any'. Mutually exclusive with assignee_username."),
1426
1492
  assignee_username: z
1427
1493
  .string()
1428
1494
  .optional()
1429
- .describe("Returns merge requests assigned to the given username"),
1495
+ .describe("Returns merge requests assigned to the given username. Mutually exclusive with assignee_id."),
1430
1496
  author_id: z.coerce
1431
1497
  .string()
1432
1498
  .optional()
1433
- .describe("Returns merge requests created by the given user ID"),
1499
+ .describe("Returns merge requests created by the given user ID (integer). Mutually exclusive with author_username."),
1434
1500
  author_username: z
1435
1501
  .string()
1436
1502
  .optional()
1437
- .describe("Returns merge requests created by the given username"),
1503
+ .describe("Returns merge requests created by the given username. Mutually exclusive with author_id."),
1438
1504
  reviewer_id: z.coerce
1439
1505
  .string()
1440
1506
  .optional()
1441
- .describe("Returns merge requests which have the user as a reviewer. user id or none or any"),
1507
+ .describe("Returns merge requests which have the user as a reviewer. Must be an integer, 'none', or 'any'. Mutually exclusive with reviewer_username."),
1442
1508
  reviewer_username: z
1443
1509
  .string()
1444
1510
  .optional()
1445
- .describe("Returns merge requests which have the user as a reviewer"),
1511
+ .describe("Returns merge requests which have the user as a reviewer by username. Mutually exclusive with reviewer_id."),
1446
1512
  created_after: z
1447
1513
  .string()
1448
1514
  .optional()
@@ -1497,7 +1563,7 @@ export const ListMergeRequestsSchema = z
1497
1563
  .enum(["yes", "no"])
1498
1564
  .optional()
1499
1565
  .describe("Filter merge requests against their wip status"),
1500
- with_labels_details: z.boolean().optional().describe("Return more details for each label"),
1566
+ with_labels_details: z.coerce.boolean().optional().describe("Return more details for each label"),
1501
1567
  })
1502
1568
  .merge(PaginationOptionsSchema);
1503
1569
  export const GetIssueSchema = z.object({
@@ -1509,17 +1575,18 @@ export const UpdateIssueSchema = z.object({
1509
1575
  issue_iid: z.coerce.string().describe("The internal ID of the project issue"),
1510
1576
  title: z.string().optional().describe("The title of the issue"),
1511
1577
  description: z.string().optional().describe("The description of the issue"),
1512
- assignee_ids: z.array(z.number()).optional().describe("Array of user IDs to assign issue to"),
1513
- confidential: z.boolean().optional().describe("Set the issue to be confidential"),
1514
- discussion_locked: z.boolean().optional().describe("Flag to lock discussions"),
1578
+ assignee_ids: z.array(z.coerce.number()).optional().describe("Array of user IDs to assign issue to"),
1579
+ confidential: z.coerce.boolean().optional().describe("Set the issue to be confidential"),
1580
+ discussion_locked: z.coerce.boolean().optional().describe("Flag to lock discussions"),
1515
1581
  due_date: z.string().optional().describe("Date the issue is due (YYYY-MM-DD)"),
1516
1582
  labels: z.array(z.string()).optional().describe("Array of label names"),
1517
1583
  milestone_id: z.coerce.string().optional().describe("Milestone ID to assign"),
1518
1584
  state_event: z.enum(["close", "reopen"]).optional().describe("Update issue state (close/reopen)"),
1519
- weight: z.number().optional().describe("Weight of the issue (0-9)"),
1585
+ weight: z.coerce.number().optional().describe("Weight of the issue (numeric, typically hours of work)"),
1520
1586
  issue_type: z
1521
1587
  .enum(["issue", "incident", "test_case", "task"])
1522
- .describe("the type of issue. One of issue, incident, test_case or task."),
1588
+ .optional()
1589
+ .describe("The type of issue. One of issue, incident, test_case or task."),
1523
1590
  });
1524
1591
  export const DeleteIssueSchema = z.object({
1525
1592
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1559,7 +1626,7 @@ export const DeleteIssueLinkSchema = z.object({
1559
1626
  export const ListNamespacesSchema = z
1560
1627
  .object({
1561
1628
  search: z.string().optional().describe("Search term for namespaces"),
1562
- owned: z.boolean().optional().describe("Filter for namespaces owned by current user"),
1629
+ owned: z.coerce.boolean().optional().describe("Filter for namespaces owned by current user"),
1563
1630
  })
1564
1631
  .merge(PaginationOptionsSchema);
1565
1632
  export const GetNamespaceSchema = z.object({
@@ -1575,14 +1642,14 @@ export const GetProjectSchema = z.object({
1575
1642
  export const ListProjectsSchema = z
1576
1643
  .object({
1577
1644
  search: z.string().optional().describe("Search term for projects"),
1578
- search_namespaces: z.boolean().optional().describe("Needs to be true if search is full path"),
1579
- owned: z.boolean().optional().describe("Filter for projects owned by current user"),
1645
+ search_namespaces: z.coerce.boolean().optional().describe("Needs to be true if search is full path"),
1646
+ owned: z.coerce.boolean().optional().describe("Filter for projects owned by current user"),
1580
1647
  membership: z
1581
1648
  .boolean()
1582
1649
  .optional()
1583
1650
  .describe("Filter for projects where current user is a member"),
1584
- simple: z.boolean().optional().describe("Return only limited fields"),
1585
- archived: z.boolean().optional().describe("Filter for archived projects"),
1651
+ simple: z.coerce.boolean().optional().describe("Return only limited fields"),
1652
+ archived: z.coerce.boolean().optional().describe("Filter for archived projects"),
1586
1653
  visibility: z
1587
1654
  .enum(["public", "internal", "private"])
1588
1655
  .optional()
@@ -1603,7 +1670,7 @@ export const ListProjectsSchema = z
1603
1670
  .boolean()
1604
1671
  .optional()
1605
1672
  .describe("Filter projects with merge requests feature enabled"),
1606
- min_access_level: z.number().optional().describe("Filter by minimum access level"),
1673
+ min_access_level: z.coerce.number().optional().describe("Filter by minimum access level"),
1607
1674
  })
1608
1675
  .merge(PaginationOptionsSchema);
1609
1676
  // Label operation schemas
@@ -1613,13 +1680,13 @@ export const ListLabelsSchema = z.object({
1613
1680
  .boolean()
1614
1681
  .optional()
1615
1682
  .describe("Whether or not to include issue and merge request counts"),
1616
- include_ancestor_groups: z.boolean().optional().describe("Include ancestor groups"),
1683
+ include_ancestor_groups: z.coerce.boolean().optional().describe("Include ancestor groups"),
1617
1684
  search: z.string().optional().describe("Keyword to filter labels by"),
1618
1685
  });
1619
1686
  export const GetLabelSchema = z.object({
1620
1687
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1621
1688
  label_id: z.coerce.string().describe("The ID or title of a project's label"),
1622
- include_ancestor_groups: z.boolean().optional().describe("Include ancestor groups"),
1689
+ include_ancestor_groups: z.coerce.boolean().optional().describe("Include ancestor groups"),
1623
1690
  });
1624
1691
  export const CreateLabelSchema = z.object({
1625
1692
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1628,7 +1695,7 @@ export const CreateLabelSchema = z.object({
1628
1695
  .string()
1629
1696
  .describe("The color of the label given in 6-digit hex notation with leading '#' sign"),
1630
1697
  description: z.string().optional().describe("The description of the label"),
1631
- priority: z.number().nullable().optional().describe("The priority of the label"),
1698
+ priority: z.coerce.number().nullable().optional().describe("The priority of the label"),
1632
1699
  });
1633
1700
  export const UpdateLabelSchema = z.object({
1634
1701
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1639,7 +1706,7 @@ export const UpdateLabelSchema = z.object({
1639
1706
  .optional()
1640
1707
  .describe("The color of the label given in 6-digit hex notation with leading '#' sign"),
1641
1708
  description: z.string().optional().describe("The new description of the label"),
1642
- priority: z.number().nullable().optional().describe("The new priority of the label"),
1709
+ priority: z.coerce.number().nullable().optional().describe("The new priority of the label"),
1643
1710
  });
1644
1711
  export const DeleteLabelSchema = z.object({
1645
1712
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1649,14 +1716,14 @@ export const DeleteLabelSchema = z.object({
1649
1716
  export const ListGroupProjectsSchema = z
1650
1717
  .object({
1651
1718
  group_id: z.coerce.string().describe("Group ID or path"),
1652
- include_subgroups: z.boolean().optional().describe("Include projects from subgroups"),
1719
+ include_subgroups: z.coerce.boolean().optional().describe("Include projects from subgroups"),
1653
1720
  search: z.string().optional().describe("Search term to filter projects"),
1654
1721
  order_by: z
1655
1722
  .enum(["name", "path", "created_at", "updated_at", "last_activity_at"])
1656
1723
  .optional()
1657
1724
  .describe("Field to sort by"),
1658
1725
  sort: z.enum(["asc", "desc"]).optional().describe("Sort direction"),
1659
- archived: z.boolean().optional().describe("Filter for archived projects"),
1726
+ archived: z.coerce.boolean().optional().describe("Filter for archived projects"),
1660
1727
  visibility: z
1661
1728
  .enum(["public", "internal", "private"])
1662
1729
  .optional()
@@ -1669,24 +1736,24 @@ export const ListGroupProjectsSchema = z
1669
1736
  .boolean()
1670
1737
  .optional()
1671
1738
  .describe("Filter projects with merge requests feature enabled"),
1672
- min_access_level: z.number().optional().describe("Filter by minimum access level"),
1739
+ min_access_level: z.coerce.number().optional().describe("Filter by minimum access level"),
1673
1740
  with_programming_language: z.string().optional().describe("Filter by programming language"),
1674
- starred: z.boolean().optional().describe("Filter by starred projects"),
1675
- statistics: z.boolean().optional().describe("Include project statistics"),
1676
- with_custom_attributes: z.boolean().optional().describe("Include custom attributes"),
1677
- with_security_reports: z.boolean().optional().describe("Include security reports"),
1741
+ starred: z.coerce.boolean().optional().describe("Filter by starred projects"),
1742
+ statistics: z.coerce.boolean().optional().describe("Include project statistics"),
1743
+ with_custom_attributes: z.coerce.boolean().optional().describe("Include custom attributes"),
1744
+ with_security_reports: z.coerce.boolean().optional().describe("Include security reports"),
1678
1745
  })
1679
1746
  .merge(PaginationOptionsSchema);
1680
1747
  // Add wiki operation schemas
1681
1748
  export const ListWikiPagesSchema = z
1682
1749
  .object({
1683
1750
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1684
- with_content: z.boolean().optional().describe("Include content of the wiki pages"),
1751
+ with_content: z.coerce.boolean().optional().describe("Include content of the wiki pages"),
1685
1752
  })
1686
1753
  .merge(PaginationOptionsSchema);
1687
1754
  export const GetWikiPageSchema = z.object({
1688
1755
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1689
- slug: z.string().describe("URL-encoded slug of the wiki page"),
1756
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1690
1757
  });
1691
1758
  export const CreateWikiPageSchema = z.object({
1692
1759
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
@@ -1696,14 +1763,14 @@ export const CreateWikiPageSchema = z.object({
1696
1763
  });
1697
1764
  export const UpdateWikiPageSchema = z.object({
1698
1765
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1699
- slug: z.string().describe("URL-encoded slug of the wiki page"),
1766
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1700
1767
  title: z.string().optional().describe("New title of the wiki page"),
1701
1768
  content: z.string().optional().describe("New content of the wiki page"),
1702
1769
  format: z.string().optional().describe("Content format, e.g., markdown, rdoc"),
1703
1770
  });
1704
1771
  export const DeleteWikiPageSchema = z.object({
1705
1772
  project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
1706
- slug: z.string().describe("URL-encoded slug of the wiki page"),
1773
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1707
1774
  });
1708
1775
  // Define wiki response schemas
1709
1776
  export const GitLabWikiPageSchema = z.object({
@@ -1714,6 +1781,34 @@ export const GitLabWikiPageSchema = z.object({
1714
1781
  created_at: z.string().optional(),
1715
1782
  updated_at: z.string().optional(),
1716
1783
  });
1784
+ // Group Wiki operation schemas
1785
+ export const ListGroupWikiPagesSchema = z
1786
+ .object({
1787
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1788
+ with_content: z.boolean().optional().describe("Include content of the wiki pages"),
1789
+ })
1790
+ .merge(PaginationOptionsSchema);
1791
+ export const GetGroupWikiPageSchema = z.object({
1792
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1793
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1794
+ });
1795
+ export const CreateGroupWikiPageSchema = z.object({
1796
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1797
+ title: z.string().describe("Title of the wiki page"),
1798
+ content: z.string().describe("Content of the wiki page"),
1799
+ format: z.string().optional().describe("Content format, e.g., markdown, rdoc"),
1800
+ });
1801
+ export const UpdateGroupWikiPageSchema = z.object({
1802
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1803
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1804
+ title: z.string().optional().describe("New title of the wiki page"),
1805
+ content: z.string().optional().describe("New content of the wiki page"),
1806
+ format: z.string().optional().describe("Content format, e.g., markdown, rdoc"),
1807
+ });
1808
+ export const DeleteGroupWikiPageSchema = z.object({
1809
+ group_id: z.coerce.string().describe("Group ID or URL-encoded path"),
1810
+ slug: z.string().describe("Slug of the wiki page (will be URL-encoded internally)"),
1811
+ });
1717
1812
  // Merge Request Thread position schema - used for diff notes
1718
1813
  // Extremely flexible position schema for API responses - accepts any structure
1719
1814
  // Strict position schema for creating draft notes and merge request threads
@@ -1839,7 +1934,7 @@ export const GitLabDraftNoteSchema = z
1839
1934
  updated_at: z.string().optional(),
1840
1935
  discussion_id: z.string().nullable().optional(),
1841
1936
  position: z.record(z.unknown()).nullable().optional(),
1842
- resolve_discussion: z.boolean().optional(),
1937
+ resolve_discussion: z.coerce.boolean().optional(),
1843
1938
  })
1844
1939
  .transform(data => ({
1845
1940
  // Normalize the response to always have consistent field names
@@ -1910,12 +2005,12 @@ export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
1910
2005
  export const ResolveMergeRequestThreadSchema = ProjectParamsSchema.extend({
1911
2006
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
1912
2007
  discussion_id: z.coerce.string().describe("The ID of a thread"),
1913
- resolved: z.boolean().describe("Whether to resolve the thread"),
2008
+ resolved: z.coerce.boolean().describe("Whether to resolve the thread"),
1914
2009
  });
1915
2010
  // Milestone related schemas
1916
2011
  // Schema for listing project milestones
1917
2012
  export const ListProjectMilestonesSchema = ProjectParamsSchema.extend({
1918
- iids: z.array(z.number()).optional().describe("Return only the milestones having the given iid"),
2013
+ iids: z.array(z.coerce.number()).optional().describe("Return only the milestones having the given iid"),
1919
2014
  state: z
1920
2015
  .enum(["active", "closed"])
1921
2016
  .optional()
@@ -1928,7 +2023,7 @@ export const ListProjectMilestonesSchema = ProjectParamsSchema.extend({
1928
2023
  .string()
1929
2024
  .optional()
1930
2025
  .describe("Return only milestones with a title or description matching the provided string"),
1931
- include_ancestors: z.boolean().optional().describe("Include ancestor groups"),
2026
+ include_ancestors: z.coerce.boolean().optional().describe("Include ancestor groups"),
1932
2027
  updated_before: z
1933
2028
  .string()
1934
2029
  .optional()
@@ -1987,21 +2082,21 @@ export const ListCommitsSchema = z.object({
1987
2082
  .describe("Only commits before or on this date are returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ"),
1988
2083
  path: z.string().optional().describe("The file path"),
1989
2084
  author: z.string().optional().describe("Search commits by commit author"),
1990
- all: z.boolean().optional().describe("Retrieve every commit from the repository"),
1991
- with_stats: z.boolean().optional().describe("Stats about each commit are added to the response"),
2085
+ all: z.coerce.boolean().optional().describe("Retrieve every commit from the repository"),
2086
+ with_stats: z.coerce.boolean().optional().describe("Stats about each commit are added to the response"),
1992
2087
  first_parent: z
1993
2088
  .boolean()
1994
2089
  .optional()
1995
2090
  .describe("Follow only the first parent commit upon seeing a merge commit"),
1996
2091
  order: z.enum(["default", "topo"]).optional().describe("List commits in order"),
1997
- trailers: z.boolean().optional().describe("Parse and include Git trailers for every commit"),
1998
- page: z.number().optional().describe("Page number for pagination (default: 1)"),
1999
- per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
2092
+ trailers: z.coerce.boolean().optional().describe("Parse and include Git trailers for every commit"),
2093
+ page: z.coerce.number().optional().describe("Page number for pagination (default: 1)"),
2094
+ per_page: z.coerce.number().optional().describe("Number of items per page (max: 100, default: 20)"),
2000
2095
  });
2001
2096
  export const GetCommitSchema = z.object({
2002
2097
  project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
2003
2098
  sha: z.string().describe("The commit hash or name of a repository branch or tag"),
2004
- stats: z.boolean().optional().describe("Include commit stats"),
2099
+ stats: z.coerce.boolean().optional().describe("Include commit stats"),
2005
2100
  });
2006
2101
  export const GetCommitDiffSchema = z.object({
2007
2102
  project_id: z.coerce.string().describe("Project ID or complete URL-encoded path to project"),
@@ -2040,31 +2135,31 @@ export const MyIssuesSchema = z.object({
2040
2135
  .string()
2041
2136
  .optional()
2042
2137
  .describe("Return issues updated before the given time (ISO 8601)"),
2043
- per_page: z.number().optional().describe("Number of items per page (default: 20, max: 100)"),
2044
- page: z.number().optional().describe("Page number for pagination (default: 1)"),
2138
+ per_page: z.coerce.number().optional().describe("Number of items per page (default: 20, max: 100)"),
2139
+ page: z.coerce.number().optional().describe("Page number for pagination (default: 1)"),
2045
2140
  });
2046
2141
  // Schema for listing project members
2047
2142
  export const ListProjectMembersSchema = z.object({
2048
2143
  project_id: z.string().describe("Project ID or URL-encoded path"),
2049
2144
  query: z.string().optional().describe("Search for members by name or username"),
2050
- user_ids: z.array(z.number()).optional().describe("Filter by user IDs"),
2051
- skip_users: z.array(z.number()).optional().describe("User IDs to exclude"),
2145
+ user_ids: z.array(z.coerce.number()).optional().describe("Filter by user IDs"),
2146
+ skip_users: z.array(z.coerce.number()).optional().describe("User IDs to exclude"),
2052
2147
  include_inheritance: z
2053
2148
  .boolean()
2054
2149
  .optional()
2055
2150
  .describe("Include inherited members. Defaults to false."),
2056
- per_page: z.number().optional().describe("Number of items per page (default: 20, max: 100)"),
2057
- page: z.number().optional().describe("Page number for pagination (default: 1)"),
2151
+ per_page: z.coerce.number().optional().describe("Number of items per page (default: 20, max: 100)"),
2152
+ page: z.coerce.number().optional().describe("Page number for pagination (default: 1)"),
2058
2153
  });
2059
2154
  // Schema for GitLab project member
2060
2155
  export const GitLabProjectMemberSchema = z.object({
2061
- id: z.number(),
2156
+ id: z.coerce.number(),
2062
2157
  username: z.string(),
2063
2158
  name: z.string(),
2064
2159
  state: z.string(),
2065
2160
  avatar_url: z.string().nullable(),
2066
2161
  web_url: z.string(),
2067
- access_level: z.number(),
2162
+ access_level: z.coerce.number(),
2068
2163
  access_level_description: z.string().optional(),
2069
2164
  created_at: z.string(),
2070
2165
  expires_at: z.string().nullable().optional(),
@@ -2072,7 +2167,7 @@ export const GitLabProjectMemberSchema = z.object({
2072
2167
  });
2073
2168
  // Markdown upload schemas
2074
2169
  export const GitLabMarkdownUploadSchema = z.object({
2075
- id: z.number(),
2170
+ id: z.coerce.number(),
2076
2171
  alt: z.string(),
2077
2172
  url: z.string(),
2078
2173
  full_path: z.string(),
@@ -2094,11 +2189,11 @@ export const DownloadAttachmentSchema = z.object({
2094
2189
  export const GroupIteration = z.object({
2095
2190
  id: z.coerce.string(),
2096
2191
  iid: z.coerce.string(),
2097
- sequence: z.number(),
2192
+ sequence: z.coerce.number(),
2098
2193
  group_id: z.coerce.string(),
2099
2194
  title: z.string().optional().nullable(),
2100
2195
  description: z.string().optional().nullable(),
2101
- state: z.number(),
2196
+ state: z.coerce.number(),
2102
2197
  created_at: z.string(),
2103
2198
  updated_at: z.string(),
2104
2199
  due_date: z.string().optional().nullable(),
@@ -2160,7 +2255,7 @@ export const GitLabEventSchema = z
2160
2255
  created_at: z.string(),
2161
2256
  author: GitLabEventAuthorSchema,
2162
2257
  author_username: z.string(),
2163
- imported: z.boolean(),
2258
+ imported: z.coerce.boolean(),
2164
2259
  imported_from: z.string(),
2165
2260
  })
2166
2261
  .passthrough(); // Allow additional fields
@@ -2187,8 +2282,8 @@ export const ListEventsSchema = z.object({
2187
2282
  .enum(["asc", "desc"])
2188
2283
  .optional()
2189
2284
  .describe("Direction to sort the results by creation date. Default: desc"),
2190
- page: z.number().optional().describe("Returns the specified results page. Default: 1"),
2191
- per_page: z.number().optional().describe("Number of results per page. Default: 20"),
2285
+ page: z.coerce.number().optional().describe("Returns the specified results page. Default: 1"),
2286
+ per_page: z.coerce.number().optional().describe("Number of results per page. Default: 20"),
2192
2287
  });
2193
2288
  // Get project events schema
2194
2289
  export const GetProjectEventsSchema = z.object({
@@ -2213,17 +2308,17 @@ export const GetProjectEventsSchema = z.object({
2213
2308
  .enum(["asc", "desc"])
2214
2309
  .optional()
2215
2310
  .describe("Direction to sort the results by creation date. Default: desc"),
2216
- page: z.number().optional().describe("Returns the specified results page. Default: 1"),
2217
- per_page: z.number().optional().describe("Number of results per page. Default: 20"),
2311
+ page: z.coerce.number().optional().describe("Returns the specified results page. Default: 1"),
2312
+ per_page: z.coerce.number().optional().describe("Number of results per page. Default: 20"),
2218
2313
  });
2219
2314
  // Merge Request Versions schemas - Response schemas based on GitLab API documentation
2220
2315
  export const GitLabMergeRequestVersionSchema = z.object({
2221
- id: z.number(),
2316
+ id: z.coerce.number(),
2222
2317
  head_commit_sha: z.string(),
2223
2318
  base_commit_sha: z.string(),
2224
2319
  start_commit_sha: z.string(),
2225
2320
  created_at: z.string(),
2226
- merge_request_id: z.number(),
2321
+ merge_request_id: z.coerce.number(),
2227
2322
  state: z.string(),
2228
2323
  real_size: z.string(),
2229
2324
  patch_id_sha: z.string(),
@@ -2239,7 +2334,7 @@ export const ExecuteGraphQLSchema = z.object({
2239
2334
  });
2240
2335
  // Release schemas
2241
2336
  export const GitLabReleaseAssetLinkSchema = z.object({
2242
- id: z.number().optional(),
2337
+ id: z.coerce.number().optional(),
2243
2338
  name: z.string(),
2244
2339
  url: z.string(),
2245
2340
  direct_asset_path: z.string().optional(),
@@ -2250,7 +2345,7 @@ export const GitLabReleaseAssetSourceSchema = z.object({
2250
2345
  url: z.string(),
2251
2346
  });
2252
2347
  export const GitLabReleaseAssetsSchema = z.object({
2253
- count: z.number().optional(),
2348
+ count: z.coerce.number().optional(),
2254
2349
  sources: z.array(GitLabReleaseAssetSourceSchema).optional(),
2255
2350
  links: z.array(GitLabReleaseAssetLinkSchema).optional(),
2256
2351
  evidence_file_path: z.string().optional(),
@@ -2269,7 +2364,7 @@ export const GitLabReleaseSchema = z.object({
2269
2364
  released_at: z.string().nullable().optional(),
2270
2365
  author: z
2271
2366
  .object({
2272
- id: z.number(),
2367
+ id: z.coerce.number(),
2273
2368
  name: z.string(),
2274
2369
  username: z.string(),
2275
2370
  state: z.string(),
@@ -2309,8 +2404,8 @@ export const GitLabReleaseSchema = z.object({
2309
2404
  self: z.string().optional(),
2310
2405
  })
2311
2406
  .optional(),
2312
- upcoming_release: z.boolean().optional(),
2313
- historical_release: z.boolean().optional(),
2407
+ upcoming_release: z.coerce.boolean().optional(),
2408
+ historical_release: z.coerce.boolean().optional(),
2314
2409
  });
2315
2410
  export const ListReleasesSchema = z
2316
2411
  .object({
@@ -2424,7 +2519,7 @@ export const GitLabArtifactEntrySchema = z.object({
2424
2519
  name: z.string(),
2425
2520
  path: z.string(),
2426
2521
  type: z.enum(["file", "directory"]),
2427
- size: z.number().optional(),
2522
+ size: z.coerce.number().optional(),
2428
2523
  mode: z.string().optional(),
2429
2524
  });
2430
2525
  export const DownloadJobArtifactsSchema = z.object({
@@ -2449,6 +2544,170 @@ export const DownloadReleaseAssetSchema = z.object({
2449
2544
  .string()
2450
2545
  .describe("Path to the release asset file as specified when creating or updating its link"),
2451
2546
  });
2547
+ // --- Work item schemas (GraphQL-based) ---
2548
+ // Case-insensitive work item type enum (accepts "ISSUE", "Issue", "issue")
2549
+ const workItemTypeEnum = z.string().transform(v => v.toLowerCase()).pipe(z.enum(["issue", "task", "incident", "test_case", "epic", "key_result", "objective", "requirement", "ticket"]));
2550
+ // Common params for work item tools
2551
+ const WorkItemParamsSchema = z.object({
2552
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2553
+ iid: z.coerce.number().describe("The internal ID (IID) of the work item"),
2554
+ });
2555
+ export const GetWorkItemSchema = WorkItemParamsSchema;
2556
+ export const ListWorkItemsSchema = z.object({
2557
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2558
+ types: z
2559
+ .array(workItemTypeEnum)
2560
+ .optional()
2561
+ .describe("Filter by work item types. If not set, returns all types."),
2562
+ state: z
2563
+ .enum(["opened", "closed"])
2564
+ .optional()
2565
+ .describe("Filter by state"),
2566
+ search: z
2567
+ .string()
2568
+ .optional()
2569
+ .describe("Search in title and description"),
2570
+ assignee_usernames: z
2571
+ .array(z.string())
2572
+ .optional()
2573
+ .describe("Filter by assignee usernames"),
2574
+ label_names: z
2575
+ .array(z.string())
2576
+ .optional()
2577
+ .describe("Filter by label names"),
2578
+ first: z
2579
+ .coerce.number()
2580
+ .optional()
2581
+ .default(20)
2582
+ .describe("Number of items to return (max 100). Default 20."),
2583
+ after: z
2584
+ .string()
2585
+ .optional()
2586
+ .describe("Cursor for pagination (from previous response's endCursor)"),
2587
+ });
2588
+ export const CreateWorkItemSchema = z.object({
2589
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2590
+ title: z.string().describe("Title of the work item"),
2591
+ type: workItemTypeEnum
2592
+ .optional()
2593
+ .default("issue")
2594
+ .describe("Type of work item to create. Defaults to 'issue'."),
2595
+ description: z.string().optional().describe("Description of the work item (Markdown supported)"),
2596
+ labels: z.array(z.string()).optional().describe("Array of label names to assign"),
2597
+ assignee_usernames: z.array(z.string()).optional().describe("Array of usernames to assign"),
2598
+ parent_iid: z.coerce.number().optional().describe("IID of the parent work item to set hierarchy"),
2599
+ weight: z.coerce.number().optional().describe("Weight of the work item"),
2600
+ health_status: z.enum(["onTrack", "needsAttention", "atRisk"]).optional().describe("Set health status"),
2601
+ start_date: z.string().optional().describe("Start date in YYYY-MM-DD format"),
2602
+ due_date: z.string().optional().describe("Due date in YYYY-MM-DD format"),
2603
+ milestone_id: z.string().optional().describe("Milestone ID (GitLab global ID format, e.g. 'gid://gitlab/Milestone/123', or numeric ID)"),
2604
+ iteration_id: z.string().optional().describe("Iteration ID (e.g. 'gid://gitlab/Iteration/123' or numeric ID). Use list_group_iterations to find available iterations."),
2605
+ confidential: z.coerce.boolean().optional().describe("Set confidentiality"),
2606
+ });
2607
+ export const UpdateWorkItemSchema = WorkItemParamsSchema.extend({
2608
+ title: z.string().optional().describe("New title"),
2609
+ description: z.string().optional().describe("New description (Markdown supported)"),
2610
+ add_labels: z.array(z.string()).optional().describe("Label names to add"),
2611
+ remove_labels: z.array(z.string()).optional().describe("Label names to remove"),
2612
+ assignee_usernames: z.array(z.string()).optional().describe("Set assignees by username (replaces existing)"),
2613
+ state_event: z.enum(["close", "reopen"]).optional().describe("Close or reopen the work item"),
2614
+ weight: z.coerce.number().optional().describe("Set weight (issues, tasks, epics only)"),
2615
+ status: z.string().optional().describe("Set status by ID. Use list_work_item_statuses to get available status IDs."),
2616
+ parent_iid: z.coerce.number().optional().describe("Set parent work item by IID. Use with parent_project_id if parent is in a different project."),
2617
+ parent_project_id: z.coerce.string().optional().describe("Project ID or path of the parent work item (defaults to same project as the work item)"),
2618
+ remove_parent: z.coerce.boolean().optional().describe("Set to true to remove the parent from hierarchy"),
2619
+ children_to_add: z.array(z.object({
2620
+ project_id: z.coerce.string().describe("Project ID or path of the child work item"),
2621
+ iid: z.coerce.number().describe("IID of the child work item"),
2622
+ })).optional().describe("Array of children to add to this work item's hierarchy"),
2623
+ children_to_remove: z.array(z.object({
2624
+ project_id: z.coerce.string().describe("Project ID or path of the child work item"),
2625
+ iid: z.coerce.number().describe("IID of the child work item"),
2626
+ })).optional().describe("Array of children to remove from this work item's hierarchy"),
2627
+ health_status: z.enum(["onTrack", "needsAttention", "atRisk"]).optional().describe("Set health status on issues and epics"),
2628
+ start_date: z.string().optional().describe("Start date in YYYY-MM-DD format"),
2629
+ due_date: z.string().optional().describe("Due date in YYYY-MM-DD format"),
2630
+ milestone_id: z.string().optional().describe("Milestone ID (GitLab global ID format, e.g. 'gid://gitlab/Milestone/123', or numeric ID)"),
2631
+ iteration_id: z.string().optional().describe("Iteration ID (e.g. 'gid://gitlab/Iteration/123' or numeric ID). Use list_group_iterations to find available iterations."),
2632
+ confidential: z.coerce.boolean().optional().describe("Set confidentiality"),
2633
+ linked_items_to_add: z.array(z.object({
2634
+ project_id: z.coerce.string().describe("Project ID or path of the work item to link"),
2635
+ iid: z.coerce.number().describe("IID of the work item to link"),
2636
+ link_type: z.enum(["RELATED", "BLOCKED_BY", "BLOCKS"]).optional().default("RELATED").describe("Link type: RELATED, BLOCKED_BY, or BLOCKS. Defaults to RELATED."),
2637
+ })).optional().describe("Work items to link"),
2638
+ linked_items_to_remove: z.array(z.object({
2639
+ project_id: z.coerce.string().describe("Project ID or path of the linked work item to remove"),
2640
+ iid: z.coerce.number().describe("IID of the linked work item to remove"),
2641
+ })).optional().describe("Linked work items to remove"),
2642
+ custom_fields: z.array(z.object({
2643
+ custom_field_id: z.string().describe("Custom field ID (e.g. 'gid://gitlab/IssuablesCustomField/123' or numeric ID)"),
2644
+ text_value: z.string().optional().describe("Text value (for text fields)"),
2645
+ number_value: z.coerce.number().optional().describe("Number value (for number fields)"),
2646
+ selected_option_ids: z.array(z.string()).optional().describe("Selected option IDs (for select fields)"),
2647
+ date_value: z.string().optional().describe("Date value in YYYY-MM-DD format (for date fields)"),
2648
+ })).optional().describe("Custom field values to set"),
2649
+ severity: z
2650
+ .enum(["UNKNOWN", "LOW", "MEDIUM", "HIGH", "CRITICAL"])
2651
+ .optional()
2652
+ .describe("Incident only: set severity level"),
2653
+ escalation_status: z
2654
+ .enum(["TRIGGERED", "ACKNOWLEDGED", "RESOLVED", "IGNORED"])
2655
+ .optional()
2656
+ .describe("Incident only: set escalation status"),
2657
+ });
2658
+ export const ConvertWorkItemTypeSchema = z.object({
2659
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2660
+ iid: z.coerce.number().describe("The internal ID of the work item"),
2661
+ new_type: workItemTypeEnum.describe("The target work item type to convert to"),
2662
+ });
2663
+ export const ListWorkItemStatusesSchema = z.object({
2664
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2665
+ work_item_type: workItemTypeEnum
2666
+ .optional()
2667
+ .default("issue")
2668
+ .describe("The work item type to list available statuses for. Defaults to 'issue'."),
2669
+ });
2670
+ export const ListWorkItemNotesSchema = z.object({
2671
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2672
+ iid: z.coerce.number().describe("The internal ID of the work item"),
2673
+ page_size: z.coerce.number().optional().default(20).describe("Number of discussions to return (default 20)"),
2674
+ after: z.string().optional().describe("Cursor for pagination"),
2675
+ sort: z.enum(["CREATED_ASC", "CREATED_DESC"]).optional().default("CREATED_ASC").describe("Sort order for discussions"),
2676
+ });
2677
+ export const CreateWorkItemNoteSchema = z.object({
2678
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2679
+ iid: z.coerce.number().describe("The internal ID of the work item"),
2680
+ body: z.string().describe("Note body (Markdown supported)"),
2681
+ internal: z.coerce.boolean().optional().default(false).describe("Create as internal/confidential note (only visible to project members)"),
2682
+ discussion_id: z.string().optional().describe("Discussion ID to reply to (for threaded replies). If omitted, creates a new top-level note."),
2683
+ });
2684
+ export const MoveWorkItemSchema = z.object({
2685
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path of the source project"),
2686
+ iid: z.coerce.number().describe("The internal ID of the work item to move"),
2687
+ target_project_id: z.coerce.string().describe("Project ID or URL-encoded path of the target project"),
2688
+ });
2689
+ export const ListCustomFieldDefinitionsSchema = z.object({
2690
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2691
+ work_item_type: workItemTypeEnum
2692
+ .optional()
2693
+ .default("issue")
2694
+ .describe("The work item type to list custom field definitions for. Defaults to 'issue'."),
2695
+ });
2696
+ // --- Incident Timeline Event schemas ---
2697
+ export const GetTimelineEventsSchema = z.object({
2698
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2699
+ incident_iid: z.coerce.number().describe("The internal ID (IID) of the incident"),
2700
+ });
2701
+ export const CreateTimelineEventSchema = z.object({
2702
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2703
+ incident_iid: z.coerce.number().describe("The internal ID (IID) of the incident"),
2704
+ note: z.string().describe("Description of the timeline event (Markdown supported)"),
2705
+ occurred_at: z.string().describe("When the event occurred in ISO 8601 format (e.g. '2026-03-15T09:00:00.000Z')"),
2706
+ tag_names: z
2707
+ .array(z.enum(["Start time", "End time", "Impact detected", "Response initiated", "Impact mitigated", "Cause identified"]))
2708
+ .optional()
2709
+ .describe("Timeline event tags to attach. Available: 'Start time', 'End time', 'Impact detected', 'Response initiated', 'Impact mitigated', 'Cause identified'."),
2710
+ });
2452
2711
  // --- Webhook schemas ---
2453
2712
  export const ListWebhooksSchema = z
2454
2713
  .object({
@@ -2477,7 +2736,7 @@ export const ListWebhookEventsSchema = z
2477
2736
  .describe("Group ID or URL-encoded path. Provide either project_id or group_id, not both."),
2478
2737
  hook_id: z.coerce.number().describe("ID of the webhook"),
2479
2738
  status: z
2480
- .union([z.number(), z.string()])
2739
+ .union([z.coerce.number(), z.string()])
2481
2740
  .optional()
2482
2741
  .describe("Filter by response status code (e.g. 200, 500) or category: successful, client_failure, server_failure"),
2483
2742
  summary: z
@@ -2490,7 +2749,7 @@ export const ListWebhookEventsSchema = z
2490
2749
  .optional()
2491
2750
  .default(20)
2492
2751
  .describe("Number of events per page"),
2493
- page: z.number().optional().describe("Page number for pagination"),
2752
+ page: z.coerce.number().optional().describe("Page number for pagination"),
2494
2753
  })
2495
2754
  .refine(data => (data.project_id || data.group_id) && !(data.project_id && data.group_id), {
2496
2755
  message: "Provide exactly one of project_id or group_id",