@zereight/mcp-gitlab 1.0.51 → 1.0.53
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 +21 -13
- package/build/index.js +132 -2
- package/build/schemas.js +28 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,8 +26,9 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
26
26
|
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
|
|
27
27
|
"GITLAB_API_URL": "your_gitlab_api_url",
|
|
28
28
|
"GITLAB_READ_ONLY_MODE": "false",
|
|
29
|
-
"USE_GITLAB_WIKI": "false",
|
|
30
|
-
"USE_MILESTONE": "false"
|
|
29
|
+
"USE_GITLAB_WIKI": "false", // use wiki api?
|
|
30
|
+
"USE_MILESTONE": "false", // use milestone api?
|
|
31
|
+
"USE_PIPELINE": "false" // use pipeline api?
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -55,6 +56,8 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
55
56
|
"USE_GITLAB_WIKI",
|
|
56
57
|
"-e",
|
|
57
58
|
"USE_MILESTONE",
|
|
59
|
+
"-e",
|
|
60
|
+
"USE_PIPELINE",
|
|
58
61
|
"iwakitakuma/gitlab-mcp"
|
|
59
62
|
],
|
|
60
63
|
"env": {
|
|
@@ -62,7 +65,8 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
62
65
|
"GITLAB_API_URL": "https://gitlab.com/api/v4", // Optional, for self-hosted GitLab
|
|
63
66
|
"GITLAB_READ_ONLY_MODE": "false",
|
|
64
67
|
"USE_GITLAB_WIKI": "true",
|
|
65
|
-
"USE_MILESTONE": "true"
|
|
68
|
+
"USE_MILESTONE": "true",
|
|
69
|
+
"USE_PIPELINE": "true"
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
@@ -82,6 +86,7 @@ $ sh scripts/image_push.sh docker_user_name
|
|
|
82
86
|
- `GITLAB_READ_ONLY_MODE`: When set to 'true', restricts the server to only expose read-only operations. Useful for enhanced security or when write access is not needed. Also useful for using with Cursor and it's 40 tool limit.
|
|
83
87
|
- `USE_GITLAB_WIKI`: When set to 'true', enables the wiki-related tools (list_wiki_pages, get_wiki_page, create_wiki_page, update_wiki_page, delete_wiki_page). By default, wiki features are disabled.
|
|
84
88
|
- `USE_MILESTONE`: When set to 'true', enables the milestone-related tools (list_milestones, get_milestone, create_milestone, edit_milestone, delete_milestone, get_milestone_issue, get_milestone_merge_requests, promote_milestone, get_milestone_burndown_events). By default, milestone features are disabled.
|
|
89
|
+
- `USE_PIPELINE`: When set to 'true', enables the pipeline-related tools (list_pipelines, get_pipeline, list_pipeline_jobs, get_pipeline_job, get_pipeline_job_output, create_pipeline, retry_pipeline, cancel_pipeline). By default, pipeline features are disabled.
|
|
85
90
|
|
|
86
91
|
## Tools 🛠️
|
|
87
92
|
|
|
@@ -137,14 +142,17 @@ $ sh scripts/image_push.sh docker_user_name
|
|
|
137
142
|
48. `list_pipeline_jobs` - List all jobs in a specific pipeline
|
|
138
143
|
49. `get_pipeline_job` - Get details of a GitLab pipeline job number
|
|
139
144
|
50. `get_pipeline_job_output` - Get the output/trace of a GitLab pipeline job number
|
|
140
|
-
51. `
|
|
141
|
-
52. `
|
|
142
|
-
53. `
|
|
143
|
-
54. `
|
|
144
|
-
55. `
|
|
145
|
-
56. `
|
|
146
|
-
57. `
|
|
147
|
-
58. `
|
|
148
|
-
59. `
|
|
149
|
-
60. `
|
|
145
|
+
51. `create_pipeline` - Create a new pipeline for a branch or tag
|
|
146
|
+
52. `retry_pipeline` - Retry a failed or canceled pipeline
|
|
147
|
+
53. `cancel_pipeline` - Cancel a running pipeline
|
|
148
|
+
54. `list_merge_requests` - List merge requests in a GitLab project with filtering options
|
|
149
|
+
55. `list_milestones` - List milestones in a GitLab project with filtering options
|
|
150
|
+
56. `get_milestone` - Get details of a specific milestone
|
|
151
|
+
57. `create_milestone` - Create a new milestone in a GitLab project
|
|
152
|
+
58. `edit_milestone ` - Edit an existing milestone in a GitLab project
|
|
153
|
+
59. `delete_milestone` - Delete a milestone from a GitLab project
|
|
154
|
+
60. `get_milestone_issue` - Get issues associated with a specific milestone
|
|
155
|
+
61. `get_milestone_merge_requests` - Get merge requests associated with a specific milestone
|
|
156
|
+
62. `promote_milestone` - Promote a milestone to the next stage
|
|
157
|
+
63. `get_milestone_burndown_events` - Get burndown events for a specific milestone
|
|
150
158
|
<!-- TOOLS-END -->
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ 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, 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,
|
|
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, 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,
|
|
17
17
|
// pipeline job schemas
|
|
18
18
|
GetPipelineJobOutputSchema, GitLabPipelineJobSchema,
|
|
19
19
|
// Discussion Schemas
|
|
@@ -49,6 +49,7 @@ const GITLAB_PERSONAL_ACCESS_TOKEN = process.env.GITLAB_PERSONAL_ACCESS_TOKEN;
|
|
|
49
49
|
const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
|
|
50
50
|
const USE_GITLAB_WIKI = process.env.USE_GITLAB_WIKI === "true";
|
|
51
51
|
const USE_MILESTONE = process.env.USE_MILESTONE === "true";
|
|
52
|
+
const USE_PIPELINE = process.env.USE_PIPELINE === "true";
|
|
52
53
|
// Add proxy configuration
|
|
53
54
|
const HTTP_PROXY = process.env.HTTP_PROXY;
|
|
54
55
|
const HTTPS_PROXY = process.env.HTTPS_PROXY;
|
|
@@ -339,6 +340,21 @@ const allTools = [
|
|
|
339
340
|
description: "Get the output/trace of a GitLab pipeline job number",
|
|
340
341
|
inputSchema: zodToJsonSchema(GetPipelineJobOutputSchema),
|
|
341
342
|
},
|
|
343
|
+
{
|
|
344
|
+
name: "create_pipeline",
|
|
345
|
+
description: "Create a new pipeline for a branch or tag",
|
|
346
|
+
inputSchema: zodToJsonSchema(CreatePipelineSchema),
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
name: "retry_pipeline",
|
|
350
|
+
description: "Retry a failed or canceled pipeline",
|
|
351
|
+
inputSchema: zodToJsonSchema(RetryPipelineSchema),
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
name: "cancel_pipeline",
|
|
355
|
+
description: "Cancel a running pipeline",
|
|
356
|
+
inputSchema: zodToJsonSchema(CancelPipelineSchema),
|
|
357
|
+
},
|
|
342
358
|
{
|
|
343
359
|
name: "list_merge_requests",
|
|
344
360
|
description: "List merge requests in a GitLab project with filtering options",
|
|
@@ -446,6 +462,17 @@ const milestoneToolNames = [
|
|
|
446
462
|
"promote_milestone",
|
|
447
463
|
"get_milestone_burndown_events",
|
|
448
464
|
];
|
|
465
|
+
// Define which tools are related to pipelines and can be toggled by USE_PIPELINE
|
|
466
|
+
const pipelineToolNames = [
|
|
467
|
+
"list_pipelines",
|
|
468
|
+
"get_pipeline",
|
|
469
|
+
"list_pipeline_jobs",
|
|
470
|
+
"get_pipeline_job",
|
|
471
|
+
"get_pipeline_job_output",
|
|
472
|
+
"create_pipeline",
|
|
473
|
+
"retry_pipeline",
|
|
474
|
+
"cancel_pipeline",
|
|
475
|
+
];
|
|
449
476
|
/**
|
|
450
477
|
* Smart URL handling for GitLab API
|
|
451
478
|
*
|
|
@@ -1857,6 +1884,69 @@ async function getPipelineJobOutput(projectId, jobId) {
|
|
|
1857
1884
|
await handleGitLabError(response);
|
|
1858
1885
|
return await response.text();
|
|
1859
1886
|
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Create a new pipeline
|
|
1889
|
+
*
|
|
1890
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
1891
|
+
* @param {string} ref - The branch or tag to run the pipeline on
|
|
1892
|
+
* @param {Array} variables - Optional variables for the pipeline
|
|
1893
|
+
* @returns {Promise<GitLabPipeline>} The created pipeline
|
|
1894
|
+
*/
|
|
1895
|
+
async function createPipeline(projectId, ref, variables) {
|
|
1896
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1897
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/pipeline`);
|
|
1898
|
+
const body = { ref };
|
|
1899
|
+
if (variables && variables.length > 0) {
|
|
1900
|
+
body.variables = variables.reduce((acc, { key, value }) => {
|
|
1901
|
+
acc[key] = value;
|
|
1902
|
+
return acc;
|
|
1903
|
+
}, {});
|
|
1904
|
+
}
|
|
1905
|
+
const response = await fetch(url.toString(), {
|
|
1906
|
+
method: "POST",
|
|
1907
|
+
headers: DEFAULT_HEADERS,
|
|
1908
|
+
body: JSON.stringify(body),
|
|
1909
|
+
});
|
|
1910
|
+
await handleGitLabError(response);
|
|
1911
|
+
const data = await response.json();
|
|
1912
|
+
return GitLabPipelineSchema.parse(data);
|
|
1913
|
+
}
|
|
1914
|
+
/**
|
|
1915
|
+
* Retry a pipeline
|
|
1916
|
+
*
|
|
1917
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
1918
|
+
* @param {number} pipelineId - The ID of the pipeline to retry
|
|
1919
|
+
* @returns {Promise<GitLabPipeline>} The retried pipeline
|
|
1920
|
+
*/
|
|
1921
|
+
async function retryPipeline(projectId, pipelineId) {
|
|
1922
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1923
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/retry`);
|
|
1924
|
+
const response = await fetch(url.toString(), {
|
|
1925
|
+
method: "POST",
|
|
1926
|
+
headers: DEFAULT_HEADERS,
|
|
1927
|
+
});
|
|
1928
|
+
await handleGitLabError(response);
|
|
1929
|
+
const data = await response.json();
|
|
1930
|
+
return GitLabPipelineSchema.parse(data);
|
|
1931
|
+
}
|
|
1932
|
+
/**
|
|
1933
|
+
* Cancel a pipeline
|
|
1934
|
+
*
|
|
1935
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
1936
|
+
* @param {number} pipelineId - The ID of the pipeline to cancel
|
|
1937
|
+
* @returns {Promise<GitLabPipeline>} The canceled pipeline
|
|
1938
|
+
*/
|
|
1939
|
+
async function cancelPipeline(projectId, pipelineId) {
|
|
1940
|
+
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1941
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/cancel`);
|
|
1942
|
+
const response = await fetch(url.toString(), {
|
|
1943
|
+
method: "POST",
|
|
1944
|
+
headers: DEFAULT_HEADERS,
|
|
1945
|
+
});
|
|
1946
|
+
await handleGitLabError(response);
|
|
1947
|
+
const data = await response.json();
|
|
1948
|
+
return GitLabPipelineSchema.parse(data);
|
|
1949
|
+
}
|
|
1860
1950
|
/**
|
|
1861
1951
|
* Get the repository tree for a project
|
|
1862
1952
|
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
@@ -2064,9 +2154,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2064
2154
|
? tools0
|
|
2065
2155
|
: tools0.filter(tool => !wikiToolNames.includes(tool.name));
|
|
2066
2156
|
// Toggle milestone tools by USE_MILESTONE flag
|
|
2067
|
-
|
|
2157
|
+
const tools2 = USE_MILESTONE
|
|
2068
2158
|
? tools1
|
|
2069
2159
|
: tools1.filter(tool => !milestoneToolNames.includes(tool.name));
|
|
2160
|
+
// Toggle pipeline tools by USE_PIPELINE flag
|
|
2161
|
+
let tools = USE_PIPELINE
|
|
2162
|
+
? tools2
|
|
2163
|
+
: tools2.filter(tool => !pipelineToolNames.includes(tool.name));
|
|
2070
2164
|
// <<< START: Gemini 호환성을 위해 $schema 제거 >>>
|
|
2071
2165
|
tools = tools.map(tool => {
|
|
2072
2166
|
// inputSchema가 존재하고 객체인지 확인
|
|
@@ -2561,6 +2655,42 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2561
2655
|
],
|
|
2562
2656
|
};
|
|
2563
2657
|
}
|
|
2658
|
+
case "create_pipeline": {
|
|
2659
|
+
const { project_id, ref, variables } = CreatePipelineSchema.parse(request.params.arguments);
|
|
2660
|
+
const pipeline = await createPipeline(project_id, ref, variables);
|
|
2661
|
+
return {
|
|
2662
|
+
content: [
|
|
2663
|
+
{
|
|
2664
|
+
type: "text",
|
|
2665
|
+
text: `Created pipeline #${pipeline.id} for ${ref}. Status: ${pipeline.status}\nWeb URL: ${pipeline.web_url}`,
|
|
2666
|
+
},
|
|
2667
|
+
],
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
case "retry_pipeline": {
|
|
2671
|
+
const { project_id, pipeline_id } = RetryPipelineSchema.parse(request.params.arguments);
|
|
2672
|
+
const pipeline = await retryPipeline(project_id, pipeline_id);
|
|
2673
|
+
return {
|
|
2674
|
+
content: [
|
|
2675
|
+
{
|
|
2676
|
+
type: "text",
|
|
2677
|
+
text: `Retried pipeline #${pipeline.id}. Status: ${pipeline.status}\nWeb URL: ${pipeline.web_url}`,
|
|
2678
|
+
},
|
|
2679
|
+
],
|
|
2680
|
+
};
|
|
2681
|
+
}
|
|
2682
|
+
case "cancel_pipeline": {
|
|
2683
|
+
const { project_id, pipeline_id } = CancelPipelineSchema.parse(request.params.arguments);
|
|
2684
|
+
const pipeline = await cancelPipeline(project_id, pipeline_id);
|
|
2685
|
+
return {
|
|
2686
|
+
content: [
|
|
2687
|
+
{
|
|
2688
|
+
type: "text",
|
|
2689
|
+
text: `Canceled pipeline #${pipeline.id}. Status: ${pipeline.status}\nWeb URL: ${pipeline.web_url}`,
|
|
2690
|
+
},
|
|
2691
|
+
],
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2564
2694
|
case "list_merge_requests": {
|
|
2565
2695
|
const args = ListMergeRequestsSchema.parse(request.params.arguments);
|
|
2566
2696
|
const mergeRequests = await listMergeRequests(args.project_id, args);
|
package/build/schemas.js
CHANGED
|
@@ -150,6 +150,28 @@ export const ListPipelineJobsSchema = z.object({
|
|
|
150
150
|
page: z.number().optional().describe("Page number for pagination"),
|
|
151
151
|
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
152
152
|
});
|
|
153
|
+
// Schema for creating a new pipeline
|
|
154
|
+
export const CreatePipelineSchema = z.object({
|
|
155
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
156
|
+
ref: z.string().describe("The branch or tag to run the pipeline on"),
|
|
157
|
+
variables: z
|
|
158
|
+
.array(z.object({
|
|
159
|
+
key: z.string().describe("The key of the variable"),
|
|
160
|
+
value: z.string().describe("The value of the variable"),
|
|
161
|
+
}))
|
|
162
|
+
.optional()
|
|
163
|
+
.describe("An array of variables to use for the pipeline"),
|
|
164
|
+
});
|
|
165
|
+
// Schema for retrying a pipeline
|
|
166
|
+
export const RetryPipelineSchema = z.object({
|
|
167
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
168
|
+
pipeline_id: z.number().describe("The ID of the pipeline to retry"),
|
|
169
|
+
});
|
|
170
|
+
// Schema for canceling a pipeline
|
|
171
|
+
export const CancelPipelineSchema = z.object({
|
|
172
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
173
|
+
pipeline_id: z.number().describe("The ID of the pipeline to cancel"),
|
|
174
|
+
});
|
|
153
175
|
// Schema for the input parameters for pipeline job operations
|
|
154
176
|
export const GetPipelineJobOutputSchema = z.object({
|
|
155
177
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -550,21 +572,21 @@ export const GitLabDiscussionNoteSchema = z.object({
|
|
|
550
572
|
old_path: z.string(),
|
|
551
573
|
new_path: z.string(),
|
|
552
574
|
position_type: z.enum(["text", "image", "file"]),
|
|
553
|
-
old_line: z.number().
|
|
554
|
-
new_line: z.number().
|
|
575
|
+
old_line: z.number().nullish(), // This is missing for image diffs
|
|
576
|
+
new_line: z.number().nullish(), // This is missing for image diffs
|
|
555
577
|
line_range: z
|
|
556
578
|
.object({
|
|
557
579
|
start: z.object({
|
|
558
580
|
line_code: z.string(),
|
|
559
581
|
type: z.enum(["new", "old", "expanded"]),
|
|
560
|
-
old_line: z.number().
|
|
561
|
-
new_line: z.number().
|
|
582
|
+
old_line: z.number().nullish(), // This is missing for image diffs
|
|
583
|
+
new_line: z.number().nullish(), // This is missing for image diffs
|
|
562
584
|
}),
|
|
563
585
|
end: z.object({
|
|
564
586
|
line_code: z.string(),
|
|
565
587
|
type: z.enum(["new", "old", "expanded"]),
|
|
566
|
-
old_line: z.number().
|
|
567
|
-
new_line: z.number().
|
|
588
|
+
old_line: z.number().nullish(), // This is missing for image diffs
|
|
589
|
+
new_line: z.number().nullish(), // This is missing for image diffs
|
|
568
590
|
}),
|
|
569
591
|
})
|
|
570
592
|
.nullable()
|