@zereight/mcp-gitlab 2.1.61 → 2.1.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +1 -1
- package/README.md +116 -116
- package/README.zh-CN.md +1 -1
- package/build/index.js +3 -1
- package/build/schemas.js +21 -18
- package/build/test/gitlab-pipeline-schedule-schema.test.js +32 -0
- package/build/test/group-milestone-schema.test.js +4 -4
- package/build/test/streamable-http-concurrent-session.test.js +16 -0
- package/build/test/test-health-check.js +9 -0
- package/build/test/test-update-project.js +1 -1
- package/build/test/utils/merge-request-position.test.js +1 -1
- package/build/tools/registry.js +2 -3
- package/build/utils/schema.js +46 -23
- package/package.json +2 -3
package/README.ko.md
CHANGED
|
@@ -110,7 +110,7 @@ command = lib.getExe inputs.gitlab-mcp.packages.${system}.default;
|
|
|
110
110
|
|
|
111
111
|
예시는 기존 `mcp-gitlab`보다 충돌 가능성이 낮은 `zereight-mcp-gitlab` 별칭을 사용합니다. MCP 클라이언트가 찾지 못하면 `which zereight-mcp-gitlab`의 절대 경로를 사용하세요.
|
|
112
112
|
|
|
113
|
-
전역 설치를 쓰지 않으려면 `npx -y @zereight/mcp-gitlab@2.1.
|
|
113
|
+
전역 설치를 쓰지 않으려면 `npx -y @zereight/mcp-gitlab@2.1.61`처럼 직전 안정 버전(문서가 권장하는 버전)으로 고정하세요. 항상 최신 버전을 원하면 `npx -y @zereight/mcp-gitlab@latest`를 사용하세요. 새 버전이 나오면 서버가 시작 시 stderr로 알려줍니다(`GITLAB_DISABLE_VERSION_CHECK=true`로 비활성화 가능).
|
|
114
114
|
|
|
115
115
|
#### CLI 인자 사용하기(환경 변수 문제가 있는 클라이언트용)
|
|
116
116
|
|
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ The store path is pinned by your lock file; update it with `nix flake update git
|
|
|
115
115
|
|
|
116
116
|
The examples use `zereight-mcp-gitlab`, a less collision-prone alias for the legacy `mcp-gitlab` binary. If your MCP client cannot find it, use the absolute path from `which zereight-mcp-gitlab`.
|
|
117
117
|
|
|
118
|
-
No global install? Pin `npx` to the previous stable release (the version these docs recommend), for example `npx -y @zereight/mcp-gitlab@2.1.
|
|
118
|
+
No global install? Pin `npx` to the previous stable release (the version these docs recommend), for example `npx -y @zereight/mcp-gitlab@2.1.61`. If you always want the newest release, use `npx -y @zereight/mcp-gitlab@latest` instead. The server prints a notice to stderr on startup when a newer version is available (disable with `GITLAB_DISABLE_VERSION_CHECK=true`).
|
|
119
119
|
|
|
120
120
|
#### Using CLI Arguments (for clients with env var issues)
|
|
121
121
|
|
|
@@ -583,23 +583,23 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
583
583
|
|
|
584
584
|
<!-- TOOLS-START -->
|
|
585
585
|
|
|
586
|
-
1. `merge_merge_request` - Merge a merge request
|
|
587
|
-
2. `approve_merge_request` - Approve a merge request
|
|
588
|
-
3. `unapprove_merge_request` - Unapprove a
|
|
589
|
-
4. `get_merge_request_approval_state` - Get merge request approval details including approvers
|
|
590
|
-
5. `get_merge_request_conflicts` - Get the conflicts of a merge request
|
|
591
|
-
6. `list_merge_request_pipelines` - List pipelines for a merge request with pagination
|
|
586
|
+
1. `merge_merge_request` - Merge a merge request
|
|
587
|
+
2. `approve_merge_request` - Approve a merge request
|
|
588
|
+
3. `unapprove_merge_request` - Unapprove a merge request
|
|
589
|
+
4. `get_merge_request_approval_state` - Get merge request approval details including approvers
|
|
590
|
+
5. `get_merge_request_conflicts` - Get the conflicts of a merge request
|
|
591
|
+
6. `list_merge_request_pipelines` - List pipelines for a merge request with pagination
|
|
592
592
|
7. `execute_graphql` - Execute a GitLab GraphQL query
|
|
593
|
-
8. `create_or_update_file` - Create or update a
|
|
593
|
+
8. `create_or_update_file` - Create or update a file in a GitLab project
|
|
594
594
|
9. `search_repositories` - Search for GitLab projects
|
|
595
595
|
10. `create_repository` - Create a new GitLab project
|
|
596
|
-
11. `create_group` - Create
|
|
597
|
-
12. `get_file_contents` - Get
|
|
598
|
-
13. `push_files` - Push multiple files
|
|
599
|
-
14. `create_issue` - Create a new issue
|
|
600
|
-
15. `create_merge_request` - Create a new merge request
|
|
601
|
-
16. `fork_repository` - Fork a
|
|
602
|
-
17. `create_branch` - Create a new branch
|
|
596
|
+
11. `create_group` - Create new group or subgroup
|
|
597
|
+
12. `get_file_contents` - Get contents of a file or directory from a GitLab project
|
|
598
|
+
13. `push_files` - Push multiple files in a single commit
|
|
599
|
+
14. `create_issue` - Create a new issue
|
|
600
|
+
15. `create_merge_request` - Create a new merge request
|
|
601
|
+
16. `fork_repository` - Fork a project to your account or specified namespace
|
|
602
|
+
17. `create_branch` - Create a new branch
|
|
603
603
|
18. `get_branch` - Get branch details (commit, protection status)
|
|
604
604
|
19. `list_branches` - List branches in project with search filter
|
|
605
605
|
20. `delete_branch` - Delete branch from project
|
|
@@ -608,15 +608,15 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
608
608
|
23. `protect_branch` - Protect a repository branch (set push/merge/unprotect access levels)
|
|
609
609
|
24. `unprotect_branch` - Remove protection from a previously protected branch
|
|
610
610
|
25. `update_default_branch` - Change the default branch of a project
|
|
611
|
-
26. `get_merge_request` - Get details of a merge request
|
|
612
|
-
27. `get_merge_request_diffs` - Get the changes/diffs of a merge request (
|
|
613
|
-
28. `list_merge_request_changed_files` -
|
|
614
|
-
29. `list_merge_request_diffs` - List merge request diffs with pagination
|
|
615
|
-
30. `get_merge_request_file_diff` -
|
|
611
|
+
26. `get_merge_request` - Get details of a merge request (mergeRequestIid or branchName required). Set include_summaries=true for deployment/commit/approval summaries
|
|
612
|
+
27. `get_merge_request_diffs` - Get the changes/diffs of a merge request (mergeRequestIid or branchName required)
|
|
613
|
+
28. `list_merge_request_changed_files` - List changed file paths in a merge request without diff content (mergeRequestIid or branchName required)
|
|
614
|
+
29. `list_merge_request_diffs` - List merge request diffs with pagination (mergeRequestIid or branchName required)
|
|
615
|
+
30. `get_merge_request_file_diff` - Get diffs for specific files from a merge request (mergeRequestIid or branchName required)
|
|
616
616
|
31. `list_merge_request_versions` - List all versions of a merge request
|
|
617
617
|
32. `get_merge_request_version` - Get a specific version of a merge request
|
|
618
|
-
33. `get_branch_diffs` - Get
|
|
619
|
-
34. `update_merge_request` - Update a merge request (
|
|
618
|
+
33. `get_branch_diffs` - Get diffs between two branches or commits
|
|
619
|
+
34. `update_merge_request` - Update a merge request (mergeRequestIid or branchName required)
|
|
620
620
|
35. `create_note` - Create a new note (comment) to an issue or merge request
|
|
621
621
|
36. `create_merge_request_thread` - Create a new thread on a merge request
|
|
622
622
|
37. `resolve_merge_request_thread` - Resolve a thread on a merge request
|
|
@@ -624,18 +624,18 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
624
624
|
39. `delete_merge_request_discussion_note` - Delete a discussion note on a merge request
|
|
625
625
|
40. `update_merge_request_discussion_note` - Update a discussion note on a merge request
|
|
626
626
|
41. `create_merge_request_discussion_note` - Add a new discussion note to an existing merge request thread
|
|
627
|
-
42. `create_merge_request_note` - Add a new note to
|
|
627
|
+
42. `create_merge_request_note` - Add a new note to a merge request
|
|
628
628
|
43. `delete_merge_request_note` - Delete an existing merge request note
|
|
629
629
|
44. `get_merge_request_note` - Get a specific note for a merge request
|
|
630
630
|
45. `get_merge_request_notes` - List notes for a merge request
|
|
631
|
-
46. `update_merge_request_note` - Modify an existing merge request
|
|
631
|
+
46. `update_merge_request_note` - Modify an existing merge request note
|
|
632
632
|
47. `get_draft_note` - Get a single draft note from a merge request
|
|
633
633
|
48. `list_draft_notes` - List draft notes for a merge request
|
|
634
634
|
49. `create_draft_note` - Create a draft note for a merge request
|
|
635
635
|
50. `update_draft_note` - Update an existing draft note
|
|
636
636
|
51. `delete_draft_note` - Delete a draft note
|
|
637
637
|
52. `publish_draft_note` - Publish a single draft note
|
|
638
|
-
53. `bulk_publish_draft_notes` - Publish all draft notes for a merge request
|
|
638
|
+
53. `bulk_publish_draft_notes` - Publish all draft notes for a merge request. Optionally sets reviewer_state and posts a summary note (GitLab 19.2+). Can set reviewer_state even with no drafts.
|
|
639
639
|
54. `list_merge_request_emoji_reactions` - List all emoji reactions on a merge request
|
|
640
640
|
55. `list_merge_request_note_emoji_reactions` - List all emoji reactions on a merge request note. Pass discussion_id for discussion thread replies.
|
|
641
641
|
56. `create_merge_request_emoji_reaction` - Add an emoji reaction to a merge request (e.g. thumbsup, rocket, eyes)
|
|
@@ -643,30 +643,30 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
643
643
|
58. `create_merge_request_note_emoji_reaction` - Add an emoji reaction to a merge request note. Pass discussion_id for discussion thread replies.
|
|
644
644
|
59. `delete_merge_request_note_emoji_reaction` - Remove an emoji reaction from a merge request note. Pass discussion_id for discussion thread replies.
|
|
645
645
|
60. `update_issue_note` - Modify an existing issue thread note
|
|
646
|
-
61. `create_issue_note` - Add a
|
|
646
|
+
61. `create_issue_note` - Add a note to an issue, optionally replying to a discussion thread
|
|
647
647
|
62. `list_issue_emoji_reactions` - List all emoji reactions on an issue
|
|
648
648
|
63. `list_issue_note_emoji_reactions` - List all emoji reactions on an issue note. Pass discussion_id for discussion thread replies.
|
|
649
649
|
64. `create_issue_emoji_reaction` - Add an emoji reaction to an issue (e.g. thumbsup, rocket, eyes)
|
|
650
650
|
65. `delete_issue_emoji_reaction` - Remove an emoji reaction from an issue
|
|
651
651
|
66. `create_issue_note_emoji_reaction` - Add an emoji reaction to an issue note. Pass discussion_id for discussion thread replies.
|
|
652
652
|
67. `delete_issue_note_emoji_reaction` - Remove an emoji reaction from an issue note. Pass discussion_id for discussion thread replies.
|
|
653
|
-
68. `list_issues` - List issues (default: created by current user
|
|
654
|
-
69. `my_issues` - List issues assigned to the authenticated user
|
|
655
|
-
70. `get_issue` - Get details of a specific issue
|
|
656
|
-
71. `update_issue` - Update an issue
|
|
657
|
-
72. `update_issue_description_patch` - Apply a patch (search/replace or unified diff) to an issue description. Reduces token usage by
|
|
658
|
-
73. `delete_issue` - Delete an issue
|
|
653
|
+
68. `list_issues` - List issues (default: created by current user; use scope='all' for all)
|
|
654
|
+
69. `my_issues` - List issues assigned to the authenticated user
|
|
655
|
+
70. `get_issue` - Get details of a specific issue. Returns a slim milestone by default; set full_response=true for the complete milestone object
|
|
656
|
+
71. `update_issue` - Update an issue. Returns a slim confirmation by default; set full_response=true for the complete updated issue object
|
|
657
|
+
72. `update_issue_description_patch` - Apply a patch (search/replace or unified diff) to an issue description. Reduces token usage by allowing small changes without sending the full description. Supports dry_run to preview changes and create_note to summarize updates.
|
|
658
|
+
73. `delete_issue` - Delete an issue
|
|
659
659
|
74. `list_todos` - List GitLab to-do items for the current user
|
|
660
660
|
75. `mark_todo_done` - Mark a GitLab to-do item as done
|
|
661
661
|
76. `mark_all_todos_done` - Mark all pending GitLab to-do items as done for the current user
|
|
662
662
|
77. `list_issue_links` - List all issue links for a specific issue
|
|
663
|
-
78. `list_issue_discussions` - List discussions for an issue
|
|
663
|
+
78. `list_issue_discussions` - List discussions for an issue
|
|
664
664
|
79. `get_issue_link` - Get a specific issue link
|
|
665
665
|
80. `create_issue_link` - Create an issue link between two issues
|
|
666
666
|
81. `delete_issue_link` - Delete an issue link
|
|
667
|
-
82. `list_namespaces` - List all namespaces available to the current user
|
|
668
|
-
83. `get_namespace` - Get details of a namespace by ID or path
|
|
669
|
-
84. `verify_namespace` - Verify if a namespace path exists
|
|
667
|
+
82. `list_namespaces` - List all namespaces (users and groups) available to the current user. Filter by kind='group' for groups only.
|
|
668
|
+
83. `get_namespace` - Get details of a namespace (user or group) by ID or path. Groups are namespaces with kind='group'.
|
|
669
|
+
84. `verify_namespace` - Verify if a namespace path exists. Use parent_id to scope the check to a specific parent namespace — required for nested namespaces where the same path may exist under different parents.
|
|
670
670
|
85. `get_project` - Get details of a specific project
|
|
671
671
|
86. `list_projects` - List projects accessible by the current user
|
|
672
672
|
87. `update_project` - Update project settings such as description, visibility, default branch, and feature access levels
|
|
@@ -677,39 +677,39 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
677
677
|
92. `create_label` - Create a new label in a project
|
|
678
678
|
93. `update_label` - Update an existing label in a project
|
|
679
679
|
94. `delete_label` - Delete a label from a project
|
|
680
|
-
95. `list_group_projects` - List projects in a
|
|
681
|
-
96. `list_wiki_pages` - List wiki pages in a
|
|
680
|
+
95. `list_group_projects` - List projects in a group
|
|
681
|
+
96. `list_wiki_pages` - List wiki pages in a project
|
|
682
682
|
97. `get_wiki_page` - Get details of a specific wiki page
|
|
683
|
-
98. `create_wiki_page` - Create a
|
|
684
|
-
99. `update_wiki_page` - Update
|
|
685
|
-
100. `delete_wiki_page` - Delete a wiki page from a
|
|
686
|
-
101. `list_group_wiki_pages` - List wiki pages in a
|
|
683
|
+
98. `create_wiki_page` - Create a wiki page in a project
|
|
684
|
+
99. `update_wiki_page` - Update a wiki page in a project
|
|
685
|
+
100. `delete_wiki_page` - Delete a wiki page from a project
|
|
686
|
+
101. `list_group_wiki_pages` - List wiki pages in a group
|
|
687
687
|
102. `get_group_wiki_page` - Get details of a specific group wiki page
|
|
688
|
-
103. `create_group_wiki_page` - Create a
|
|
689
|
-
104. `update_group_wiki_page` - Update
|
|
690
|
-
105. `delete_group_wiki_page` - Delete a wiki page from a
|
|
691
|
-
106. `get_repository_tree` -
|
|
692
|
-
107. `list_pipelines` - List pipelines
|
|
693
|
-
108. `get_pipeline` - Get details of a specific pipeline
|
|
688
|
+
103. `create_group_wiki_page` - Create a wiki page in a group
|
|
689
|
+
104. `update_group_wiki_page` - Update a wiki page in a group
|
|
690
|
+
105. `delete_group_wiki_page` - Delete a wiki page from a group
|
|
691
|
+
106. `get_repository_tree` - List files and directories in a repository
|
|
692
|
+
107. `list_pipelines` - List pipelines with filtering options
|
|
693
|
+
108. `get_pipeline` - Get details of a specific pipeline
|
|
694
694
|
109. `get_pipeline_variables` - Get variables configured for a pipeline
|
|
695
695
|
110. `get_pipeline_test_report` - Get pipeline test report
|
|
696
696
|
111. `get_pipeline_test_report_summary` - Get pipeline test report summary
|
|
697
697
|
112. `delete_pipeline` - Delete a pipeline. Requires the project Owner role, cannot be undone, and does not automatically delete child pipelines.
|
|
698
698
|
113. `update_pipeline_metadata` - Update pipeline metadata
|
|
699
|
-
114. `list_deployments` - List deployments
|
|
700
|
-
115. `get_deployment` - Get details
|
|
699
|
+
114. `list_deployments` - List deployments with filtering options
|
|
700
|
+
115. `get_deployment` - Get deployment details, including approval_summary, approvals, and pending_approval_count when GitLab provides them
|
|
701
701
|
116. `create_deployment` - Create a deployment
|
|
702
702
|
117. `update_deployment` - Update a deployment status
|
|
703
703
|
118. `delete_deployment` - Delete a deployment
|
|
704
704
|
119. `list_deployment_merge_requests` - List merge requests shipped with a deployment
|
|
705
705
|
120. `approve_deployment` - Approve or reject a protected-environment deployment
|
|
706
|
-
121. `list_environments` - List environments in a
|
|
707
|
-
122. `get_environment` - Get details of a specific environment
|
|
706
|
+
121. `list_environments` - List environments in a project
|
|
707
|
+
122. `get_environment` - Get details of a specific environment
|
|
708
708
|
123. `update_environment` - Update an environment
|
|
709
709
|
124. `delete_environment` - Delete a stopped environment
|
|
710
710
|
125. `stop_environment` - Stop an environment
|
|
711
711
|
126. `stop_stale_environments` - Stop eligible stale environments; protected environments are excluded and environments are stopped, not deleted
|
|
712
|
-
127. `delete_review_app_environments` - Schedule deletion of stopped review-app environments one week later;
|
|
712
|
+
127. `delete_review_app_environments` - Schedule deletion of stopped review-app environments one week later; dry_run defaults to true and actual scheduling requires dry_run=false
|
|
713
713
|
128. `list_pipeline_triggers` - List project pipeline trigger tokens
|
|
714
714
|
129. `get_pipeline_trigger` - Get a project pipeline trigger
|
|
715
715
|
130. `create_pipeline_trigger` - Create a project pipeline trigger
|
|
@@ -717,11 +717,11 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
717
717
|
132. `delete_pipeline_trigger` - Delete a project pipeline trigger
|
|
718
718
|
133. `trigger_pipeline` - Trigger a pipeline with a pipeline trigger token
|
|
719
719
|
134. `list_pipeline_jobs` - List all jobs in a specific pipeline
|
|
720
|
-
135. `list_pipeline_trigger_jobs` - List
|
|
720
|
+
135. `list_pipeline_trigger_jobs` - List trigger jobs (bridges) in a pipeline
|
|
721
721
|
136. `get_pipeline_job` - Get details of a GitLab pipeline job number
|
|
722
|
-
137. `get_pipeline_job_output` - Get the output/trace of a
|
|
722
|
+
137. `get_pipeline_job_output` - Get the output/trace of a pipeline job with optional pagination
|
|
723
723
|
138. `validate_ci_lint` - Validate provided GitLab CI/CD YAML content for a project
|
|
724
|
-
139. `validate_project_ci_lint` - Validate an existing
|
|
724
|
+
139. `validate_project_ci_lint` - Validate an existing .gitlab-ci.yml configuration for a project
|
|
725
725
|
140. `list_ci_catalog_resources` - List GitLab CI/CD Catalog resources/components visible to the user
|
|
726
726
|
141. `get_ci_catalog_resource` - Get details for a GitLab CI/CD Catalog resource, including versions and components
|
|
727
727
|
142. `create_pipeline` - Create a new pipeline for a branch or tag
|
|
@@ -733,7 +733,7 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
733
733
|
148. `create_pipeline_schedule` - Create a new pipeline schedule for a branch or tag
|
|
734
734
|
149. `update_pipeline_schedule` - Update an existing pipeline schedule
|
|
735
735
|
150. `delete_pipeline_schedule` - Delete a pipeline schedule
|
|
736
|
-
151. `play_pipeline_schedule` - Run a pipeline schedule immediately
|
|
736
|
+
151. `play_pipeline_schedule` - Run a pipeline schedule immediately
|
|
737
737
|
152. `take_ownership_pipeline_schedule` - Take ownership of a pipeline schedule
|
|
738
738
|
153. `get_pipeline_schedule_variable` - Get a single variable of a pipeline schedule
|
|
739
739
|
154. `create_pipeline_schedule_variable` - Create a variable for a pipeline schedule
|
|
@@ -746,25 +746,25 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
746
746
|
161. `erase_pipeline_job` - Erase a pipeline job log and artifacts
|
|
747
747
|
162. `wait_for_pipeline` - Wait for a pipeline to reach a terminal status
|
|
748
748
|
163. `wait_for_job` - Wait for a job to reach a terminal status
|
|
749
|
-
164. `list_job_artifacts` - List artifact files in a job's
|
|
750
|
-
165. `download_job_artifacts` - Download
|
|
751
|
-
166. `get_job_artifact_file` - Get
|
|
752
|
-
167. `list_merge_requests` - List merge requests
|
|
753
|
-
168. `list_group_merge_requests` - List merge requests across all projects of a group and its subgroups
|
|
754
|
-
169. `list_milestones` - List milestones
|
|
749
|
+
164. `list_job_artifacts` - List artifact files in a job's archive
|
|
750
|
+
165. `download_job_artifacts` - Download job artifact archive (zip) and save to a local path
|
|
751
|
+
166. `get_job_artifact_file` - Get content of a single file from a job's artifacts
|
|
752
|
+
167. `list_merge_requests` - List merge requests (without project_id: user's MRs; with project_id: project MRs)
|
|
753
|
+
168. `list_group_merge_requests` - List merge requests across all projects of a group and its subgroups
|
|
754
|
+
169. `list_milestones` - List milestones with filtering options
|
|
755
755
|
170. `get_milestone` - Get details of a specific milestone
|
|
756
|
-
171. `create_milestone` - Create a new milestone
|
|
757
|
-
172. `edit_milestone` - Edit an existing milestone
|
|
758
|
-
173. `delete_milestone` - Delete a milestone
|
|
756
|
+
171. `create_milestone` - Create a new milestone
|
|
757
|
+
172. `edit_milestone` - Edit an existing milestone
|
|
758
|
+
173. `delete_milestone` - Delete a milestone
|
|
759
759
|
174. `get_milestone_issue` - Get issues associated with a specific milestone
|
|
760
760
|
175. `get_milestone_merge_requests` - Get merge requests associated with a specific milestone
|
|
761
761
|
176. `promote_milestone` - Promote a milestone to the next stage
|
|
762
762
|
177. `get_milestone_burndown_events` - Get burndown events for a specific milestone
|
|
763
|
-
178. `list_group_milestones` - List milestones
|
|
763
|
+
178. `list_group_milestones` - List group milestones with filtering options
|
|
764
764
|
179. `get_group_milestone` - Get details of a specific group milestone
|
|
765
|
-
180. `create_group_milestone` - Create a new milestone
|
|
765
|
+
180. `create_group_milestone` - Create a new group milestone
|
|
766
766
|
181. `edit_group_milestone` - Edit an existing group milestone
|
|
767
|
-
182. `delete_group_milestone` - Delete a milestone
|
|
767
|
+
182. `delete_group_milestone` - Delete a group milestone
|
|
768
768
|
183. `get_group_milestone_issue` - Get issues associated with a specific group milestone
|
|
769
769
|
184. `get_group_milestone_merge_requests` - Get merge requests associated with a specific group milestone
|
|
770
770
|
185. `get_group_milestone_burndown_events` - Get burndown events for a specific group milestone
|
|
@@ -775,66 +775,66 @@ Register the skill directory in your AI client to get optimal tool usage guidanc
|
|
|
775
775
|
190. `get_commit` - Get details of a specific commit
|
|
776
776
|
191. `get_commit_diff` - Get changes/diffs of a specific commit
|
|
777
777
|
192. `get_file_blame` - Get git blame for a file at a given ref. Each entry maps a contiguous range of source lines to the commit that last changed them (id, author, authored_date, message). Use range_start/range_end to limit blame to specific lines.
|
|
778
|
-
193. `list_commit_statuses` - List statuses for a
|
|
779
|
-
194. `create_commit_status` - Create or update the status of a
|
|
778
|
+
193. `list_commit_statuses` - List statuses for a commit
|
|
779
|
+
194. `create_commit_status` - Create or update the status of a commit
|
|
780
780
|
195. `list_group_iterations` - List group iterations with filtering options
|
|
781
|
-
196. `upload_markdown` - Upload a file
|
|
782
|
-
197. `download_attachment` - Download an uploaded file from a
|
|
783
|
-
198. `health_check` - Verify server status and authentication
|
|
784
|
-
199. `list_events` - List
|
|
785
|
-
200. `get_project_events` - List
|
|
781
|
+
196. `upload_markdown` - Upload a file for use in markdown content
|
|
782
|
+
197. `download_attachment` - Download an uploaded file from a project (images returned as base64; use local_path to save to disk)
|
|
783
|
+
198. `health_check` - Verify server status and authentication. Always reports the MCP server version (mcp_server_version). When authenticated, also reports the GitLab instance version from GET /api/v4/version (version, revision, enterprise). Version lookup failures do not fail the health check — those fields are omitted.
|
|
784
|
+
199. `list_events` - List events for the authenticated user (before/after: YYYY-MM-DD)
|
|
785
|
+
200. `get_project_events` - List events for a project (before/after: YYYY-MM-DD)
|
|
786
786
|
201. `list_releases` - List all releases for a project
|
|
787
787
|
202. `get_release` - Get a release by tag name
|
|
788
|
-
203. `create_release` - Create a new release
|
|
789
|
-
204. `update_release` - Update an existing release
|
|
790
|
-
205. `delete_release` - Delete a release
|
|
791
|
-
206. `create_release_evidence` - Create release evidence
|
|
788
|
+
203. `create_release` - Create a new release
|
|
789
|
+
204. `update_release` - Update an existing release
|
|
790
|
+
205. `delete_release` - Delete a release (does not delete the tag)
|
|
791
|
+
206. `create_release_evidence` - Create release evidence (Premium/Ultimate)
|
|
792
792
|
207. `download_release_asset` - Download a release asset file by direct asset path
|
|
793
|
-
208. `list_tags` - List repository tags
|
|
794
|
-
209. `get_tag` - Get
|
|
795
|
-
210. `create_tag` - Create a new tag
|
|
796
|
-
211. `delete_tag` - Delete a tag
|
|
797
|
-
212. `get_tag_signature` - Get the signature of a signed tag
|
|
798
|
-
213. `get_work_item` - Get a
|
|
799
|
-
214. `list_work_items` - List work items
|
|
800
|
-
215. `create_work_item` - Create a
|
|
801
|
-
216. `update_work_item` - Update a work item
|
|
802
|
-
217. `convert_work_item_type` - Convert a work item to a different type
|
|
803
|
-
218. `list_work_item_statuses` - List available statuses for a work item type
|
|
804
|
-
219. `list_custom_field_definitions` - List
|
|
805
|
-
220. `move_work_item` - Move a work item
|
|
806
|
-
221. `list_work_item_notes` - List notes and discussions on a work item
|
|
807
|
-
222. `create_work_item_note` - Add a note
|
|
793
|
+
208. `list_tags` - List repository tags for a project
|
|
794
|
+
209. `get_tag` - Get a repository tag by name
|
|
795
|
+
210. `create_tag` - Create a new repository tag
|
|
796
|
+
211. `delete_tag` - Delete a repository tag
|
|
797
|
+
212. `get_tag_signature` - Get the X.509 signature of a signed tag (404 if unsigned)
|
|
798
|
+
213. `get_work_item` - Get a work item with full details including status, hierarchy, type, and widgets
|
|
799
|
+
214. `list_work_items` - List work items with filters (type, state, search, assignees, labels)
|
|
800
|
+
215. `create_work_item` - Create a work item (issue, task, incident, epic, etc.) with full field support
|
|
801
|
+
216. `update_work_item` - Update a work item (title, description, labels, assignees, state, parent, custom fields, etc.)
|
|
802
|
+
217. `convert_work_item_type` - Convert a work item to a different type
|
|
803
|
+
218. `list_work_item_statuses` - List available statuses for a work item type (Premium/Ultimate)
|
|
804
|
+
219. `list_custom_field_definitions` - List custom field definitions for a work item type
|
|
805
|
+
220. `move_work_item` - Move a work item to a different project
|
|
806
|
+
221. `list_work_item_notes` - List notes and discussions on a work item
|
|
807
|
+
222. `create_work_item_note` - Add a note to a work item (supports Markdown, internal notes, threads)
|
|
808
808
|
223. `list_work_item_emoji_reactions` - List all emoji reactions on a work item
|
|
809
809
|
224. `list_work_item_note_emoji_reactions` - List all emoji reactions on a work item note (comment, thread, or thread reply)
|
|
810
810
|
225. `create_work_item_emoji_reaction` - Add an emoji reaction to a work item (e.g. thumbsup, rocket, eyes)
|
|
811
811
|
226. `delete_work_item_emoji_reaction` - Remove an emoji reaction from a work item
|
|
812
812
|
227. `create_work_item_note_emoji_reaction` - Add an emoji reaction to a work item note (comment, thread, or thread reply)
|
|
813
813
|
228. `delete_work_item_note_emoji_reaction` - Remove an emoji reaction from a work item note (comment, thread, or thread reply)
|
|
814
|
-
229. `get_timeline_events` - List timeline events for an incident
|
|
815
|
-
230. `create_timeline_event` - Create a timeline event on an incident
|
|
816
|
-
231. `list_webhooks` - List
|
|
817
|
-
232. `create_webhook` - Create a webhook on a
|
|
814
|
+
229. `get_timeline_events` - List timeline events for an incident
|
|
815
|
+
230. `create_timeline_event` - Create a timeline event on an incident
|
|
816
|
+
231. `list_webhooks` - List webhooks for a project or group
|
|
817
|
+
232. `create_webhook` - Create a webhook on a project or group
|
|
818
818
|
233. `update_webhook` - Update an existing project or group webhook
|
|
819
819
|
234. `delete_webhook` - Delete a project or group webhook
|
|
820
|
-
235. `list_webhook_events` - List recent webhook events (past 7 days)
|
|
821
|
-
236. `get_webhook_event` - Get full details of a specific webhook event
|
|
822
|
-
237. `search_code` - Search for code across all projects
|
|
823
|
-
238. `search_project_code` - Search for code within a specific
|
|
824
|
-
239. `search_group_code` - Search for code within a specific
|
|
825
|
-
240. `list_project_variables` - List CI/CD variables for a project
|
|
826
|
-
241. `get_project_variable` - Get a single CI/CD variable from a project
|
|
827
|
-
242. `create_project_variable` - Create a
|
|
828
|
-
243. `update_project_variable` - Update an existing CI/CD variable in a project
|
|
829
|
-
244. `delete_project_variable` - Delete a CI/CD variable from a project
|
|
830
|
-
245. `list_group_variables` - List CI/CD variables for a group
|
|
831
|
-
246. `get_group_variable` - Get a single CI/CD variable from a group
|
|
832
|
-
247. `create_group_variable` - Create a
|
|
833
|
-
248. `update_group_variable` - Update an existing CI/CD variable in a group
|
|
834
|
-
249. `delete_group_variable` - Delete a CI/CD variable from a group
|
|
835
|
-
250. `get_dependency_proxy_settings` - Get dependency proxy settings for a group
|
|
820
|
+
235. `list_webhook_events` - List recent webhook events (past 7 days)
|
|
821
|
+
236. `get_webhook_event` - Get full details of a specific webhook event
|
|
822
|
+
237. `search_code` - Search for code across all projects (requires advanced search or Zoekt)
|
|
823
|
+
238. `search_project_code` - Search for code within a specific project (requires advanced search or Zoekt)
|
|
824
|
+
239. `search_group_code` - Search for code within a specific group (requires advanced search or Zoekt)
|
|
825
|
+
240. `list_project_variables` - List CI/CD variables for a project
|
|
826
|
+
241. `get_project_variable` - Get a single CI/CD variable from a project
|
|
827
|
+
242. `create_project_variable` - Create a CI/CD variable for a project
|
|
828
|
+
243. `update_project_variable` - Update an existing CI/CD variable in a project
|
|
829
|
+
244. `delete_project_variable` - Delete a CI/CD variable from a project
|
|
830
|
+
245. `list_group_variables` - List CI/CD variables for a group
|
|
831
|
+
246. `get_group_variable` - Get a single CI/CD variable from a group
|
|
832
|
+
247. `create_group_variable` - Create a CI/CD variable for a group
|
|
833
|
+
248. `update_group_variable` - Update an existing CI/CD variable in a group
|
|
834
|
+
249. `delete_group_variable` - Delete a CI/CD variable from a group
|
|
835
|
+
250. `get_dependency_proxy_settings` - Get dependency proxy settings for a group
|
|
836
836
|
251. `update_dependency_proxy_settings` - Update dependency proxy settings for a group (enable/disable, credentials for authenticated Docker Hub pulls)
|
|
837
|
-
252. `list_dependency_proxy_blobs` - List cached dependency proxy blobs for a group
|
|
837
|
+
252. `list_dependency_proxy_blobs` - List cached dependency proxy blobs for a group
|
|
838
838
|
253. `purge_dependency_proxy_cache` - Schedule purge of all cached dependency proxy blobs for a group
|
|
839
839
|
254. `list_project_vulnerabilities` - List vulnerabilities for a project with optional state, severity, and report type filters (GraphQL-backed, cursor pagination)
|
|
840
840
|
255. `get_vulnerability` - Get full details of a specific vulnerability
|
package/README.zh-CN.md
CHANGED
|
@@ -110,7 +110,7 @@ command = lib.getExe inputs.gitlab-mcp.packages.${system}.default;
|
|
|
110
110
|
|
|
111
111
|
示例使用 `zereight-mcp-gitlab`,这是比旧的 `mcp-gitlab` 更不容易冲突的别名。如果 MCP 客户端找不到它,请使用 `which zereight-mcp-gitlab` 输出的绝对路径。
|
|
112
112
|
|
|
113
|
-
如果不想全局安装,请将 `npx` 固定到上一个稳定版本(即文档推荐的版本),例如 `npx -y @zereight/mcp-gitlab@2.1.
|
|
113
|
+
如果不想全局安装,请将 `npx` 固定到上一个稳定版本(即文档推荐的版本),例如 `npx -y @zereight/mcp-gitlab@2.1.61`。如果始终想使用最新版本,请改用 `npx -y @zereight/mcp-gitlab@latest`。有新版本发布时,服务器会在启动时通过 stderr 提示(可用 `GITLAB_DISABLE_VERSION_CHECK=true` 关闭)。
|
|
114
114
|
|
|
115
115
|
#### 使用 CLI 参数(适用于环境变量有问题的客户端)
|
|
116
116
|
|
package/build/index.js
CHANGED
|
@@ -10233,6 +10233,7 @@ async function handleToolCall(params) {
|
|
|
10233
10233
|
status: authenticated ? "ok" : "error",
|
|
10234
10234
|
authenticated,
|
|
10235
10235
|
gitlab_url: getEffectiveApiUrl(),
|
|
10236
|
+
mcp_server_version: SERVER_VERSION,
|
|
10236
10237
|
...(versionMetadata ?? {}),
|
|
10237
10238
|
}),
|
|
10238
10239
|
},
|
|
@@ -10389,7 +10390,7 @@ async function handleToolCall(params) {
|
|
|
10389
10390
|
// Sensitive fields are also covered by REDACT_PATHS if arguments are logged elsewhere.
|
|
10390
10391
|
logger.debug({ tool: params.name }, "Tool call failed");
|
|
10391
10392
|
if (error instanceof z.ZodError) {
|
|
10392
|
-
throw new Error(`Invalid arguments: ${error.
|
|
10393
|
+
throw new Error(`Invalid arguments: ${error.issues
|
|
10393
10394
|
.map(e => `${e.path.join(".")}: ${e.message}`)
|
|
10394
10395
|
.join(", ")}`);
|
|
10395
10396
|
}
|
|
@@ -11583,6 +11584,7 @@ async function startStreamableHTTPServer() {
|
|
|
11583
11584
|
}
|
|
11584
11585
|
res.status(isHealthy ? 200 : 503).json({
|
|
11585
11586
|
status: isHealthy ? "healthy" : "degraded",
|
|
11587
|
+
version: SERVER_VERSION,
|
|
11586
11588
|
activeSessions,
|
|
11587
11589
|
maxSessions: MAX_SESSIONS,
|
|
11588
11590
|
uptime: process.uptime(),
|
package/build/schemas.js
CHANGED
|
@@ -589,9 +589,9 @@ export const CreatePipelineTriggerSchema = z.object({ project_id: z.coerce.strin
|
|
|
589
589
|
export const UpdatePipelineTriggerSchema = PipelineTriggerIdSchema.extend({ description: z.string() });
|
|
590
590
|
export const TriggerPipelineSchema = z.object({
|
|
591
591
|
project_id: z.coerce.string(), token: z.string(), ref: z.string(),
|
|
592
|
-
variables: z.record(z.string()).optional(),
|
|
592
|
+
variables: z.record(z.string(), z.string()).optional(),
|
|
593
593
|
inputs: z
|
|
594
|
-
.record(z.unknown())
|
|
594
|
+
.record(z.string(), z.unknown())
|
|
595
595
|
.optional()
|
|
596
596
|
.describe("Structured pipeline inputs; supported from GitLab 17.10 behind a feature flag and generally available from GitLab 18.1. Omit on older GitLab versions."),
|
|
597
597
|
});
|
|
@@ -663,7 +663,9 @@ export const GitLabPipelineScheduleSchema = z.object({
|
|
|
663
663
|
inputs: z
|
|
664
664
|
.array(z.object({
|
|
665
665
|
name: z.string(),
|
|
666
|
-
|
|
666
|
+
// Optional: Zod 4 rejects a missing key on required unknown (Zod 3 accepted it),
|
|
667
|
+
// and schedule inputs is a new API surface (18.1+) whose response shape is still settling.
|
|
668
|
+
value: z.unknown().optional(),
|
|
667
669
|
}))
|
|
668
670
|
.optional(),
|
|
669
671
|
});
|
|
@@ -870,11 +872,11 @@ export const PlayPipelineJobSchema = z.object({
|
|
|
870
872
|
}))
|
|
871
873
|
.optional()
|
|
872
874
|
.describe("Custom job variables to use when running the job"),
|
|
873
|
-
job_inputs: z.record(z.unknown()).optional().describe("Typed job input values"),
|
|
875
|
+
job_inputs: z.record(z.string(), z.unknown()).optional().describe("Typed job input values"),
|
|
874
876
|
});
|
|
875
877
|
// Schema for retrying a job
|
|
876
878
|
export const RetryPipelineJobSchema = PipelineJobControlSchema.extend({
|
|
877
|
-
job_inputs: z.record(z.unknown()).optional().describe("Typed job input values"),
|
|
879
|
+
job_inputs: z.record(z.string(), z.unknown()).optional().describe("Typed job input values"),
|
|
878
880
|
});
|
|
879
881
|
// Schema for canceling a job
|
|
880
882
|
export const CancelPipelineJobSchema = z.object({
|
|
@@ -1263,8 +1265,8 @@ export const GitLabCommitSchema = z.object({
|
|
|
1263
1265
|
total: z.coerce.number().optional().nullable(),
|
|
1264
1266
|
})
|
|
1265
1267
|
.optional(), // Only present when with_stats=true
|
|
1266
|
-
trailers: z.record(z.string()).optional().default({}), // Git trailers, may be empty object
|
|
1267
|
-
extended_trailers: z.record(z.array(z.string())).optional().default({}), // Extended trailers, may be empty object
|
|
1268
|
+
trailers: z.record(z.string(), z.string()).optional().default({}), // Git trailers, may be empty object
|
|
1269
|
+
extended_trailers: z.record(z.string(), z.array(z.string())).optional().default({}), // Extended trailers, may be empty object
|
|
1268
1270
|
});
|
|
1269
1271
|
export const GitLabCommitStatusSchema = z
|
|
1270
1272
|
.object({
|
|
@@ -2129,8 +2131,7 @@ const MergeRequestParamsSchema = ProjectParamsSchema.extend({
|
|
|
2129
2131
|
project_id: z
|
|
2130
2132
|
.preprocess(value => (value === undefined || value === null ? value : String(value)), z
|
|
2131
2133
|
.string({
|
|
2132
|
-
|
|
2133
|
-
invalid_type_error: "project_id is required",
|
|
2134
|
+
error: "project_id is required",
|
|
2134
2135
|
})
|
|
2135
2136
|
.refine(value => value === "" || value.trim().length > 0, "project_id is required")
|
|
2136
2137
|
.transform(value => (value === "" ? value : value.trim())))
|
|
@@ -2283,8 +2284,7 @@ export const ListMergeRequestPipelinesSchema = ProjectParamsSchema.extend({
|
|
|
2283
2284
|
merge_request_iid: z
|
|
2284
2285
|
.preprocess(value => (value === undefined || value === null ? value : String(value)), z
|
|
2285
2286
|
.string({
|
|
2286
|
-
|
|
2287
|
-
invalid_type_error: "merge_request_iid is required",
|
|
2287
|
+
error: "merge_request_iid is required",
|
|
2288
2288
|
})
|
|
2289
2289
|
.refine(value => value.trim().length > 0, "merge_request_iid is required")
|
|
2290
2290
|
.transform(value => value.trim()))
|
|
@@ -2806,7 +2806,7 @@ export const GitLabWikiPageSchema = z.object({
|
|
|
2806
2806
|
slug: z.string(),
|
|
2807
2807
|
format: z.string(),
|
|
2808
2808
|
content: z.string().optional(),
|
|
2809
|
-
front_matter: z.record(z.unknown()).optional(),
|
|
2809
|
+
front_matter: z.record(z.string(), z.unknown()).optional(),
|
|
2810
2810
|
created_at: z.string().optional(),
|
|
2811
2811
|
updated_at: z.string().optional(),
|
|
2812
2812
|
});
|
|
@@ -2978,7 +2978,7 @@ export const GitLabDraftNoteSchema = z
|
|
|
2978
2978
|
merge_request_id: z.coerce.number().nullable().optional(),
|
|
2979
2979
|
commit_id: z.string().nullable().optional(),
|
|
2980
2980
|
discussion_id: z.string().nullable().optional(),
|
|
2981
|
-
position: z.record(z.unknown()).nullable().optional(),
|
|
2981
|
+
position: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
2982
2982
|
resolve_discussion: z.coerce.boolean().optional(),
|
|
2983
2983
|
})
|
|
2984
2984
|
.transform(data => ({
|
|
@@ -3564,7 +3564,10 @@ export const GitLabMergeRequestVersionDetailSchema = GitLabMergeRequestVersionSc
|
|
|
3564
3564
|
// GraphQL generic execution schema
|
|
3565
3565
|
export const ExecuteGraphQLSchema = z.object({
|
|
3566
3566
|
query: z.string().describe("GraphQL query string"),
|
|
3567
|
-
variables: z
|
|
3567
|
+
variables: z
|
|
3568
|
+
.record(z.string(), z.any())
|
|
3569
|
+
.optional()
|
|
3570
|
+
.describe("Variables object for the GraphQL query"),
|
|
3568
3571
|
});
|
|
3569
3572
|
// Release schemas
|
|
3570
3573
|
export const GitLabReleaseAssetLinkSchema = z.object({
|
|
@@ -3857,10 +3860,10 @@ export const GitLabTagSignatureSchema = z.object({
|
|
|
3857
3860
|
});
|
|
3858
3861
|
// --- Work item schemas (GraphQL-based) ---
|
|
3859
3862
|
// Case-insensitive work item type enum (accepts "ISSUE", "Issue", "issue")
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3863
|
+
// Case-insensitive enum: lowercase the input, then validate against allowed values.
|
|
3864
|
+
// (z.preprocess form so the enum stays visible to JSON Schema conversion;
|
|
3865
|
+
// a transform().pipe() chain only exposes its input side as a plain string.)
|
|
3866
|
+
const workItemTypeEnum = z.preprocess(v => (typeof v === "string" ? v.toLowerCase() : v), z.enum([
|
|
3864
3867
|
"issue",
|
|
3865
3868
|
"task",
|
|
3866
3869
|
"incident",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { GitLabPipelineScheduleSchema } from "../schemas.js";
|
|
4
|
+
const BASE_SCHEDULE = {
|
|
5
|
+
id: 13,
|
|
6
|
+
description: "Nightly build",
|
|
7
|
+
cron: "0 1 * * *",
|
|
8
|
+
active: true,
|
|
9
|
+
created_at: "2026-01-01T00:00:00Z",
|
|
10
|
+
updated_at: "2026-02-01T00:00:00Z",
|
|
11
|
+
};
|
|
12
|
+
test("pipeline schedule response accepts inputs without value", () => {
|
|
13
|
+
// Zod 4 rejects a missing key on required unknown (Zod 3 accepted it);
|
|
14
|
+
// schedule inputs must tolerate a valueless entry.
|
|
15
|
+
const parsed = GitLabPipelineScheduleSchema.parse({
|
|
16
|
+
...BASE_SCHEDULE,
|
|
17
|
+
inputs: [{ name: "deploy_strategy" }],
|
|
18
|
+
});
|
|
19
|
+
assert.equal(parsed.inputs?.[0].name, "deploy_strategy");
|
|
20
|
+
assert.equal("value" in (parsed.inputs?.[0] ?? {}), false);
|
|
21
|
+
});
|
|
22
|
+
test("pipeline schedule response keeps inputs with value", () => {
|
|
23
|
+
const parsed = GitLabPipelineScheduleSchema.parse({
|
|
24
|
+
...BASE_SCHEDULE,
|
|
25
|
+
inputs: [
|
|
26
|
+
{ name: "deploy_strategy", value: "blue-green" },
|
|
27
|
+
{ name: "matrix", value: { os: "linux" } },
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
assert.equal(parsed.inputs?.[0].value, "blue-green");
|
|
31
|
+
assert.deepEqual(parsed.inputs?.[1].value, { os: "linux" });
|
|
32
|
+
});
|
|
@@ -17,8 +17,9 @@ test("group milestone response keeps group_id and rejects missing group_id", ()
|
|
|
17
17
|
});
|
|
18
18
|
assert.equal(parsed.group_id, "16");
|
|
19
19
|
assert.equal("project_id" in parsed, false);
|
|
20
|
-
// Project schema
|
|
21
|
-
|
|
20
|
+
// Project schema rejects a group payload (missing project_id) — why group schema exists.
|
|
21
|
+
// (Zod 3 coerced the missing key to the string "undefined"; Zod 4 rejects it.)
|
|
22
|
+
assert.throws(() => GitLabMilestonesSchema.parse({
|
|
22
23
|
id: 12,
|
|
23
24
|
iid: 3,
|
|
24
25
|
group_id: 16,
|
|
@@ -30,8 +31,7 @@ test("group milestone response keeps group_id and rejects missing group_id", ()
|
|
|
30
31
|
updated_at: "2013-10-02T09:24:18Z",
|
|
31
32
|
created_at: "2013-10-02T09:24:18Z",
|
|
32
33
|
expired: false,
|
|
33
|
-
});
|
|
34
|
-
assert.equal(coerced.project_id, "undefined");
|
|
34
|
+
}));
|
|
35
35
|
});
|
|
36
36
|
test("group milestone issues schema accepts page and per_page", () => {
|
|
37
37
|
const parsed = GetGroupMilestoneIssuesSchema.parse({
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { after, before, describe, test } from "node:test";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { Buffer } from "node:buffer";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path, { dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
4
7
|
import { cleanupServers, findAvailablePort, HOST, launchServer, TransportMode, } from "./utils/server-launcher.js";
|
|
5
8
|
import { findMockServerPort, MockGitLabServer } from "./utils/mock-gitlab-server.js";
|
|
6
9
|
import { CustomHeaderClient } from "./clients/custom-header-client.js";
|
|
7
10
|
const MOCK_TOKEN = "mock-concurrent-token-12345";
|
|
8
11
|
const TEST_PROJECT_ID = "123";
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
const packageJsonPath = path.resolve(__dirname, "../package.json");
|
|
15
|
+
const PACKAGE_VERSION = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
|
|
9
16
|
function fileResponse(filePath, content) {
|
|
10
17
|
return {
|
|
11
18
|
file_name: filePath.split("/").at(-1),
|
|
@@ -129,6 +136,14 @@ describe("Streamable HTTP health check capacity logging", { timeout: 20_000 }, (
|
|
|
129
136
|
if (mockGitLab)
|
|
130
137
|
await mockGitLab.stop();
|
|
131
138
|
});
|
|
139
|
+
test("reports server version when healthy", async () => {
|
|
140
|
+
const response = await fetch(`${baseUrl}/health`);
|
|
141
|
+
const body = (await response.json());
|
|
142
|
+
assert.strictEqual(response.status, 200);
|
|
143
|
+
assert.strictEqual(body.status, "healthy");
|
|
144
|
+
assert.strictEqual(body.version, PACKAGE_VERSION);
|
|
145
|
+
assert.strictEqual(body.activeSessions, 0);
|
|
146
|
+
});
|
|
132
147
|
test("logs active session capacity when health check is degraded", async () => {
|
|
133
148
|
const client = new CustomHeaderClient({ Authorization: `Bearer ${MOCK_TOKEN}` });
|
|
134
149
|
await client.connect(mcpUrl);
|
|
@@ -137,6 +152,7 @@ describe("Streamable HTTP health check capacity logging", { timeout: 20_000 }, (
|
|
|
137
152
|
const body = (await response.json());
|
|
138
153
|
assert.strictEqual(response.status, 503);
|
|
139
154
|
assert.strictEqual(body.status, "degraded");
|
|
155
|
+
assert.strictEqual(body.version, PACKAGE_VERSION);
|
|
140
156
|
assert.strictEqual(body.activeSessions, 1);
|
|
141
157
|
assert.strictEqual(body.maxSessions, 1);
|
|
142
158
|
// ponytail: poll stdout; fixed 100ms sleep flakes under CI jitter
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { describe, test } from "node:test";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { spawn } from "child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path, { dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
4
7
|
import { MockGitLabServer, findMockServerPort } from "./utils/mock-gitlab-server.js";
|
|
5
8
|
const MOCK_TOKEN = "glpat-mock-token-12345";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
const packageJsonPath = path.resolve(__dirname, "../package.json");
|
|
12
|
+
const PACKAGE_VERSION = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
|
|
6
13
|
function createMockGitLabServer(port) {
|
|
7
14
|
return new MockGitLabServer({
|
|
8
15
|
port,
|
|
@@ -73,6 +80,7 @@ describe("When health_check runs", () => {
|
|
|
73
80
|
const result = await callHealthCheckAsync(baseEnv(mockGitLab.getUrl()));
|
|
74
81
|
assert.equal(result.status, "ok");
|
|
75
82
|
assert.equal(result.authenticated, true);
|
|
83
|
+
assert.equal(result.mcp_server_version, PACKAGE_VERSION);
|
|
76
84
|
assert.equal(result.version, "18.3.1-ee");
|
|
77
85
|
assert.equal(result.revision, "abc1234");
|
|
78
86
|
assert.equal(result.enterprise, true);
|
|
@@ -94,6 +102,7 @@ describe("When health_check runs", () => {
|
|
|
94
102
|
const result = await callHealthCheckAsync(baseEnv(mockGitLab.getUrl()));
|
|
95
103
|
assert.equal(result.status, "ok");
|
|
96
104
|
assert.equal(result.authenticated, true);
|
|
105
|
+
assert.equal(result.mcp_server_version, PACKAGE_VERSION);
|
|
97
106
|
assert.equal("version" in result, false);
|
|
98
107
|
assert.equal("revision" in result, false);
|
|
99
108
|
assert.equal("enterprise" in result, false);
|
|
@@ -101,7 +101,7 @@ describe("update_project", () => {
|
|
|
101
101
|
await assert.rejects(() => callUpdateProject({ project_id: TEST_PROJECT_ID, issues_access_level: "public" }, {
|
|
102
102
|
GITLAB_API_URL: "https://gitlab.example.com/api/v4",
|
|
103
103
|
GITLAB_PERSONAL_ACCESS_TOKEN: MOCK_TOKEN,
|
|
104
|
-
}), /Invalid enum value/);
|
|
104
|
+
}), /(Invalid enum value|Invalid option)/);
|
|
105
105
|
});
|
|
106
106
|
test("rejects empty updates before calling GitLab", async () => {
|
|
107
107
|
await assert.rejects(() => callUpdateProject({ project_id: TEST_PROJECT_ID }, {
|
package/build/tools/registry.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
2
1
|
import { toJSONSchema } from "../utils/schema.js";
|
|
3
2
|
import { USE_GITLAB_WIKI, USE_MILESTONE, USE_PIPELINE, SSE, STREAMABLE_HTTP, } from "../config.js";
|
|
4
3
|
import { getToolDescription } from "./tool-descriptions.js";
|
|
@@ -39,7 +38,7 @@ export const allTools = [
|
|
|
39
38
|
{
|
|
40
39
|
name: "execute_graphql",
|
|
41
40
|
description: "Execute a GitLab GraphQL query",
|
|
42
|
-
inputSchema:
|
|
41
|
+
inputSchema: toJSONSchema(ExecuteGraphQLSchema),
|
|
43
42
|
},
|
|
44
43
|
{
|
|
45
44
|
name: "create_or_update_file",
|
|
@@ -917,7 +916,7 @@ export const allTools = [
|
|
|
917
916
|
},
|
|
918
917
|
{
|
|
919
918
|
name: "health_check",
|
|
920
|
-
description: "Verify server status and authentication. When authenticated, also reports the GitLab instance version from GET /api/v4/version (version, revision, enterprise). Version lookup failures do not fail the health check — those fields are omitted.",
|
|
919
|
+
description: "Verify server status and authentication. Always reports the MCP server version (mcp_server_version). When authenticated, also reports the GitLab instance version from GET /api/v4/version (version, revision, enterprise). Version lookup failures do not fail the health check — those fields are omitted.",
|
|
921
920
|
inputSchema: toJSONSchema(HealthCheckSchema),
|
|
922
921
|
},
|
|
923
922
|
{
|
package/build/utils/schema.js
CHANGED
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
2
|
/**
|
|
4
3
|
* Convert a Zod schema to JSON Schema, fixing nullable/optional fields
|
|
5
4
|
* so they are not marked as required, and extracting required fields from the Zod schema.
|
|
6
5
|
*/
|
|
7
6
|
export const toJSONSchema = (schema) => {
|
|
8
|
-
|
|
7
|
+
// Zod 4 native conversion. (zod-to-json-schema only understands Zod 3
|
|
8
|
+
// internals and silently emits an empty schema for Zod 4 schemas.)
|
|
9
|
+
// draft-7 keeps output closest to the previous converter; io:"input"
|
|
10
|
+
// describes tool arguments (preprocess/coerce evaluated input-side).
|
|
11
|
+
const jsonSchema = z.toJSONSchema(schema, { target: "draft-7", io: "input" });
|
|
12
|
+
// Public classes only (no _def access): works on both Zod 3 and Zod 4,
|
|
13
|
+
// whose internals differ (_def.typeName vs _zod.def.type).
|
|
9
14
|
const isOptionalLikeField = (zodType) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
if (zodType instanceof z.ZodOptional ||
|
|
16
|
+
zodType instanceof z.ZodNullable ||
|
|
17
|
+
zodType instanceof z.ZodDefault ||
|
|
18
|
+
zodType instanceof z.ZodCatch) {
|
|
13
19
|
return true;
|
|
14
20
|
}
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
// ZodEffects (v3 preprocess/refine/transform): unwrap the inner schema.
|
|
22
|
+
const ZodEffects = z.ZodEffects;
|
|
23
|
+
if (ZodEffects &&
|
|
24
|
+
zodType instanceof ZodEffects &&
|
|
25
|
+
typeof zodType.innerType === "function") {
|
|
26
|
+
return isOptionalLikeField(zodType.innerType());
|
|
17
27
|
}
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
// ZodBranded: unwrap to the branded schema.
|
|
29
|
+
const ZodBranded = z.ZodBranded;
|
|
30
|
+
if (ZodBranded &&
|
|
31
|
+
zodType instanceof ZodBranded &&
|
|
32
|
+
typeof zodType.unwrap === "function") {
|
|
33
|
+
return isOptionalLikeField(zodType.unwrap());
|
|
20
34
|
}
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
// Pipes (v3 ZodPipeline / v4 ZodPipe/ZodPreprocess from preprocess/transform):
|
|
36
|
+
// optional-like when either side is optional-like.
|
|
37
|
+
const maybeIn = zodType.in;
|
|
38
|
+
const maybeOut = zodType.out;
|
|
39
|
+
if (maybeIn instanceof z.ZodType && maybeOut instanceof z.ZodType) {
|
|
40
|
+
return isOptionalLikeField(maybeIn) || isOptionalLikeField(maybeOut);
|
|
23
41
|
}
|
|
24
42
|
return false;
|
|
25
43
|
};
|
|
26
|
-
// Extract required fields from Zod schema
|
|
27
|
-
|
|
44
|
+
// Extract required fields from Zod schema (authoritative for the root object:
|
|
45
|
+
// the native converter marks defaulted fields as required, we keep the
|
|
46
|
+
// previous convention that defaulted/optional-like fields are not required).
|
|
47
|
+
const { zodRequiredFields, hasAuthoritativeRequired } = (() => {
|
|
28
48
|
if (schema instanceof z.ZodObject) {
|
|
29
49
|
const shape = schema.shape;
|
|
30
50
|
const requiredFields = [];
|
|
@@ -34,9 +54,9 @@ export const toJSONSchema = (schema) => {
|
|
|
34
54
|
requiredFields.push(key);
|
|
35
55
|
}
|
|
36
56
|
});
|
|
37
|
-
return requiredFields;
|
|
57
|
+
return { zodRequiredFields: requiredFields, hasAuthoritativeRequired: true };
|
|
38
58
|
}
|
|
39
|
-
return [];
|
|
59
|
+
return { zodRequiredFields: [], hasAuthoritativeRequired: false };
|
|
40
60
|
})();
|
|
41
61
|
// Post-process to fix nullable/optional fields and strip verbose keys
|
|
42
62
|
function fixNullableOptional(obj, isRoot = false) {
|
|
@@ -47,14 +67,13 @@ export const toJSONSchema = (schema) => {
|
|
|
47
67
|
delete obj.additionalProperties;
|
|
48
68
|
// If this object has properties, process them
|
|
49
69
|
if (obj.properties) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
zodRequiredFields.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
70
|
+
let requiredSet;
|
|
71
|
+
if (isRoot && hasAuthoritativeRequired) {
|
|
72
|
+
// Zod shape is the source of truth at root level.
|
|
73
|
+
requiredSet = new Set(zodRequiredFields.filter(field => obj.properties[field]));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
requiredSet = new Set(obj.required || []);
|
|
58
77
|
}
|
|
59
78
|
Object.keys(obj.properties).forEach(key => {
|
|
60
79
|
const prop = obj.properties[key];
|
|
@@ -66,6 +85,10 @@ export const toJSONSchema = (schema) => {
|
|
|
66
85
|
else if (Array.isArray(prop.type) && prop.type.includes("null")) {
|
|
67
86
|
requiredSet.delete(key);
|
|
68
87
|
}
|
|
88
|
+
// Fields with defaults are not required (previous converter semantics).
|
|
89
|
+
if (prop && typeof prop === "object" && "default" in prop) {
|
|
90
|
+
requiredSet.delete(key);
|
|
91
|
+
}
|
|
69
92
|
// Recursively process nested objects (not root)
|
|
70
93
|
obj.properties[key] = fixNullableOptional(prop, false);
|
|
71
94
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.62",
|
|
4
4
|
"mcpName": "io.github.zereight/gitlab-mcp",
|
|
5
5
|
"description": "GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more",
|
|
6
6
|
"keywords": [
|
|
@@ -85,8 +85,7 @@
|
|
|
85
85
|
"tldts": "^6.1.86",
|
|
86
86
|
"tough-cookie": "^5.1.2",
|
|
87
87
|
"undici": "^6.28.0",
|
|
88
|
-
"zod": "^
|
|
89
|
-
"zod-to-json-schema": "3.24.5"
|
|
88
|
+
"zod": "^4.6.5"
|
|
90
89
|
},
|
|
91
90
|
"devDependencies": {
|
|
92
91
|
"@types/express": "^5.0.2",
|