@zereight/mcp-gitlab 1.0.36 → 1.0.38

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 CHANGED
@@ -55,31 +55,33 @@ When using with the Claude App, you need to set up your API key and URLs directl
55
55
  11. `get_merge_request_diffs` - Get the changes/diffs of a merge request (Either mergeRequestIid or branchName must be provided)
56
56
  12. `update_merge_request` - Update a merge request (Either mergeRequestIid or branchName must be provided)
57
57
  13. `create_note` - Create a new note (comment) to an issue or merge request
58
- 14. `mr_discussions` - List discussion items for a merge request
59
- 15. `update_merge_request_note` - Modify an existing merge request thread note
60
- 16. `list_issues` - List issues in a GitLab project with filtering options
61
- 17. `get_issue` - Get details of a specific issue in a GitLab project
62
- 18. `update_issue` - Update an issue in a GitLab project
63
- 19. `delete_issue` - Delete an issue from a GitLab project
64
- 20. `list_issue_links` - List all issue links for a specific issue
65
- 21. `get_issue_link` - Get a specific issue link
66
- 22. `create_issue_link` - Create an issue link between two issues
67
- 23. `delete_issue_link` - Delete an issue link
68
- 24. `list_namespaces` - List all namespaces available to the current user
69
- 25. `get_namespace` - Get details of a namespace by ID or path
70
- 26. `verify_namespace` - Verify if a namespace path exists
71
- 27. `get_project` - Get details of a specific project
72
- 28. `list_projects` - List projects accessible by the current user
73
- 29. `list_labels` - List labels for a project
74
- 30. `get_label` - Get a single label from a project
75
- 31. `create_label` - Create a new label in a project
76
- 32. `update_label` - Update an existing label in a project
77
- 33. `delete_label` - Delete a label from a project
78
- 34. `list_group_projects` - List projects in a GitLab group with filtering options
79
- 35. `list_wiki_pages` - List wiki pages in a GitLab project
80
- 36. `get_wiki_page` - Get details of a specific wiki page
81
- 37. `create_wiki_page` - Create a new wiki page in a GitLab project
82
- 38. `update_wiki_page` - Update an existing wiki page in a GitLab project
83
- 39. `delete_wiki_page` - Delete a wiki page from a GitLab project
84
- 40. `get_repository_tree` - Get the repository tree for a GitLab project (list files and directories)
58
+ 14. `create_merge_request_thread` - Create a new thread on a merge request
59
+ 15. `mr_discussions` - List discussion items for a merge request
60
+ 16. `update_merge_request_note` - Modify an existing merge request thread note
61
+ 17. `create_merge_request_note` - Add a new note to an existing merge request thread
62
+ 18. `list_issues` - List issues in a GitLab project with filtering options
63
+ 19. `get_issue` - Get details of a specific issue in a GitLab project
64
+ 20. `update_issue` - Update an issue in a GitLab project
65
+ 21. `delete_issue` - Delete an issue from a GitLab project
66
+ 22. `list_issue_links` - List all issue links for a specific issue
67
+ 23. `get_issue_link` - Get a specific issue link
68
+ 24. `create_issue_link` - Create an issue link between two issues
69
+ 25. `delete_issue_link` - Delete an issue link
70
+ 26. `list_namespaces` - List all namespaces available to the current user
71
+ 27. `get_namespace` - Get details of a namespace by ID or path
72
+ 28. `verify_namespace` - Verify if a namespace path exists
73
+ 29. `get_project` - Get details of a specific project
74
+ 30. `list_projects` - List projects accessible by the current user
75
+ 31. `list_labels` - List labels for a project
76
+ 32. `get_label` - Get a single label from a project
77
+ 33. `create_label` - Create a new label in a project
78
+ 34. `update_label` - Update an existing label in a project
79
+ 35. `delete_label` - Delete a label from a project
80
+ 36. `list_group_projects` - List projects in a GitLab group with filtering options
81
+ 37. `list_wiki_pages` - List wiki pages in a GitLab project
82
+ 38. `get_wiki_page` - Get details of a specific wiki page
83
+ 39. `create_wiki_page` - Create a new wiki page in a GitLab project
84
+ 40. `update_wiki_page` - Update an existing wiki page in a GitLab project
85
+ 41. `delete_wiki_page` - Delete a wiki page from a GitLab project
86
+ 42. `get_repository_tree` - Get the repository tree for a GitLab project (list files and directories)
85
87
  <!-- TOOLS-END -->
package/build/index.js CHANGED
@@ -13,10 +13,11 @@ 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, 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, 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
+ CreateMergeRequestNoteSchema, // Added
20
21
  ListMergeRequestDiscussionsSchema, GitLabTreeItemSchema, GetRepositoryTreeSchema, } from "./schemas.js";
21
22
  /**
22
23
  * Read version from package.json
@@ -150,6 +151,11 @@ const allTools = [
150
151
  description: "Create a new note (comment) to an issue or merge request",
151
152
  inputSchema: zodToJsonSchema(CreateNoteSchema),
152
153
  },
154
+ {
155
+ name: "create_merge_request_thread",
156
+ description: "Create a new thread on a merge request",
157
+ inputSchema: zodToJsonSchema(CreateMergeRequestThreadSchema),
158
+ },
153
159
  {
154
160
  name: "mr_discussions",
155
161
  description: "List discussion items for a merge request",
@@ -160,6 +166,11 @@ const allTools = [
160
166
  description: "Modify an existing merge request thread note",
161
167
  inputSchema: zodToJsonSchema(UpdateMergeRequestNoteSchema),
162
168
  },
169
+ {
170
+ name: "create_merge_request_note",
171
+ description: "Add a new note to an existing merge request thread",
172
+ inputSchema: zodToJsonSchema(CreateMergeRequestNoteSchema),
173
+ },
163
174
  {
164
175
  name: "list_issues",
165
176
  description: "List issues in a GitLab project with filtering options",
@@ -737,8 +748,12 @@ async function listMergeRequestDiscussions(projectId, mergeRequestIid) {
737
748
  async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
738
749
  projectId = decodeURIComponent(projectId); // Decode project ID
739
750
  const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
740
- const payload = { body };
741
- if (resolved !== undefined) {
751
+ // Only one of body or resolved can be sent according to GitLab API
752
+ const payload = {};
753
+ if (body !== undefined) {
754
+ payload.body = body;
755
+ }
756
+ else if (resolved !== undefined) {
742
757
  payload.resolved = resolved;
743
758
  }
744
759
  const response = await fetch(url.toString(), {
@@ -750,6 +765,33 @@ async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId,
750
765
  const data = await response.json();
751
766
  return GitLabDiscussionNoteSchema.parse(data);
752
767
  }
768
+ /**
769
+ * Add a new note to an existing merge request thread
770
+ * 기존 병합 요청 스레드에 새 노트 추가
771
+ *
772
+ * @param {string} projectId - The ID or URL-encoded path of the project
773
+ * @param {number} mergeRequestIid - The IID of a merge request
774
+ * @param {string} discussionId - The ID of a thread
775
+ * @param {string} body - The content of the new note
776
+ * @param {string} [createdAt] - The creation date of the note (ISO 8601 format)
777
+ * @returns {Promise<GitLabDiscussionNote>} The created note
778
+ */
779
+ async function createMergeRequestNote(projectId, mergeRequestIid, discussionId, body, createdAt) {
780
+ projectId = decodeURIComponent(projectId); // Decode project ID
781
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes`);
782
+ const payload = { body };
783
+ if (createdAt) {
784
+ payload.created_at = createdAt;
785
+ }
786
+ const response = await fetch(url.toString(), {
787
+ ...DEFAULT_FETCH_CONFIG,
788
+ method: "POST",
789
+ body: JSON.stringify(payload),
790
+ });
791
+ await handleGitLabError(response);
792
+ const data = await response.json();
793
+ return GitLabDiscussionNoteSchema.parse(data);
794
+ }
753
795
  /**
754
796
  * Create or update a file in a GitLab project
755
797
  * 파일 생성 또는 업데이트
@@ -1076,6 +1118,43 @@ noteableIid, body) {
1076
1118
  }
1077
1119
  return await response.json();
1078
1120
  }
1121
+ /**
1122
+ * Create a new thread on a merge request
1123
+ * 📦 새로운 함수: createMergeRequestThread - 병합 요청에 새로운 스레드(토론)를 생성하는 함수
1124
+ * (New function: createMergeRequestThread - Function to create a new thread (discussion) on a merge request)
1125
+ *
1126
+ * This function provides more capabilities than createNote, including the ability to:
1127
+ * - Create diff notes (comments on specific lines of code)
1128
+ * - Specify exact positions for comments
1129
+ * - Set creation timestamps
1130
+ *
1131
+ * @param {string} projectId - The ID or URL-encoded path of the project
1132
+ * @param {number} mergeRequestIid - The internal ID of the merge request
1133
+ * @param {string} body - The content of the thread
1134
+ * @param {MergeRequestThreadPosition} [position] - Position information for diff notes
1135
+ * @param {string} [createdAt] - ISO 8601 formatted creation date
1136
+ * @returns {Promise<GitLabDiscussion>} The created discussion thread
1137
+ */
1138
+ async function createMergeRequestThread(projectId, mergeRequestIid, body, position, createdAt) {
1139
+ projectId = decodeURIComponent(projectId); // Decode project ID
1140
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`);
1141
+ const payload = { body };
1142
+ // Add optional parameters if provided
1143
+ if (position) {
1144
+ payload.position = position;
1145
+ }
1146
+ if (createdAt) {
1147
+ payload.created_at = createdAt;
1148
+ }
1149
+ const response = await fetch(url.toString(), {
1150
+ ...DEFAULT_FETCH_CONFIG,
1151
+ method: "POST",
1152
+ body: JSON.stringify(payload),
1153
+ });
1154
+ await handleGitLabError(response);
1155
+ const data = await response.json();
1156
+ return GitLabDiscussionSchema.parse(data);
1157
+ }
1079
1158
  /**
1080
1159
  * List all namespaces
1081
1160
  * 사용 가능한 모든 네임스페이스 목록 조회
@@ -1611,12 +1690,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1611
1690
  }
1612
1691
  case "update_merge_request_note": {
1613
1692
  const args = UpdateMergeRequestNoteSchema.parse(request.params.arguments);
1614
- const note = await updateMergeRequestNote(args.project_id, args.merge_request_iid, args.discussion_id, args.note_id, args.body, args.resolved // Pass resolved if provided
1693
+ const note = await updateMergeRequestNote(args.project_id, args.merge_request_iid, args.discussion_id, args.note_id, args.body, // Now optional
1694
+ args.resolved // Now one of body or resolved must be provided, not both
1615
1695
  );
1616
1696
  return {
1617
1697
  content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
1618
1698
  };
1619
1699
  }
1700
+ case "create_merge_request_note": {
1701
+ const args = CreateMergeRequestNoteSchema.parse(request.params.arguments);
1702
+ const note = await createMergeRequestNote(args.project_id, args.merge_request_iid, args.discussion_id, args.body, args.created_at);
1703
+ return {
1704
+ content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
1705
+ };
1706
+ }
1620
1707
  case "get_merge_request": {
1621
1708
  const args = GetMergeRequestSchema.parse(request.params.arguments);
1622
1709
  const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid, args.source_branch);
@@ -1735,6 +1822,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1735
1822
  content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
1736
1823
  };
1737
1824
  }
1825
+ case "create_merge_request_thread": {
1826
+ const args = CreateMergeRequestThreadSchema.parse(request.params.arguments);
1827
+ const { project_id, merge_request_iid, body, position, created_at } = args;
1828
+ const thread = await createMergeRequestThread(project_id, merge_request_iid, body, position, created_at);
1829
+ return {
1830
+ content: [{ type: "text", text: JSON.stringify(thread, null, 2) }],
1831
+ };
1832
+ }
1738
1833
  case "list_issues": {
1739
1834
  const args = ListIssuesSchema.parse(request.params.arguments);
1740
1835
  const { project_id, ...options } = args;
package/build/schemas.js CHANGED
@@ -400,13 +400,13 @@ export const GitLabDiscussionNoteSchema = z.object({
400
400
  .object({
401
401
  start: z.object({
402
402
  line_code: z.string(),
403
- type: z.enum(["new", "old"]),
403
+ type: z.enum(["new", "old", "expanded"]),
404
404
  old_line: z.number().nullable(),
405
405
  new_line: z.number().nullable(),
406
406
  }),
407
407
  end: z.object({
408
408
  line_code: z.string(),
409
- type: z.enum(["new", "old"]),
409
+ type: z.enum(["new", "old", "expanded"]),
410
410
  old_line: z.number().nullable(),
411
411
  new_line: z.number().nullable(),
412
412
  }),
@@ -434,8 +434,19 @@ export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
434
434
  merge_request_iid: z.number().describe("The IID of a merge request"),
435
435
  discussion_id: z.string().describe("The ID of a thread"),
436
436
  note_id: z.number().describe("The ID of a thread note"),
437
+ body: z.string().optional().describe("The content of the note or reply"),
438
+ resolved: z.boolean().optional().describe("Resolve or unresolve the note"),
439
+ }).refine(data => data.body !== undefined || data.resolved !== undefined, {
440
+ message: "At least one of 'body' or 'resolved' must be provided"
441
+ }).refine(data => !(data.body !== undefined && data.resolved !== undefined), {
442
+ message: "Only one of 'body' or 'resolved' can be provided, not both"
443
+ });
444
+ // Input schema for adding a note to an existing merge request discussion
445
+ export const CreateMergeRequestNoteSchema = ProjectParamsSchema.extend({
446
+ merge_request_iid: z.number().describe("The IID of a merge request"),
447
+ discussion_id: z.string().describe("The ID of a thread"),
437
448
  body: z.string().describe("The content of the note or reply"),
438
- resolved: z.boolean().optional().describe("Resolve or unresolve the note"), // Optional based on API docs
449
+ created_at: z.string().optional().describe("Date the note was created at (ISO 8601 format)"),
439
450
  });
440
451
  // API Operation Parameter Schemas
441
452
  export const CreateOrUpdateFileSchema = ProjectParamsSchema.extend({
@@ -919,3 +930,25 @@ export const GitLabWikiPageSchema = z.object({
919
930
  created_at: z.string().optional(),
920
931
  updated_at: z.string().optional(),
921
932
  });
933
+ // Merge Request Thread position schema - used for diff notes
934
+ export const MergeRequestThreadPositionSchema = z.object({
935
+ base_sha: z.string().describe("Base commit SHA in the source branch"),
936
+ head_sha: z.string().describe("SHA referencing HEAD of the source branch"),
937
+ start_sha: z.string().describe("SHA referencing the start commit of the source branch"),
938
+ position_type: z.enum(["text", "image", "file"]).describe("Type of position reference"),
939
+ new_path: z.string().optional().describe("File path after change"),
940
+ old_path: z.string().optional().describe("File path before change"),
941
+ new_line: z.number().nullable().optional().describe("Line number after change"),
942
+ old_line: z.number().nullable().optional().describe("Line number before change"),
943
+ width: z.number().optional().describe("Width of the image (for image diffs)"),
944
+ height: z.number().optional().describe("Height of the image (for image diffs)"),
945
+ x: z.number().optional().describe("X coordinate on the image (for image diffs)"),
946
+ y: z.number().optional().describe("Y coordinate on the image (for image diffs)"),
947
+ });
948
+ // Schema for creating a new merge request thread
949
+ export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
950
+ merge_request_iid: z.number().describe("The IID of a merge request"),
951
+ body: z.string().describe("The content of the thread"),
952
+ position: MergeRequestThreadPositionSchema.optional().describe("Position when creating a diff note"),
953
+ created_at: z.string().optional().describe("Date the thread was created at (ISO 8601 format)"),
954
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zereight/mcp-gitlab",
3
- "version": "1.0.36",
3
+ "version": "1.0.38",
4
4
  "description": "MCP server for using the GitLab API",
5
5
  "license": "MIT",
6
6
  "author": "zereight",