@zereight/mcp-gitlab 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -27
- package/build/index.js +119 -2
- package/build/schemas.js +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,10 +52,10 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
52
52
|
"GITLAB_READ_ONLY_MODE",
|
|
53
53
|
"-e",
|
|
54
54
|
"USE_GITLAB_WIKI",
|
|
55
|
-
"nkwd/mcp
|
|
55
|
+
"nkwd/gitlab-mcp"
|
|
56
56
|
],
|
|
57
57
|
"env": {
|
|
58
|
-
"
|
|
58
|
+
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
|
|
59
59
|
"GITLAB_API_URL": "https://gitlab.com/api/v4", // Optional, for self-hosted GitLab
|
|
60
60
|
"GITLAB_READ_ONLY_MODE": "false",
|
|
61
61
|
"USE_GITLAB_WIKI": "true"
|
|
@@ -93,29 +93,32 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
93
93
|
15. `mr_discussions` - List discussion items for a merge request
|
|
94
94
|
16. `update_merge_request_note` - Modify an existing merge request thread note
|
|
95
95
|
17. `create_merge_request_note` - Add a new note to an existing merge request thread
|
|
96
|
-
18. `
|
|
97
|
-
19. `
|
|
98
|
-
20. `
|
|
99
|
-
21. `
|
|
100
|
-
22. `
|
|
101
|
-
23. `
|
|
102
|
-
24. `
|
|
103
|
-
25. `
|
|
104
|
-
26. `
|
|
105
|
-
27. `
|
|
106
|
-
28. `
|
|
107
|
-
29. `
|
|
108
|
-
30. `
|
|
109
|
-
31. `
|
|
110
|
-
32. `
|
|
111
|
-
33. `
|
|
112
|
-
34. `
|
|
113
|
-
35. `
|
|
114
|
-
36. `
|
|
115
|
-
37. `
|
|
116
|
-
38. `
|
|
117
|
-
39. `
|
|
118
|
-
40. `
|
|
119
|
-
41. `
|
|
120
|
-
42. `
|
|
96
|
+
18. `update_issue_note` - Update the content of an existing issue note
|
|
97
|
+
19. `create_issue_note` - Add a new note to an existing issue thread
|
|
98
|
+
20. `list_issues` - List issues in a GitLab project with filtering options
|
|
99
|
+
21. `get_issue` - Get details of a specific issue in a GitLab project
|
|
100
|
+
22. `update_issue` - Update an issue in a GitLab project
|
|
101
|
+
23. `delete_issue` - Delete an issue from a GitLab project
|
|
102
|
+
24. `list_issue_links` - List all issue links for a specific issue
|
|
103
|
+
25. `list_issue_discussions` - List discussions for an issue in a GitLab project
|
|
104
|
+
26. `get_issue_link` - Get a specific issue link
|
|
105
|
+
27. `create_issue_link` - Create an issue link between two issues
|
|
106
|
+
28. `delete_issue_link` - Delete an issue link
|
|
107
|
+
29. `list_namespaces` - List all namespaces available to the current user
|
|
108
|
+
30. `get_namespace` - Get details of a namespace by ID or path
|
|
109
|
+
31. `verify_namespace` - Verify if a namespace path exists
|
|
110
|
+
32. `get_project` - Get details of a specific project
|
|
111
|
+
33. `list_projects` - List projects accessible by the current user
|
|
112
|
+
34. `list_labels` - List labels for a project
|
|
113
|
+
35. `get_label` - Get a single label from a project
|
|
114
|
+
36. `create_label` - Create a new label in a project
|
|
115
|
+
37. `update_label` - Update an existing label in a project
|
|
116
|
+
38. `delete_label` - Delete a label from a project
|
|
117
|
+
39. `list_group_projects` - List projects in a GitLab group with filtering options
|
|
118
|
+
40. `list_wiki_pages` - List wiki pages in a GitLab project
|
|
119
|
+
41. `get_wiki_page` - Get details of a specific wiki page
|
|
120
|
+
42. `create_wiki_page` - Create a new wiki page in a GitLab project
|
|
121
|
+
43. `update_wiki_page` - Update an existing wiki page in a GitLab project
|
|
122
|
+
44. `delete_wiki_page` - Delete a wiki page from a GitLab project
|
|
123
|
+
45. `get_repository_tree` - Get the repository tree for a GitLab project (list files and directories)
|
|
121
124
|
<!-- TOOLS-END -->
|
package/build/index.js
CHANGED
|
@@ -13,12 +13,12 @@ import { dirname } from "path";
|
|
|
13
13
|
import fs from "fs";
|
|
14
14
|
import path from "path";
|
|
15
15
|
import { URL } from "url";
|
|
16
|
-
import { GitLabForkSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabIssueSchema, GitLabMergeRequestSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabSearchResponseSchema, GitLabTreeSchema, GitLabCommitSchema, GitLabNamespaceSchema, GitLabNamespaceExistsResponseSchema, GitLabProjectSchema, CreateOrUpdateFileSchema, SearchRepositoriesSchema, CreateRepositorySchema, GetFileContentsSchema, PushFilesSchema, CreateIssueSchema, CreateMergeRequestSchema, ForkRepositorySchema, CreateBranchSchema, GitLabMergeRequestDiffSchema, GetMergeRequestSchema, GetMergeRequestDiffsSchema, UpdateMergeRequestSchema, ListIssuesSchema, GetIssueSchema, UpdateIssueSchema, DeleteIssueSchema, GitLabIssueLinkSchema, GitLabIssueWithLinkDetailsSchema, ListIssueLinksSchema, GetIssueLinkSchema, CreateIssueLinkSchema, DeleteIssueLinkSchema, ListNamespacesSchema, GetNamespaceSchema, VerifyNamespaceSchema, GetProjectSchema, ListProjectsSchema, ListLabelsSchema, GetLabelSchema, CreateLabelSchema, UpdateLabelSchema, DeleteLabelSchema, CreateNoteSchema, CreateMergeRequestThreadSchema, ListGroupProjectsSchema, ListWikiPagesSchema, GetWikiPageSchema, CreateWikiPageSchema, UpdateWikiPageSchema, DeleteWikiPageSchema, GitLabWikiPageSchema,
|
|
16
|
+
import { GitLabForkSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabIssueSchema, GitLabMergeRequestSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabSearchResponseSchema, GitLabTreeSchema, GitLabCommitSchema, GitLabNamespaceSchema, GitLabNamespaceExistsResponseSchema, GitLabProjectSchema, CreateOrUpdateFileSchema, SearchRepositoriesSchema, CreateRepositorySchema, GetFileContentsSchema, PushFilesSchema, CreateIssueSchema, CreateMergeRequestSchema, ForkRepositorySchema, CreateBranchSchema, GitLabMergeRequestDiffSchema, GetMergeRequestSchema, GetMergeRequestDiffsSchema, UpdateMergeRequestSchema, ListIssuesSchema, GetIssueSchema, UpdateIssueSchema, DeleteIssueSchema, GitLabIssueLinkSchema, GitLabIssueWithLinkDetailsSchema, ListIssueLinksSchema, ListIssueDiscussionsSchema, GetIssueLinkSchema, CreateIssueLinkSchema, DeleteIssueLinkSchema, ListNamespacesSchema, GetNamespaceSchema, VerifyNamespaceSchema, GetProjectSchema, ListProjectsSchema, ListLabelsSchema, GetLabelSchema, CreateLabelSchema, UpdateLabelSchema, DeleteLabelSchema, CreateNoteSchema, CreateMergeRequestThreadSchema, ListGroupProjectsSchema, ListWikiPagesSchema, GetWikiPageSchema, CreateWikiPageSchema, UpdateWikiPageSchema, DeleteWikiPageSchema, GitLabWikiPageSchema,
|
|
17
17
|
// Discussion Schemas
|
|
18
18
|
GitLabDiscussionNoteSchema, // Added
|
|
19
19
|
GitLabDiscussionSchema, UpdateMergeRequestNoteSchema, // Added
|
|
20
20
|
CreateMergeRequestNoteSchema, // Added
|
|
21
|
-
ListMergeRequestDiscussionsSchema, GitLabTreeItemSchema, GetRepositoryTreeSchema, } from "./schemas.js";
|
|
21
|
+
ListMergeRequestDiscussionsSchema, GitLabTreeItemSchema, GetRepositoryTreeSchema, UpdateIssueNoteSchema, CreateIssueNoteSchema, } from "./schemas.js";
|
|
22
22
|
/**
|
|
23
23
|
* Read version from package.json
|
|
24
24
|
*/
|
|
@@ -171,6 +171,16 @@ const allTools = [
|
|
|
171
171
|
description: "Add a new note to an existing merge request thread",
|
|
172
172
|
inputSchema: zodToJsonSchema(CreateMergeRequestNoteSchema),
|
|
173
173
|
},
|
|
174
|
+
{
|
|
175
|
+
name: "update_issue_note",
|
|
176
|
+
description: "Modify an existing issue thread note",
|
|
177
|
+
inputSchema: zodToJsonSchema(UpdateIssueNoteSchema),
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "create_issue_note",
|
|
181
|
+
description: "Add a new note to an existing issue thread",
|
|
182
|
+
inputSchema: zodToJsonSchema(CreateIssueNoteSchema),
|
|
183
|
+
},
|
|
174
184
|
{
|
|
175
185
|
name: "list_issues",
|
|
176
186
|
description: "List issues in a GitLab project with filtering options",
|
|
@@ -196,6 +206,11 @@ const allTools = [
|
|
|
196
206
|
description: "List all issue links for a specific issue",
|
|
197
207
|
inputSchema: zodToJsonSchema(ListIssueLinksSchema),
|
|
198
208
|
},
|
|
209
|
+
{
|
|
210
|
+
name: "list_issue_discussions",
|
|
211
|
+
description: "List discussions for an issue in a GitLab project",
|
|
212
|
+
inputSchema: zodToJsonSchema(ListIssueDiscussionsSchema),
|
|
213
|
+
},
|
|
199
214
|
{
|
|
200
215
|
name: "get_issue_link",
|
|
201
216
|
description: "Get a specific issue link",
|
|
@@ -307,6 +322,7 @@ const readOnlyTools = [
|
|
|
307
322
|
"list_issues",
|
|
308
323
|
"get_issue",
|
|
309
324
|
"list_issue_links",
|
|
325
|
+
"list_issue_discussions",
|
|
310
326
|
"get_issue_link",
|
|
311
327
|
"list_namespaces",
|
|
312
328
|
"get_namespace",
|
|
@@ -733,6 +749,38 @@ async function listMergeRequestDiscussions(projectId, mergeRequestIid) {
|
|
|
733
749
|
// Ensure the response is parsed as an array of discussions
|
|
734
750
|
return z.array(GitLabDiscussionSchema).parse(data);
|
|
735
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* List discussions for an issue
|
|
754
|
+
*
|
|
755
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
756
|
+
* @param {number} issueIid - The internal ID of the project issue
|
|
757
|
+
* @param {Object} options - Pagination and sorting options
|
|
758
|
+
* @returns {Promise<GitLabDiscussion[]>} List of issue discussions
|
|
759
|
+
*/
|
|
760
|
+
async function listIssueDiscussions(projectId, issueIid, options = {}) {
|
|
761
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
762
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/discussions`);
|
|
763
|
+
// Add query parameters for pagination and sorting
|
|
764
|
+
if (options.page) {
|
|
765
|
+
url.searchParams.append("page", options.page.toString());
|
|
766
|
+
}
|
|
767
|
+
if (options.per_page) {
|
|
768
|
+
url.searchParams.append("per_page", options.per_page.toString());
|
|
769
|
+
}
|
|
770
|
+
if (options.sort) {
|
|
771
|
+
url.searchParams.append("sort", options.sort);
|
|
772
|
+
}
|
|
773
|
+
if (options.order_by) {
|
|
774
|
+
url.searchParams.append("order_by", options.order_by);
|
|
775
|
+
}
|
|
776
|
+
const response = await fetch(url.toString(), {
|
|
777
|
+
...DEFAULT_FETCH_CONFIG,
|
|
778
|
+
});
|
|
779
|
+
await handleGitLabError(response);
|
|
780
|
+
const data = await response.json();
|
|
781
|
+
// Parse the response as an array of discussions
|
|
782
|
+
return z.array(GitLabDiscussionSchema).parse(data);
|
|
783
|
+
}
|
|
736
784
|
/**
|
|
737
785
|
* Modify an existing merge request thread note
|
|
738
786
|
* 병합 요청 토론 노트 수정
|
|
@@ -765,6 +813,53 @@ async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId,
|
|
|
765
813
|
const data = await response.json();
|
|
766
814
|
return GitLabDiscussionNoteSchema.parse(data);
|
|
767
815
|
}
|
|
816
|
+
/**
|
|
817
|
+
* Update an issue discussion note
|
|
818
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
819
|
+
* @param {number} issueIid - The IID of an issue
|
|
820
|
+
* @param {string} discussionId - The ID of a thread
|
|
821
|
+
* @param {number} noteId - The ID of a thread note
|
|
822
|
+
* @param {string} body - The new content of the note
|
|
823
|
+
* @returns {Promise<GitLabDiscussionNote>} The updated note
|
|
824
|
+
*/
|
|
825
|
+
async function updateIssueNote(projectId, issueIid, discussionId, noteId, body) {
|
|
826
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
827
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/discussions/${discussionId}/notes/${noteId}`);
|
|
828
|
+
const payload = { body };
|
|
829
|
+
const response = await fetch(url.toString(), {
|
|
830
|
+
...DEFAULT_FETCH_CONFIG,
|
|
831
|
+
method: "PUT",
|
|
832
|
+
body: JSON.stringify(payload),
|
|
833
|
+
});
|
|
834
|
+
await handleGitLabError(response);
|
|
835
|
+
const data = await response.json();
|
|
836
|
+
return GitLabDiscussionNoteSchema.parse(data);
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Create a note in an issue discussion
|
|
840
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
841
|
+
* @param {number} issueIid - The IID of an issue
|
|
842
|
+
* @param {string} discussionId - The ID of a thread
|
|
843
|
+
* @param {string} body - The content of the new note
|
|
844
|
+
* @param {string} [createdAt] - The creation date of the note (ISO 8601 format)
|
|
845
|
+
* @returns {Promise<GitLabDiscussionNote>} The created note
|
|
846
|
+
*/
|
|
847
|
+
async function createIssueNote(projectId, issueIid, discussionId, body, createdAt) {
|
|
848
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
849
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/discussions/${discussionId}/notes`);
|
|
850
|
+
const payload = { body };
|
|
851
|
+
if (createdAt) {
|
|
852
|
+
payload.created_at = createdAt;
|
|
853
|
+
}
|
|
854
|
+
const response = await fetch(url.toString(), {
|
|
855
|
+
...DEFAULT_FETCH_CONFIG,
|
|
856
|
+
method: "POST",
|
|
857
|
+
body: JSON.stringify(payload),
|
|
858
|
+
});
|
|
859
|
+
await handleGitLabError(response);
|
|
860
|
+
const data = await response.json();
|
|
861
|
+
return GitLabDiscussionNoteSchema.parse(data);
|
|
862
|
+
}
|
|
768
863
|
/**
|
|
769
864
|
* Add a new note to an existing merge request thread
|
|
770
865
|
* 기존 병합 요청 스레드에 새 노트 추가
|
|
@@ -1704,6 +1799,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1704
1799
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
1705
1800
|
};
|
|
1706
1801
|
}
|
|
1802
|
+
case "update_issue_note": {
|
|
1803
|
+
const args = UpdateIssueNoteSchema.parse(request.params.arguments);
|
|
1804
|
+
const note = await updateIssueNote(args.project_id, args.issue_iid, args.discussion_id, args.note_id, args.body);
|
|
1805
|
+
return {
|
|
1806
|
+
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
case "create_issue_note": {
|
|
1810
|
+
const args = CreateIssueNoteSchema.parse(request.params.arguments);
|
|
1811
|
+
const note = await createIssueNote(args.project_id, args.issue_iid, args.discussion_id, args.body, args.created_at);
|
|
1812
|
+
return {
|
|
1813
|
+
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1707
1816
|
case "get_merge_request": {
|
|
1708
1817
|
const args = GetMergeRequestSchema.parse(request.params.arguments);
|
|
1709
1818
|
const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid, args.source_branch);
|
|
@@ -1872,6 +1981,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1872
1981
|
content: [{ type: "text", text: JSON.stringify(links, null, 2) }],
|
|
1873
1982
|
};
|
|
1874
1983
|
}
|
|
1984
|
+
case "list_issue_discussions": {
|
|
1985
|
+
const args = ListIssueDiscussionsSchema.parse(request.params.arguments);
|
|
1986
|
+
const { project_id, issue_iid, ...options } = args;
|
|
1987
|
+
const discussions = await listIssueDiscussions(project_id, issue_iid, options);
|
|
1988
|
+
return {
|
|
1989
|
+
content: [{ type: "text", text: JSON.stringify(discussions, null, 2) }],
|
|
1990
|
+
};
|
|
1991
|
+
}
|
|
1875
1992
|
case "get_issue_link": {
|
|
1876
1993
|
const args = GetIssueLinkSchema.parse(request.params.arguments);
|
|
1877
1994
|
const link = await getIssueLink(args.project_id, args.issue_iid, args.issue_link_id);
|
package/build/schemas.js
CHANGED
|
@@ -448,6 +448,20 @@ export const CreateMergeRequestNoteSchema = ProjectParamsSchema.extend({
|
|
|
448
448
|
body: z.string().describe("The content of the note or reply"),
|
|
449
449
|
created_at: z.string().optional().describe("Date the note was created at (ISO 8601 format)"),
|
|
450
450
|
});
|
|
451
|
+
// Input schema for updating an issue discussion note
|
|
452
|
+
export const UpdateIssueNoteSchema = ProjectParamsSchema.extend({
|
|
453
|
+
issue_iid: z.number().describe("The IID of an issue"),
|
|
454
|
+
discussion_id: z.string().describe("The ID of a thread"),
|
|
455
|
+
note_id: z.number().describe("The ID of a thread note"),
|
|
456
|
+
body: z.string().describe("The content of the note or reply"),
|
|
457
|
+
});
|
|
458
|
+
// Input schema for adding a note to an existing issue discussion
|
|
459
|
+
export const CreateIssueNoteSchema = ProjectParamsSchema.extend({
|
|
460
|
+
issue_iid: z.number().describe("The IID of an issue"),
|
|
461
|
+
discussion_id: z.string().describe("The ID of a thread"),
|
|
462
|
+
body: z.string().describe("The content of the note or reply"),
|
|
463
|
+
created_at: z.string().optional().describe("Date the note was created at (ISO 8601 format)"),
|
|
464
|
+
});
|
|
451
465
|
// API Operation Parameter Schemas
|
|
452
466
|
export const CreateOrUpdateFileSchema = ProjectParamsSchema.extend({
|
|
453
467
|
file_path: z.string().describe("Path where to create/update the file"),
|
|
@@ -691,6 +705,14 @@ export const ListIssueLinksSchema = z.object({
|
|
|
691
705
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
692
706
|
issue_iid: z.number().describe("The internal ID of a project's issue"),
|
|
693
707
|
});
|
|
708
|
+
export const ListIssueDiscussionsSchema = z.object({
|
|
709
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
710
|
+
issue_iid: z.number().describe("The internal ID of the project issue"),
|
|
711
|
+
page: z.number().optional().describe("Page number for pagination"),
|
|
712
|
+
per_page: z.number().optional().describe("Number of items per page"),
|
|
713
|
+
sort: z.enum(["asc", "desc"]).optional().describe("Return issue discussions sorted in ascending or descending order"),
|
|
714
|
+
order_by: z.enum(["created_at", "updated_at"]).optional().describe("Return issue discussions ordered by created_at or updated_at fields"),
|
|
715
|
+
});
|
|
694
716
|
export const GetIssueLinkSchema = z.object({
|
|
695
717
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
696
718
|
issue_iid: z.number().describe("The internal ID of a project's issue"),
|