gitlab-mcp 1.0.0 → 1.2.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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config/env.d.ts +56 -0
  3. package/dist/config/env.js +163 -0
  4. package/dist/config/env.js.map +1 -0
  5. package/dist/http-app.d.ts +45 -0
  6. package/dist/http-app.js +550 -0
  7. package/dist/http-app.js.map +1 -0
  8. package/dist/http.d.ts +2 -0
  9. package/dist/http.js +65 -0
  10. package/dist/http.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +65 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/lib/auth-context.d.ts +9 -0
  15. package/dist/lib/auth-context.js +9 -0
  16. package/dist/lib/auth-context.js.map +1 -0
  17. package/dist/lib/gitlab-client.d.ts +331 -0
  18. package/dist/lib/gitlab-client.js +1025 -0
  19. package/dist/lib/gitlab-client.js.map +1 -0
  20. package/dist/lib/logger.d.ts +2 -0
  21. package/dist/lib/logger.js +13 -0
  22. package/dist/lib/logger.js.map +1 -0
  23. package/dist/lib/network.d.ts +3 -0
  24. package/dist/lib/network.js +38 -0
  25. package/dist/lib/network.js.map +1 -0
  26. package/dist/lib/oauth.d.ts +29 -0
  27. package/dist/lib/oauth.js +220 -0
  28. package/dist/lib/oauth.js.map +1 -0
  29. package/dist/lib/output.d.ts +14 -0
  30. package/dist/lib/output.js +38 -0
  31. package/dist/lib/output.js.map +1 -0
  32. package/dist/lib/policy.d.ts +25 -0
  33. package/dist/lib/policy.js +48 -0
  34. package/dist/lib/policy.js.map +1 -0
  35. package/dist/lib/request-runtime.d.ts +26 -0
  36. package/dist/lib/request-runtime.js +323 -0
  37. package/dist/lib/request-runtime.js.map +1 -0
  38. package/dist/lib/sanitize.d.ts +1 -0
  39. package/dist/lib/sanitize.js +21 -0
  40. package/dist/lib/sanitize.js.map +1 -0
  41. package/dist/lib/session-capacity.d.ts +8 -0
  42. package/dist/lib/session-capacity.js +7 -0
  43. package/dist/lib/session-capacity.js.map +1 -0
  44. package/dist/server/build-server.d.ts +3 -0
  45. package/dist/server/build-server.js +13 -0
  46. package/dist/server/build-server.js.map +1 -0
  47. package/dist/tools/gitlab.d.ts +9 -0
  48. package/dist/tools/gitlab.js +2576 -0
  49. package/dist/tools/gitlab.js.map +1 -0
  50. package/dist/tools/health.d.ts +2 -0
  51. package/dist/tools/health.js +21 -0
  52. package/dist/tools/health.js.map +1 -0
  53. package/dist/tools/mr-code-context.d.ts +38 -0
  54. package/dist/tools/mr-code-context.js +330 -0
  55. package/dist/tools/mr-code-context.js.map +1 -0
  56. package/{src/types/context.ts → dist/types/context.d.ts} +5 -6
  57. package/dist/types/context.js +2 -0
  58. package/dist/types/context.js.map +1 -0
  59. package/docs/configuration.md +6 -6
  60. package/docs/mcp-integration-testing-best-practices.md +981 -0
  61. package/package.json +21 -1
  62. package/.dockerignore +0 -7
  63. package/.editorconfig +0 -9
  64. package/.env.example +0 -75
  65. package/.github/workflows/nodejs.yml +0 -31
  66. package/.github/workflows/npm-publish.yml +0 -31
  67. package/.husky/pre-commit +0 -1
  68. package/.nvmrc +0 -1
  69. package/.prettierrc.json +0 -6
  70. package/Dockerfile +0 -20
  71. package/docker-compose.yml +0 -10
  72. package/eslint.config.js +0 -23
  73. package/scripts/get-oauth-token.example.sh +0 -15
  74. package/src/config/env.ts +0 -171
  75. package/src/http.ts +0 -605
  76. package/src/index.ts +0 -77
  77. package/src/lib/auth-context.ts +0 -19
  78. package/src/lib/gitlab-client.ts +0 -1810
  79. package/src/lib/logger.ts +0 -17
  80. package/src/lib/network.ts +0 -45
  81. package/src/lib/oauth.ts +0 -287
  82. package/src/lib/output.ts +0 -51
  83. package/src/lib/policy.ts +0 -78
  84. package/src/lib/request-runtime.ts +0 -376
  85. package/src/lib/sanitize.ts +0 -25
  86. package/src/server/build-server.ts +0 -17
  87. package/src/tools/gitlab.ts +0 -3128
  88. package/src/tools/health.ts +0 -27
  89. package/src/tools/mr-code-context.ts +0 -473
  90. package/tests/auth-context.test.ts +0 -102
  91. package/tests/gitlab-client.test.ts +0 -674
  92. package/tests/graphql-guard.test.ts +0 -121
  93. package/tests/integration/agent-loop.integration.test.ts +0 -552
  94. package/tests/integration/server.integration.test.ts +0 -543
  95. package/tests/mr-code-context.test.ts +0 -600
  96. package/tests/oauth.test.ts +0 -43
  97. package/tests/output.test.ts +0 -186
  98. package/tests/policy.test.ts +0 -324
  99. package/tests/request-runtime.test.ts +0 -252
  100. package/tests/sanitize.test.ts +0 -123
  101. package/tests/upload-reference.test.ts +0 -84
  102. package/tsconfig.build.json +0 -11
  103. package/tsconfig.json +0 -21
  104. package/vitest.config.ts +0 -12
@@ -0,0 +1,550 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
3
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import express from "express";
6
+ import { runWithSessionAuth } from "./lib/auth-context.js";
7
+ import { hasReachedSessionCapacity } from "./lib/session-capacity.js";
8
+ import { createMcpServer } from "./server/build-server.js";
9
+ export function setupMcpHttpApp(deps) {
10
+ const { context, env: appEnv, logger: appLogger } = deps;
11
+ const app = createMcpExpressApp({ host: appEnv.HTTP_HOST });
12
+ app.use(express.json({ limit: "2mb" }));
13
+ app.use((error, req, res, next) => {
14
+ if (req.path !== "/mcp" || !isJsonBodyParserError(error)) {
15
+ next(error);
16
+ return;
17
+ }
18
+ if (error.type === "entity.too.large") {
19
+ res.status(413).json({
20
+ jsonrpc: "2.0",
21
+ error: {
22
+ code: -32013,
23
+ message: "JSON payload exceeds 2mb limit"
24
+ },
25
+ id: null
26
+ });
27
+ return;
28
+ }
29
+ res.status(400).json({
30
+ jsonrpc: "2.0",
31
+ error: {
32
+ code: -32700,
33
+ message: "Invalid JSON payload"
34
+ },
35
+ id: null
36
+ });
37
+ });
38
+ const sessions = new Map();
39
+ const pendingSessions = new Set();
40
+ const sseSessions = new Map();
41
+ /* ---- /healthz ---- */
42
+ app.get("/healthz", (_req, res) => {
43
+ res.status(200).json({
44
+ status: hasReachedSessionCapacity({
45
+ streamableSessions: sessions.size,
46
+ pendingSessions: pendingSessions.size,
47
+ sseSessions: sseSessions.size,
48
+ maxSessions: appEnv.MAX_SESSIONS
49
+ })
50
+ ? "degraded"
51
+ : "ok",
52
+ server: appEnv.MCP_SERVER_NAME,
53
+ activeSessions: sessions.size,
54
+ activeSseSessions: sseSessions.size,
55
+ pendingSessions: pendingSessions.size,
56
+ maxSessions: appEnv.MAX_SESSIONS,
57
+ remoteAuthorization: appEnv.REMOTE_AUTHORIZATION,
58
+ readOnlyMode: appEnv.GITLAB_READ_ONLY_MODE,
59
+ sseEnabled: appEnv.SSE
60
+ });
61
+ });
62
+ /* ---- SSE endpoints ---- */
63
+ if (appEnv.SSE) {
64
+ app.get("/sse", async (req, res) => {
65
+ let sessionId;
66
+ try {
67
+ const parsedAuth = parseRequestAuth(req);
68
+ const fallbackToken = appEnv.REMOTE_AUTHORIZATION
69
+ ? undefined
70
+ : appEnv.GITLAB_PERSONAL_ACCESS_TOKEN;
71
+ if (hasReachedSessionCapacity({
72
+ streamableSessions: sessions.size,
73
+ pendingSessions: pendingSessions.size,
74
+ sseSessions: sseSessions.size,
75
+ maxSessions: appEnv.MAX_SESSIONS
76
+ })) {
77
+ res.status(503).send(`Maximum ${appEnv.MAX_SESSIONS} concurrent sessions reached`);
78
+ return;
79
+ }
80
+ const server = createMcpServer(context);
81
+ const transport = new SSEServerTransport("/messages", res);
82
+ sessionId = transport.sessionId;
83
+ const state = {
84
+ sessionId,
85
+ server,
86
+ transport,
87
+ lastAccessAt: Date.now(),
88
+ closed: false
89
+ };
90
+ sseSessions.set(sessionId, state);
91
+ const currentSessionId = sessionId;
92
+ res.on("close", () => {
93
+ void closeSseSession(currentSessionId, "client-close");
94
+ });
95
+ await runWithSessionAuth({
96
+ sessionId,
97
+ token: parsedAuth?.token ?? fallbackToken,
98
+ apiUrl: parsedAuth?.apiUrl ?? appEnv.GITLAB_API_URL,
99
+ header: parsedAuth?.header,
100
+ updatedAt: Date.now()
101
+ }, async () => {
102
+ await server.connect(transport);
103
+ });
104
+ appLogger.info({ sessionId }, "MCP SSE session initialized");
105
+ }
106
+ catch (error) {
107
+ if (sessionId) {
108
+ await closeSseSession(sessionId, "connect-error");
109
+ }
110
+ appLogger.error({ err: error, sessionId }, "Failed to initialize SSE session");
111
+ if (!res.headersSent) {
112
+ res.status(500).send("Failed to initialize SSE session");
113
+ }
114
+ }
115
+ });
116
+ app.post("/messages", async (req, res) => {
117
+ let sessionId;
118
+ try {
119
+ sessionId = String(req.query.sessionId ?? "");
120
+ if (!sessionId) {
121
+ res.status(400).send("Missing sessionId");
122
+ return;
123
+ }
124
+ const session = sseSessions.get(sessionId);
125
+ if (!session || session.closed) {
126
+ res.status(400).send("No transport found for sessionId");
127
+ return;
128
+ }
129
+ const parsedAuth = parseRequestAuth(req);
130
+ const fallbackToken = appEnv.REMOTE_AUTHORIZATION
131
+ ? undefined
132
+ : appEnv.GITLAB_PERSONAL_ACCESS_TOKEN;
133
+ session.lastAccessAt = Date.now();
134
+ await runWithSessionAuth({
135
+ sessionId,
136
+ token: parsedAuth?.token ?? fallbackToken,
137
+ apiUrl: parsedAuth?.apiUrl ?? appEnv.GITLAB_API_URL,
138
+ header: parsedAuth?.header,
139
+ updatedAt: Date.now()
140
+ }, async () => {
141
+ await session.transport.handlePostMessage(req, res, req.body);
142
+ });
143
+ }
144
+ catch (error) {
145
+ appLogger.error({ err: error, sessionId }, "SSE post message failed");
146
+ if (!res.headersSent) {
147
+ res.status(500).send("SSE message processing failed");
148
+ }
149
+ }
150
+ });
151
+ }
152
+ /* ---- /mcp (streamable HTTP) ---- */
153
+ app.all("/mcp", async (req, res) => {
154
+ const incomingSessionId = req.header("mcp-session-id") ?? undefined;
155
+ let session = incomingSessionId ? sessions.get(incomingSessionId) : undefined;
156
+ let createdSession = false;
157
+ try {
158
+ const parsedAuth = parseRequestAuth(req);
159
+ if (appEnv.REMOTE_AUTHORIZATION && !parsedAuth?.token) {
160
+ res.status(401).json({
161
+ jsonrpc: "2.0",
162
+ error: {
163
+ code: -32010,
164
+ message: "Missing remote authorization token. Provide 'Authorization: Bearer <token>' or 'Private-Token'."
165
+ },
166
+ id: null
167
+ });
168
+ return;
169
+ }
170
+ if (appEnv.REMOTE_AUTHORIZATION && appEnv.ENABLE_DYNAMIC_API_URL && !parsedAuth?.apiUrl) {
171
+ res.status(400).json({
172
+ jsonrpc: "2.0",
173
+ error: {
174
+ code: -32011,
175
+ message: "Missing 'X-GitLab-API-URL' while ENABLE_DYNAMIC_API_URL=true and REMOTE_AUTHORIZATION=true."
176
+ },
177
+ id: null
178
+ });
179
+ return;
180
+ }
181
+ if (incomingSessionId && !session) {
182
+ res.status(404).json({
183
+ jsonrpc: "2.0",
184
+ error: {
185
+ code: -32001,
186
+ message: `Unknown session '${incomingSessionId}'`
187
+ },
188
+ id: null
189
+ });
190
+ return;
191
+ }
192
+ if (!session) {
193
+ if (req.method !== "POST") {
194
+ res.status(400).json({
195
+ jsonrpc: "2.0",
196
+ error: {
197
+ code: -32000,
198
+ message: "Session not initialized. First call must be a POST initialize request."
199
+ },
200
+ id: null
201
+ });
202
+ return;
203
+ }
204
+ if (hasReachedSessionCapacity({
205
+ streamableSessions: sessions.size,
206
+ pendingSessions: pendingSessions.size,
207
+ sseSessions: sseSessions.size,
208
+ maxSessions: appEnv.MAX_SESSIONS
209
+ })) {
210
+ res.status(503).json({
211
+ jsonrpc: "2.0",
212
+ error: {
213
+ code: -32002,
214
+ message: `Maximum ${appEnv.MAX_SESSIONS} concurrent sessions reached`
215
+ },
216
+ id: null
217
+ });
218
+ return;
219
+ }
220
+ session = await createSession(parsedAuth);
221
+ createdSession = true;
222
+ }
223
+ else {
224
+ refreshSessionAuth(session, parsedAuth);
225
+ }
226
+ if (!session) {
227
+ throw new Error("Session state missing after initialization");
228
+ }
229
+ const activeSession = session;
230
+ if (!checkSessionRateLimit(activeSession)) {
231
+ res.status(429).json({
232
+ jsonrpc: "2.0",
233
+ error: {
234
+ code: -32003,
235
+ message: `Rate limit exceeded: max ${appEnv.MAX_REQUESTS_PER_MINUTE} requests/min per session`
236
+ },
237
+ id: null
238
+ });
239
+ return;
240
+ }
241
+ await enqueueSessionRequest(activeSession, async () => {
242
+ const runtimeAuth = buildRuntimeAuth(activeSession);
243
+ await runWithSessionAuth(runtimeAuth, async () => {
244
+ await activeSession.transport.handleRequest(req, res, req.body);
245
+ });
246
+ });
247
+ }
248
+ catch (error) {
249
+ appLogger.error({
250
+ err: error,
251
+ method: req.method,
252
+ sessionId: incomingSessionId
253
+ }, "MCP HTTP request failed");
254
+ if (!res.headersSent && isClientHeaderValidationError(error)) {
255
+ res.status(400).json({
256
+ jsonrpc: "2.0",
257
+ error: {
258
+ code: -32012,
259
+ message: error.message
260
+ },
261
+ id: null
262
+ });
263
+ return;
264
+ }
265
+ if (!res.headersSent) {
266
+ res.status(500).json({
267
+ jsonrpc: "2.0",
268
+ error: {
269
+ code: -32603,
270
+ message: "Internal server error"
271
+ },
272
+ id: null
273
+ });
274
+ }
275
+ }
276
+ finally {
277
+ if (createdSession && session) {
278
+ await discardPendingSessionIfUninitialized(session);
279
+ }
280
+ }
281
+ });
282
+ /* ---- Internal helpers (closures) ---- */
283
+ async function createSession(initialAuth) {
284
+ const server = createMcpServer(context);
285
+ const state = {
286
+ server,
287
+ transport: undefined,
288
+ lastAccessAt: Date.now(),
289
+ queue: Promise.resolve(),
290
+ activeRequests: 0,
291
+ closed: false,
292
+ auth: initialAuth,
293
+ rateLimit: {
294
+ windowStart: Date.now(),
295
+ count: 0
296
+ }
297
+ };
298
+ pendingSessions.add(state);
299
+ const transport = new StreamableHTTPServerTransport({
300
+ sessionIdGenerator: () => randomUUID(),
301
+ enableJsonResponse: appEnv.HTTP_JSON_ONLY,
302
+ onsessioninitialized: (sessionId) => {
303
+ state.sessionId = sessionId;
304
+ state.lastAccessAt = Date.now();
305
+ sessions.set(sessionId, state);
306
+ pendingSessions.delete(state);
307
+ appLogger.info({ sessionId }, "MCP session initialized");
308
+ },
309
+ onsessionclosed: async (sessionId) => {
310
+ await closeSession(sessionId, "transport-close");
311
+ }
312
+ });
313
+ state.transport = transport;
314
+ transport.onerror = (error) => {
315
+ appLogger.error({ err: error, sessionId: state.sessionId }, "MCP transport error");
316
+ };
317
+ try {
318
+ await server.connect(transport);
319
+ return state;
320
+ }
321
+ catch (error) {
322
+ pendingSessions.delete(state);
323
+ if (state.sessionId) {
324
+ await closeSession(state.sessionId, "transport-close");
325
+ throw error;
326
+ }
327
+ state.closed = true;
328
+ try {
329
+ await transport.close();
330
+ }
331
+ catch (closeError) {
332
+ appLogger.warn({ err: closeError }, "Failed to close transport after session init failure");
333
+ }
334
+ try {
335
+ await server.close();
336
+ }
337
+ catch (closeError) {
338
+ appLogger.warn({ err: closeError }, "Failed to close MCP server after session init failure");
339
+ }
340
+ throw error;
341
+ }
342
+ }
343
+ function checkSessionRateLimit(session) {
344
+ const now = Date.now();
345
+ const oneMinute = 60_000;
346
+ if (now - session.rateLimit.windowStart >= oneMinute) {
347
+ session.rateLimit.windowStart = now;
348
+ session.rateLimit.count = 0;
349
+ }
350
+ if (session.rateLimit.count >= appEnv.MAX_REQUESTS_PER_MINUTE) {
351
+ return false;
352
+ }
353
+ session.rateLimit.count += 1;
354
+ return true;
355
+ }
356
+ function refreshSessionAuth(session, auth) {
357
+ if (!auth) {
358
+ return;
359
+ }
360
+ session.auth = auth;
361
+ session.lastAccessAt = Date.now();
362
+ }
363
+ function buildRuntimeAuth(session) {
364
+ const fallbackToken = appEnv.REMOTE_AUTHORIZATION
365
+ ? undefined
366
+ : appEnv.GITLAB_PERSONAL_ACCESS_TOKEN;
367
+ return {
368
+ sessionId: session.sessionId,
369
+ token: session.auth?.token ?? fallbackToken,
370
+ apiUrl: session.auth?.apiUrl ?? appEnv.GITLAB_API_URL,
371
+ header: session.auth?.header,
372
+ updatedAt: session.auth?.updatedAt ?? Date.now()
373
+ };
374
+ }
375
+ function parseRequestAuth(req) {
376
+ if (!appEnv.REMOTE_AUTHORIZATION) {
377
+ return undefined;
378
+ }
379
+ const privateToken = req.header("private-token")?.trim();
380
+ const authorization = req.header("authorization")?.trim();
381
+ const bearerToken = authorization?.toLowerCase().startsWith("bearer ")
382
+ ? authorization.slice(7).trim()
383
+ : undefined;
384
+ const token = privateToken || bearerToken;
385
+ let apiUrl;
386
+ if (appEnv.ENABLE_DYNAMIC_API_URL) {
387
+ const dynamicApiUrl = req.header("x-gitlab-api-url")?.trim();
388
+ if (dynamicApiUrl) {
389
+ try {
390
+ const parsedApiUrl = new URL(dynamicApiUrl);
391
+ if (!isHttpUrl(parsedApiUrl)) {
392
+ throw new Error("unsupported protocol");
393
+ }
394
+ apiUrl = parsedApiUrl.toString();
395
+ }
396
+ catch {
397
+ throw new Error(`Invalid x-gitlab-api-url header: '${dynamicApiUrl}'`);
398
+ }
399
+ }
400
+ }
401
+ if (!token && !apiUrl) {
402
+ return undefined;
403
+ }
404
+ return {
405
+ token,
406
+ apiUrl,
407
+ header: privateToken ? "private-token" : bearerToken ? "authorization" : undefined,
408
+ updatedAt: Date.now()
409
+ };
410
+ }
411
+ async function enqueueSessionRequest(session, task) {
412
+ const queued = session.queue.then(async () => {
413
+ session.activeRequests += 1;
414
+ session.lastAccessAt = Date.now();
415
+ try {
416
+ await task();
417
+ }
418
+ finally {
419
+ session.activeRequests -= 1;
420
+ session.lastAccessAt = Date.now();
421
+ }
422
+ });
423
+ session.queue = queued.catch(() => undefined);
424
+ await queued;
425
+ }
426
+ async function garbageCollectSessions() {
427
+ const now = Date.now();
428
+ const timeoutMs = appEnv.SESSION_TIMEOUT_SECONDS * 1000;
429
+ for (const [sessionId, session] of sessions) {
430
+ if (session.activeRequests > 0 || session.closed) {
431
+ continue;
432
+ }
433
+ if (now - session.lastAccessAt < timeoutMs) {
434
+ continue;
435
+ }
436
+ await closeSession(sessionId, "idle-timeout");
437
+ }
438
+ for (const [sessionId, session] of sseSessions) {
439
+ if (session.closed) {
440
+ continue;
441
+ }
442
+ if (now - session.lastAccessAt < timeoutMs) {
443
+ continue;
444
+ }
445
+ await closeSseSession(sessionId, "idle-timeout");
446
+ }
447
+ }
448
+ async function discardPendingSessionIfUninitialized(session) {
449
+ if (session.closed || session.sessionId || !pendingSessions.has(session)) {
450
+ return;
451
+ }
452
+ session.closed = true;
453
+ pendingSessions.delete(session);
454
+ try {
455
+ await session.transport.close();
456
+ }
457
+ catch (error) {
458
+ appLogger.warn({ err: error }, "Failed to close uninitialized transport cleanly");
459
+ }
460
+ try {
461
+ await session.server.close();
462
+ }
463
+ catch (error) {
464
+ appLogger.warn({ err: error }, "Failed to close uninitialized MCP server cleanly");
465
+ }
466
+ appLogger.info("Discarded uninitialized pending session");
467
+ }
468
+ async function closeSession(sessionId, reason) {
469
+ const session = sessions.get(sessionId);
470
+ if (!session || session.closed) {
471
+ return;
472
+ }
473
+ session.closed = true;
474
+ sessions.delete(sessionId);
475
+ try {
476
+ await session.transport.close();
477
+ }
478
+ catch (error) {
479
+ appLogger.warn({ err: error, sessionId, reason }, "Failed to close transport cleanly");
480
+ }
481
+ try {
482
+ await session.server.close();
483
+ }
484
+ catch (error) {
485
+ appLogger.warn({ err: error, sessionId, reason }, "Failed to close MCP server cleanly");
486
+ }
487
+ appLogger.info({ sessionId, reason }, "MCP session closed");
488
+ }
489
+ async function closeSseSession(sessionId, reason) {
490
+ const session = sseSessions.get(sessionId);
491
+ if (!session || session.closed) {
492
+ return;
493
+ }
494
+ session.closed = true;
495
+ sseSessions.delete(sessionId);
496
+ try {
497
+ await session.transport.close();
498
+ }
499
+ catch (error) {
500
+ appLogger.warn({ err: error, sessionId, reason }, "Failed to close SSE transport cleanly");
501
+ }
502
+ try {
503
+ await session.server.close();
504
+ }
505
+ catch (error) {
506
+ appLogger.warn({ err: error, sessionId, reason }, "Failed to close SSE MCP server cleanly");
507
+ }
508
+ appLogger.info({ sessionId, reason }, "MCP SSE session closed");
509
+ }
510
+ async function shutdown(httpServer, gcIntervalHandle) {
511
+ appLogger.info("Shutting down HTTP server");
512
+ clearInterval(gcIntervalHandle);
513
+ const pendingClose = [...sessions.keys()].map((sessionId) => closeSession(sessionId, "shutdown"));
514
+ const pendingSseClose = [...sseSessions.keys()].map((sessionId) => closeSseSession(sessionId, "shutdown"));
515
+ const pendingInitClose = [...pendingSessions].map((session) => discardPendingSessionIfUninitialized(session));
516
+ await Promise.allSettled([...pendingClose, ...pendingSseClose, ...pendingInitClose]);
517
+ await new Promise((resolve, reject) => {
518
+ httpServer.close((error) => {
519
+ if (error) {
520
+ reject(error);
521
+ return;
522
+ }
523
+ resolve();
524
+ });
525
+ });
526
+ }
527
+ return {
528
+ app,
529
+ sessions,
530
+ pendingSessions,
531
+ sseSessions,
532
+ closeSession,
533
+ closeSseSession,
534
+ garbageCollectSessions,
535
+ shutdown
536
+ };
537
+ }
538
+ function isClientHeaderValidationError(error) {
539
+ return error instanceof Error && error.message.startsWith("Invalid x-gitlab-api-url header:");
540
+ }
541
+ function isJsonBodyParserError(error) {
542
+ return (error instanceof Error &&
543
+ "type" in error &&
544
+ (error.type === "entity.parse.failed" ||
545
+ error.type === "entity.too.large"));
546
+ }
547
+ function isHttpUrl(url) {
548
+ return url.protocol === "http:" || url.protocol === "https:";
549
+ }
550
+ //# sourceMappingURL=http-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-app.js","sourceRoot":"","sources":["../src/http-app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAElF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,kBAAkB,EAAoB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAyD3D,MAAM,UAAU,eAAe,CAAC,IAAyB;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAEzD,MAAM,GAAG,GAAG,mBAAmB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5D,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CACL,CAAC,KAAc,EAAE,GAAoB,EAAE,GAAqB,EAAE,IAA0B,EAAE,EAAE;QAC1F,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,KAAK,CAAC,CAAC;YACZ,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACtC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,CAAC,KAAK;oBACZ,OAAO,EAAE,gCAAgC;iBAC1C;gBACD,EAAE,EAAE,IAAI;aACT,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACL,IAAI,EAAE,CAAC,KAAK;gBACZ,OAAO,EAAE,sBAAsB;aAChC;YACD,EAAE,EAAE,IAAI;SACT,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAgB,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEvD,wBAAwB;IAExB,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,MAAM,EAAE,yBAAyB,CAAC;gBAChC,kBAAkB,EAAE,QAAQ,CAAC,IAAI;gBACjC,eAAe,EAAE,eAAe,CAAC,IAAI;gBACrC,WAAW,EAAE,WAAW,CAAC,IAAI;gBAC7B,WAAW,EAAE,MAAM,CAAC,YAAY;aACjC,CAAC;gBACA,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,IAAI;YACR,MAAM,EAAE,MAAM,CAAC,eAAe;YAC9B,cAAc,EAAE,QAAQ,CAAC,IAAI;YAC7B,iBAAiB,EAAE,WAAW,CAAC,IAAI;YACnC,eAAe,EAAE,eAAe,CAAC,IAAI;YACrC,WAAW,EAAE,MAAM,CAAC,YAAY;YAChC,mBAAmB,EAAE,MAAM,CAAC,oBAAoB;YAChD,YAAY,EAAE,MAAM,CAAC,qBAAqB;YAC1C,UAAU,EAAE,MAAM,CAAC,GAAG;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAE7B,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACjC,IAAI,SAA6B,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;gBACzC,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB;oBAC/C,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,MAAM,CAAC,4BAA4B,CAAC;gBAExC,IACE,yBAAyB,CAAC;oBACxB,kBAAkB,EAAE,QAAQ,CAAC,IAAI;oBACjC,eAAe,EAAE,eAAe,CAAC,IAAI;oBACrC,WAAW,EAAE,WAAW,CAAC,IAAI;oBAC7B,WAAW,EAAE,MAAM,CAAC,YAAY;iBACjC,CAAC,EACF,CAAC;oBACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,YAAY,8BAA8B,CAAC,CAAC;oBACnF,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;gBACxC,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;gBAC3D,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;gBAChC,MAAM,KAAK,GAAoB;oBAC7B,SAAS;oBACT,MAAM;oBACN,SAAS;oBACT,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;oBACxB,MAAM,EAAE,KAAK;iBACd,CAAC;gBACF,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAClC,MAAM,gBAAgB,GAAG,SAAS,CAAC;gBAEnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBACnB,KAAK,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;gBACzD,CAAC,CAAC,CAAC;gBAEH,MAAM,kBAAkB,CACtB;oBACE,SAAS;oBACT,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,aAAa;oBACzC,MAAM,EAAE,UAAU,EAAE,MAAM,IAAI,MAAM,CAAC,cAAc;oBACnD,MAAM,EAAE,UAAU,EAAE,MAAM;oBAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACtB,EACD,KAAK,IAAI,EAAE;oBACT,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAClC,CAAC,CACF,CAAC;gBACF,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,6BAA6B,CAAC,CAAC;YAC/D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,eAAe,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;gBACpD,CAAC;gBACD,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kCAAkC,CAAC,CAAC;gBAC/E,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACvC,IAAI,SAA6B,CAAC;YAClC,IAAI,CAAC;gBACH,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;gBAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC3C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC/B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;oBACzD,OAAO;gBACT,CAAC;gBAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;gBACzC,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB;oBAC/C,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,MAAM,CAAC,4BAA4B,CAAC;gBACxC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAElC,MAAM,kBAAkB,CACtB;oBACE,SAAS;oBACT,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,aAAa;oBACzC,MAAM,EAAE,UAAU,EAAE,MAAM,IAAI,MAAM,CAAC,cAAc;oBACnD,MAAM,EAAE,UAAU,EAAE,MAAM;oBAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACtB,EACD,KAAK,IAAI,EAAE;oBACT,MAAM,OAAO,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBAChE,CAAC,CACF,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,yBAAyB,CAAC,CAAC;gBACtE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sCAAsC;IAEtC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACjC,MAAM,iBAAiB,GAAG,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,SAAS,CAAC;QACpE,IAAI,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9E,IAAI,cAAc,GAAG,KAAK,CAAC;QAE3B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAEzC,IAAI,MAAM,CAAC,oBAAoB,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;gBACtD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EACL,iGAAiG;qBACpG;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,MAAM,CAAC,oBAAoB,IAAI,MAAM,CAAC,sBAAsB,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBACxF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EACL,6FAA6F;qBAChG;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,iBAAiB,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,oBAAoB,iBAAiB,GAAG;qBAClD;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC1B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACnB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE;4BACL,IAAI,EAAE,CAAC,KAAK;4BACZ,OAAO,EAAE,wEAAwE;yBAClF;wBACD,EAAE,EAAE,IAAI;qBACT,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,IACE,yBAAyB,CAAC;oBACxB,kBAAkB,EAAE,QAAQ,CAAC,IAAI;oBACjC,eAAe,EAAE,eAAe,CAAC,IAAI;oBACrC,WAAW,EAAE,WAAW,CAAC,IAAI;oBAC7B,WAAW,EAAE,MAAM,CAAC,YAAY;iBACjC,CAAC,EACF,CAAC;oBACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACnB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE;4BACL,IAAI,EAAE,CAAC,KAAK;4BACZ,OAAO,EAAE,WAAW,MAAM,CAAC,YAAY,8BAA8B;yBACtE;wBACD,EAAE,EAAE,IAAI;qBACT,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;gBAC1C,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;YACD,MAAM,aAAa,GAAG,OAAO,CAAC;YAE9B,IAAI,CAAC,qBAAqB,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,4BAA4B,MAAM,CAAC,uBAAuB,2BAA2B;qBAC/F;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,qBAAqB,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;gBACpD,MAAM,WAAW,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBACpD,MAAM,kBAAkB,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;oBAC/C,MAAM,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBAClE,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,CACb;gBACE,GAAG,EAAE,KAAK;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,iBAAiB;aAC7B,EACD,yBAAyB,CAC1B,CAAC;YAEF,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,KAAK,CAAC,OAAO;qBACvB;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,uBAAuB;qBACjC;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAC;YACL,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,cAAc,IAAI,OAAO,EAAE,CAAC;gBAC9B,MAAM,oCAAoC,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2CAA2C;IAE3C,KAAK,UAAU,aAAa,CAAC,WAAyB;QACpD,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,KAAK,GAAiB;YAC1B,MAAM;YACN,SAAS,EAAE,SAAqD;YAChE,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE;YACxB,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE;gBACT,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,KAAK,EAAE,CAAC;aACT;SACF,CAAC;QAEF,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAE3B,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;YAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;YACtC,kBAAkB,EAAE,MAAM,CAAC,cAAc;YACzC,oBAAoB,EAAE,CAAC,SAAS,EAAE,EAAE;gBAClC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC5B,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC/B,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC9B,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,yBAAyB,CAAC,CAAC;YAC3D,CAAC;YACD,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;gBACnC,MAAM,YAAY,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YACnD,CAAC;SACF,CAAC,CAAC;QAEH,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAE5B,SAAS,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC5B,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,qBAAqB,CAAC,CAAC;QACrF,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChC,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAE9B,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;gBACvD,MAAM,KAAK,CAAC;YACd,CAAC;YAED,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,sDAAsD,CAAC,CAAC;YAC9F,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,SAAS,CAAC,IAAI,CACZ,EAAE,GAAG,EAAE,UAAU,EAAE,EACnB,uDAAuD,CACxD,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,SAAS,qBAAqB,CAAC,OAAqB;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,CAAC;QAEzB,IAAI,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,WAAW,IAAI,SAAS,EAAE,CAAC;YACrD,OAAO,CAAC,SAAS,CAAC,WAAW,GAAG,GAAG,CAAC;YACpC,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,MAAM,CAAC,uBAAuB,EAAE,CAAC;YAC9D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS,kBAAkB,CAAC,OAAqB,EAAE,IAAkB;QACnE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QACpB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,CAAC;IAED,SAAS,gBAAgB,CAAC,OAAqB;QAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB;YAC/C,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC,4BAA4B,CAAC;QAExC,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,aAAa;YAC3C,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,MAAM,CAAC,cAAc;YACrD,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM;YAC5B,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;SACjD,CAAC;IACJ,CAAC;IAED,SAAS,gBAAgB,CAAC,GAAoB;QAC5C,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACjC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC;QACzD,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC;QAE1D,MAAM,WAAW,GAAG,aAAa,EAAE,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YACpE,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YAC/B,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,KAAK,GAAG,YAAY,IAAI,WAAW,CAAC;QAE1C,IAAI,MAA0B,CAAC;QAE/B,IAAI,MAAM,CAAC,sBAAsB,EAAE,CAAC;YAClC,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC;YAC7D,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;oBAC5C,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;wBAC7B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;oBAC1C,CAAC;oBACD,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,aAAa,GAAG,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO;YACL,KAAK;YACL,MAAM;YACN,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;YAClF,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,qBAAqB,CAClC,OAAqB,EACrB,IAAyB;QAEzB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC3C,OAAO,CAAC,cAAc,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAElC,IAAI,CAAC;gBACH,MAAM,IAAI,EAAE,CAAC;YACf,CAAC;oBAAS,CAAC;gBACT,OAAO,CAAC,cAAc,IAAI,CAAC,CAAC;gBAC5B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC;IACf,CAAC;IAED,KAAK,UAAU,sBAAsB;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,CAAC,uBAAuB,GAAG,IAAI,CAAC;QAExD,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC5C,IAAI,OAAO,CAAC,cAAc,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACjD,SAAS;YACX,CAAC;YAED,IAAI,GAAG,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,EAAE,CAAC;gBAC3C,SAAS;YACX,CAAC;YAED,MAAM,YAAY,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAChD,CAAC;QAED,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,WAAW,EAAE,CAAC;YAC/C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,SAAS;YACX,CAAC;YAED,IAAI,GAAG,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,EAAE,CAAC;gBAC3C,SAAS;YACX,CAAC;YAED,MAAM,eAAe,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,KAAK,UAAU,oCAAoC,CAAC,OAAqB;QACvE,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;QACtB,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,iDAAiD,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,kDAAkD,CAAC,CAAC;QACrF,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,UAAU,YAAY,CACzB,SAAiB,EACjB,MAAuD;QAEvD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;QACtB,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE3B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,mCAAmC,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,oCAAoC,CAAC,CAAC;QAC1F,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,UAAU,eAAe,CAC5B,SAAiB,EACjB,MAAsE;QAEtE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE9B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAC7F,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,wCAAwC,CAAC,CAAC;QAC9F,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,UAAU,QAAQ,CACrB,UAAsB,EACtB,gBAAgD;QAEhD,SAAS,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAE5C,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAEhC,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1D,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,CACpC,CAAC;QACF,MAAM,eAAe,GAAG,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAChE,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CACvC,CAAC;QACF,MAAM,gBAAgB,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAC5D,oCAAoC,CAAC,OAAO,CAAC,CAC9C,CAAC;QACF,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,eAAe,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC;QAErF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,KAAK,CAAC,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,GAAG;QACH,QAAQ;QACR,eAAe;QACf,WAAW;QACX,YAAY;QACZ,eAAe;QACf,sBAAsB;QACtB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAc;IACnD,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC;AAChG,CAAC;AAMD,SAAS,qBAAqB,CAAC,KAAc;IAC3C,OAAO,CACL,KAAK,YAAY,KAAK;QACtB,MAAM,IAAI,KAAK;QACf,CAAE,KAA2B,CAAC,IAAI,KAAK,qBAAqB;YACzD,KAA2B,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAC5D,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAQ;IACzB,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAC/D,CAAC"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/http.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from "node:http";
3
+ import { env } from "./config/env.js";
4
+ import { GitLabClient } from "./lib/gitlab-client.js";
5
+ import { logger } from "./lib/logger.js";
6
+ import { configureNetworkRuntime } from "./lib/network.js";
7
+ import { OutputFormatter } from "./lib/output.js";
8
+ import { ToolPolicyEngine } from "./lib/policy.js";
9
+ import { GitLabRequestRuntime } from "./lib/request-runtime.js";
10
+ import { setupMcpHttpApp } from "./http-app.js";
11
+ /* ------------------------------------------------------------------ */
12
+ /* Module entry point */
13
+ /* ------------------------------------------------------------------ */
14
+ const requestRuntime = new GitLabRequestRuntime(env, logger);
15
+ configureNetworkRuntime(env, logger);
16
+ const context = {
17
+ env,
18
+ logger,
19
+ gitlab: new GitLabClient(env.GITLAB_API_URL, env.GITLAB_PERSONAL_ACCESS_TOKEN, {
20
+ apiUrls: env.GITLAB_API_URLS,
21
+ timeoutMs: env.GITLAB_HTTP_TIMEOUT_MS,
22
+ beforeRequest: (requestContext) => requestRuntime.beforeRequest(requestContext)
23
+ }),
24
+ policy: new ToolPolicyEngine({
25
+ readOnlyMode: env.GITLAB_READ_ONLY_MODE,
26
+ allowedTools: env.GITLAB_ALLOWED_TOOLS,
27
+ deniedToolsRegex: env.GITLAB_DENIED_TOOLS_REGEX
28
+ ? new RegExp(env.GITLAB_DENIED_TOOLS_REGEX)
29
+ : undefined,
30
+ enabledFeatures: {
31
+ wiki: env.USE_GITLAB_WIKI,
32
+ milestone: env.USE_MILESTONE,
33
+ pipeline: env.USE_PIPELINE,
34
+ release: env.USE_RELEASE
35
+ }
36
+ }),
37
+ formatter: new OutputFormatter({
38
+ responseMode: env.GITLAB_RESPONSE_MODE,
39
+ maxBytes: env.GITLAB_MAX_RESPONSE_BYTES
40
+ })
41
+ };
42
+ const { app, shutdown, garbageCollectSessions } = setupMcpHttpApp({ context, env, logger });
43
+ const httpServer = createServer(app);
44
+ httpServer.listen(env.HTTP_PORT, env.HTTP_HOST, () => {
45
+ logger.info({
46
+ host: env.HTTP_HOST,
47
+ port: env.HTTP_PORT,
48
+ transport: env.SSE ? "streamable-http+sse" : "streamable-http",
49
+ jsonOnly: env.HTTP_JSON_ONLY,
50
+ maxSessions: env.MAX_SESSIONS,
51
+ sessionTimeoutSeconds: env.SESSION_TIMEOUT_SECONDS,
52
+ remoteAuthEnabled: env.REMOTE_AUTHORIZATION
53
+ }, "MCP HTTP server started");
54
+ });
55
+ const gcInterval = setInterval(() => {
56
+ void garbageCollectSessions();
57
+ }, 30_000);
58
+ gcInterval.unref();
59
+ process.once("SIGINT", () => {
60
+ void shutdown(httpServer, gcInterval);
61
+ });
62
+ process.once("SIGTERM", () => {
63
+ void shutdown(httpServer, gcInterval);
64
+ });
65
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};