@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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/build/index.js +92 -77
  3. 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
- throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorBody}`);
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: {
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- method: "GET",
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- method: "GET",
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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
- headers: DEFAULT_HEADERS,
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.29",
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
+ }