@zereight/mcp-gitlab 1.0.22 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -9,7 +9,11 @@ import { fileURLToPath } from "url";
9
9
  import { dirname } from "path";
10
10
  import fs from "fs";
11
11
  import path from "path";
12
- 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, } from "./schemas.js";
12
+ 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,
13
+ // Discussion Schemas
14
+ GitLabDiscussionNoteSchema, // Added
15
+ GitLabDiscussionSchema, UpdateMergeRequestNoteSchema, // Added
16
+ ListMergeRequestDiscussionsSchema, } from "./schemas.js";
13
17
  /**
14
18
  * Read version from package.json
15
19
  */
@@ -417,6 +421,51 @@ async function createMergeRequest(projectId, options) {
417
421
  const data = await response.json();
418
422
  return GitLabMergeRequestSchema.parse(data);
419
423
  }
424
+ /**
425
+ * List merge request discussion items
426
+ * 병합 요청 토론 목록 조회
427
+ *
428
+ * @param {string} projectId - The ID or URL-encoded path of the project
429
+ * @param {number} mergeRequestIid - The IID of a merge request
430
+ * @returns {Promise<GitLabDiscussion[]>} List of discussions
431
+ */
432
+ async function listMergeRequestDiscussions(projectId, mergeRequestIid) {
433
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`);
434
+ const response = await fetch(url.toString(), {
435
+ headers: DEFAULT_HEADERS,
436
+ });
437
+ await handleGitLabError(response);
438
+ const data = await response.json();
439
+ // Ensure the response is parsed as an array of discussions
440
+ return z.array(GitLabDiscussionSchema).parse(data);
441
+ }
442
+ /**
443
+ * Modify an existing merge request thread note
444
+ * 병합 요청 토론 노트 수정
445
+ *
446
+ * @param {string} projectId - The ID or URL-encoded path of the project
447
+ * @param {number} mergeRequestIid - The IID of a merge request
448
+ * @param {string} discussionId - The ID of a thread
449
+ * @param {number} noteId - The ID of a thread note
450
+ * @param {string} body - The new content of the note
451
+ * @param {boolean} [resolved] - Resolve/unresolve state
452
+ * @returns {Promise<GitLabDiscussionNote>} The updated note
453
+ */
454
+ async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
455
+ const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
456
+ const payload = { body };
457
+ if (resolved !== undefined) {
458
+ payload.resolved = resolved;
459
+ }
460
+ const response = await fetch(url.toString(), {
461
+ method: "PUT",
462
+ headers: DEFAULT_HEADERS,
463
+ body: JSON.stringify(payload),
464
+ });
465
+ await handleGitLabError(response);
466
+ const data = await response.json();
467
+ return GitLabDiscussionNoteSchema.parse(data);
468
+ }
420
469
  /**
421
470
  * Create or update a file in a GitLab project
422
471
  * 파일 생성 또는 업데이트
@@ -1077,6 +1126,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1077
1126
  description: "Create a new note (comment) to an issue or merge request",
1078
1127
  inputSchema: zodToJsonSchema(CreateNoteSchema),
1079
1128
  },
1129
+ {
1130
+ name: "list_merge_request_discussions",
1131
+ description: "List discussion items for a merge request",
1132
+ inputSchema: zodToJsonSchema(ListMergeRequestDiscussionsSchema),
1133
+ },
1134
+ {
1135
+ name: "update_merge_request_note",
1136
+ description: "Modify an existing merge request thread note",
1137
+ inputSchema: zodToJsonSchema(UpdateMergeRequestNoteSchema),
1138
+ },
1080
1139
  {
1081
1140
  name: "list_issues",
1082
1141
  description: "List issues in a GitLab project with filtering options",
@@ -1269,6 +1328,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1269
1328
  ],
1270
1329
  };
1271
1330
  }
1331
+ case "update_merge_request_note": {
1332
+ const args = UpdateMergeRequestNoteSchema.parse(request.params.arguments);
1333
+ 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
1334
+ );
1335
+ return {
1336
+ content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
1337
+ };
1338
+ }
1272
1339
  case "get_merge_request": {
1273
1340
  const args = GetMergeRequestSchema.parse(request.params.arguments);
1274
1341
  const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid);
@@ -1295,6 +1362,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1295
1362
  ],
1296
1363
  };
1297
1364
  }
1365
+ case "list_merge_request_discussions": {
1366
+ const args = ListMergeRequestDiscussionsSchema.parse(request.params.arguments);
1367
+ const discussions = await listMergeRequestDiscussions(args.project_id, args.merge_request_iid);
1368
+ return {
1369
+ content: [
1370
+ { type: "text", text: JSON.stringify(discussions, null, 2) },
1371
+ ],
1372
+ };
1373
+ }
1298
1374
  case "list_namespaces": {
1299
1375
  const args = ListNamespacesSchema.parse(request.params.arguments);
1300
1376
  const url = new URL(`${GITLAB_API_URL}/namespaces`);
package/build/schemas.js CHANGED
@@ -6,6 +6,10 @@ export const GitLabAuthorSchema = z.object({
6
6
  date: z.string(),
7
7
  });
8
8
  // Namespace related schemas
9
+ // Base schema for project-related operations
10
+ const ProjectParamsSchema = z.object({
11
+ project_id: z.string().describe("Project ID or URL-encoded path"), // Changed from owner/repo to match GitLab API
12
+ });
9
13
  export const GitLabNamespaceSchema = z.object({
10
14
  id: z.number(),
11
15
  name: z.string(),
@@ -324,10 +328,71 @@ export const GitLabMergeRequestSchema = z.object({
324
328
  squash: z.boolean().optional(),
325
329
  labels: z.array(z.string()).optional(),
326
330
  });
327
- // API Operation Parameter Schemas
328
- const ProjectParamsSchema = z.object({
329
- project_id: z.string().describe("Project ID or URL-encoded path"), // Changed from owner/repo to match GitLab API
331
+ // Discussion related schemas
332
+ export const GitLabDiscussionNoteSchema = z.object({
333
+ id: z.number(),
334
+ type: z.enum(["DiscussionNote", "DiffNote", "Note"]).nullable(), // Allow null type for regular notes
335
+ body: z.string(),
336
+ attachment: z.any().nullable(), // Can be string or object, handle appropriately
337
+ author: GitLabUserSchema,
338
+ created_at: z.string(),
339
+ updated_at: z.string(),
340
+ system: z.boolean(),
341
+ noteable_id: z.number(),
342
+ noteable_type: z.enum(["Issue", "MergeRequest", "Snippet", "Commit", "Epic"]),
343
+ project_id: z.number().optional(), // Optional for group-level discussions like Epics
344
+ noteable_iid: z.number().nullable(),
345
+ resolvable: z.boolean().optional(),
346
+ resolved: z.boolean().optional(),
347
+ resolved_by: GitLabUserSchema.nullable().optional(),
348
+ resolved_at: z.string().nullable().optional(),
349
+ position: z.object({
350
+ base_sha: z.string(),
351
+ start_sha: z.string(),
352
+ head_sha: z.string(),
353
+ old_path: z.string(),
354
+ new_path: z.string(),
355
+ position_type: z.enum(["text", "image", "file"]),
356
+ old_line: z.number().nullable(),
357
+ new_line: z.number().nullable(),
358
+ line_range: z.object({
359
+ start: z.object({
360
+ line_code: z.string(),
361
+ type: z.enum(["new", "old"]),
362
+ old_line: z.number().nullable(),
363
+ new_line: z.number().nullable(),
364
+ }),
365
+ end: z.object({
366
+ line_code: z.string(),
367
+ type: z.enum(["new", "old"]),
368
+ old_line: z.number().nullable(),
369
+ new_line: z.number().nullable(),
370
+ }),
371
+ }).nullable().optional(), // For multi-line diff notes
372
+ width: z.number().optional(), // For image diff notes
373
+ height: z.number().optional(), // For image diff notes
374
+ x: z.number().optional(), // For image diff notes
375
+ y: z.number().optional(), // For image diff notes
376
+ }).optional(),
377
+ });
378
+ export const GitLabDiscussionSchema = z.object({
379
+ id: z.string(),
380
+ individual_note: z.boolean(),
381
+ notes: z.array(GitLabDiscussionNoteSchema),
330
382
  });
383
+ // Input schema for listing merge request discussions
384
+ export const ListMergeRequestDiscussionsSchema = ProjectParamsSchema.extend({
385
+ merge_request_iid: z.number().describe("The IID of a merge request"),
386
+ });
387
+ // Input schema for updating a merge request discussion note
388
+ export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
389
+ merge_request_iid: z.number().describe("The IID of a merge request"),
390
+ discussion_id: z.string().describe("The ID of a thread"),
391
+ note_id: z.number().describe("The ID of a thread note"),
392
+ body: z.string().describe("The content of the note or reply"),
393
+ resolved: z.boolean().optional().describe("Resolve or unresolve the note"), // Optional based on API docs
394
+ });
395
+ // API Operation Parameter Schemas
331
396
  export const CreateOrUpdateFileSchema = ProjectParamsSchema.extend({
332
397
  file_path: z.string().describe("Path where to create/update the file"),
333
398
  content: z.string().describe("Content of the file"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zereight/mcp-gitlab",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "MCP server for using the GitLab API",
5
5
  "license": "MIT",
6
6
  "author": "zereight",