@zereight/mcp-gitlab 1.0.55 → 1.0.57
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 +26 -2
- package/build/index.js +84 -39
- package/build/schemas.js +46 -56
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -36,8 +36,8 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
#### Docker
|
|
39
|
-
|
|
40
|
-
```json
|
|
39
|
+
- stdio
|
|
40
|
+
```mcp.json
|
|
41
41
|
{
|
|
42
42
|
"mcpServers": {
|
|
43
43
|
"GitLab communication server": {
|
|
@@ -73,6 +73,30 @@ When using with the Claude App, you need to set up your API key and URLs directl
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
- sse
|
|
77
|
+
```shell
|
|
78
|
+
docker run -i --rm \
|
|
79
|
+
-e GITLAB_PERSONAL_ACCESS_TOKEN=your_gitlab_token \
|
|
80
|
+
-e GITLAB_API_URL= "https://gitlab.com/api/v4"\
|
|
81
|
+
-e GITLAB_READ_ONLY_MODE=true \
|
|
82
|
+
-e USE_GITLAB_WIKI=true \
|
|
83
|
+
-e USE_MILESTONE=true \
|
|
84
|
+
-e USE_PIPELINE=true \
|
|
85
|
+
-e SSE=true \
|
|
86
|
+
-p 3333:3002 \
|
|
87
|
+
gitlab-mcp
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"mcpServers": {
|
|
93
|
+
"GitLab communication server": {
|
|
94
|
+
"url": "http://localhost:3333/sse"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
76
100
|
#### Docker Image Push
|
|
77
101
|
|
|
78
102
|
```shell
|
package/build/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
4
5
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
6
|
import fetch from "node-fetch";
|
|
6
7
|
import { SocksProxyAgent } from "socks-proxy-agent";
|
|
@@ -12,6 +13,7 @@ import { fileURLToPath } from "url";
|
|
|
12
13
|
import { dirname } from "path";
|
|
13
14
|
import fs from "fs";
|
|
14
15
|
import path from "path";
|
|
16
|
+
import express from "express";
|
|
15
17
|
// Add type imports for proxy agents
|
|
16
18
|
import { Agent } from "http";
|
|
17
19
|
import { Agent as HttpsAgent } from 'https';
|
|
@@ -21,7 +23,7 @@ import { GitLabForkSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLab
|
|
|
21
23
|
GetPipelineJobOutputSchema, GitLabPipelineJobSchema,
|
|
22
24
|
// Discussion Schemas
|
|
23
25
|
GitLabDiscussionNoteSchema, // Added
|
|
24
|
-
GitLabDiscussionSchema, UpdateMergeRequestNoteSchema, // Added
|
|
26
|
+
GitLabDiscussionSchema, PaginatedDiscussionsResponseSchema, UpdateMergeRequestNoteSchema, // Added
|
|
25
27
|
CreateMergeRequestNoteSchema, // Added
|
|
26
28
|
ListMergeRequestDiscussionsSchema, UpdateIssueNoteSchema, CreateIssueNoteSchema, ListMergeRequestsSchema, GitLabMilestonesSchema, ListProjectMilestonesSchema, GetProjectMilestoneSchema, CreateProjectMilestoneSchema, EditProjectMilestoneSchema, DeleteProjectMilestoneSchema, GetMilestoneIssuesSchema, GetMilestoneMergeRequestsSchema, PromoteProjectMilestoneSchema, GetMilestoneBurndownEventsSchema, GitLabCompareResultSchema, GetBranchDiffsSchema, } from "./schemas.js";
|
|
27
29
|
/**
|
|
@@ -53,6 +55,7 @@ const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
|
|
|
53
55
|
const USE_GITLAB_WIKI = process.env.USE_GITLAB_WIKI === "true";
|
|
54
56
|
const USE_MILESTONE = process.env.USE_MILESTONE === "true";
|
|
55
57
|
const USE_PIPELINE = process.env.USE_PIPELINE === "true";
|
|
58
|
+
const SSE = process.env.SSE === "true";
|
|
56
59
|
// Add proxy configuration
|
|
57
60
|
const HTTP_PROXY = process.env.HTTP_PROXY;
|
|
58
61
|
const HTTPS_PROXY = process.env.HTTPS_PROXY;
|
|
@@ -692,12 +695,14 @@ async function listIssues(projectId, options = {}) {
|
|
|
692
695
|
// Add all query parameters
|
|
693
696
|
Object.entries(options).forEach(([key, value]) => {
|
|
694
697
|
if (value !== undefined) {
|
|
695
|
-
if (key === "
|
|
698
|
+
if (key === "labels" && Array.isArray(value)) {
|
|
696
699
|
// Handle array of labels
|
|
697
|
-
|
|
700
|
+
value.forEach(label => {
|
|
701
|
+
url.searchParams.append("labels[]", label.toString());
|
|
702
|
+
});
|
|
698
703
|
}
|
|
699
704
|
else {
|
|
700
|
-
url.searchParams.append(
|
|
705
|
+
url.searchParams.append("labels[]", value.toString());
|
|
701
706
|
}
|
|
702
707
|
}
|
|
703
708
|
});
|
|
@@ -919,55 +924,66 @@ async function createMergeRequest(projectId, options) {
|
|
|
919
924
|
return GitLabMergeRequestSchema.parse(data);
|
|
920
925
|
}
|
|
921
926
|
/**
|
|
922
|
-
*
|
|
923
|
-
*
|
|
927
|
+
* Shared helper function for listing discussions
|
|
928
|
+
* 토론 목록 조회를 위한 공유 헬퍼 함수
|
|
924
929
|
*
|
|
925
930
|
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
926
|
-
* @param {
|
|
927
|
-
* @
|
|
931
|
+
* @param {"issues" | "merge_requests"} resourceType - The type of resource (issues or merge_requests)
|
|
932
|
+
* @param {number} resourceIid - The IID of the issue or merge request
|
|
933
|
+
* @param {PaginationOptions} options - Pagination and sorting options
|
|
934
|
+
* @returns {Promise<PaginatedDiscussionsResponse>} Paginated list of discussions
|
|
928
935
|
*/
|
|
929
|
-
async function
|
|
936
|
+
async function listDiscussions(projectId, resourceType, resourceIid, options = {}) {
|
|
930
937
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
931
|
-
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}
|
|
938
|
+
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/${resourceType}/${resourceIid}/discussions`);
|
|
939
|
+
// Add query parameters for pagination and sorting
|
|
940
|
+
if (options.page) {
|
|
941
|
+
url.searchParams.append("page", options.page.toString());
|
|
942
|
+
}
|
|
943
|
+
if (options.per_page) {
|
|
944
|
+
url.searchParams.append("per_page", options.per_page.toString());
|
|
945
|
+
}
|
|
932
946
|
const response = await fetch(url.toString(), {
|
|
933
947
|
...DEFAULT_FETCH_CONFIG,
|
|
934
948
|
});
|
|
935
949
|
await handleGitLabError(response);
|
|
936
|
-
const
|
|
937
|
-
//
|
|
938
|
-
|
|
950
|
+
const discussions = await response.json();
|
|
951
|
+
// Extract pagination headers
|
|
952
|
+
const pagination = {
|
|
953
|
+
x_next_page: response.headers.get("x-next-page") ? parseInt(response.headers.get("x-next-page")) : null,
|
|
954
|
+
x_page: response.headers.get("x-page") ? parseInt(response.headers.get("x-page")) : undefined,
|
|
955
|
+
x_per_page: response.headers.get("x-per-page") ? parseInt(response.headers.get("x-per-page")) : undefined,
|
|
956
|
+
x_prev_page: response.headers.get("x-prev-page") ? parseInt(response.headers.get("x-prev-page")) : null,
|
|
957
|
+
x_total: response.headers.get("x-total") ? parseInt(response.headers.get("x-total")) : null,
|
|
958
|
+
x_total_pages: response.headers.get("x-total-pages") ? parseInt(response.headers.get("x-total-pages")) : null,
|
|
959
|
+
};
|
|
960
|
+
return PaginatedDiscussionsResponseSchema.parse({
|
|
961
|
+
items: discussions,
|
|
962
|
+
pagination: pagination,
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* List merge request discussion items
|
|
967
|
+
* 병합 요청 토론 목록 조회
|
|
968
|
+
*
|
|
969
|
+
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
970
|
+
* @param {number} mergeRequestIid - The IID of a merge request
|
|
971
|
+
* @param {DiscussionPaginationOptions} options - Pagination and sorting options
|
|
972
|
+
* @returns {Promise<GitLabDiscussion[]>} List of discussions
|
|
973
|
+
*/
|
|
974
|
+
async function listMergeRequestDiscussions(projectId, mergeRequestIid, options = {}) {
|
|
975
|
+
return listDiscussions(projectId, "merge_requests", mergeRequestIid, options);
|
|
939
976
|
}
|
|
940
977
|
/**
|
|
941
978
|
* List discussions for an issue
|
|
942
979
|
*
|
|
943
980
|
* @param {string} projectId - The ID or URL-encoded path of the project
|
|
944
981
|
* @param {number} issueIid - The internal ID of the project issue
|
|
945
|
-
* @param {
|
|
982
|
+
* @param {DiscussionPaginationOptions} options - Pagination and sorting options
|
|
946
983
|
* @returns {Promise<GitLabDiscussion[]>} List of issue discussions
|
|
947
984
|
*/
|
|
948
985
|
async function listIssueDiscussions(projectId, issueIid, options = {}) {
|
|
949
|
-
|
|
950
|
-
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/discussions`);
|
|
951
|
-
// Add query parameters for pagination and sorting
|
|
952
|
-
if (options.page) {
|
|
953
|
-
url.searchParams.append("page", options.page.toString());
|
|
954
|
-
}
|
|
955
|
-
if (options.per_page) {
|
|
956
|
-
url.searchParams.append("per_page", options.per_page.toString());
|
|
957
|
-
}
|
|
958
|
-
if (options.sort) {
|
|
959
|
-
url.searchParams.append("sort", options.sort);
|
|
960
|
-
}
|
|
961
|
-
if (options.order_by) {
|
|
962
|
-
url.searchParams.append("order_by", options.order_by);
|
|
963
|
-
}
|
|
964
|
-
const response = await fetch(url.toString(), {
|
|
965
|
-
...DEFAULT_FETCH_CONFIG,
|
|
966
|
-
});
|
|
967
|
-
await handleGitLabError(response);
|
|
968
|
-
const data = await response.json();
|
|
969
|
-
// Parse the response as an array of discussions
|
|
970
|
-
return z.array(GitLabDiscussionSchema).parse(data);
|
|
986
|
+
return listDiscussions(projectId, "issues", issueIid, options);
|
|
971
987
|
}
|
|
972
988
|
/**
|
|
973
989
|
* Modify an existing merge request thread note
|
|
@@ -2457,7 +2473,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2457
2473
|
}
|
|
2458
2474
|
case "mr_discussions": {
|
|
2459
2475
|
const args = ListMergeRequestDiscussionsSchema.parse(request.params.arguments);
|
|
2460
|
-
const
|
|
2476
|
+
const { project_id, merge_request_iid, ...options } = args;
|
|
2477
|
+
const discussions = await listMergeRequestDiscussions(project_id, merge_request_iid, options);
|
|
2461
2478
|
return {
|
|
2462
2479
|
content: [{ type: "text", text: JSON.stringify(discussions, null, 2) }],
|
|
2463
2480
|
};
|
|
@@ -2966,8 +2983,36 @@ async function runServer() {
|
|
|
2966
2983
|
console.error(`GitLab MCP Server v${SERVER_VERSION}`);
|
|
2967
2984
|
console.error(`API URL: ${GITLAB_API_URL}`);
|
|
2968
2985
|
console.error("========================");
|
|
2969
|
-
|
|
2970
|
-
|
|
2986
|
+
if (!SSE) {
|
|
2987
|
+
const transport = new StdioServerTransport();
|
|
2988
|
+
await server.connect(transport);
|
|
2989
|
+
}
|
|
2990
|
+
else {
|
|
2991
|
+
const app = express();
|
|
2992
|
+
const transports = {};
|
|
2993
|
+
app.get("/sse", async (_, res) => {
|
|
2994
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
2995
|
+
transports[transport.sessionId] = transport;
|
|
2996
|
+
res.on("close", () => {
|
|
2997
|
+
delete transports[transport.sessionId];
|
|
2998
|
+
});
|
|
2999
|
+
await server.connect(transport);
|
|
3000
|
+
});
|
|
3001
|
+
app.post("/messages", async (req, res) => {
|
|
3002
|
+
const sessionId = req.query.sessionId;
|
|
3003
|
+
const transport = transports[sessionId];
|
|
3004
|
+
if (transport) {
|
|
3005
|
+
await transport.handlePostMessage(req, res);
|
|
3006
|
+
}
|
|
3007
|
+
else {
|
|
3008
|
+
res.status(400).send("No transport found for sessionId");
|
|
3009
|
+
}
|
|
3010
|
+
});
|
|
3011
|
+
const PORT = process.env.PORT || 3002;
|
|
3012
|
+
app.listen(PORT, () => {
|
|
3013
|
+
console.log(`Server is running on port ${PORT}`);
|
|
3014
|
+
});
|
|
3015
|
+
}
|
|
2971
3016
|
console.error("GitLab MCP Server running on stdio");
|
|
2972
3017
|
}
|
|
2973
3018
|
catch (error) {
|
package/build/schemas.js
CHANGED
|
@@ -90,6 +90,12 @@ export const GitLabPipelineJobSchema = z.object({
|
|
|
90
90
|
.optional(),
|
|
91
91
|
web_url: z.string().optional(),
|
|
92
92
|
});
|
|
93
|
+
// Shared base schema for various pagination options
|
|
94
|
+
// See https://docs.gitlab.com/api/rest/#pagination
|
|
95
|
+
export const PaginationOptionsSchema = z.object({
|
|
96
|
+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
97
|
+
per_page: z.number().optional().describe("Number of items per page (max: 100, default: 20)"),
|
|
98
|
+
});
|
|
93
99
|
// Schema for listing pipelines
|
|
94
100
|
export const ListPipelinesSchema = z.object({
|
|
95
101
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -130,9 +136,7 @@ export const ListPipelinesSchema = z.object({
|
|
|
130
136
|
.optional()
|
|
131
137
|
.describe("Order pipelines by"),
|
|
132
138
|
sort: z.enum(["asc", "desc"]).optional().describe("Sort pipelines"),
|
|
133
|
-
|
|
134
|
-
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
135
|
-
});
|
|
139
|
+
}).merge(PaginationOptionsSchema);
|
|
136
140
|
// Schema for getting a specific pipeline
|
|
137
141
|
export const GetPipelineSchema = z.object({
|
|
138
142
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -147,9 +151,7 @@ export const ListPipelineJobsSchema = z.object({
|
|
|
147
151
|
.optional()
|
|
148
152
|
.describe("The scope of jobs to show"),
|
|
149
153
|
include_retried: z.boolean().optional().describe("Whether to include retried jobs"),
|
|
150
|
-
|
|
151
|
-
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
152
|
-
});
|
|
154
|
+
}).merge(PaginationOptionsSchema);
|
|
153
155
|
// Schema for creating a new pipeline
|
|
154
156
|
export const CreatePipelineSchema = z.object({
|
|
155
157
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -287,7 +289,7 @@ export const GitLabRepositorySchema = z.object({
|
|
|
287
289
|
container_registry_access_level: z.string().optional(),
|
|
288
290
|
issues_enabled: z.boolean().optional(),
|
|
289
291
|
merge_requests_enabled: z.boolean().optional(),
|
|
290
|
-
merge_requests_template: z.string().optional(),
|
|
292
|
+
merge_requests_template: z.string().nullable().optional(),
|
|
291
293
|
wiki_enabled: z.boolean().optional(),
|
|
292
294
|
jobs_enabled: z.boolean().optional(),
|
|
293
295
|
snippets_enabled: z.boolean().optional(),
|
|
@@ -643,15 +645,39 @@ export const GitLabDiscussionNoteSchema = z.object({
|
|
|
643
645
|
})
|
|
644
646
|
.optional(),
|
|
645
647
|
});
|
|
648
|
+
// Reusable pagination schema for GitLab API responses.
|
|
649
|
+
// See https://docs.gitlab.com/api/rest/#pagination
|
|
650
|
+
export const GitLabPaginationSchema = z.object({
|
|
651
|
+
x_next_page: z.number().nullable().optional(),
|
|
652
|
+
x_page: z.number().optional(),
|
|
653
|
+
x_per_page: z.number().optional(),
|
|
654
|
+
x_prev_page: z.number().nullable().optional(),
|
|
655
|
+
x_total: z.number().nullable().optional(),
|
|
656
|
+
x_total_pages: z.number().nullable().optional(),
|
|
657
|
+
});
|
|
658
|
+
// Base paginated response schema that can be extended.
|
|
659
|
+
// See https://docs.gitlab.com/api/rest/#pagination
|
|
660
|
+
export const PaginatedResponseSchema = z.object({
|
|
661
|
+
pagination: GitLabPaginationSchema.optional(),
|
|
662
|
+
});
|
|
646
663
|
export const GitLabDiscussionSchema = z.object({
|
|
647
664
|
id: z.string(),
|
|
648
665
|
individual_note: z.boolean(),
|
|
649
666
|
notes: z.array(GitLabDiscussionNoteSchema),
|
|
650
667
|
});
|
|
668
|
+
// Create a schema for paginated discussions response
|
|
669
|
+
export const PaginatedDiscussionsResponseSchema = z.object({
|
|
670
|
+
items: z.array(GitLabDiscussionSchema),
|
|
671
|
+
pagination: GitLabPaginationSchema,
|
|
672
|
+
});
|
|
673
|
+
export const ListIssueDiscussionsSchema = z.object({
|
|
674
|
+
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
675
|
+
issue_iid: z.number().describe("The internal ID of the project issue"),
|
|
676
|
+
}).merge(PaginationOptionsSchema);
|
|
651
677
|
// Input schema for listing merge request discussions
|
|
652
678
|
export const ListMergeRequestDiscussionsSchema = ProjectParamsSchema.extend({
|
|
653
679
|
merge_request_iid: z.number().describe("The IID of a merge request"),
|
|
654
|
-
});
|
|
680
|
+
}).merge(PaginationOptionsSchema);
|
|
655
681
|
// Input schema for updating a merge request discussion note
|
|
656
682
|
export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
|
|
657
683
|
merge_request_iid: z.number().describe("The IID of a merge request"),
|
|
@@ -699,9 +725,7 @@ export const CreateOrUpdateFileSchema = ProjectParamsSchema.extend({
|
|
|
699
725
|
});
|
|
700
726
|
export const SearchRepositoriesSchema = z.object({
|
|
701
727
|
search: z.string().describe("Search query"), // Changed from query to match GitLab API
|
|
702
|
-
|
|
703
|
-
per_page: z.number().optional().describe("Number of results per page (default: 20)"),
|
|
704
|
-
});
|
|
728
|
+
}).merge(PaginationOptionsSchema);
|
|
705
729
|
export const CreateRepositorySchema = z.object({
|
|
706
730
|
name: z.string().describe("Repository name"),
|
|
707
731
|
description: z.string().optional().describe("Repository description"),
|
|
@@ -809,10 +833,10 @@ export const ListIssuesSchema = z.object({
|
|
|
809
833
|
created_after: z.string().optional().describe("Return issues created after the given time"),
|
|
810
834
|
created_before: z.string().optional().describe("Return issues created before the given time"),
|
|
811
835
|
due_date: z.string().optional().describe("Return issues that have the due date"),
|
|
812
|
-
|
|
836
|
+
labels: z.array(z.string()).optional().describe("Array of label names"),
|
|
813
837
|
milestone: z.string().optional().describe("Milestone title"),
|
|
814
838
|
scope: z
|
|
815
|
-
.enum(["
|
|
839
|
+
.enum(["created_by_me", "assigned_to_me", "all"])
|
|
816
840
|
.optional()
|
|
817
841
|
.describe("Return issues from a specific scope"),
|
|
818
842
|
search: z.string().optional().describe("Search for specific terms"),
|
|
@@ -823,9 +847,7 @@ export const ListIssuesSchema = z.object({
|
|
|
823
847
|
updated_after: z.string().optional().describe("Return issues updated after the given time"),
|
|
824
848
|
updated_before: z.string().optional().describe("Return issues updated before the given time"),
|
|
825
849
|
with_labels_details: z.boolean().optional().describe("Return more details for each label"),
|
|
826
|
-
|
|
827
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
828
|
-
});
|
|
850
|
+
}).merge(PaginationOptionsSchema);
|
|
829
851
|
// Merge Requests API operation schemas
|
|
830
852
|
export const ListMergeRequestsSchema = z.object({
|
|
831
853
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -895,9 +917,7 @@ export const ListMergeRequestsSchema = z.object({
|
|
|
895
917
|
.describe("Return merge requests from a specific source branch"),
|
|
896
918
|
wip: z.enum(["yes", "no"]).optional().describe("Filter merge requests against their wip status"),
|
|
897
919
|
with_labels_details: z.boolean().optional().describe("Return more details for each label"),
|
|
898
|
-
|
|
899
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
900
|
-
});
|
|
920
|
+
}).merge(PaginationOptionsSchema);
|
|
901
921
|
export const GetIssueSchema = z.object({
|
|
902
922
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
903
923
|
issue_iid: z.number().describe("The internal ID of the project issue"),
|
|
@@ -930,20 +950,6 @@ export const ListIssueLinksSchema = z.object({
|
|
|
930
950
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
931
951
|
issue_iid: z.number().describe("The internal ID of a project's issue"),
|
|
932
952
|
});
|
|
933
|
-
export const ListIssueDiscussionsSchema = z.object({
|
|
934
|
-
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
935
|
-
issue_iid: z.number().describe("The internal ID of the project issue"),
|
|
936
|
-
page: z.number().optional().describe("Page number for pagination"),
|
|
937
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
938
|
-
sort: z
|
|
939
|
-
.enum(["asc", "desc"])
|
|
940
|
-
.optional()
|
|
941
|
-
.describe("Return issue discussions sorted in ascending or descending order"),
|
|
942
|
-
order_by: z
|
|
943
|
-
.enum(["created_at", "updated_at"])
|
|
944
|
-
.optional()
|
|
945
|
-
.describe("Return issue discussions ordered by created_at or updated_at fields"),
|
|
946
|
-
});
|
|
947
953
|
export const GetIssueLinkSchema = z.object({
|
|
948
954
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
949
955
|
issue_iid: z.number().describe("The internal ID of a project's issue"),
|
|
@@ -967,10 +973,8 @@ export const DeleteIssueLinkSchema = z.object({
|
|
|
967
973
|
// Namespace API operation schemas
|
|
968
974
|
export const ListNamespacesSchema = z.object({
|
|
969
975
|
search: z.string().optional().describe("Search term for namespaces"),
|
|
970
|
-
page: z.number().optional().describe("Page number for pagination"),
|
|
971
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
972
976
|
owned: z.boolean().optional().describe("Filter for namespaces owned by current user"),
|
|
973
|
-
});
|
|
977
|
+
}).merge(PaginationOptionsSchema);
|
|
974
978
|
export const GetNamespaceSchema = z.object({
|
|
975
979
|
namespace_id: z.string().describe("Namespace ID or full path"),
|
|
976
980
|
});
|
|
@@ -983,8 +987,6 @@ export const GetProjectSchema = z.object({
|
|
|
983
987
|
});
|
|
984
988
|
export const ListProjectsSchema = z.object({
|
|
985
989
|
search: z.string().optional().describe("Search term for projects"),
|
|
986
|
-
page: z.number().optional().describe("Page number for pagination"),
|
|
987
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
988
990
|
search_namespaces: z.boolean().optional().describe("Needs to be true if search is full path"),
|
|
989
991
|
owned: z.boolean().optional().describe("Filter for projects owned by current user"),
|
|
990
992
|
membership: z.boolean().optional().describe("Filter for projects where current user is a member"),
|
|
@@ -1011,7 +1013,7 @@ export const ListProjectsSchema = z.object({
|
|
|
1011
1013
|
.optional()
|
|
1012
1014
|
.describe("Filter projects with merge requests feature enabled"),
|
|
1013
1015
|
min_access_level: z.number().optional().describe("Filter by minimum access level"),
|
|
1014
|
-
});
|
|
1016
|
+
}).merge(PaginationOptionsSchema);
|
|
1015
1017
|
// Label operation schemas
|
|
1016
1018
|
export const ListLabelsSchema = z.object({
|
|
1017
1019
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
@@ -1061,8 +1063,6 @@ export const ListGroupProjectsSchema = z.object({
|
|
|
1061
1063
|
.optional()
|
|
1062
1064
|
.describe("Field to sort by"),
|
|
1063
1065
|
sort: z.enum(["asc", "desc"]).optional().describe("Sort direction"),
|
|
1064
|
-
page: z.number().optional().describe("Page number"),
|
|
1065
|
-
per_page: z.number().optional().describe("Number of results per page"),
|
|
1066
1066
|
archived: z.boolean().optional().describe("Filter for archived projects"),
|
|
1067
1067
|
visibility: z
|
|
1068
1068
|
.enum(["public", "internal", "private"])
|
|
@@ -1082,13 +1082,11 @@ export const ListGroupProjectsSchema = z.object({
|
|
|
1082
1082
|
statistics: z.boolean().optional().describe("Include project statistics"),
|
|
1083
1083
|
with_custom_attributes: z.boolean().optional().describe("Include custom attributes"),
|
|
1084
1084
|
with_security_reports: z.boolean().optional().describe("Include security reports"),
|
|
1085
|
-
});
|
|
1085
|
+
}).merge(PaginationOptionsSchema);
|
|
1086
1086
|
// Add wiki operation schemas
|
|
1087
1087
|
export const ListWikiPagesSchema = z.object({
|
|
1088
1088
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
1089
|
-
|
|
1090
|
-
per_page: z.number().optional().describe("Number of items per page"),
|
|
1091
|
-
});
|
|
1089
|
+
}).merge(PaginationOptionsSchema);
|
|
1092
1090
|
export const GetWikiPageSchema = z.object({
|
|
1093
1091
|
project_id: z.string().describe("Project ID or URL-encoded path"),
|
|
1094
1092
|
slug: z.string().describe("URL-encoded slug of the wiki page"),
|
|
@@ -1166,9 +1164,7 @@ export const ListProjectMilestonesSchema = ProjectParamsSchema.extend({
|
|
|
1166
1164
|
.string()
|
|
1167
1165
|
.optional()
|
|
1168
1166
|
.describe("Return milestones updated after the specified date (ISO 8601 format)"),
|
|
1169
|
-
|
|
1170
|
-
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
1171
|
-
});
|
|
1167
|
+
}).merge(PaginationOptionsSchema);
|
|
1172
1168
|
// Schema for getting a single milestone
|
|
1173
1169
|
export const GetProjectMilestoneSchema = ProjectParamsSchema.extend({
|
|
1174
1170
|
milestone_id: z.number().describe("The ID of a project milestone"),
|
|
@@ -1196,14 +1192,8 @@ export const DeleteProjectMilestoneSchema = GetProjectMilestoneSchema;
|
|
|
1196
1192
|
// Schema for getting issues assigned to a milestone
|
|
1197
1193
|
export const GetMilestoneIssuesSchema = GetProjectMilestoneSchema;
|
|
1198
1194
|
// Schema for getting merge requests assigned to a milestone
|
|
1199
|
-
export const GetMilestoneMergeRequestsSchema = GetProjectMilestoneSchema.
|
|
1200
|
-
page: z.number().optional().describe("Page number for pagination"),
|
|
1201
|
-
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
1202
|
-
});
|
|
1195
|
+
export const GetMilestoneMergeRequestsSchema = GetProjectMilestoneSchema.merge(PaginationOptionsSchema);
|
|
1203
1196
|
// Schema for promoting a project milestone to a group milestone
|
|
1204
1197
|
export const PromoteProjectMilestoneSchema = GetProjectMilestoneSchema;
|
|
1205
1198
|
// Schema for getting burndown chart events for a milestone
|
|
1206
|
-
export const GetMilestoneBurndownEventsSchema = GetProjectMilestoneSchema.
|
|
1207
|
-
page: z.number().optional().describe("Page number for pagination"),
|
|
1208
|
-
per_page: z.number().optional().describe("Number of items per page (max 100)"),
|
|
1209
|
-
});
|
|
1199
|
+
export const GetMilestoneBurndownEventsSchema = GetProjectMilestoneSchema.merge(PaginationOptionsSchema);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.57",
|
|
4
4
|
"description": "MCP server for using the GitLab API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zereight",
|
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@modelcontextprotocol/sdk": "1.8.0",
|
|
33
|
-
"form-data": "^4.0.0",
|
|
34
33
|
"@types/node-fetch": "^2.6.12",
|
|
34
|
+
"express": "^5.1.0",
|
|
35
|
+
"form-data": "^4.0.0",
|
|
35
36
|
"http-proxy-agent": "^7.0.2",
|
|
36
37
|
"https-proxy-agent": "^7.0.6",
|
|
37
38
|
"node-fetch": "^3.3.2",
|
|
@@ -39,13 +40,14 @@
|
|
|
39
40
|
"zod-to-json-schema": "^3.23.5"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
43
|
+
"@types/express": "^5.0.2",
|
|
42
44
|
"@types/node": "^22.13.10",
|
|
43
|
-
"typescript": "^5.8.2",
|
|
44
|
-
"zod": "^3.24.2",
|
|
45
45
|
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
|
46
46
|
"@typescript-eslint/parser": "^8.21.0",
|
|
47
47
|
"eslint": "^9.18.0",
|
|
48
48
|
"prettier": "^3.4.2",
|
|
49
|
-
"ts-node": "^10.9.2"
|
|
49
|
+
"ts-node": "^10.9.2",
|
|
50
|
+
"typescript": "^5.8.2",
|
|
51
|
+
"zod": "^3.24.2"
|
|
50
52
|
}
|
|
51
53
|
}
|