@zereight/mcp-gitlab 1.0.29 → 1.0.31
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/LICENSE +21 -0
- package/build/index.js +92 -77
- package/package.json +5 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Roo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/build/index.js
CHANGED
|
@@ -3,12 +3,16 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
5
|
import fetch from "node-fetch";
|
|
6
|
+
import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
7
|
+
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
8
|
+
import { HttpProxyAgent } from 'http-proxy-agent';
|
|
6
9
|
import { z } from "zod";
|
|
7
10
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
8
11
|
import { fileURLToPath } from "url";
|
|
9
12
|
import { dirname } from "path";
|
|
10
13
|
import fs from "fs";
|
|
11
14
|
import path from "path";
|
|
15
|
+
import { URL } from 'url';
|
|
12
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, GetIssueLinkSchema, CreateIssueLinkSchema, DeleteIssueLinkSchema, ListNamespacesSchema, GetNamespaceSchema, VerifyNamespaceSchema, GetProjectSchema, ListProjectsSchema, ListLabelsSchema, GetLabelSchema, CreateLabelSchema, UpdateLabelSchema, DeleteLabelSchema, CreateNoteSchema, ListGroupProjectsSchema,
|
|
13
17
|
// Discussion Schemas
|
|
14
18
|
GitLabDiscussionNoteSchema, // Added
|
|
@@ -40,6 +44,44 @@ const server = new Server({
|
|
|
40
44
|
});
|
|
41
45
|
const GITLAB_PERSONAL_ACCESS_TOKEN = process.env.GITLAB_PERSONAL_ACCESS_TOKEN;
|
|
42
46
|
const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
|
|
47
|
+
// Add proxy configuration
|
|
48
|
+
const HTTP_PROXY = process.env.HTTP_PROXY;
|
|
49
|
+
const HTTPS_PROXY = process.env.HTTPS_PROXY;
|
|
50
|
+
// Configure proxy agents if proxies are set
|
|
51
|
+
let httpAgent = undefined;
|
|
52
|
+
let httpsAgent = undefined;
|
|
53
|
+
if (HTTP_PROXY) {
|
|
54
|
+
if (HTTP_PROXY.startsWith('socks')) {
|
|
55
|
+
httpAgent = new SocksProxyAgent(HTTP_PROXY);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
httpAgent = new HttpProxyAgent(HTTP_PROXY);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (HTTPS_PROXY) {
|
|
62
|
+
if (HTTPS_PROXY.startsWith('socks')) {
|
|
63
|
+
httpsAgent = new SocksProxyAgent(HTTPS_PROXY);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
httpsAgent = new HttpsProxyAgent(HTTPS_PROXY);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Modify DEFAULT_HEADERS to include agent configuration
|
|
70
|
+
const DEFAULT_HEADERS = {
|
|
71
|
+
Accept: "application/json",
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
74
|
+
};
|
|
75
|
+
// Create a default fetch configuration object that includes proxy agents if set
|
|
76
|
+
const DEFAULT_FETCH_CONFIG = {
|
|
77
|
+
headers: DEFAULT_HEADERS,
|
|
78
|
+
agent: (parsedUrl) => {
|
|
79
|
+
if (parsedUrl.protocol === 'https:') {
|
|
80
|
+
return httpsAgent;
|
|
81
|
+
}
|
|
82
|
+
return httpAgent;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
43
85
|
// Define all available tools
|
|
44
86
|
const allTools = [
|
|
45
87
|
{
|
|
@@ -259,15 +301,6 @@ if (!GITLAB_PERSONAL_ACCESS_TOKEN) {
|
|
|
259
301
|
console.error("GITLAB_PERSONAL_ACCESS_TOKEN environment variable is not set");
|
|
260
302
|
process.exit(1);
|
|
261
303
|
}
|
|
262
|
-
/**
|
|
263
|
-
* Common headers for GitLab API requests
|
|
264
|
-
* GitLab API 공통 헤더 (Common headers for GitLab API)
|
|
265
|
-
*/
|
|
266
|
-
const DEFAULT_HEADERS = {
|
|
267
|
-
Accept: "application/json",
|
|
268
|
-
"Content-Type": "application/json",
|
|
269
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
270
|
-
};
|
|
271
304
|
/**
|
|
272
305
|
* Utility function for handling GitLab API errors
|
|
273
306
|
* API 에러 처리를 위한 유틸리티 함수 (Utility function for handling API errors)
|
|
@@ -278,7 +311,16 @@ const DEFAULT_HEADERS = {
|
|
|
278
311
|
async function handleGitLabError(response) {
|
|
279
312
|
if (!response.ok) {
|
|
280
313
|
const errorBody = await response.text();
|
|
281
|
-
|
|
314
|
+
// Check specifically for Rate Limit error
|
|
315
|
+
if (response.status === 403 && errorBody.includes("User API Key Rate limit exceeded")) {
|
|
316
|
+
console.error("GitLab API Rate Limit Exceeded:", errorBody);
|
|
317
|
+
console.log("User API Key Rate limit exceeded. Please try again later.");
|
|
318
|
+
throw new Error(`GitLab API Rate Limit Exceeded: ${errorBody}`);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
// Handle other API errors
|
|
322
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorBody}`);
|
|
323
|
+
}
|
|
282
324
|
}
|
|
283
325
|
}
|
|
284
326
|
/**
|
|
@@ -290,14 +332,13 @@ async function handleGitLabError(response) {
|
|
|
290
332
|
* @returns {Promise<GitLabFork>} The created fork
|
|
291
333
|
*/
|
|
292
334
|
async function forkProject(projectId, namespace) {
|
|
293
|
-
// API 엔드포인트 URL 생성
|
|
294
335
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/fork`);
|
|
295
336
|
if (namespace) {
|
|
296
337
|
url.searchParams.append("namespace", namespace);
|
|
297
338
|
}
|
|
298
339
|
const response = await fetch(url.toString(), {
|
|
340
|
+
...DEFAULT_FETCH_CONFIG,
|
|
299
341
|
method: "POST",
|
|
300
|
-
headers: DEFAULT_HEADERS,
|
|
301
342
|
});
|
|
302
343
|
// 이미 존재하는 프로젝트인 경우 처리
|
|
303
344
|
if (response.status === 409) {
|
|
@@ -318,8 +359,8 @@ async function forkProject(projectId, namespace) {
|
|
|
318
359
|
async function createBranch(projectId, options) {
|
|
319
360
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/branches`);
|
|
320
361
|
const response = await fetch(url.toString(), {
|
|
362
|
+
...DEFAULT_FETCH_CONFIG,
|
|
321
363
|
method: "POST",
|
|
322
|
-
headers: DEFAULT_HEADERS,
|
|
323
364
|
body: JSON.stringify({
|
|
324
365
|
branch: options.name,
|
|
325
366
|
ref: options.ref,
|
|
@@ -338,7 +379,7 @@ async function createBranch(projectId, options) {
|
|
|
338
379
|
async function getDefaultBranchRef(projectId) {
|
|
339
380
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}`);
|
|
340
381
|
const response = await fetch(url.toString(), {
|
|
341
|
-
|
|
382
|
+
...DEFAULT_FETCH_CONFIG,
|
|
342
383
|
});
|
|
343
384
|
await handleGitLabError(response);
|
|
344
385
|
const project = GitLabRepositorySchema.parse(await response.json());
|
|
@@ -362,7 +403,7 @@ async function getFileContents(projectId, filePath, ref) {
|
|
|
362
403
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/files/${encodedPath}`);
|
|
363
404
|
url.searchParams.append("ref", ref);
|
|
364
405
|
const response = await fetch(url.toString(), {
|
|
365
|
-
|
|
406
|
+
...DEFAULT_FETCH_CONFIG,
|
|
366
407
|
});
|
|
367
408
|
// 파일을 찾을 수 없는 경우 처리
|
|
368
409
|
if (response.status === 404) {
|
|
@@ -389,8 +430,8 @@ async function getFileContents(projectId, filePath, ref) {
|
|
|
389
430
|
async function createIssue(projectId, options) {
|
|
390
431
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues`);
|
|
391
432
|
const response = await fetch(url.toString(), {
|
|
433
|
+
...DEFAULT_FETCH_CONFIG,
|
|
392
434
|
method: "POST",
|
|
393
|
-
headers: DEFAULT_HEADERS,
|
|
394
435
|
body: JSON.stringify({
|
|
395
436
|
title: options.title,
|
|
396
437
|
description: options.description,
|
|
@@ -431,7 +472,7 @@ async function listIssues(projectId, options = {}) {
|
|
|
431
472
|
}
|
|
432
473
|
});
|
|
433
474
|
const response = await fetch(url.toString(), {
|
|
434
|
-
|
|
475
|
+
...DEFAULT_FETCH_CONFIG,
|
|
435
476
|
});
|
|
436
477
|
await handleGitLabError(response);
|
|
437
478
|
const data = await response.json();
|
|
@@ -448,7 +489,7 @@ async function listIssues(projectId, options = {}) {
|
|
|
448
489
|
async function getIssue(projectId, issueIid) {
|
|
449
490
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}`);
|
|
450
491
|
const response = await fetch(url.toString(), {
|
|
451
|
-
|
|
492
|
+
...DEFAULT_FETCH_CONFIG,
|
|
452
493
|
});
|
|
453
494
|
await handleGitLabError(response);
|
|
454
495
|
const data = await response.json();
|
|
@@ -471,8 +512,8 @@ async function updateIssue(projectId, issueIid, options) {
|
|
|
471
512
|
body.labels = body.labels.join(",");
|
|
472
513
|
}
|
|
473
514
|
const response = await fetch(url.toString(), {
|
|
515
|
+
...DEFAULT_FETCH_CONFIG,
|
|
474
516
|
method: "PUT",
|
|
475
|
-
headers: DEFAULT_HEADERS,
|
|
476
517
|
body: JSON.stringify(body),
|
|
477
518
|
});
|
|
478
519
|
await handleGitLabError(response);
|
|
@@ -490,8 +531,8 @@ async function updateIssue(projectId, issueIid, options) {
|
|
|
490
531
|
async function deleteIssue(projectId, issueIid) {
|
|
491
532
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}`);
|
|
492
533
|
const response = await fetch(url.toString(), {
|
|
534
|
+
...DEFAULT_FETCH_CONFIG,
|
|
493
535
|
method: "DELETE",
|
|
494
|
-
headers: DEFAULT_HEADERS,
|
|
495
536
|
});
|
|
496
537
|
await handleGitLabError(response);
|
|
497
538
|
}
|
|
@@ -506,7 +547,7 @@ async function deleteIssue(projectId, issueIid) {
|
|
|
506
547
|
async function listIssueLinks(projectId, issueIid) {
|
|
507
548
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links`);
|
|
508
549
|
const response = await fetch(url.toString(), {
|
|
509
|
-
|
|
550
|
+
...DEFAULT_FETCH_CONFIG,
|
|
510
551
|
});
|
|
511
552
|
await handleGitLabError(response);
|
|
512
553
|
const data = await response.json();
|
|
@@ -524,7 +565,7 @@ async function listIssueLinks(projectId, issueIid) {
|
|
|
524
565
|
async function getIssueLink(projectId, issueIid, issueLinkId) {
|
|
525
566
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links/${issueLinkId}`);
|
|
526
567
|
const response = await fetch(url.toString(), {
|
|
527
|
-
|
|
568
|
+
...DEFAULT_FETCH_CONFIG,
|
|
528
569
|
});
|
|
529
570
|
await handleGitLabError(response);
|
|
530
571
|
const data = await response.json();
|
|
@@ -544,8 +585,8 @@ async function getIssueLink(projectId, issueIid, issueLinkId) {
|
|
|
544
585
|
async function createIssueLink(projectId, issueIid, targetProjectId, targetIssueIid, linkType = "relates_to") {
|
|
545
586
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links`);
|
|
546
587
|
const response = await fetch(url.toString(), {
|
|
588
|
+
...DEFAULT_FETCH_CONFIG,
|
|
547
589
|
method: "POST",
|
|
548
|
-
headers: DEFAULT_HEADERS,
|
|
549
590
|
body: JSON.stringify({
|
|
550
591
|
target_project_id: targetProjectId,
|
|
551
592
|
target_issue_iid: targetIssueIid,
|
|
@@ -568,8 +609,8 @@ async function createIssueLink(projectId, issueIid, targetProjectId, targetIssue
|
|
|
568
609
|
async function deleteIssueLink(projectId, issueIid, issueLinkId) {
|
|
569
610
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links/${issueLinkId}`);
|
|
570
611
|
const response = await fetch(url.toString(), {
|
|
612
|
+
...DEFAULT_FETCH_CONFIG,
|
|
571
613
|
method: "DELETE",
|
|
572
|
-
headers: DEFAULT_HEADERS,
|
|
573
614
|
});
|
|
574
615
|
await handleGitLabError(response);
|
|
575
616
|
}
|
|
@@ -584,12 +625,8 @@ async function deleteIssueLink(projectId, issueIid, issueLinkId) {
|
|
|
584
625
|
async function createMergeRequest(projectId, options) {
|
|
585
626
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests`);
|
|
586
627
|
const response = await fetch(url.toString(), {
|
|
628
|
+
...DEFAULT_FETCH_CONFIG,
|
|
587
629
|
method: "POST",
|
|
588
|
-
headers: {
|
|
589
|
-
Accept: "application/json",
|
|
590
|
-
"Content-Type": "application/json",
|
|
591
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
592
|
-
},
|
|
593
630
|
body: JSON.stringify({
|
|
594
631
|
title: options.title,
|
|
595
632
|
description: options.description,
|
|
@@ -621,7 +658,7 @@ async function createMergeRequest(projectId, options) {
|
|
|
621
658
|
async function listMergeRequestDiscussions(projectId, mergeRequestIid) {
|
|
622
659
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`);
|
|
623
660
|
const response = await fetch(url.toString(), {
|
|
624
|
-
|
|
661
|
+
...DEFAULT_FETCH_CONFIG,
|
|
625
662
|
});
|
|
626
663
|
await handleGitLabError(response);
|
|
627
664
|
const data = await response.json();
|
|
@@ -647,8 +684,8 @@ async function updateMergeRequestNote(projectId, mergeRequestIid, discussionId,
|
|
|
647
684
|
payload.resolved = resolved;
|
|
648
685
|
}
|
|
649
686
|
const response = await fetch(url.toString(), {
|
|
687
|
+
...DEFAULT_FETCH_CONFIG,
|
|
650
688
|
method: "PUT",
|
|
651
|
-
headers: DEFAULT_HEADERS,
|
|
652
689
|
body: JSON.stringify(payload),
|
|
653
690
|
});
|
|
654
691
|
await handleGitLabError(response);
|
|
@@ -714,12 +751,8 @@ async function createOrUpdateFile(projectId, filePath, content, commitMessage, b
|
|
|
714
751
|
}
|
|
715
752
|
}
|
|
716
753
|
const response = await fetch(url.toString(), {
|
|
754
|
+
...DEFAULT_FETCH_CONFIG,
|
|
717
755
|
method,
|
|
718
|
-
headers: {
|
|
719
|
-
Accept: "application/json",
|
|
720
|
-
"Content-Type": "application/json",
|
|
721
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
722
|
-
},
|
|
723
756
|
body: JSON.stringify(body),
|
|
724
757
|
});
|
|
725
758
|
if (!response.ok) {
|
|
@@ -744,12 +777,8 @@ async function createTree(projectId, files, ref) {
|
|
|
744
777
|
url.searchParams.append("ref", ref);
|
|
745
778
|
}
|
|
746
779
|
const response = await fetch(url.toString(), {
|
|
780
|
+
...DEFAULT_FETCH_CONFIG,
|
|
747
781
|
method: "POST",
|
|
748
|
-
headers: {
|
|
749
|
-
Accept: "application/json",
|
|
750
|
-
"Content-Type": "application/json",
|
|
751
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
752
|
-
},
|
|
753
782
|
body: JSON.stringify({
|
|
754
783
|
files: files.map((file) => ({
|
|
755
784
|
file_path: file.path,
|
|
@@ -782,12 +811,8 @@ async function createTree(projectId, files, ref) {
|
|
|
782
811
|
async function createCommit(projectId, message, branch, actions) {
|
|
783
812
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/commits`);
|
|
784
813
|
const response = await fetch(url.toString(), {
|
|
814
|
+
...DEFAULT_FETCH_CONFIG,
|
|
785
815
|
method: "POST",
|
|
786
|
-
headers: {
|
|
787
|
-
Accept: "application/json",
|
|
788
|
-
"Content-Type": "application/json",
|
|
789
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
790
|
-
},
|
|
791
816
|
body: JSON.stringify({
|
|
792
817
|
branch,
|
|
793
818
|
commit_message: message,
|
|
@@ -827,11 +852,7 @@ async function searchProjects(query, page = 1, perPage = 20) {
|
|
|
827
852
|
url.searchParams.append("order_by", "id");
|
|
828
853
|
url.searchParams.append("sort", "desc");
|
|
829
854
|
const response = await fetch(url.toString(), {
|
|
830
|
-
|
|
831
|
-
Accept: "application/json",
|
|
832
|
-
"Content-Type": "application/json",
|
|
833
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
834
|
-
},
|
|
855
|
+
...DEFAULT_FETCH_CONFIG,
|
|
835
856
|
});
|
|
836
857
|
if (!response.ok) {
|
|
837
858
|
const errorBody = await response.text();
|
|
@@ -858,12 +879,8 @@ async function searchProjects(query, page = 1, perPage = 20) {
|
|
|
858
879
|
*/
|
|
859
880
|
async function createRepository(options) {
|
|
860
881
|
const response = await fetch(`${GITLAB_API_URL}/projects`, {
|
|
882
|
+
...DEFAULT_FETCH_CONFIG,
|
|
861
883
|
method: "POST",
|
|
862
|
-
headers: {
|
|
863
|
-
Accept: "application/json",
|
|
864
|
-
"Content-Type": "application/json",
|
|
865
|
-
Authorization: `Bearer ${GITLAB_PERSONAL_ACCESS_TOKEN}`,
|
|
866
|
-
},
|
|
867
884
|
body: JSON.stringify({
|
|
868
885
|
name: options.name,
|
|
869
886
|
description: options.description,
|
|
@@ -891,7 +908,7 @@ async function createRepository(options) {
|
|
|
891
908
|
async function getMergeRequest(projectId, mergeRequestIid) {
|
|
892
909
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}`);
|
|
893
910
|
const response = await fetch(url.toString(), {
|
|
894
|
-
|
|
911
|
+
...DEFAULT_FETCH_CONFIG,
|
|
895
912
|
});
|
|
896
913
|
await handleGitLabError(response);
|
|
897
914
|
return GitLabMergeRequestSchema.parse(await response.json());
|
|
@@ -911,7 +928,7 @@ async function getMergeRequestDiffs(projectId, mergeRequestIid, view) {
|
|
|
911
928
|
url.searchParams.append("view", view);
|
|
912
929
|
}
|
|
913
930
|
const response = await fetch(url.toString(), {
|
|
914
|
-
|
|
931
|
+
...DEFAULT_FETCH_CONFIG,
|
|
915
932
|
});
|
|
916
933
|
await handleGitLabError(response);
|
|
917
934
|
const data = (await response.json());
|
|
@@ -929,8 +946,8 @@ async function getMergeRequestDiffs(projectId, mergeRequestIid, view) {
|
|
|
929
946
|
async function updateMergeRequest(projectId, mergeRequestIid, options) {
|
|
930
947
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}`);
|
|
931
948
|
const response = await fetch(url.toString(), {
|
|
949
|
+
...DEFAULT_FETCH_CONFIG,
|
|
932
950
|
method: "PUT",
|
|
933
|
-
headers: DEFAULT_HEADERS,
|
|
934
951
|
body: JSON.stringify(options),
|
|
935
952
|
});
|
|
936
953
|
await handleGitLabError(response);
|
|
@@ -953,8 +970,8 @@ noteableIid, body) {
|
|
|
953
970
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/${noteableType}s/${noteableIid}/notes` // Using plural form (issues/merge_requests) as per GitLab API documentation
|
|
954
971
|
);
|
|
955
972
|
const response = await fetch(url.toString(), {
|
|
973
|
+
...DEFAULT_FETCH_CONFIG,
|
|
956
974
|
method: "POST",
|
|
957
|
-
headers: DEFAULT_HEADERS,
|
|
958
975
|
body: JSON.stringify({ body }),
|
|
959
976
|
});
|
|
960
977
|
if (!response.ok) {
|
|
@@ -985,7 +1002,7 @@ async function listNamespaces(options) {
|
|
|
985
1002
|
url.searchParams.append("top_level_only", "true");
|
|
986
1003
|
}
|
|
987
1004
|
const response = await fetch(url.toString(), {
|
|
988
|
-
|
|
1005
|
+
...DEFAULT_FETCH_CONFIG,
|
|
989
1006
|
});
|
|
990
1007
|
await handleGitLabError(response);
|
|
991
1008
|
const data = await response.json();
|
|
@@ -1001,7 +1018,7 @@ async function listNamespaces(options) {
|
|
|
1001
1018
|
async function getNamespace(id) {
|
|
1002
1019
|
const url = new URL(`${GITLAB_API_URL}/namespaces/${encodeURIComponent(id)}`);
|
|
1003
1020
|
const response = await fetch(url.toString(), {
|
|
1004
|
-
|
|
1021
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1005
1022
|
});
|
|
1006
1023
|
await handleGitLabError(response);
|
|
1007
1024
|
const data = await response.json();
|
|
@@ -1021,7 +1038,7 @@ async function verifyNamespaceExistence(namespacePath, parentId) {
|
|
|
1021
1038
|
url.searchParams.append("parent_id", parentId.toString());
|
|
1022
1039
|
}
|
|
1023
1040
|
const response = await fetch(url.toString(), {
|
|
1024
|
-
|
|
1041
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1025
1042
|
});
|
|
1026
1043
|
await handleGitLabError(response);
|
|
1027
1044
|
const data = await response.json();
|
|
@@ -1050,7 +1067,7 @@ async function getProject(projectId, options = {}) {
|
|
|
1050
1067
|
url.searchParams.append("with_custom_attributes", "true");
|
|
1051
1068
|
}
|
|
1052
1069
|
const response = await fetch(url.toString(), {
|
|
1053
|
-
|
|
1070
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1054
1071
|
});
|
|
1055
1072
|
await handleGitLabError(response);
|
|
1056
1073
|
const data = await response.json();
|
|
@@ -1078,8 +1095,7 @@ async function listProjects(options = {}) {
|
|
|
1078
1095
|
}
|
|
1079
1096
|
// Make the API request
|
|
1080
1097
|
const response = await fetch(`${GITLAB_API_URL}/projects?${params.toString()}`, {
|
|
1081
|
-
|
|
1082
|
-
headers: DEFAULT_HEADERS,
|
|
1098
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1083
1099
|
});
|
|
1084
1100
|
// Handle errors
|
|
1085
1101
|
await handleGitLabError(response);
|
|
@@ -1110,7 +1126,7 @@ async function listLabels(projectId, options = {}) {
|
|
|
1110
1126
|
});
|
|
1111
1127
|
// Make the API request
|
|
1112
1128
|
const response = await fetch(url.toString(), {
|
|
1113
|
-
|
|
1129
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1114
1130
|
});
|
|
1115
1131
|
// Handle errors
|
|
1116
1132
|
await handleGitLabError(response);
|
|
@@ -1134,7 +1150,7 @@ async function getLabel(projectId, labelId, includeAncestorGroups) {
|
|
|
1134
1150
|
}
|
|
1135
1151
|
// Make the API request
|
|
1136
1152
|
const response = await fetch(url.toString(), {
|
|
1137
|
-
|
|
1153
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1138
1154
|
});
|
|
1139
1155
|
// Handle errors
|
|
1140
1156
|
await handleGitLabError(response);
|
|
@@ -1152,8 +1168,8 @@ async function getLabel(projectId, labelId, includeAncestorGroups) {
|
|
|
1152
1168
|
async function createLabel(projectId, options) {
|
|
1153
1169
|
// Make the API request
|
|
1154
1170
|
const response = await fetch(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/labels`, {
|
|
1171
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1155
1172
|
method: "POST",
|
|
1156
|
-
headers: DEFAULT_HEADERS,
|
|
1157
1173
|
body: JSON.stringify(options),
|
|
1158
1174
|
});
|
|
1159
1175
|
// Handle errors
|
|
@@ -1173,8 +1189,8 @@ async function createLabel(projectId, options) {
|
|
|
1173
1189
|
async function updateLabel(projectId, labelId, options) {
|
|
1174
1190
|
// Make the API request
|
|
1175
1191
|
const response = await fetch(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/labels/${encodeURIComponent(String(labelId))}`, {
|
|
1192
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1176
1193
|
method: "PUT",
|
|
1177
|
-
headers: DEFAULT_HEADERS,
|
|
1178
1194
|
body: JSON.stringify(options),
|
|
1179
1195
|
});
|
|
1180
1196
|
// Handle errors
|
|
@@ -1192,8 +1208,8 @@ async function updateLabel(projectId, labelId, options) {
|
|
|
1192
1208
|
async function deleteLabel(projectId, labelId) {
|
|
1193
1209
|
// Make the API request
|
|
1194
1210
|
const response = await fetch(`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/labels/${encodeURIComponent(String(labelId))}`, {
|
|
1211
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1195
1212
|
method: "DELETE",
|
|
1196
|
-
headers: DEFAULT_HEADERS,
|
|
1197
1213
|
});
|
|
1198
1214
|
// Handle errors
|
|
1199
1215
|
await handleGitLabError(response);
|
|
@@ -1240,8 +1256,7 @@ async function listGroupProjects(options) {
|
|
|
1240
1256
|
if (options.with_security_reports !== undefined)
|
|
1241
1257
|
url.searchParams.append("with_security_reports", options.with_security_reports.toString());
|
|
1242
1258
|
const response = await fetch(url.toString(), {
|
|
1243
|
-
|
|
1244
|
-
headers: DEFAULT_HEADERS,
|
|
1259
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1245
1260
|
});
|
|
1246
1261
|
await handleGitLabError(response);
|
|
1247
1262
|
const projects = await response.json();
|
|
@@ -1416,7 +1431,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1416
1431
|
url.searchParams.append("owned", args.owned.toString());
|
|
1417
1432
|
}
|
|
1418
1433
|
const response = await fetch(url.toString(), {
|
|
1419
|
-
|
|
1434
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1420
1435
|
});
|
|
1421
1436
|
await handleGitLabError(response);
|
|
1422
1437
|
const data = await response.json();
|
|
@@ -1431,7 +1446,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1431
1446
|
const args = GetNamespaceSchema.parse(request.params.arguments);
|
|
1432
1447
|
const url = new URL(`${GITLAB_API_URL}/namespaces/${encodeURIComponent(args.namespace_id)}`);
|
|
1433
1448
|
const response = await fetch(url.toString(), {
|
|
1434
|
-
|
|
1449
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1435
1450
|
});
|
|
1436
1451
|
await handleGitLabError(response);
|
|
1437
1452
|
const data = await response.json();
|
|
@@ -1444,7 +1459,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1444
1459
|
const args = VerifyNamespaceSchema.parse(request.params.arguments);
|
|
1445
1460
|
const url = new URL(`${GITLAB_API_URL}/namespaces/${encodeURIComponent(args.path)}/exists`);
|
|
1446
1461
|
const response = await fetch(url.toString(), {
|
|
1447
|
-
|
|
1462
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1448
1463
|
});
|
|
1449
1464
|
await handleGitLabError(response);
|
|
1450
1465
|
const data = await response.json();
|
|
@@ -1459,7 +1474,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1459
1474
|
const args = GetProjectSchema.parse(request.params.arguments);
|
|
1460
1475
|
const url = new URL(`${GITLAB_API_URL}/projects/${encodeURIComponent(args.project_id)}`);
|
|
1461
1476
|
const response = await fetch(url.toString(), {
|
|
1462
|
-
|
|
1477
|
+
...DEFAULT_FETCH_CONFIG,
|
|
1463
1478
|
});
|
|
1464
1479
|
await handleGitLabError(response);
|
|
1465
1480
|
const data = await response.json();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "MCP server for using the GitLab API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zereight",
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@modelcontextprotocol/sdk": "1.8.0",
|
|
26
26
|
"@types/node-fetch": "^2.6.12",
|
|
27
|
+
"http-proxy-agent": "^7.0.2",
|
|
28
|
+
"https-proxy-agent": "^7.0.6",
|
|
27
29
|
"node-fetch": "^3.3.2",
|
|
30
|
+
"socks-proxy-agent": "^8.0.5",
|
|
28
31
|
"zod-to-json-schema": "^3.23.5"
|
|
29
32
|
},
|
|
30
33
|
"devDependencies": {
|
|
@@ -32,4 +35,4 @@
|
|
|
32
35
|
"typescript": "^5.8.2",
|
|
33
36
|
"zod": "^3.24.2"
|
|
34
37
|
}
|
|
35
|
-
}
|
|
38
|
+
}
|