@zereight/mcp-gitlab 1.0.63 → 1.0.64
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 +1 -0
- package/build/index.js +78 -1
- package/build/schemas.js +2 -2
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ $ sh scripts/image_push.sh docker_user_name
|
|
|
111
111
|
- `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.
|
|
112
112
|
- `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.
|
|
113
113
|
- `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.
|
|
114
|
+
- `GITLAB_AUTH_COOKIE_PATH`: Path to an authentication cookie file for GitLab instances that require cookie-based authentication. When provided, the cookie will be included in all GitLab API requests.
|
|
114
115
|
|
|
115
116
|
## Tools 🛠️
|
|
116
117
|
|
package/build/index.js
CHANGED
|
@@ -3,7 +3,9 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
5
5
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import
|
|
6
|
+
import nodeFetch from "node-fetch";
|
|
7
|
+
import fetchCookie from "fetch-cookie";
|
|
8
|
+
import { CookieJar, parse as parseCookie } from "tough-cookie";
|
|
7
9
|
import { SocksProxyAgent } from "socks-proxy-agent";
|
|
8
10
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
9
11
|
import { HttpProxyAgent } from "http-proxy-agent";
|
|
@@ -51,6 +53,7 @@ const server = new Server({
|
|
|
51
53
|
},
|
|
52
54
|
});
|
|
53
55
|
const GITLAB_PERSONAL_ACCESS_TOKEN = process.env.GITLAB_PERSONAL_ACCESS_TOKEN;
|
|
56
|
+
const GITLAB_AUTH_COOKIE_PATH = process.env.GITLAB_AUTH_COOKIE_PATH;
|
|
54
57
|
const IS_OLD = process.env.GITLAB_IS_OLD === "true";
|
|
55
58
|
const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
|
|
56
59
|
const USE_GITLAB_WIKI = process.env.USE_GITLAB_WIKI === "true";
|
|
@@ -91,6 +94,76 @@ if (HTTPS_PROXY) {
|
|
|
91
94
|
}
|
|
92
95
|
httpsAgent = httpsAgent || new HttpsAgent(sslOptions);
|
|
93
96
|
httpAgent = httpAgent || new Agent();
|
|
97
|
+
// Create cookie jar with clean Netscape file parsing
|
|
98
|
+
const createCookieJar = () => {
|
|
99
|
+
if (!GITLAB_AUTH_COOKIE_PATH)
|
|
100
|
+
return null;
|
|
101
|
+
try {
|
|
102
|
+
const cookiePath = GITLAB_AUTH_COOKIE_PATH.startsWith("~/")
|
|
103
|
+
? path.join(process.env.HOME || "", GITLAB_AUTH_COOKIE_PATH.slice(2))
|
|
104
|
+
: GITLAB_AUTH_COOKIE_PATH;
|
|
105
|
+
const jar = new CookieJar();
|
|
106
|
+
const cookieContent = fs.readFileSync(cookiePath, "utf8");
|
|
107
|
+
cookieContent.split("\n").forEach(line => {
|
|
108
|
+
// Handle #HttpOnly_ prefix
|
|
109
|
+
if (line.startsWith("#HttpOnly_")) {
|
|
110
|
+
line = line.slice(10);
|
|
111
|
+
}
|
|
112
|
+
// Skip comments and empty lines
|
|
113
|
+
if (line.startsWith("#") || !line.trim()) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Parse Netscape format: domain, flag, path, secure, expires, name, value
|
|
117
|
+
const parts = line.split("\t");
|
|
118
|
+
if (parts.length >= 7) {
|
|
119
|
+
const [domain, , path, secure, expires, name, value] = parts;
|
|
120
|
+
// Build cookie string in standard format
|
|
121
|
+
const cookieStr = `${name}=${value}; Domain=${domain}; Path=${path}${secure === "TRUE" ? "; Secure" : ""}${expires !== "0" ? `; Expires=${new Date(parseInt(expires) * 1000).toUTCString()}` : ""}`;
|
|
122
|
+
// Use tough-cookie's parse function for robust parsing
|
|
123
|
+
const cookie = parseCookie(cookieStr);
|
|
124
|
+
if (cookie) {
|
|
125
|
+
const url = `${secure === "TRUE" ? "https" : "http"}://${domain.startsWith(".") ? domain.slice(1) : domain}`;
|
|
126
|
+
jar.setCookieSync(cookie, url);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return jar;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error("Error loading cookie file:", error);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
// Initialize cookie jar and fetch
|
|
138
|
+
const cookieJar = createCookieJar();
|
|
139
|
+
const fetch = cookieJar ? fetchCookie(nodeFetch, cookieJar) : nodeFetch;
|
|
140
|
+
// Ensure session is established for the current request
|
|
141
|
+
async function ensureSessionForRequest() {
|
|
142
|
+
if (!cookieJar || !GITLAB_AUTH_COOKIE_PATH)
|
|
143
|
+
return;
|
|
144
|
+
// Extract the base URL from GITLAB_API_URL
|
|
145
|
+
const apiUrl = new URL(GITLAB_API_URL);
|
|
146
|
+
const baseUrl = `${apiUrl.protocol}//${apiUrl.hostname}`;
|
|
147
|
+
// Check if we already have GitLab session cookies
|
|
148
|
+
const gitlabCookies = cookieJar.getCookiesSync(baseUrl);
|
|
149
|
+
const hasSessionCookie = gitlabCookies.some(cookie => cookie.key === '_gitlab_session' || cookie.key === 'remember_user_token');
|
|
150
|
+
if (!hasSessionCookie) {
|
|
151
|
+
try {
|
|
152
|
+
// Establish session with a lightweight request
|
|
153
|
+
await fetch(`${GITLAB_API_URL}/user`, {
|
|
154
|
+
...DEFAULT_FETCH_CONFIG,
|
|
155
|
+
redirect: 'follow'
|
|
156
|
+
}).catch(() => {
|
|
157
|
+
// Ignore errors - the important thing is that cookies get set during redirects
|
|
158
|
+
});
|
|
159
|
+
// Small delay to ensure cookies are fully processed
|
|
160
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
// Ignore session establishment errors
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
94
167
|
// Modify DEFAULT_HEADERS to include agent configuration
|
|
95
168
|
const DEFAULT_HEADERS = {
|
|
96
169
|
Accept: "application/json",
|
|
@@ -2362,6 +2435,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2362
2435
|
if (!request.params.arguments) {
|
|
2363
2436
|
throw new Error("Arguments are required");
|
|
2364
2437
|
}
|
|
2438
|
+
// Ensure session is established for every request if cookie authentication is enabled
|
|
2439
|
+
if (GITLAB_AUTH_COOKIE_PATH) {
|
|
2440
|
+
await ensureSessionForRequest();
|
|
2441
|
+
}
|
|
2365
2442
|
switch (request.params.name) {
|
|
2366
2443
|
case "fork_repository": {
|
|
2367
2444
|
const forkArgs = ForkRepositorySchema.parse(request.params.arguments);
|
package/build/schemas.js
CHANGED
|
@@ -274,14 +274,14 @@ export const GitLabRepositorySchema = z.object({
|
|
|
274
274
|
project_access: z
|
|
275
275
|
.object({
|
|
276
276
|
access_level: z.number(),
|
|
277
|
-
notification_level: z.number().optional(),
|
|
277
|
+
notification_level: z.number().nullable().optional(),
|
|
278
278
|
})
|
|
279
279
|
.optional()
|
|
280
280
|
.nullable(),
|
|
281
281
|
group_access: z
|
|
282
282
|
.object({
|
|
283
283
|
access_level: z.number(),
|
|
284
|
-
notification_level: z.number().optional(),
|
|
284
|
+
notification_level: z.number().nullable().optional(),
|
|
285
285
|
})
|
|
286
286
|
.optional()
|
|
287
287
|
.nullable(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.64",
|
|
4
4
|
"description": "MCP server for using the GitLab API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zereight",
|
|
@@ -33,11 +33,13 @@
|
|
|
33
33
|
"@modelcontextprotocol/sdk": "1.8.0",
|
|
34
34
|
"@types/node-fetch": "^2.6.12",
|
|
35
35
|
"express": "^5.1.0",
|
|
36
|
+
"fetch-cookie": "^3.1.0",
|
|
36
37
|
"form-data": "^4.0.0",
|
|
37
38
|
"http-proxy-agent": "^7.0.2",
|
|
38
39
|
"https-proxy-agent": "^7.0.6",
|
|
39
40
|
"node-fetch": "^3.3.2",
|
|
40
41
|
"socks-proxy-agent": "^8.0.5",
|
|
42
|
+
"tough-cookie": "^5.1.2",
|
|
41
43
|
"zod-to-json-schema": "^3.23.5"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|