@ekho/gitlab-mcp 1.1.0
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/PLAN.md +517 -0
- package/README.md +429 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -0
- package/dist/groups/access_tokens/tools.d.ts +3 -0
- package/dist/groups/access_tokens/tools.js +198 -0
- package/dist/groups/access_tokens/tools.js.map +1 -0
- package/dist/groups/admin/tools.d.ts +3 -0
- package/dist/groups/admin/tools.js +136 -0
- package/dist/groups/admin/tools.js.map +1 -0
- package/dist/groups/ai_catalog/queries.d.ts +3 -0
- package/dist/groups/ai_catalog/queries.js +75 -0
- package/dist/groups/ai_catalog/queries.js.map +1 -0
- package/dist/groups/ai_catalog/tools.d.ts +3 -0
- package/dist/groups/ai_catalog/tools.js +40 -0
- package/dist/groups/ai_catalog/tools.js.map +1 -0
- package/dist/groups/analytics/queries.d.ts +1 -0
- package/dist/groups/analytics/queries.js +28 -0
- package/dist/groups/analytics/queries.js.map +1 -0
- package/dist/groups/analytics/tools.d.ts +3 -0
- package/dist/groups/analytics/tools.js +110 -0
- package/dist/groups/analytics/tools.js.map +1 -0
- package/dist/groups/audit_events/tools.d.ts +3 -0
- package/dist/groups/audit_events/tools.js +112 -0
- package/dist/groups/audit_events/tools.js.map +1 -0
- package/dist/groups/boards/tools.d.ts +3 -0
- package/dist/groups/boards/tools.js +46 -0
- package/dist/groups/boards/tools.js.map +1 -0
- package/dist/groups/branches/tools.d.ts +3 -0
- package/dist/groups/branches/tools.js +122 -0
- package/dist/groups/branches/tools.js.map +1 -0
- package/dist/groups/ci_catalog/queries.d.ts +2 -0
- package/dist/groups/ci_catalog/queries.js +63 -0
- package/dist/groups/ci_catalog/queries.js.map +1 -0
- package/dist/groups/ci_catalog/tools.d.ts +3 -0
- package/dist/groups/ci_catalog/tools.js +45 -0
- package/dist/groups/ci_catalog/tools.js.map +1 -0
- package/dist/groups/ci_lint/tools.d.ts +3 -0
- package/dist/groups/ci_lint/tools.js +36 -0
- package/dist/groups/ci_lint/tools.js.map +1 -0
- package/dist/groups/ci_variables/tools.d.ts +3 -0
- package/dist/groups/ci_variables/tools.js +201 -0
- package/dist/groups/ci_variables/tools.js.map +1 -0
- package/dist/groups/code_search/tools.d.ts +3 -0
- package/dist/groups/code_search/tools.js +70 -0
- package/dist/groups/code_search/tools.js.map +1 -0
- package/dist/groups/commits/tools.d.ts +3 -0
- package/dist/groups/commits/tools.js +192 -0
- package/dist/groups/commits/tools.js.map +1 -0
- package/dist/groups/compliance/queries.d.ts +1 -0
- package/dist/groups/compliance/queries.js +22 -0
- package/dist/groups/compliance/queries.js.map +1 -0
- package/dist/groups/compliance/tools.d.ts +3 -0
- package/dist/groups/compliance/tools.js +104 -0
- package/dist/groups/compliance/tools.js.map +1 -0
- package/dist/groups/container_registry/tools.d.ts +3 -0
- package/dist/groups/container_registry/tools.js +113 -0
- package/dist/groups/container_registry/tools.js.map +1 -0
- package/dist/groups/custom_roles/queries.d.ts +5 -0
- package/dist/groups/custom_roles/queries.js +69 -0
- package/dist/groups/custom_roles/queries.js.map +1 -0
- package/dist/groups/custom_roles/tools.d.ts +3 -0
- package/dist/groups/custom_roles/tools.js +84 -0
- package/dist/groups/custom_roles/tools.js.map +1 -0
- package/dist/groups/deployments/tools.d.ts +3 -0
- package/dist/groups/deployments/tools.js +98 -0
- package/dist/groups/deployments/tools.js.map +1 -0
- package/dist/groups/discussions/tools.d.ts +3 -0
- package/dist/groups/discussions/tools.js +144 -0
- package/dist/groups/discussions/tools.js.map +1 -0
- package/dist/groups/duo_chat/queries.d.ts +4 -0
- package/dist/groups/duo_chat/queries.js +76 -0
- package/dist/groups/duo_chat/queries.js.map +1 -0
- package/dist/groups/duo_chat/tools.d.ts +3 -0
- package/dist/groups/duo_chat/tools.js +95 -0
- package/dist/groups/duo_chat/tools.js.map +1 -0
- package/dist/groups/environments/tools.d.ts +3 -0
- package/dist/groups/environments/tools.js +105 -0
- package/dist/groups/environments/tools.js.map +1 -0
- package/dist/groups/events/tools.d.ts +3 -0
- package/dist/groups/events/tools.js +64 -0
- package/dist/groups/events/tools.js.map +1 -0
- package/dist/groups/feature_flags/tools.d.ts +3 -0
- package/dist/groups/feature_flags/tools.js +137 -0
- package/dist/groups/feature_flags/tools.js.map +1 -0
- package/dist/groups/groups/tools.d.ts +3 -0
- package/dist/groups/groups/tools.js +145 -0
- package/dist/groups/groups/tools.js.map +1 -0
- package/dist/groups/integrations/tools.d.ts +3 -0
- package/dist/groups/integrations/tools.js +143 -0
- package/dist/groups/integrations/tools.js.map +1 -0
- package/dist/groups/jobs/tools.d.ts +3 -0
- package/dist/groups/jobs/tools.js +209 -0
- package/dist/groups/jobs/tools.js.map +1 -0
- package/dist/groups/keys/tools.d.ts +3 -0
- package/dist/groups/keys/tools.js +140 -0
- package/dist/groups/keys/tools.js.map +1 -0
- package/dist/groups/labels/tools.d.ts +3 -0
- package/dist/groups/labels/tools.js +110 -0
- package/dist/groups/labels/tools.js.map +1 -0
- package/dist/groups/members/tools.d.ts +3 -0
- package/dist/groups/members/tools.js +136 -0
- package/dist/groups/members/tools.js.map +1 -0
- package/dist/groups/merge_requests/tools.d.ts +3 -0
- package/dist/groups/merge_requests/tools.js +288 -0
- package/dist/groups/merge_requests/tools.js.map +1 -0
- package/dist/groups/milestones/tools.d.ts +3 -0
- package/dist/groups/milestones/tools.js +143 -0
- package/dist/groups/milestones/tools.js.map +1 -0
- package/dist/groups/packages/tools.d.ts +3 -0
- package/dist/groups/packages/tools.js +157 -0
- package/dist/groups/packages/tools.js.map +1 -0
- package/dist/groups/pipeline_schedules/tools.d.ts +3 -0
- package/dist/groups/pipeline_schedules/tools.js +127 -0
- package/dist/groups/pipeline_schedules/tools.js.map +1 -0
- package/dist/groups/pipeline_triggers/tools.d.ts +3 -0
- package/dist/groups/pipeline_triggers/tools.js +74 -0
- package/dist/groups/pipeline_triggers/tools.js.map +1 -0
- package/dist/groups/pipelines/tools.d.ts +3 -0
- package/dist/groups/pipelines/tools.js +140 -0
- package/dist/groups/pipelines/tools.js.map +1 -0
- package/dist/groups/projects/tools.d.ts +3 -0
- package/dist/groups/projects/tools.js +189 -0
- package/dist/groups/projects/tools.js.map +1 -0
- package/dist/groups/protected_environments/tools.d.ts +3 -0
- package/dist/groups/protected_environments/tools.js +77 -0
- package/dist/groups/protected_environments/tools.js.map +1 -0
- package/dist/groups/releases/tools.d.ts +3 -0
- package/dist/groups/releases/tools.js +153 -0
- package/dist/groups/releases/tools.js.map +1 -0
- package/dist/groups/repository_files/tools.d.ts +3 -0
- package/dist/groups/repository_files/tools.js +163 -0
- package/dist/groups/repository_files/tools.js.map +1 -0
- package/dist/groups/runners/tools.d.ts +3 -0
- package/dist/groups/runners/tools.js +108 -0
- package/dist/groups/runners/tools.js.map +1 -0
- package/dist/groups/search/tools.d.ts +3 -0
- package/dist/groups/search/tools.js +58 -0
- package/dist/groups/search/tools.js.map +1 -0
- package/dist/groups/secrets/queries.d.ts +10 -0
- package/dist/groups/secrets/queries.js +121 -0
- package/dist/groups/secrets/queries.js.map +1 -0
- package/dist/groups/secrets/tools.d.ts +8 -0
- package/dist/groups/secrets/tools.js +167 -0
- package/dist/groups/secrets/tools.js.map +1 -0
- package/dist/groups/security_policies/queries.d.ts +3 -0
- package/dist/groups/security_policies/queries.js +75 -0
- package/dist/groups/security_policies/queries.js.map +1 -0
- package/dist/groups/security_policies/tools.d.ts +3 -0
- package/dist/groups/security_policies/tools.js +40 -0
- package/dist/groups/security_policies/tools.js.map +1 -0
- package/dist/groups/security_reports/queries.d.ts +1 -0
- package/dist/groups/security_reports/queries.js +75 -0
- package/dist/groups/security_reports/queries.js.map +1 -0
- package/dist/groups/security_reports/tools.d.ts +3 -0
- package/dist/groups/security_reports/tools.js +51 -0
- package/dist/groups/security_reports/tools.js.map +1 -0
- package/dist/groups/snippets/tools.d.ts +3 -0
- package/dist/groups/snippets/tools.js +148 -0
- package/dist/groups/snippets/tools.js.map +1 -0
- package/dist/groups/statistics/queries.d.ts +2 -0
- package/dist/groups/statistics/queries.js +32 -0
- package/dist/groups/statistics/queries.js.map +1 -0
- package/dist/groups/statistics/tools.d.ts +3 -0
- package/dist/groups/statistics/tools.js +35 -0
- package/dist/groups/statistics/tools.js.map +1 -0
- package/dist/groups/tags/tools.d.ts +3 -0
- package/dist/groups/tags/tools.js +97 -0
- package/dist/groups/tags/tools.js.map +1 -0
- package/dist/groups/todos/tools.d.ts +3 -0
- package/dist/groups/todos/tools.js +93 -0
- package/dist/groups/todos/tools.js.map +1 -0
- package/dist/groups/users/tools.d.ts +3 -0
- package/dist/groups/users/tools.js +121 -0
- package/dist/groups/users/tools.js.map +1 -0
- package/dist/groups/vulnerabilities/queries.d.ts +3 -0
- package/dist/groups/vulnerabilities/queries.js +104 -0
- package/dist/groups/vulnerabilities/queries.js.map +1 -0
- package/dist/groups/vulnerabilities/tools.d.ts +3 -0
- package/dist/groups/vulnerabilities/tools.js +131 -0
- package/dist/groups/vulnerabilities/tools.js.map +1 -0
- package/dist/groups/webhooks/tools.d.ts +3 -0
- package/dist/groups/webhooks/tools.js +213 -0
- package/dist/groups/webhooks/tools.js.map +1 -0
- package/dist/groups/wiki/tools.d.ts +3 -0
- package/dist/groups/wiki/tools.js +142 -0
- package/dist/groups/wiki/tools.js.map +1 -0
- package/dist/groups/work_items/queries.d.ts +16 -0
- package/dist/groups/work_items/queries.js +181 -0
- package/dist/groups/work_items/queries.js.map +1 -0
- package/dist/groups/work_items/tools.d.ts +3 -0
- package/dist/groups/work_items/tools.js +250 -0
- package/dist/groups/work_items/tools.js.map +1 -0
- package/dist/http/errors.d.ts +21 -0
- package/dist/http/errors.js +62 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/graphql.d.ts +29 -0
- package/dist/http/graphql.js +93 -0
- package/dist/http/graphql.js.map +1 -0
- package/dist/http/rest.d.ts +96 -0
- package/dist/http/rest.js +369 -0
- package/dist/http/rest.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/args.d.ts +51 -0
- package/dist/shared/args.js +46 -0
- package/dist/shared/args.js.map +1 -0
- package/dist/shared/handlers.d.ts +6 -0
- package/dist/shared/handlers.js +14 -0
- package/dist/shared/handlers.js.map +1 -0
- package/dist/shared/ids.d.ts +18 -0
- package/dist/shared/ids.js +43 -0
- package/dist/shared/ids.js.map +1 -0
- package/dist/tools/meta.d.ts +3 -0
- package/dist/tools/meta.js +22 -0
- package/dist/tools/meta.js.map +1 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.js +117 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +18 -0
- package/dist/tools/types.js +20 -0
- package/dist/tools/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { FormData, request } from 'undici';
|
|
3
|
+
import { authHeader } from '../config.js';
|
|
4
|
+
import { GitLabApiError, summarizeBody } from './errors.js';
|
|
5
|
+
export class RestClient {
|
|
6
|
+
cfg;
|
|
7
|
+
dispatcher;
|
|
8
|
+
constructor(cfg, dispatcher) {
|
|
9
|
+
this.cfg = cfg;
|
|
10
|
+
this.dispatcher = dispatcher;
|
|
11
|
+
}
|
|
12
|
+
async request(opts) {
|
|
13
|
+
const method = opts.method ?? 'GET';
|
|
14
|
+
const url = this.buildUrl(opts.path, opts.query);
|
|
15
|
+
const maxRetries = opts.maxRetries ?? this.cfg.maxRetries;
|
|
16
|
+
let attempt = 0;
|
|
17
|
+
let lastError;
|
|
18
|
+
while (attempt <= maxRetries) {
|
|
19
|
+
try {
|
|
20
|
+
return await this.execute(method, url, opts);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
lastError = err;
|
|
24
|
+
if (!(err instanceof GitLabApiError) || !err.isRetryable || attempt === maxRetries) {
|
|
25
|
+
if (opts.nullOn404 && err instanceof GitLabApiError && err.status === 404) {
|
|
26
|
+
return {
|
|
27
|
+
data: null,
|
|
28
|
+
status: 404,
|
|
29
|
+
headers: {},
|
|
30
|
+
links: {},
|
|
31
|
+
pagination: emptyPagination(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
const delay = this.backoffDelay(attempt, err);
|
|
37
|
+
await sleep(delay);
|
|
38
|
+
attempt += 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
throw lastError instanceof Error ? lastError : new Error('REST request failed');
|
|
42
|
+
}
|
|
43
|
+
async execute(method, url, opts) {
|
|
44
|
+
const headers = {
|
|
45
|
+
Accept: 'application/json',
|
|
46
|
+
'User-Agent': this.cfg.userAgent,
|
|
47
|
+
...authHeader(this.cfg),
|
|
48
|
+
...(opts.headers ?? {}),
|
|
49
|
+
};
|
|
50
|
+
let body;
|
|
51
|
+
if (opts.body !== undefined && opts.body !== null) {
|
|
52
|
+
body = JSON.stringify(opts.body);
|
|
53
|
+
headers['Content-Type'] = 'application/json';
|
|
54
|
+
}
|
|
55
|
+
const res = await request(url, {
|
|
56
|
+
method,
|
|
57
|
+
headers,
|
|
58
|
+
signal: AbortSignal.timeout(this.cfg.requestTimeoutMs),
|
|
59
|
+
...(body !== undefined ? { body } : {}),
|
|
60
|
+
...(this.dispatcher ? { dispatcher: this.dispatcher } : {}),
|
|
61
|
+
});
|
|
62
|
+
const responseHeaders = flattenHeaders(res.headers);
|
|
63
|
+
const text = await res.body.text();
|
|
64
|
+
const parsed = parseBody(text, responseHeaders['content-type']);
|
|
65
|
+
if (res.statusCode >= 400) {
|
|
66
|
+
const requestId = responseHeaders['x-request-id'];
|
|
67
|
+
throw new GitLabApiError({
|
|
68
|
+
message: `GitLab ${method} ${url} → ${res.statusCode}: ${summarizeBody(parsed)}`,
|
|
69
|
+
status: res.statusCode,
|
|
70
|
+
method,
|
|
71
|
+
url,
|
|
72
|
+
...(requestId ? { requestId } : {}),
|
|
73
|
+
body: parsed,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
data: parsed,
|
|
78
|
+
status: res.statusCode,
|
|
79
|
+
headers: responseHeaders,
|
|
80
|
+
links: parseLinkHeader(responseHeaders['link']),
|
|
81
|
+
pagination: parsePagination(responseHeaders),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async requestMultipart(opts) {
|
|
85
|
+
const method = opts.method ?? 'POST';
|
|
86
|
+
const url = this.buildUrl(opts.path, opts.query);
|
|
87
|
+
const maxRetries = opts.maxRetries ?? this.cfg.maxRetries;
|
|
88
|
+
let attempt = 0;
|
|
89
|
+
let lastError;
|
|
90
|
+
while (attempt <= maxRetries) {
|
|
91
|
+
try {
|
|
92
|
+
const form = buildFormData(opts.fields);
|
|
93
|
+
return await this.executeRaw(method, url, opts.headers, form, 'json');
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
lastError = err;
|
|
97
|
+
if (!(err instanceof GitLabApiError) || !err.isRetryable || attempt === maxRetries) {
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
await sleep(this.backoffDelay(attempt, err));
|
|
101
|
+
attempt += 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
throw lastError instanceof Error ? lastError : new Error('multipart request failed');
|
|
105
|
+
}
|
|
106
|
+
async uploadBinary(opts) {
|
|
107
|
+
const method = opts.method ?? 'PUT';
|
|
108
|
+
const url = this.buildUrl(opts.path, opts.query);
|
|
109
|
+
const maxRetries = opts.maxRetries ?? this.cfg.maxRetries;
|
|
110
|
+
let attempt = 0;
|
|
111
|
+
let lastError;
|
|
112
|
+
while (attempt <= maxRetries) {
|
|
113
|
+
try {
|
|
114
|
+
const headers = {
|
|
115
|
+
Accept: 'application/json',
|
|
116
|
+
'User-Agent': this.cfg.userAgent,
|
|
117
|
+
'Content-Type': opts.contentType,
|
|
118
|
+
...authHeader(this.cfg),
|
|
119
|
+
...(opts.headers ?? {}),
|
|
120
|
+
};
|
|
121
|
+
const res = await request(url, {
|
|
122
|
+
method,
|
|
123
|
+
headers,
|
|
124
|
+
body: Buffer.from(opts.body),
|
|
125
|
+
signal: AbortSignal.timeout(this.cfg.requestTimeoutMs),
|
|
126
|
+
...(this.dispatcher ? { dispatcher: this.dispatcher } : {}),
|
|
127
|
+
});
|
|
128
|
+
const responseHeaders = flattenHeaders(res.headers);
|
|
129
|
+
const text = await res.body.text();
|
|
130
|
+
const parsed = parseBody(text, responseHeaders['content-type']);
|
|
131
|
+
if (res.statusCode >= 400) {
|
|
132
|
+
throw new GitLabApiError({
|
|
133
|
+
message: `GitLab ${method} ${url} → ${res.statusCode}: ${summarizeBody(parsed)}`,
|
|
134
|
+
status: res.statusCode,
|
|
135
|
+
method,
|
|
136
|
+
url,
|
|
137
|
+
body: parsed,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
data: parsed,
|
|
142
|
+
status: res.statusCode,
|
|
143
|
+
headers: responseHeaders,
|
|
144
|
+
links: parseLinkHeader(responseHeaders['link']),
|
|
145
|
+
pagination: parsePagination(responseHeaders),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
lastError = err;
|
|
150
|
+
if (!(err instanceof GitLabApiError) || !err.isRetryable || attempt === maxRetries) {
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
await sleep(this.backoffDelay(attempt, err));
|
|
154
|
+
attempt += 1;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
throw lastError instanceof Error ? lastError : new Error('binary upload failed');
|
|
158
|
+
}
|
|
159
|
+
async downloadBinary(opts) {
|
|
160
|
+
const url = this.buildUrl(opts.path, opts.query);
|
|
161
|
+
const maxRetries = opts.maxRetries ?? this.cfg.maxRetries;
|
|
162
|
+
const maxInline = opts.maxInlineBytes ?? 1024 * 1024;
|
|
163
|
+
let attempt = 0;
|
|
164
|
+
let lastError;
|
|
165
|
+
while (attempt <= maxRetries) {
|
|
166
|
+
try {
|
|
167
|
+
const headers = {
|
|
168
|
+
'User-Agent': this.cfg.userAgent,
|
|
169
|
+
...authHeader(this.cfg),
|
|
170
|
+
...(opts.headers ?? {}),
|
|
171
|
+
};
|
|
172
|
+
const res = await request(url, {
|
|
173
|
+
method: 'GET',
|
|
174
|
+
headers,
|
|
175
|
+
signal: AbortSignal.timeout(this.cfg.requestTimeoutMs),
|
|
176
|
+
...(this.dispatcher ? { dispatcher: this.dispatcher } : {}),
|
|
177
|
+
});
|
|
178
|
+
const responseHeaders = flattenHeaders(res.headers);
|
|
179
|
+
if (res.statusCode >= 400) {
|
|
180
|
+
const text = await res.body.text();
|
|
181
|
+
const parsed = parseBody(text, responseHeaders['content-type']);
|
|
182
|
+
throw new GitLabApiError({
|
|
183
|
+
message: `GitLab GET ${url} → ${res.statusCode}: ${summarizeBody(parsed)}`,
|
|
184
|
+
status: res.statusCode,
|
|
185
|
+
method: 'GET',
|
|
186
|
+
url,
|
|
187
|
+
body: parsed,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const buf = Buffer.from(await res.body.arrayBuffer());
|
|
191
|
+
const contentType = responseHeaders['content-type'];
|
|
192
|
+
if (opts.saveTo) {
|
|
193
|
+
await writeFile(opts.saveTo, buf);
|
|
194
|
+
return {
|
|
195
|
+
status: res.statusCode,
|
|
196
|
+
size: buf.length,
|
|
197
|
+
content_type: contentType,
|
|
198
|
+
saved_to: opts.saveTo,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (buf.length > maxInline) {
|
|
202
|
+
return {
|
|
203
|
+
status: res.statusCode,
|
|
204
|
+
size: buf.length,
|
|
205
|
+
content_type: contentType,
|
|
206
|
+
content_base64: buf.subarray(0, maxInline).toString('base64'),
|
|
207
|
+
truncated: true,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
status: res.statusCode,
|
|
212
|
+
size: buf.length,
|
|
213
|
+
content_type: contentType,
|
|
214
|
+
content_base64: buf.toString('base64'),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
lastError = err;
|
|
219
|
+
if (!(err instanceof GitLabApiError) || !err.isRetryable || attempt === maxRetries) {
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
await sleep(this.backoffDelay(attempt, err));
|
|
223
|
+
attempt += 1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
throw lastError instanceof Error ? lastError : new Error('binary download failed');
|
|
227
|
+
}
|
|
228
|
+
async executeRaw(method, url, extraHeaders, body, parseAs) {
|
|
229
|
+
const headers = {
|
|
230
|
+
Accept: 'application/json',
|
|
231
|
+
'User-Agent': this.cfg.userAgent,
|
|
232
|
+
...authHeader(this.cfg),
|
|
233
|
+
...(extraHeaders ?? {}),
|
|
234
|
+
};
|
|
235
|
+
// For FormData, let undici set Content-Type with the boundary.
|
|
236
|
+
const res = await request(url, {
|
|
237
|
+
method,
|
|
238
|
+
headers,
|
|
239
|
+
body,
|
|
240
|
+
signal: AbortSignal.timeout(this.cfg.requestTimeoutMs),
|
|
241
|
+
...(this.dispatcher ? { dispatcher: this.dispatcher } : {}),
|
|
242
|
+
});
|
|
243
|
+
const responseHeaders = flattenHeaders(res.headers);
|
|
244
|
+
const text = await res.body.text();
|
|
245
|
+
const parsed = parseAs === 'json' ? parseBody(text, responseHeaders['content-type']) : text;
|
|
246
|
+
if (res.statusCode >= 400) {
|
|
247
|
+
const requestId = responseHeaders['x-request-id'];
|
|
248
|
+
throw new GitLabApiError({
|
|
249
|
+
message: `GitLab ${method} ${url} → ${res.statusCode}: ${summarizeBody(parsed)}`,
|
|
250
|
+
status: res.statusCode,
|
|
251
|
+
method,
|
|
252
|
+
url,
|
|
253
|
+
...(requestId ? { requestId } : {}),
|
|
254
|
+
body: parsed,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
data: parsed,
|
|
259
|
+
status: res.statusCode,
|
|
260
|
+
headers: responseHeaders,
|
|
261
|
+
links: parseLinkHeader(responseHeaders['link']),
|
|
262
|
+
pagination: parsePagination(responseHeaders),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
buildUrl(path, query) {
|
|
266
|
+
const base = this.cfg.baseUrl.replace(/\/$/, '');
|
|
267
|
+
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
268
|
+
const url = new URL(`${base}/api/v4${normalizedPath}`);
|
|
269
|
+
if (query) {
|
|
270
|
+
for (const [key, value] of Object.entries(query)) {
|
|
271
|
+
if (value === undefined || value === null)
|
|
272
|
+
continue;
|
|
273
|
+
if (Array.isArray(value)) {
|
|
274
|
+
for (const v of value)
|
|
275
|
+
url.searchParams.append(`${key}[]`, String(v));
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
url.searchParams.set(key, String(value));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return url.toString();
|
|
283
|
+
}
|
|
284
|
+
backoffDelay(attempt, err) {
|
|
285
|
+
if (err.status === 429) {
|
|
286
|
+
// Respect Retry-After if present in body context — undici doesn't expose
|
|
287
|
+
// headers on the error directly, so fall back to exponential.
|
|
288
|
+
}
|
|
289
|
+
const base = 250;
|
|
290
|
+
const jitter = Math.random() * 100;
|
|
291
|
+
return Math.min(base * 2 ** attempt + jitter, 10_000);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function flattenHeaders(headers) {
|
|
295
|
+
const out = {};
|
|
296
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
297
|
+
if (v === undefined)
|
|
298
|
+
continue;
|
|
299
|
+
out[k.toLowerCase()] = Array.isArray(v) ? v.join(', ') : v;
|
|
300
|
+
}
|
|
301
|
+
return out;
|
|
302
|
+
}
|
|
303
|
+
function parseBody(text, contentType) {
|
|
304
|
+
if (!text)
|
|
305
|
+
return null;
|
|
306
|
+
if (contentType && contentType.includes('application/json')) {
|
|
307
|
+
try {
|
|
308
|
+
return JSON.parse(text);
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
return text;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return text;
|
|
315
|
+
}
|
|
316
|
+
export function parseLinkHeader(header) {
|
|
317
|
+
if (!header)
|
|
318
|
+
return {};
|
|
319
|
+
const out = {};
|
|
320
|
+
for (const part of header.split(',')) {
|
|
321
|
+
const match = /<([^>]+)>;\s*rel="([^"]+)"/.exec(part.trim());
|
|
322
|
+
if (match && match[1] && match[2])
|
|
323
|
+
out[match[2]] = match[1];
|
|
324
|
+
}
|
|
325
|
+
return out;
|
|
326
|
+
}
|
|
327
|
+
function parsePagination(headers) {
|
|
328
|
+
const num = (v) => v === undefined || v === '' ? undefined : Number(v);
|
|
329
|
+
return {
|
|
330
|
+
page: num(headers['x-page']),
|
|
331
|
+
perPage: num(headers['x-per-page']),
|
|
332
|
+
total: num(headers['x-total']),
|
|
333
|
+
totalPages: num(headers['x-total-pages']),
|
|
334
|
+
nextPage: num(headers['x-next-page']),
|
|
335
|
+
prevPage: num(headers['x-prev-page']),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function emptyPagination() {
|
|
339
|
+
return {
|
|
340
|
+
page: undefined,
|
|
341
|
+
perPage: undefined,
|
|
342
|
+
total: undefined,
|
|
343
|
+
totalPages: undefined,
|
|
344
|
+
nextPage: undefined,
|
|
345
|
+
prevPage: undefined,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function sleep(ms) {
|
|
349
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
350
|
+
}
|
|
351
|
+
function buildFormData(fields) {
|
|
352
|
+
const form = new FormData();
|
|
353
|
+
for (const f of fields) {
|
|
354
|
+
if (f.fileName !== undefined) {
|
|
355
|
+
const bytes = f.contentBase64 !== undefined
|
|
356
|
+
? Buffer.from(f.contentBase64, 'base64')
|
|
357
|
+
: Buffer.from(f.contentText ?? '', 'utf8');
|
|
358
|
+
const blob = new Blob([new Uint8Array(bytes)], {
|
|
359
|
+
type: f.contentType ?? 'application/octet-stream',
|
|
360
|
+
});
|
|
361
|
+
form.append(f.name, blob, f.fileName);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
form.append(f.name, f.value ?? '');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return form;
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=rest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../src/http/rest.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { loadConfig } from './config.js';
|
|
5
|
+
import { RestClient } from './http/rest.js';
|
|
6
|
+
import { GraphQLClient } from './http/graphql.js';
|
|
7
|
+
import { registerAllTools } from './tools/registry.js';
|
|
8
|
+
async function main() {
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
const rest = new RestClient(config);
|
|
11
|
+
const graphql = new GraphQLClient(config);
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name: 'gitlab-mcp',
|
|
14
|
+
version: '0.0.1',
|
|
15
|
+
});
|
|
16
|
+
registerAllTools(server, { config, rest, graphql });
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
}
|
|
20
|
+
main().catch((err) => {
|
|
21
|
+
const msg = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
22
|
+
process.stderr.write(`gitlab-mcp failed to start:\n${msg}\n`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,gBAAgB,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,GAAG,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Numeric id or full path string. Used wherever GitLab accepts both. */
|
|
3
|
+
export declare const IdOrPath: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
4
|
+
/** Common pagination args for REST list endpoints. */
|
|
5
|
+
export declare const PaginationArgs: {
|
|
6
|
+
page: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
per_page: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
};
|
|
9
|
+
/** project_id is optional — falls back to GITLAB_DEFAULT_PROJECT. */
|
|
10
|
+
export declare const ProjectIdArg: {
|
|
11
|
+
project_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
12
|
+
};
|
|
13
|
+
/** group_id is optional — falls back to GITLAB_DEFAULT_GROUP. */
|
|
14
|
+
export declare const GroupIdArg: {
|
|
15
|
+
group_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
16
|
+
};
|
|
17
|
+
/** Discriminator for endpoints that exist on both project and group. */
|
|
18
|
+
export declare const ScopeArg: {
|
|
19
|
+
scope: z.ZodEnum<["project", "group"]>;
|
|
20
|
+
scope_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
21
|
+
};
|
|
22
|
+
export declare const TargetTypeArg: z.ZodEnum<["issue", "merge_request", "commit"]>;
|
|
23
|
+
/** Diff position for inline MR discussion notes. */
|
|
24
|
+
export declare const DiffPositionSchema: z.ZodObject<{
|
|
25
|
+
base_sha: z.ZodString;
|
|
26
|
+
start_sha: z.ZodString;
|
|
27
|
+
head_sha: z.ZodString;
|
|
28
|
+
position_type: z.ZodDefault<z.ZodLiteral<"text">>;
|
|
29
|
+
new_path: z.ZodString;
|
|
30
|
+
old_path: z.ZodOptional<z.ZodString>;
|
|
31
|
+
new_line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
32
|
+
old_line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
base_sha: string;
|
|
35
|
+
start_sha: string;
|
|
36
|
+
head_sha: string;
|
|
37
|
+
position_type: "text";
|
|
38
|
+
new_path: string;
|
|
39
|
+
old_path?: string | undefined;
|
|
40
|
+
new_line?: number | null | undefined;
|
|
41
|
+
old_line?: number | null | undefined;
|
|
42
|
+
}, {
|
|
43
|
+
base_sha: string;
|
|
44
|
+
start_sha: string;
|
|
45
|
+
head_sha: string;
|
|
46
|
+
new_path: string;
|
|
47
|
+
position_type?: "text" | undefined;
|
|
48
|
+
old_path?: string | undefined;
|
|
49
|
+
new_line?: number | null | undefined;
|
|
50
|
+
old_line?: number | null | undefined;
|
|
51
|
+
}>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Numeric id or full path string. Used wherever GitLab accepts both. */
|
|
3
|
+
export const IdOrPath = z.union([z.string(), z.number()]);
|
|
4
|
+
/** Common pagination args for REST list endpoints. */
|
|
5
|
+
export const PaginationArgs = {
|
|
6
|
+
page: z.number().int().positive().optional().describe('Page number (default 1).'),
|
|
7
|
+
per_page: z
|
|
8
|
+
.number()
|
|
9
|
+
.int()
|
|
10
|
+
.positive()
|
|
11
|
+
.max(100)
|
|
12
|
+
.optional()
|
|
13
|
+
.describe('Items per page, max 100 (default 20).'),
|
|
14
|
+
};
|
|
15
|
+
/** project_id is optional — falls back to GITLAB_DEFAULT_PROJECT. */
|
|
16
|
+
export const ProjectIdArg = {
|
|
17
|
+
project_id: IdOrPath.optional().describe('Numeric id or full path (e.g. "group/sub/project"). Falls back to GITLAB_DEFAULT_PROJECT.'),
|
|
18
|
+
};
|
|
19
|
+
/** group_id is optional — falls back to GITLAB_DEFAULT_GROUP. */
|
|
20
|
+
export const GroupIdArg = {
|
|
21
|
+
group_id: IdOrPath.optional().describe('Numeric id or full path. Falls back to GITLAB_DEFAULT_GROUP.'),
|
|
22
|
+
};
|
|
23
|
+
/** Discriminator for endpoints that exist on both project and group. */
|
|
24
|
+
export const ScopeArg = {
|
|
25
|
+
scope: z.enum(['project', 'group']).describe('Which container the resource lives in.'),
|
|
26
|
+
scope_id: IdOrPath
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Project or group id/path. Falls back to GITLAB_DEFAULT_PROJECT/GROUP.'),
|
|
29
|
+
};
|
|
30
|
+
export const TargetTypeArg = z
|
|
31
|
+
.enum(['issue', 'merge_request', 'commit'])
|
|
32
|
+
.describe('Discussion target: issue, merge_request, or commit.');
|
|
33
|
+
/** Diff position for inline MR discussion notes. */
|
|
34
|
+
export const DiffPositionSchema = z
|
|
35
|
+
.object({
|
|
36
|
+
base_sha: z.string(),
|
|
37
|
+
start_sha: z.string(),
|
|
38
|
+
head_sha: z.string(),
|
|
39
|
+
position_type: z.literal('text').default('text'),
|
|
40
|
+
new_path: z.string(),
|
|
41
|
+
old_path: z.string().optional(),
|
|
42
|
+
new_line: z.number().int().nullable().optional(),
|
|
43
|
+
old_line: z.number().int().nullable().optional(),
|
|
44
|
+
})
|
|
45
|
+
.describe('Inline diff position for MR comments.');
|
|
46
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/shared/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,yEAAyE;AACzE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAE1D,sDAAsD;AACtD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACjF,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,uCAAuC,CAAC;CACrD,CAAC;AAEF,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACtC,2FAA2F,CAC5F;CACF,CAAC;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,8DAA8D,CAC/D;CACF,CAAC;AAEF,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACtF,QAAQ,EAAE,QAAQ;SACf,QAAQ,EAAE;SACV,QAAQ,CAAC,uEAAuE,CAAC;CACrF,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC;KAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;KAC1C,QAAQ,CAAC,qDAAqD,CAAC,CAAC;AAEnE,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAChD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAChD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACjD,CAAC;KACD,QAAQ,CAAC,uCAAuC,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ToolResultContent } from '../tools/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a handler body so any thrown error becomes a structured MCP error result
|
|
4
|
+
* with isError: true, and any returned value becomes a JSON-encoded text content.
|
|
5
|
+
*/
|
|
6
|
+
export declare function safe(fn: () => Promise<unknown>): Promise<ToolResultContent>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { errorResult, jsonResult } from '../tools/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a handler body so any thrown error becomes a structured MCP error result
|
|
4
|
+
* with isError: true, and any returned value becomes a JSON-encoded text content.
|
|
5
|
+
*/
|
|
6
|
+
export async function safe(fn) {
|
|
7
|
+
try {
|
|
8
|
+
return jsonResult(await fn());
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
return errorResult(err);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/shared/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAA0B,MAAM,mBAAmB,CAAC;AAEpF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,EAA0B;IACnD,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Config } from '../config.js';
|
|
2
|
+
/**
|
|
3
|
+
* GitLab REST identifiers accept either a numeric ID or a URL-encoded full path
|
|
4
|
+
* (e.g. `group/subgroup/project` → `group%2Fsubgroup%2Fproject`). This helper
|
|
5
|
+
* normalizes either form for safe interpolation into URL paths.
|
|
6
|
+
*/
|
|
7
|
+
export declare function encodeId(idOrPath: string | number): string;
|
|
8
|
+
/** Resolve a project identifier, falling back to GITLAB_DEFAULT_PROJECT. */
|
|
9
|
+
export declare function resolveProjectId(cfg: Config, projectId?: string | number): string;
|
|
10
|
+
/** Resolve a group identifier, falling back to GITLAB_DEFAULT_GROUP. */
|
|
11
|
+
export declare function resolveGroupId(cfg: Config, groupId?: string | number): string;
|
|
12
|
+
/**
|
|
13
|
+
* GitLab GraphQL uses global IDs of the form `gid://gitlab/Project/123`. This
|
|
14
|
+
* builds one from a numeric id and a type name.
|
|
15
|
+
*/
|
|
16
|
+
export declare function toGlobalId(type: string, id: string | number): string;
|
|
17
|
+
/** Build a GraphQL `fullPath` from either a numeric id (not supported) or path. */
|
|
18
|
+
export declare function projectFullPath(projectId: string): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitLab REST identifiers accept either a numeric ID or a URL-encoded full path
|
|
3
|
+
* (e.g. `group/subgroup/project` → `group%2Fsubgroup%2Fproject`). This helper
|
|
4
|
+
* normalizes either form for safe interpolation into URL paths.
|
|
5
|
+
*/
|
|
6
|
+
export function encodeId(idOrPath) {
|
|
7
|
+
if (typeof idOrPath === 'number')
|
|
8
|
+
return String(idOrPath);
|
|
9
|
+
if (/^\d+$/.test(idOrPath))
|
|
10
|
+
return idOrPath;
|
|
11
|
+
return encodeURIComponent(idOrPath);
|
|
12
|
+
}
|
|
13
|
+
/** Resolve a project identifier, falling back to GITLAB_DEFAULT_PROJECT. */
|
|
14
|
+
export function resolveProjectId(cfg, projectId) {
|
|
15
|
+
const raw = projectId ?? cfg.defaultProject;
|
|
16
|
+
if (raw === undefined || raw === '') {
|
|
17
|
+
throw new Error('project_id is required (or set GITLAB_DEFAULT_PROJECT). Pass numeric id or full path like group/subgroup/project.');
|
|
18
|
+
}
|
|
19
|
+
return encodeId(raw);
|
|
20
|
+
}
|
|
21
|
+
/** Resolve a group identifier, falling back to GITLAB_DEFAULT_GROUP. */
|
|
22
|
+
export function resolveGroupId(cfg, groupId) {
|
|
23
|
+
const raw = groupId ?? cfg.defaultGroup;
|
|
24
|
+
if (raw === undefined || raw === '') {
|
|
25
|
+
throw new Error('group_id is required (or set GITLAB_DEFAULT_GROUP). Pass numeric id or full path like group/subgroup.');
|
|
26
|
+
}
|
|
27
|
+
return encodeId(raw);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* GitLab GraphQL uses global IDs of the form `gid://gitlab/Project/123`. This
|
|
31
|
+
* builds one from a numeric id and a type name.
|
|
32
|
+
*/
|
|
33
|
+
export function toGlobalId(type, id) {
|
|
34
|
+
return `gid://gitlab/${type}/${id}`;
|
|
35
|
+
}
|
|
36
|
+
/** Build a GraphQL `fullPath` from either a numeric id (not supported) or path. */
|
|
37
|
+
export function projectFullPath(projectId) {
|
|
38
|
+
if (/^\d+$/.test(projectId)) {
|
|
39
|
+
throw new Error('GraphQL queries require a full path (group/subgroup/project), not a numeric id.');
|
|
40
|
+
}
|
|
41
|
+
return projectId.includes('%2F') ? decodeURIComponent(projectId) : projectId;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/shared/ids.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAyB;IAChD,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,SAA2B;IACvE,MAAM,GAAG,GAAG,SAAS,IAAI,GAAG,CAAC,cAAc,CAAC;IAC5C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAyB;IACnE,MAAM,GAAG,GAAG,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC;IACxC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAmB;IAC1D,OAAO,gBAAgB,IAAI,IAAI,EAAE,EAAE,CAAC;AACtC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { errorResult, jsonResult } from './types.js';
|
|
2
|
+
export function registerMetaTools(server, ctx) {
|
|
3
|
+
server.tool('metadata_get', 'Return the GitLab instance metadata (version, revision, KAS info, enterprise flag). Useful as a smoke test for the configured base URL and token.', {}, async () => {
|
|
4
|
+
try {
|
|
5
|
+
const res = await ctx.rest.request({ path: '/metadata' });
|
|
6
|
+
return jsonResult(res.data);
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
return errorResult(err);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
server.tool('user_current', 'Return the authenticated user (the owner of the configured GITLAB_TOKEN). Smoke-tests authentication.', {}, async () => {
|
|
13
|
+
try {
|
|
14
|
+
const res = await ctx.rest.request({ path: '/user' });
|
|
15
|
+
return jsonResult(res.data);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return errorResult(err);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/tools/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAoB,MAAM,YAAY,CAAC;AAEvE,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,GAAgB;IACnE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,mJAAmJ,EACnJ,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAU,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACnE,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,uGAAuG,EACvG,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/D,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|