@zereight/mcp-gitlab 1.0.59 → 1.0.61
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 +43 -23
- package/build/schemas.js +2 -0
- package/package.json +4 -2
package/build/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import path from "path";
|
|
|
16
16
|
import express from "express";
|
|
17
17
|
// Add type imports for proxy agents
|
|
18
18
|
import { Agent } from "http";
|
|
19
|
-
import { Agent as HttpsAgent } from
|
|
19
|
+
import { Agent as HttpsAgent } from "https";
|
|
20
20
|
import { URL } from "url";
|
|
21
21
|
import { GitLabForkSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabIssueSchema, GitLabMergeRequestSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabSearchResponseSchema, GitLabTreeSchema, GitLabCommitSchema, GitLabNamespaceSchema, GitLabNamespaceExistsResponseSchema, GitLabProjectSchema, GitLabUserSchema, GitLabUsersResponseSchema, GetUsersSchema, CreateOrUpdateFileSchema, SearchRepositoriesSchema, CreateRepositorySchema, GetFileContentsSchema, PushFilesSchema, CreateIssueSchema, CreateMergeRequestSchema, ForkRepositorySchema, CreateBranchSchema, GitLabDiffSchema, 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, GetRepositoryTreeSchema, GitLabTreeItemSchema, GitLabPipelineSchema, GetPipelineSchema, ListPipelinesSchema, ListPipelineJobsSchema, CreatePipelineSchema, RetryPipelineSchema, CancelPipelineSchema,
|
|
22
22
|
// pipeline job schemas
|
|
@@ -40,7 +40,7 @@ try {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
catch (error) {
|
|
43
|
-
|
|
43
|
+
// Warning: Could not read version from package.json - silently continue
|
|
44
44
|
}
|
|
45
45
|
const server = new Server({
|
|
46
46
|
name: "better-gitlab-mcp-server",
|
|
@@ -51,6 +51,7 @@ const server = new Server({
|
|
|
51
51
|
},
|
|
52
52
|
});
|
|
53
53
|
const GITLAB_PERSONAL_ACCESS_TOKEN = process.env.GITLAB_PERSONAL_ACCESS_TOKEN;
|
|
54
|
+
const IS_OLD = process.env.GITLAB_IS_OLD === "true";
|
|
54
55
|
const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
|
|
55
56
|
const USE_GITLAB_WIKI = process.env.USE_GITLAB_WIKI === "true";
|
|
56
57
|
const USE_MILESTONE = process.env.USE_MILESTONE === "true";
|
|
@@ -62,7 +63,7 @@ const HTTPS_PROXY = process.env.HTTPS_PROXY;
|
|
|
62
63
|
const NODE_TLS_REJECT_UNAUTHORIZED = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
63
64
|
const GITLAB_CA_CERT_PATH = process.env.GITLAB_CA_CERT_PATH;
|
|
64
65
|
let sslOptions = undefined;
|
|
65
|
-
if (NODE_TLS_REJECT_UNAUTHORIZED ===
|
|
66
|
+
if (NODE_TLS_REJECT_UNAUTHORIZED === "0") {
|
|
66
67
|
sslOptions = { rejectUnauthorized: false };
|
|
67
68
|
}
|
|
68
69
|
else if (GITLAB_CA_CERT_PATH) {
|
|
@@ -94,8 +95,13 @@ httpAgent = httpAgent || new Agent();
|
|
|
94
95
|
const DEFAULT_HEADERS = {
|
|
95
96
|
Accept: "application/json",
|
|
96
97
|
"Content-Type": "application/json",
|
|
97
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
98
98
|
};
|
|
99
|
+
if (IS_OLD) {
|
|
100
|
+
DEFAULT_HEADERS["Private-Token"] = `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
DEFAULT_HEADERS["Authorization"] = `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`;
|
|
104
|
+
}
|
|
99
105
|
// Create a default fetch configuration object that includes proxy agents if set
|
|
100
106
|
const DEFAULT_FETCH_CONFIG = {
|
|
101
107
|
headers: DEFAULT_HEADERS,
|
|
@@ -695,15 +701,16 @@ async function listIssues(projectId, options = {}) {
|
|
|
695
701
|
// Add all query parameters
|
|
696
702
|
Object.entries(options).forEach(([key, value]) => {
|
|
697
703
|
if (value !== undefined) {
|
|
698
|
-
|
|
704
|
+
const keys = ["labels", "assignee_username"];
|
|
705
|
+
if (keys.includes(key)) {
|
|
699
706
|
if (Array.isArray(value)) {
|
|
700
707
|
// Handle array of labels
|
|
701
708
|
value.forEach(label => {
|
|
702
|
-
url.searchParams.append(
|
|
709
|
+
url.searchParams.append(`${key}[]`, label.toString());
|
|
703
710
|
});
|
|
704
711
|
}
|
|
705
712
|
else {
|
|
706
|
-
url.searchParams.append(
|
|
713
|
+
url.searchParams.append(`${key}[]`, value.toString());
|
|
707
714
|
}
|
|
708
715
|
}
|
|
709
716
|
else {
|
|
@@ -915,6 +922,8 @@ async function createMergeRequest(projectId, options) {
|
|
|
915
922
|
labels: options.labels?.join(","),
|
|
916
923
|
allow_collaboration: options.allow_collaboration,
|
|
917
924
|
draft: options.draft,
|
|
925
|
+
remove_source_branch: options.remove_source_branch,
|
|
926
|
+
squash: options.squash,
|
|
918
927
|
}),
|
|
919
928
|
});
|
|
920
929
|
if (response.status === 400) {
|
|
@@ -955,12 +964,20 @@ async function listDiscussions(projectId, resourceType, resourceIid, options = {
|
|
|
955
964
|
const discussions = await response.json();
|
|
956
965
|
// Extract pagination headers
|
|
957
966
|
const pagination = {
|
|
958
|
-
x_next_page: response.headers.get("x-next-page")
|
|
967
|
+
x_next_page: response.headers.get("x-next-page")
|
|
968
|
+
? parseInt(response.headers.get("x-next-page"))
|
|
969
|
+
: null,
|
|
959
970
|
x_page: response.headers.get("x-page") ? parseInt(response.headers.get("x-page")) : undefined,
|
|
960
|
-
x_per_page: response.headers.get("x-per-page")
|
|
961
|
-
|
|
971
|
+
x_per_page: response.headers.get("x-per-page")
|
|
972
|
+
? parseInt(response.headers.get("x-per-page"))
|
|
973
|
+
: undefined,
|
|
974
|
+
x_prev_page: response.headers.get("x-prev-page")
|
|
975
|
+
? parseInt(response.headers.get("x-prev-page"))
|
|
976
|
+
: null,
|
|
962
977
|
x_total: response.headers.get("x-total") ? parseInt(response.headers.get("x-total")) : null,
|
|
963
|
-
x_total_pages: response.headers.get("x-total-pages")
|
|
978
|
+
x_total_pages: response.headers.get("x-total-pages")
|
|
979
|
+
? parseInt(response.headers.get("x-total-pages"))
|
|
980
|
+
: null,
|
|
964
981
|
};
|
|
965
982
|
return PaginatedDiscussionsResponseSchema.parse({
|
|
966
983
|
items: discussions,
|
|
@@ -2048,11 +2065,17 @@ async function getRepositoryTree(options) {
|
|
|
2048
2065
|
queryParams.append("page_token", options.page_token);
|
|
2049
2066
|
if (options.pagination)
|
|
2050
2067
|
queryParams.append("pagination", options.pagination);
|
|
2068
|
+
const headers = {
|
|
2069
|
+
"Content-Type": "application/json",
|
|
2070
|
+
};
|
|
2071
|
+
if (IS_OLD) {
|
|
2072
|
+
headers["Private-Token"] = `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`;
|
|
2073
|
+
}
|
|
2074
|
+
else {
|
|
2075
|
+
headers["Authorization"] = `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`;
|
|
2076
|
+
}
|
|
2051
2077
|
const response = await fetch(`${GITLAB_API_URL}/projects/${encodeURIComponent(options.project_id)}/repository/tree?${queryParams.toString()}`, {
|
|
2052
|
-
headers
|
|
2053
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
2054
|
-
"Content-Type": "application/json",
|
|
2055
|
-
},
|
|
2078
|
+
headers,
|
|
2056
2079
|
});
|
|
2057
2080
|
if (response.status === 404) {
|
|
2058
2081
|
throw new Error("Repository or path not found");
|
|
@@ -2290,9 +2313,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2290
2313
|
? tools1
|
|
2291
2314
|
: tools1.filter(tool => !milestoneToolNames.includes(tool.name));
|
|
2292
2315
|
// Toggle pipeline tools by USE_PIPELINE flag
|
|
2293
|
-
let tools = USE_PIPELINE
|
|
2294
|
-
? tools2
|
|
2295
|
-
: tools2.filter(tool => !pipelineToolNames.includes(tool.name));
|
|
2316
|
+
let tools = USE_PIPELINE ? tools2 : tools2.filter(tool => !pipelineToolNames.includes(tool.name));
|
|
2296
2317
|
// <<< START: Gemini 호환성을 위해 $schema 제거 >>>
|
|
2297
2318
|
tools = tools.map(tool => {
|
|
2298
2319
|
// inputSchema가 존재하고 객체인지 확인
|
|
@@ -2986,10 +3007,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2986
3007
|
*/
|
|
2987
3008
|
async function runServer() {
|
|
2988
3009
|
try {
|
|
2989
|
-
console.error
|
|
2990
|
-
console.error
|
|
2991
|
-
console.error
|
|
2992
|
-
console.error
|
|
3010
|
+
// Server startup banner removed - inappropriate use of console.error for logging
|
|
3011
|
+
// Server version banner removed - inappropriate use of console.error for logging
|
|
3012
|
+
// API URL banner removed - inappropriate use of console.error for logging
|
|
3013
|
+
// Server startup banner removed - inappropriate use of console.error for logging
|
|
2993
3014
|
if (!SSE) {
|
|
2994
3015
|
const transport = new StdioServerTransport();
|
|
2995
3016
|
await server.connect(transport);
|
|
@@ -3020,7 +3041,6 @@ async function runServer() {
|
|
|
3020
3041
|
console.log(`Server is running on port ${PORT}`);
|
|
3021
3042
|
});
|
|
3022
3043
|
}
|
|
3023
|
-
console.error("GitLab MCP Server running on stdio");
|
|
3024
3044
|
}
|
|
3025
3045
|
catch (error) {
|
|
3026
3046
|
console.error("Error initializing server:", error);
|
package/build/schemas.js
CHANGED
|
@@ -427,6 +427,8 @@ export const CreateMergeRequestOptionsSchema = z.object({
|
|
|
427
427
|
labels: z.array(z.string()).optional(),
|
|
428
428
|
allow_collaboration: z.boolean().optional(), // Changed from maintainer_can_modify to match GitLab API
|
|
429
429
|
draft: z.boolean().optional(),
|
|
430
|
+
remove_source_branch: z.boolean().optional().describe("Flag indicating if a merge request should remove the source branch when merging."),
|
|
431
|
+
squash: z.boolean().optional().describe("If true, squash all commits into a single commit on merge.")
|
|
430
432
|
});
|
|
431
433
|
export const GitLabDiffSchema = z.object({
|
|
432
434
|
old_path: z.string(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.61",
|
|
4
4
|
"description": "MCP server for using the GitLab API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zereight",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"watch": "tsc --watch",
|
|
22
22
|
"deploy": "npm publish --access public",
|
|
23
23
|
"generate-tools": "npx ts-node scripts/generate-tools-readme.ts",
|
|
24
|
+
"changelog": "auto-changelog -p",
|
|
24
25
|
"test": "node test/validate-api.js",
|
|
25
26
|
"test:integration": "node test/validate-api.js",
|
|
26
27
|
"lint": "eslint . --ext .ts",
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
"prettier": "^3.4.2",
|
|
49
50
|
"ts-node": "^10.9.2",
|
|
50
51
|
"typescript": "^5.8.2",
|
|
51
|
-
"zod": "^3.24.2"
|
|
52
|
+
"zod": "^3.24.2",
|
|
53
|
+
"auto-changelog": "^2.4.0"
|
|
52
54
|
}
|
|
53
55
|
}
|