@zereight/mcp-gitlab 2.0.8 → 2.0.9

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
@@ -67,6 +67,28 @@ When using with the Claude App, you need to set up your API key and URLs directl
67
67
  }
68
68
  ```
69
69
 
70
+ #### Strands Agents SDK (MCP Tools)
71
+
72
+ ```python
73
+ env_vars = {
74
+ "GITLAB_PERSONAL_ACCESS_TOKEN": gitlab_access_token,
75
+ "GITLAB_API_URL": gitlab_api_url,
76
+ "USE_GITLAB_WIKI": use_gitlab_wiki
77
+ # ......the rest of the optional parameters
78
+ }
79
+
80
+ stdio_gitlab_mcp_client = MCPClient(
81
+ lambda: stdio_client(
82
+ StdioServerParameters(
83
+ command="npx",
84
+ args=["-y", "@zereight/mcp-gitlab"],
85
+ env=env_vars,
86
+ )
87
+ )
88
+ )
89
+ ```
90
+
91
+
70
92
  #### Docker
71
93
 
72
94
  - stdio mcp.json
package/build/index.js CHANGED
@@ -22,7 +22,7 @@ import { Agent } from "http";
22
22
  import { Agent as HttpsAgent } from "https";
23
23
  import { URL } from "url";
24
24
  import { BulkPublishDraftNotesSchema, CancelPipelineJobSchema, CancelPipelineSchema, CreateBranchSchema, CreateDraftNoteSchema, CreateIssueLinkSchema, CreateIssueNoteSchema, CreateIssueSchema, CreateLabelSchema, // Added
25
- CreateMergeRequestNoteSchema, CreateMergeRequestSchema, CreateMergeRequestThreadSchema, CreateNoteSchema, CreateOrUpdateFileSchema, CreatePipelineSchema, CreateProjectMilestoneSchema, CreateRepositorySchema, CreateWikiPageSchema, DeleteDraftNoteSchema, DeleteIssueLinkSchema, DeleteIssueSchema, DeleteLabelSchema, DeleteProjectMilestoneSchema, DeleteWikiPageSchema, EditProjectMilestoneSchema, ForkRepositorySchema, GetBranchDiffsSchema, GetCommitDiffSchema, GetCommitSchema, GetDraftNoteSchema, GetFileContentsSchema, GetIssueLinkSchema, GetIssueSchema, GetLabelSchema, GetMergeRequestDiffsSchema, GetMergeRequestSchema, GetMilestoneBurndownEventsSchema, GetMilestoneIssuesSchema, GetMilestoneMergeRequestsSchema, GetNamespaceSchema,
25
+ CreateMergeRequestNoteSchema, CreateMergeRequestDiscussionNoteSchema, CreateMergeRequestSchema, CreateMergeRequestThreadSchema, CreateNoteSchema, CreateOrUpdateFileSchema, CreatePipelineSchema, CreateProjectMilestoneSchema, CreateRepositorySchema, CreateWikiPageSchema, DeleteDraftNoteSchema, DeleteIssueLinkSchema, DeleteIssueSchema, DeleteLabelSchema, DeleteProjectMilestoneSchema, DeleteWikiPageSchema, DeleteMergeRequestNoteSchema, EditProjectMilestoneSchema, ForkRepositorySchema, GetBranchDiffsSchema, GetCommitDiffSchema, GetCommitSchema, GetDraftNoteSchema, GetFileContentsSchema, GetIssueLinkSchema, GetIssueSchema, GetLabelSchema, GetMergeRequestDiffsSchema, GetMergeRequestSchema, GetMilestoneBurndownEventsSchema, GetMilestoneIssuesSchema, GetMilestoneMergeRequestsSchema, GetNamespaceSchema,
26
26
  // pipeline job schemas
27
27
  GetPipelineJobOutputSchema, GetPipelineSchema, GetProjectMilestoneSchema, GetProjectSchema, GetRepositoryTreeSchema, GetUsersSchema, GetWikiPageSchema, GitLabCommitSchema, GitLabCompareResultSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabDiffSchema,
28
28
  // Discussion Schemas
@@ -30,7 +30,7 @@ GitLabDiscussionNoteSchema, // Added
30
30
  GitLabDiscussionSchema,
31
31
  // Draft Notes Schemas
32
32
  GitLabDraftNoteSchema, GitLabForkSchema, GitLabIssueLinkSchema, GitLabIssueSchema, GitLabIssueWithLinkDetailsSchema, GitLabMarkdownUploadSchema, GitLabMergeRequestSchema, GitLabMilestonesSchema, GitLabNamespaceExistsResponseSchema, GitLabNamespaceSchema, GitLabPipelineJobSchema, GitLabPipelineSchema, GitLabPipelineTriggerJobSchema, GitLabProjectMemberSchema, GitLabProjectSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabSearchResponseSchema, GitLabTreeItemSchema, GitLabTreeSchema, GitLabUserSchema, GitLabUsersResponseSchema, GitLabWikiPageSchema, GroupIteration, ListCommitsSchema, ListDraftNotesSchema, ListGroupIterationsSchema, ListGroupProjectsSchema, ListIssueDiscussionsSchema, ListIssueLinksSchema, ListIssuesSchema, ListLabelsSchema, ListMergeRequestDiffsSchema, // Added
33
- ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListPipelineTriggerJobsSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, MarkdownUploadSchema, DownloadAttachmentSchema, MergeMergeRequestSchema, MyIssuesSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema, ExecuteGraphQLSchema, GitLabReleaseSchema, ListReleasesSchema, GetReleaseSchema, CreateReleaseSchema, UpdateReleaseSchema, DeleteReleaseSchema, CreateReleaseEvidenceSchema, DownloadReleaseAssetSchema, } from "./schemas.js";
33
+ ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListPipelineTriggerJobsSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, MarkdownUploadSchema, DownloadAttachmentSchema, MergeMergeRequestSchema, MyIssuesSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestDiscussionNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema, ExecuteGraphQLSchema, GitLabReleaseSchema, ListReleasesSchema, GetReleaseSchema, CreateReleaseSchema, UpdateReleaseSchema, DeleteReleaseSchema, CreateReleaseEvidenceSchema, DownloadReleaseAssetSchema, GetMergeRequestNotesSchema, GetMergeRequestNoteSchema, DeleteMergeRequestDiscussionNoteSchema, ResolveMergeRequestThreadSchema } from "./schemas.js";
34
34
  import { randomUUID } from "crypto";
35
35
  import { pino } from "pino";
36
36
  const logger = pino({
@@ -395,21 +395,56 @@ const allTools = [
395
395
  description: "Create a new thread on a merge request",
396
396
  inputSchema: toJSONSchema(CreateMergeRequestThreadSchema),
397
397
  },
398
+ {
399
+ name: 'resolve_merge_request_thread',
400
+ description: "Resolve a thread on a merge request",
401
+ inputSchema: toJSONSchema(ResolveMergeRequestThreadSchema),
402
+ },
398
403
  {
399
404
  name: "mr_discussions",
400
405
  description: "List discussion items for a merge request",
401
406
  inputSchema: toJSONSchema(ListMergeRequestDiscussionsSchema),
402
407
  },
403
408
  {
404
- name: "update_merge_request_note",
405
- description: "Modify an existing merge request thread note",
406
- inputSchema: toJSONSchema(UpdateMergeRequestNoteSchema),
409
+ name: "delete_merge_request_discussion_note",
410
+ description: "Delete a discussion note on a merge request",
411
+ inputSchema: toJSONSchema(DeleteMergeRequestDiscussionNoteSchema),
412
+ },
413
+ {
414
+ name: "update_merge_request_discussion_note",
415
+ description: "Update a discussion note on a merge request",
416
+ inputSchema: toJSONSchema(UpdateMergeRequestDiscussionNoteSchema),
417
+ },
418
+ {
419
+ name: "create_merge_request_discussion_note",
420
+ description: "Add a new discussion note to an existing merge request thread",
421
+ inputSchema: toJSONSchema(CreateMergeRequestDiscussionNoteSchema),
407
422
  },
408
423
  {
409
424
  name: "create_merge_request_note",
410
- description: "Add a new note to an existing merge request thread",
425
+ description: "Add a new note to a merge request",
411
426
  inputSchema: toJSONSchema(CreateMergeRequestNoteSchema),
412
427
  },
428
+ {
429
+ name: "delete_merge_request_note",
430
+ description: "Delete an existing merge request note",
431
+ inputSchema: toJSONSchema(DeleteMergeRequestNoteSchema),
432
+ },
433
+ {
434
+ name: "get_merge_request_note",
435
+ description: "Get a specific note for a merge request",
436
+ inputSchema: toJSONSchema(GetMergeRequestNoteSchema),
437
+ },
438
+ {
439
+ name: 'get_merge_request_notes',
440
+ description: "List notes for a merge request",
441
+ inputSchema: toJSONSchema(GetMergeRequestNotesSchema),
442
+ },
443
+ {
444
+ name: "update_merge_request_note",
445
+ description: "Modify an existing merge request note",
446
+ inputSchema: toJSONSchema(UpdateMergeRequestNoteSchema),
447
+ },
413
448
  {
414
449
  name: "get_draft_note",
415
450
  description: "Get a single draft note from a merge request",
@@ -1429,6 +1464,18 @@ async function listMergeRequestDiscussions(projectId, mergeRequestIid, options =
1429
1464
  async function listIssueDiscussions(projectId, issueIid, options = {}) {
1430
1465
  return listDiscussions(projectId, "issues", issueIid, options);
1431
1466
  }
1467
+ async function deleteMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, noteId) {
1468
+ projectId = decodeURIComponent(projectId); // Decode project ID
1469
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
1470
+ const response = await fetch(url.toString(), {
1471
+ ...DEFAULT_FETCH_CONFIG,
1472
+ method: "DELETE",
1473
+ });
1474
+ if (!response.ok) {
1475
+ const errorText = await response.text();
1476
+ throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorText}`);
1477
+ }
1478
+ }
1432
1479
  /**
1433
1480
  * Modify an existing merge request thread note
1434
1481
  * 병합 요청 토론 노트 수정
@@ -1441,7 +1488,7 @@ async function listIssueDiscussions(projectId, issueIid, options = {}) {
1441
1488
  * @param {boolean} [resolved] - Resolve/unresolve state
1442
1489
  * @returns {Promise<GitLabDiscussionNote>} The updated note
1443
1490
  */
1444
- async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
1491
+ async function updateMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
1445
1492
  projectId = decodeURIComponent(projectId); // Decode project ID
1446
1493
  const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
1447
1494
  // Only one of body or resolved can be sent according to GitLab API
@@ -1509,7 +1556,7 @@ async function createIssueNote(projectId, issueIid, discussionId, body, createdA
1509
1556
  return GitLabDiscussionNoteSchema.parse(data);
1510
1557
  }
1511
1558
  /**
1512
- * Add a new note to an existing merge request thread
1559
+ * Add a new discussion note to an existing merge request thread
1513
1560
  * 기존 병합 요청 스레드에 새 노트 추가
1514
1561
  *
1515
1562
  * @param {string} projectId - The ID or URL-encoded path of the project
@@ -1519,7 +1566,7 @@ async function createIssueNote(projectId, issueIid, discussionId, body, createdA
1519
1566
  * @param {string} [createdAt] - The creation date of the note (ISO 8601 format)
1520
1567
  * @returns {Promise<GitLabDiscussionNote>} The created note
1521
1568
  */
1522
- async function createMergeRequestNote(projectId, mergeRequestIid, discussionId, body, createdAt) {
1569
+ async function createMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, body, createdAt) {
1523
1570
  projectId = decodeURIComponent(projectId); // Decode project ID
1524
1571
  const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes`);
1525
1572
  const payload = { body };
@@ -1535,6 +1582,81 @@ async function createMergeRequestNote(projectId, mergeRequestIid, discussionId,
1535
1582
  const data = await response.json();
1536
1583
  return GitLabDiscussionNoteSchema.parse(data);
1537
1584
  }
1585
+ async function createMergeRequestNote(projectId, mergeRequestIid, body) {
1586
+ projectId = decodeURIComponent(projectId); // Decode project ID
1587
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes`);
1588
+ const payload = {
1589
+ id: projectId,
1590
+ merge_request_iid: mergeRequestIid,
1591
+ body,
1592
+ };
1593
+ const response = await fetch(url.toString(), {
1594
+ ...DEFAULT_FETCH_CONFIG,
1595
+ method: "POST",
1596
+ body: JSON.stringify(payload),
1597
+ });
1598
+ await handleGitLabError(response);
1599
+ const data = await response.json();
1600
+ return GitLabDiscussionNoteSchema.parse(data);
1601
+ }
1602
+ async function deleteMergeRequestNote(projectId, mergeRequestIid, noteId) {
1603
+ projectId = decodeURIComponent(projectId); // Decode project ID
1604
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
1605
+ const response = await fetch(url.toString(), {
1606
+ ...DEFAULT_FETCH_CONFIG,
1607
+ method: "DELETE",
1608
+ });
1609
+ if (!response.ok) {
1610
+ const errorText = await response.text();
1611
+ throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorText}`);
1612
+ }
1613
+ }
1614
+ async function getMergeRequestNote(projectId, mergeRequestIid, noteId) {
1615
+ projectId = decodeURIComponent(projectId); // Decode project ID
1616
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
1617
+ const response = await fetch(url.toString(), {
1618
+ ...DEFAULT_FETCH_CONFIG,
1619
+ method: "GET",
1620
+ });
1621
+ await handleGitLabError(response);
1622
+ const data = await response.json();
1623
+ return GitLabDiscussionNoteSchema.parse(data);
1624
+ }
1625
+ async function getMergeRequestNotes(projectId, mergeRequestIid, sort, order_by) {
1626
+ projectId = decodeURIComponent(projectId); // Decode project ID
1627
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes`);
1628
+ if (sort) {
1629
+ url.searchParams.append("sort", sort);
1630
+ }
1631
+ if (order_by) {
1632
+ url.searchParams.append("order_by", order_by);
1633
+ }
1634
+ const response = await fetch(url.toString(), {
1635
+ ...DEFAULT_FETCH_CONFIG,
1636
+ method: "GET",
1637
+ });
1638
+ await handleGitLabError(response);
1639
+ const data = await response.json();
1640
+ return z.array(GitLabDiscussionNoteSchema).parse(data);
1641
+ }
1642
+ async function updateMergeRequestNote(projectId, mergeRequestIid, noteId, body) {
1643
+ projectId = decodeURIComponent(projectId); // Decode project ID
1644
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
1645
+ const payload = {
1646
+ id: projectId,
1647
+ merge_request_iid: mergeRequestIid,
1648
+ note_id: noteId,
1649
+ body,
1650
+ };
1651
+ const response = await fetch(url.toString(), {
1652
+ ...DEFAULT_FETCH_CONFIG,
1653
+ method: "PUT",
1654
+ body: JSON.stringify(payload),
1655
+ });
1656
+ await handleGitLabError(response);
1657
+ const data = await response.json();
1658
+ return GitLabDiscussionNoteSchema.parse(data);
1659
+ }
1538
1660
  /**
1539
1661
  * Create or update a file in a GitLab project
1540
1662
  * 파일 생성 또는 업데이트
@@ -2145,6 +2267,21 @@ async function bulkPublishDraftNotes(projectId, mergeRequestIid) {
2145
2267
  return [];
2146
2268
  }
2147
2269
  }
2270
+ async function resolveMergeRequestThread(projectId, mergeRequestIid, discussionId, resolved) {
2271
+ projectId = decodeURIComponent(projectId);
2272
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}`);
2273
+ if (resolved !== undefined) {
2274
+ url.searchParams.append("resolved", resolved ? "true" : "false");
2275
+ }
2276
+ const response = await fetch(url.toString(), {
2277
+ ...DEFAULT_FETCH_CONFIG,
2278
+ method: "PUT",
2279
+ });
2280
+ if (!response.ok) {
2281
+ const errorText = await response.text();
2282
+ throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorText}`);
2283
+ }
2284
+ }
2148
2285
  /**
2149
2286
  * Create a new thread on a merge request
2150
2287
  * 📦 새로운 함수: createMergeRequestThread - 병합 요청에 새로운 스레드(토론)를 생성하는 함수
@@ -3762,18 +3899,61 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3762
3899
  content: [{ type: "text", text: JSON.stringify(mergeRequest, null, 2) }],
3763
3900
  };
3764
3901
  }
3765
- case "update_merge_request_note": {
3766
- const args = UpdateMergeRequestNoteSchema.parse(request.params.arguments);
3767
- const note = await updateMergeRequestNote(args.project_id, args.merge_request_iid, args.discussion_id, args.note_id, args.body, // Now optional
3902
+ case "delete_merge_request_discussion_note": {
3903
+ const args = DeleteMergeRequestDiscussionNoteSchema.parse(request.params.arguments);
3904
+ const { project_id, merge_request_iid, discussion_id, note_id } = args;
3905
+ await deleteMergeRequestDiscussionNote(project_id, merge_request_iid, discussion_id, note_id);
3906
+ return {
3907
+ content: [{ type: "text", text: "Merge request discussion note deleted successfully" }],
3908
+ };
3909
+ }
3910
+ case "update_merge_request_discussion_note": {
3911
+ const args = UpdateMergeRequestDiscussionNoteSchema.parse(request.params.arguments);
3912
+ const note = await updateMergeRequestDiscussionNote(args.project_id, args.merge_request_iid, args.discussion_id, args.note_id, args.body, // Now optional
3768
3913
  args.resolved // Now one of body or resolved must be provided, not both
3769
3914
  );
3770
3915
  return {
3771
3916
  content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
3772
3917
  };
3773
3918
  }
3919
+ case "create_merge_request_discussion_note": {
3920
+ const args = CreateMergeRequestDiscussionNoteSchema.parse(request.params.arguments);
3921
+ const note = await createMergeRequestDiscussionNote(args.project_id, args.merge_request_iid, args.discussion_id, args.body, args.created_at);
3922
+ return {
3923
+ content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
3924
+ };
3925
+ }
3774
3926
  case "create_merge_request_note": {
3775
3927
  const args = CreateMergeRequestNoteSchema.parse(request.params.arguments);
3776
- const note = await createMergeRequestNote(args.project_id, args.merge_request_iid, args.discussion_id, args.body, args.created_at);
3928
+ const note = await createMergeRequestNote(args.project_id, args.merge_request_iid, args.body);
3929
+ return {
3930
+ content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
3931
+ };
3932
+ }
3933
+ case "delete_merge_request_note": {
3934
+ const args = DeleteMergeRequestNoteSchema.parse(request.params.arguments);
3935
+ await deleteMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id);
3936
+ return {
3937
+ content: [{ type: "text", text: "Merge request note deleted successfully" }],
3938
+ };
3939
+ }
3940
+ case 'get_merge_request_note': {
3941
+ const args = GetMergeRequestNoteSchema.parse(request.params.arguments);
3942
+ const note = await getMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id);
3943
+ return {
3944
+ content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
3945
+ };
3946
+ }
3947
+ case 'get_merge_request_notes': {
3948
+ const args = GetMergeRequestNotesSchema.parse(request.params.arguments);
3949
+ const notes = await getMergeRequestNotes(args.project_id, args.merge_request_iid, args.sort, args.order_by);
3950
+ return {
3951
+ content: [{ type: "text", text: JSON.stringify(notes, null, 2) }],
3952
+ };
3953
+ }
3954
+ case 'update_merge_request_note': {
3955
+ const args = UpdateMergeRequestNoteSchema.parse(request.params.arguments);
3956
+ const note = await updateMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id, args.body);
3777
3957
  return {
3778
3958
  content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
3779
3959
  };
@@ -3995,6 +4175,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3995
4175
  content: [{ type: "text", text: JSON.stringify(thread, null, 2) }],
3996
4176
  };
3997
4177
  }
4178
+ case "resolve_merge_request_thread": {
4179
+ const args = ResolveMergeRequestThreadSchema.parse(request.params.arguments);
4180
+ const { project_id, merge_request_iid, discussion_id, resolved } = args;
4181
+ await resolveMergeRequestThread(project_id, merge_request_iid, discussion_id, resolved);
4182
+ return {
4183
+ content: [{ type: "text", text: "Thread resolved successfully" }],
4184
+ };
4185
+ }
3998
4186
  case "list_issues": {
3999
4187
  const args = ListIssuesSchema.parse(request.params.arguments);
4000
4188
  const { project_id, ...options } = args;
@@ -4675,7 +4863,7 @@ async function startStreamableHTTPServer() {
4675
4863
  // GitLab PAT format: glpat-xxxxx (min 20 chars)
4676
4864
  if (token.length < 20)
4677
4865
  return false;
4678
- if (!/^[a-zA-Z0-9_-]+$/.test(token))
4866
+ if (!/^[a-zA-Z0-9_\.-]+$/.test(token))
4679
4867
  return false;
4680
4868
  return true;
4681
4869
  };
package/build/schemas.js CHANGED
@@ -852,8 +852,38 @@ export const ListIssueDiscussionsSchema = z
852
852
  export const ListMergeRequestDiscussionsSchema = ProjectParamsSchema.extend({
853
853
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
854
854
  }).merge(PaginationOptionsSchema);
855
- // Input schema for updating a merge request discussion note
855
+ export const GetMergeRequestNotesSchema = ProjectParamsSchema.extend({
856
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
857
+ sort: z.enum(["asc", "desc"]).optional().describe("The sort order of the notes"),
858
+ order_by: z.enum(["created_at", "updated_at"]).optional().describe("The field to sort the notes by"),
859
+ });
860
+ export const GetMergeRequestNoteSchema = ProjectParamsSchema.extend({
861
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
862
+ note_id: z.coerce.string().describe("The ID of a thread note"),
863
+ });
864
+ // Input schema for updating merge request notes
856
865
  export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
866
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
867
+ note_id: z.coerce.string().describe("The ID of a thread note"),
868
+ body: z.string().describe("The content of the note or reply"),
869
+ });
870
+ // Input schema for adding a note to a merge request
871
+ export const CreateMergeRequestNoteSchema = ProjectParamsSchema.extend({
872
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
873
+ body: z.string().describe("The content of the note or reply"),
874
+ });
875
+ // delete a merge request note
876
+ export const DeleteMergeRequestNoteSchema = ProjectParamsSchema.extend({
877
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
878
+ note_id: z.coerce.string().describe("The ID of a thread note"),
879
+ });
880
+ export const DeleteMergeRequestDiscussionNoteSchema = ProjectParamsSchema.extend({
881
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
882
+ discussion_id: z.coerce.string().describe("The ID of a thread"),
883
+ note_id: z.coerce.string().describe("The ID of a thread note"),
884
+ });
885
+ // Input schema for updating a merge request discussion note
886
+ export const UpdateMergeRequestDiscussionNoteSchema = ProjectParamsSchema.extend({
857
887
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
858
888
  discussion_id: z.coerce.string().describe("The ID of a thread"),
859
889
  note_id: z.coerce.string().describe("The ID of a thread note"),
@@ -867,7 +897,7 @@ export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
867
897
  message: "Only one of 'body' or 'resolved' can be provided, not both",
868
898
  });
869
899
  // Input schema for adding a note to an existing merge request discussion
870
- export const CreateMergeRequestNoteSchema = ProjectParamsSchema.extend({
900
+ export const CreateMergeRequestDiscussionNoteSchema = ProjectParamsSchema.extend({
871
901
  merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
872
902
  discussion_id: z.coerce.string().describe("The ID of a thread"),
873
903
  body: z.string().describe("The content of the note or reply"),
@@ -1504,6 +1534,11 @@ export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
1504
1534
  position: MergeRequestThreadPositionSchema.optional().describe("Position when creating a diff note"),
1505
1535
  created_at: z.string().optional().describe("Date the thread was created at (ISO 8601 format)"),
1506
1536
  });
1537
+ export const ResolveMergeRequestThreadSchema = ProjectParamsSchema.extend({
1538
+ merge_request_iid: z.coerce.string().describe("The IID of a merge request"),
1539
+ discussion_id: z.coerce.string().describe("The ID of a thread"),
1540
+ resolved: z.boolean().describe("Whether to resolve the thread"),
1541
+ });
1507
1542
  // Milestone related schemas
1508
1543
  // Schema for listing project milestones
1509
1544
  export const ListProjectMilestonesSchema = ProjectParamsSchema.extend({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zereight/mcp-gitlab",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "MCP server for using the GitLab API",
5
5
  "license": "MIT",
6
6
  "author": "zereight",