@zereight/mcp-gitlab 1.0.22 → 1.0.24
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 +77 -7
- package/build/schemas.js +68 -3
- package/package.json +1 -1
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,
|
|
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
|
*/
|
|
@@ -56,12 +60,6 @@ function normalizeGitLabApiUrl(url) {
|
|
|
56
60
|
}
|
|
57
61
|
// Use the normalizeGitLabApiUrl function to handle various URL formats
|
|
58
62
|
const GITLAB_API_URL = normalizeGitLabApiUrl(process.env.GITLAB_API_URL || "");
|
|
59
|
-
// Add debug logging for API URL construction
|
|
60
|
-
console.log("=== MCP Server Configuration ===");
|
|
61
|
-
console.log(`GITLAB_API_URL = "${GITLAB_API_URL}"`);
|
|
62
|
-
console.log(`Example project API URL = "${GITLAB_API_URL}/projects/123"`);
|
|
63
|
-
console.log(`Example Notes API URL = "${GITLAB_API_URL}/projects/123/issues/1/notes"`);
|
|
64
|
-
console.log("===============================");
|
|
65
63
|
if (!GITLAB_PERSONAL_ACCESS_TOKEN) {
|
|
66
64
|
console.error("GITLAB_PERSONAL_ACCESS_TOKEN environment variable is not set");
|
|
67
65
|
process.exit(1);
|
|
@@ -417,6 +415,51 @@ async function createMergeRequest(projectId, options) {
|
|
|
417
415
|
const data = await response.json();
|
|
418
416
|
return GitLabMergeRequestSchema.parse(data);
|
|
419
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* List merge request discussion items
|
|
420
|
+
* 병합 요청 토론 목록 조회
|
|
421
|
+
*
|
|
422
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
423
|
+
* @param {number} mergeRequestIid - The IID of a merge request
|
|
424
|
+
* @returns {Promise<GitLabDiscussion[]>} List of discussions
|
|
425
|
+
*/
|
|
426
|
+
async function listMergeRequestDiscussions(projectId, mergeRequestIid) {
|
|
427
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`);
|
|
428
|
+
const response = await fetch(url.toString(), {
|
|
429
|
+
headers: DEFAULT_HEADERS,
|
|
430
|
+
});
|
|
431
|
+
await handleGitLabError(response);
|
|
432
|
+
const data = await response.json();
|
|
433
|
+
// Ensure the response is parsed as an array of discussions
|
|
434
|
+
return z.array(GitLabDiscussionSchema).parse(data);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Modify an existing merge request thread note
|
|
438
|
+
* 병합 요청 토론 노트 수정
|
|
439
|
+
*
|
|
440
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
441
|
+
* @param {number} mergeRequestIid - The IID of a merge request
|
|
442
|
+
* @param {string} discussionId - The ID of a thread
|
|
443
|
+
* @param {number} noteId - The ID of a thread note
|
|
444
|
+
* @param {string} body - The new content of the note
|
|
445
|
+
* @param {boolean} [resolved] - Resolve/unresolve state
|
|
446
|
+
* @returns {Promise<GitLabDiscussionNote>} The updated note
|
|
447
|
+
*/
|
|
448
|
+
async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
|
|
449
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
|
|
450
|
+
const payload = { body };
|
|
451
|
+
if (resolved !== undefined) {
|
|
452
|
+
payload.resolved = resolved;
|
|
453
|
+
}
|
|
454
|
+
const response = await fetch(url.toString(), {
|
|
455
|
+
method: "PUT",
|
|
456
|
+
headers: DEFAULT_HEADERS,
|
|
457
|
+
body: JSON.stringify(payload),
|
|
458
|
+
});
|
|
459
|
+
await handleGitLabError(response);
|
|
460
|
+
const data = await response.json();
|
|
461
|
+
return GitLabDiscussionNoteSchema.parse(data);
|
|
462
|
+
}
|
|
420
463
|
/**
|
|
421
464
|
* Create or update a file in a GitLab project
|
|
422
465
|
* 파일 생성 또는 업데이트
|
|
@@ -1077,6 +1120,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
1077
1120
|
description: "Create a new note (comment) to an issue or merge request",
|
|
1078
1121
|
inputSchema: zodToJsonSchema(CreateNoteSchema),
|
|
1079
1122
|
},
|
|
1123
|
+
{
|
|
1124
|
+
name: "list_merge_request_discussions",
|
|
1125
|
+
description: "List discussion items for a merge request",
|
|
1126
|
+
inputSchema: zodToJsonSchema(ListMergeRequestDiscussionsSchema),
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
name: "update_merge_request_note",
|
|
1130
|
+
description: "Modify an existing merge request thread note",
|
|
1131
|
+
inputSchema: zodToJsonSchema(UpdateMergeRequestNoteSchema),
|
|
1132
|
+
},
|
|
1080
1133
|
{
|
|
1081
1134
|
name: "list_issues",
|
|
1082
1135
|
description: "List issues in a GitLab project with filtering options",
|
|
@@ -1269,6 +1322,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1269
1322
|
],
|
|
1270
1323
|
};
|
|
1271
1324
|
}
|
|
1325
|
+
case "update_merge_request_note": {
|
|
1326
|
+
const args = UpdateMergeRequestNoteSchema.parse(request.params.arguments);
|
|
1327
|
+
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
|
|
1328
|
+
);
|
|
1329
|
+
return {
|
|
1330
|
+
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1272
1333
|
case "get_merge_request": {
|
|
1273
1334
|
const args = GetMergeRequestSchema.parse(request.params.arguments);
|
|
1274
1335
|
const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid);
|
|
@@ -1295,6 +1356,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1295
1356
|
],
|
|
1296
1357
|
};
|
|
1297
1358
|
}
|
|
1359
|
+
case "list_merge_request_discussions": {
|
|
1360
|
+
const args = ListMergeRequestDiscussionsSchema.parse(request.params.arguments);
|
|
1361
|
+
const discussions = await listMergeRequestDiscussions(args.project_id, args.merge_request_iid);
|
|
1362
|
+
return {
|
|
1363
|
+
content: [
|
|
1364
|
+
{ type: "text", text: JSON.stringify(discussions, null, 2) },
|
|
1365
|
+
],
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1298
1368
|
case "list_namespaces": {
|
|
1299
1369
|
const args = ListNamespacesSchema.parse(request.params.arguments);
|
|
1300
1370
|
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
|
-
//
|
|
328
|
-
const
|
|
329
|
-
|
|
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"),
|