@carbonvoice/cv-mcp-server 2.8.0 → 2.8.14
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/dist/config/env.js +152 -2
- package/dist/config/env.js.map +1 -1
- package/dist/cv-api.js +15 -0
- package/dist/cv-api.js.map +1 -1
- package/dist/interfaces/index.js +1 -0
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/user-info.interface.js +3 -0
- package/dist/interfaces/user-info.interface.js.map +1 -0
- package/dist/server.js +582 -554
- package/dist/server.js.map +1 -1
- package/dist/transports/http/diagnostics/transport-send-diagnostics.js +115 -0
- package/dist/transports/http/diagnostics/transport-send-diagnostics.js.map +1 -0
- package/dist/transports/http/middleware/add-request-id.middlware.js +2 -2
- package/dist/transports/http/middleware/add-request-id.middlware.js.map +1 -1
- package/dist/transports/http/middleware/index.js +1 -0
- package/dist/transports/http/middleware/index.js.map +1 -1
- package/dist/transports/http/middleware/log-request.middlware.js +62 -11
- package/dist/transports/http/middleware/log-request.middlware.js.map +1 -1
- package/dist/transports/http/middleware/require-bearer-auth-with-absolute-metadata.middleware.js +72 -0
- package/dist/transports/http/middleware/require-bearer-auth-with-absolute-metadata.middleware.js.map +1 -0
- package/dist/transports/http/session/index.js +4 -1
- package/dist/transports/http/session/index.js.map +1 -1
- package/dist/transports/http/session/session.config.js +10 -5
- package/dist/transports/http/session/session.config.js.map +1 -1
- package/dist/transports/http/session/session.logger.js +22 -0
- package/dist/transports/http/session/session.logger.js.map +1 -1
- package/dist/transports/http/session/session.service.js +55 -22
- package/dist/transports/http/session/session.service.js.map +1 -1
- package/dist/transports/http/session/session.types.js.map +1 -1
- package/dist/transports/http/session/tool-call-queue.service.js +73 -0
- package/dist/transports/http/session/tool-call-queue.service.js.map +1 -0
- package/dist/transports/http/streamable-stateless.js +288 -0
- package/dist/transports/http/streamable-stateless.js.map +1 -0
- package/dist/transports/http/streamable.js +379 -37
- package/dist/transports/http/streamable.js.map +1 -1
- package/dist/transports/http/utils/request-context.js +3 -2
- package/dist/transports/http/utils/request-context.js.map +1 -1
- package/dist/utils/axios-instance.js +12 -0
- package/dist/utils/axios-instance.js.map +1 -1
- package/dist/utils/format-bytes-human.js +18 -0
- package/dist/utils/format-bytes-human.js.map +1 -0
- package/dist/utils/format-to-mcp-tool-response.js +46 -10
- package/dist/utils/format-to-mcp-tool-response.js.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.js +6 -19
- package/dist/utils/logger.js.map +1 -1
- package/package.json +11 -5
|
@@ -6,12 +6,50 @@ const session_logger_1 = require("./session.logger");
|
|
|
6
6
|
const session_types_1 = require("./session.types");
|
|
7
7
|
const session_manager_1 = require("./session-manager");
|
|
8
8
|
class SessionService {
|
|
9
|
-
constructor(sessionManager, config =
|
|
9
|
+
constructor(sessionManager, config = session_config_1.SessionConfig.fromEnv()) {
|
|
10
10
|
this.sessionManager = sessionManager;
|
|
11
11
|
this.config = config;
|
|
12
12
|
this.logger = new session_logger_1.SessionLogger();
|
|
13
13
|
this.config.validate();
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Next idle window (ms) capped by optional max wall-clock lifetime from {@link SessionMetrics.createdAt}.
|
|
17
|
+
*/
|
|
18
|
+
computeEffectiveIdleTtlMs(createdAt, requestedTtlMs) {
|
|
19
|
+
if (this.config.maxWallClockAgeMs <= 0) {
|
|
20
|
+
return requestedTtlMs;
|
|
21
|
+
}
|
|
22
|
+
const deadline = createdAt.getTime() + this.config.maxWallClockAgeMs;
|
|
23
|
+
const remaining = deadline - Date.now();
|
|
24
|
+
if (remaining <= 0) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
return Math.min(requestedTtlMs, remaining);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resets the destroy timer (sliding idle TTL). Destroys the session if max wall-clock age is exceeded.
|
|
31
|
+
*/
|
|
32
|
+
refreshIdleTimer(sessionId, requestedTtlMs = this.config.ttlMs) {
|
|
33
|
+
const session = this.getSession(sessionId);
|
|
34
|
+
if (!session) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const effectiveMs = this.computeEffectiveIdleTtlMs(session.metrics.createdAt, requestedTtlMs);
|
|
38
|
+
if (effectiveMs <= 0) {
|
|
39
|
+
this.logger.logSessionTimeout();
|
|
40
|
+
this.destroySession(sessionId);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
clearTimeout(session.timeout);
|
|
44
|
+
const now = new Date();
|
|
45
|
+
session.metrics.expiresAt = new Date(now.getTime() + effectiveMs);
|
|
46
|
+
session.metrics.lastActivityAt = now;
|
|
47
|
+
session.timeout = setTimeout(() => {
|
|
48
|
+
this.logger.logSessionTimeout();
|
|
49
|
+
this.destroySession(sessionId);
|
|
50
|
+
}, effectiveMs);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
15
53
|
createSession(transport, req, sessionId) {
|
|
16
54
|
var _a, _b;
|
|
17
55
|
// Validate inputs
|
|
@@ -34,7 +72,11 @@ class SessionService {
|
|
|
34
72
|
}
|
|
35
73
|
const userId = req.auth.extra.user.id;
|
|
36
74
|
const now = new Date();
|
|
37
|
-
const
|
|
75
|
+
const initialIdleMs = this.computeEffectiveIdleTtlMs(now, this.config.ttlMs);
|
|
76
|
+
if (initialIdleMs <= 0) {
|
|
77
|
+
throw new Error('Cannot create session: MCP_SESSION_MAX_AGE_MS does not allow any remaining lifetime');
|
|
78
|
+
}
|
|
79
|
+
const expiresAt = new Date(now.getTime() + initialIdleMs);
|
|
38
80
|
// Create enhanced metrics
|
|
39
81
|
const metrics = {
|
|
40
82
|
sessionId,
|
|
@@ -47,11 +89,11 @@ class SessionService {
|
|
|
47
89
|
errorCount: 0,
|
|
48
90
|
averageResponseTime: 0,
|
|
49
91
|
};
|
|
50
|
-
// Create session with timeout
|
|
92
|
+
// Create session with idle timeout (sliding; extended on activity)
|
|
51
93
|
const timeout = setTimeout(() => {
|
|
52
94
|
this.logger.logSessionTimeout();
|
|
53
95
|
this.destroySession(sessionId);
|
|
54
|
-
},
|
|
96
|
+
}, initialIdleMs);
|
|
55
97
|
const session = {
|
|
56
98
|
transport,
|
|
57
99
|
timeout,
|
|
@@ -131,8 +173,7 @@ class SessionService {
|
|
|
131
173
|
const session = this.getSession(sessionId);
|
|
132
174
|
if (session) {
|
|
133
175
|
session.metrics.totalInteractions++;
|
|
134
|
-
|
|
135
|
-
// Don't log automatically - let the request handler decide when to log
|
|
176
|
+
this.refreshIdleTimer(sessionId);
|
|
136
177
|
}
|
|
137
178
|
}
|
|
138
179
|
recordToolCall(sessionId) {
|
|
@@ -140,7 +181,7 @@ class SessionService {
|
|
|
140
181
|
if (session) {
|
|
141
182
|
session.metrics.totalToolCalls++;
|
|
142
183
|
session.metrics.totalInteractions++; // Tool calls are also interactions
|
|
143
|
-
|
|
184
|
+
this.refreshIdleTimer(sessionId);
|
|
144
185
|
}
|
|
145
186
|
}
|
|
146
187
|
recordError(sessionId) {
|
|
@@ -164,22 +205,14 @@ class SessionService {
|
|
|
164
205
|
return session.metrics.expiresAt < new Date();
|
|
165
206
|
}
|
|
166
207
|
extendSession(sessionId, additionalTtlMs = this.config.ttlMs) {
|
|
167
|
-
const
|
|
168
|
-
if (!
|
|
208
|
+
const ok = this.refreshIdleTimer(sessionId, additionalTtlMs);
|
|
209
|
+
if (!ok) {
|
|
169
210
|
return false;
|
|
170
211
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
session.metrics.expiresAt = newExpiresAt;
|
|
176
|
-
session.metrics.lastActivityAt = new Date();
|
|
177
|
-
// Set new timeout
|
|
178
|
-
session.timeout = setTimeout(() => {
|
|
179
|
-
this.logger.logSessionTimeout();
|
|
180
|
-
this.destroySession(sessionId);
|
|
181
|
-
}, additionalTtlMs);
|
|
182
|
-
this.logger.logSessionMetrics(session.metrics);
|
|
212
|
+
const session = this.getSession(sessionId);
|
|
213
|
+
if (session) {
|
|
214
|
+
this.logger.logSessionMetrics(session.metrics);
|
|
215
|
+
}
|
|
183
216
|
return true;
|
|
184
217
|
}
|
|
185
218
|
// Public method to log session metrics
|
|
@@ -191,6 +224,6 @@ class SessionService {
|
|
|
191
224
|
}
|
|
192
225
|
}
|
|
193
226
|
exports.SessionService = SessionService;
|
|
194
|
-
// Singleton instance
|
|
227
|
+
// Singleton instance (idle TTL and caps from env)
|
|
195
228
|
exports.sessionService = new SessionService(session_manager_1.sessionManager);
|
|
196
229
|
//# sourceMappingURL=session.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.service.js","sourceRoot":"","sources":["../../../../src/transports/http/session/session.service.ts"],"names":[],"mappings":";;;AAEA,qDAAiD;AACjD,qDAAiD;AACjD,mDAMyB;AACzB,uDAAmD;AAInD,MAAa,cAAc;IAGzB,YACU,cAA+B,EAC/B,SAAwB,
|
|
1
|
+
{"version":3,"file":"session.service.js","sourceRoot":"","sources":["../../../../src/transports/http/session/session.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.types.js","sourceRoot":"","sources":["../../../../src/transports/http/session/session.types.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"session.types.js","sourceRoot":"","sources":["../../../../src/transports/http/session/session.types.ts"],"names":[],"mappings":";;;AAgEA,gBAAgB;AAChB,MAAa,YAAa,SAAQ,KAAK;IACrC,YACE,OAAe,EACR,IAAY;QAEnB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFR,SAAI,GAAJ,IAAI,CAAQ;QAGnB,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AARD,oCAQC;AAED,MAAa,iBAAkB,SAAQ,YAAY;IACjD;QACE,KAAK,CAAC,oCAAoC,EAAE,gBAAgB,CAAC,CAAC;IAChE,CAAC;CACF;AAJD,8CAIC;AAED,MAAa,oBAAqB,SAAQ,YAAY;IACpD,YAAY,SAAiB;QAC3B,KAAK,CAAC,sBAAsB,SAAS,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAChE,CAAC;CACF;AAJD,oDAIC;AAED,MAAa,6BAA8B,SAAQ,YAAY;IAC7D,YAAY,SAAiB;QAC3B,KAAK,CACH,oCAAoC,SAAS,EAAE,EAC/C,4BAA4B,CAC7B,CAAC;IACJ,CAAC;CACF;AAPD,sEAOC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toolCallQueueService = exports.ToolCallQueueService = exports.ToolCallQueueTimeoutError = exports.TOOL_CALL_QUEUE_TIMEOUT_ERROR = void 0;
|
|
4
|
+
exports.TOOL_CALL_QUEUE_TIMEOUT_ERROR = 'TOOL_CALL_QUEUE_TIMEOUT';
|
|
5
|
+
class ToolCallQueueTimeoutError extends Error {
|
|
6
|
+
constructor(message = exports.TOOL_CALL_QUEUE_TIMEOUT_ERROR) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'ToolCallQueueTimeoutError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.ToolCallQueueTimeoutError = ToolCallQueueTimeoutError;
|
|
12
|
+
/**
|
|
13
|
+
* Serializes tool calls per session ID.
|
|
14
|
+
* Each acquired lease must be released exactly once.
|
|
15
|
+
*/
|
|
16
|
+
class ToolCallQueueService {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.queueBySessionId = new Map();
|
|
19
|
+
}
|
|
20
|
+
async acquire(sessionId, waitTimeoutMs) {
|
|
21
|
+
var _a;
|
|
22
|
+
const previousQueueHead = (_a = this.queueBySessionId.get(sessionId)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
23
|
+
let releaseCurrentSlot;
|
|
24
|
+
const currentSlotPromise = new Promise((resolve) => {
|
|
25
|
+
releaseCurrentSlot = resolve;
|
|
26
|
+
});
|
|
27
|
+
const nextQueueHead = previousQueueHead
|
|
28
|
+
.catch(() => undefined)
|
|
29
|
+
.then(() => currentSlotPromise);
|
|
30
|
+
this.queueBySessionId.set(sessionId, nextQueueHead);
|
|
31
|
+
const waitStartedAtMs = Date.now();
|
|
32
|
+
let timeoutHandle;
|
|
33
|
+
const queueTimeout = new Promise((_, reject) => {
|
|
34
|
+
timeoutHandle = setTimeout(() => {
|
|
35
|
+
reject(new ToolCallQueueTimeoutError());
|
|
36
|
+
}, waitTimeoutMs);
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
await Promise.race([previousQueueHead, queueTimeout]);
|
|
40
|
+
return {
|
|
41
|
+
waitDurationMs: Date.now() - waitStartedAtMs,
|
|
42
|
+
release: () => {
|
|
43
|
+
releaseCurrentSlot();
|
|
44
|
+
if (this.queueBySessionId.get(sessionId) === nextQueueHead) {
|
|
45
|
+
this.queueBySessionId.delete(sessionId);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// Ensure timed-out request does not leave a blocked slot behind.
|
|
52
|
+
releaseCurrentSlot();
|
|
53
|
+
if (this.queueBySessionId.get(sessionId) === nextQueueHead) {
|
|
54
|
+
this.queueBySessionId.delete(sessionId);
|
|
55
|
+
}
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
if (timeoutHandle) {
|
|
60
|
+
clearTimeout(timeoutHandle);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
clearSession(sessionId) {
|
|
65
|
+
if (!sessionId) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.queueBySessionId.delete(sessionId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.ToolCallQueueService = ToolCallQueueService;
|
|
72
|
+
exports.toolCallQueueService = new ToolCallQueueService();
|
|
73
|
+
//# sourceMappingURL=tool-call-queue.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-queue.service.js","sourceRoot":"","sources":["../../../../src/transports/http/session/tool-call-queue.service.ts"],"names":[],"mappings":";;;AAAa,QAAA,6BAA6B,GAAG,yBAAyB,CAAC;AAEvE,MAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAY,OAAO,GAAG,qCAA6B;QACjD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AALD,8DAKC;AAOD;;;GAGG;AACH,MAAa,oBAAoB;IAAjC;QACU,qBAAgB,GAAG,IAAI,GAAG,EAAyB,CAAC;IA2D9D,CAAC;IAzDC,KAAK,CAAC,OAAO,CACX,SAAiB,EACjB,aAAqB;;QAErB,MAAM,iBAAiB,GACrB,MAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,mCAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAE5D,IAAI,kBAA+B,CAAC;QACpC,MAAM,kBAAkB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACvD,kBAAkB,GAAG,OAAO,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,iBAAiB;aACpC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;aACtB,IAAI,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;QAClC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAEpD,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,IAAI,aAAyC,CAAC;QAE9C,MAAM,YAAY,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YACpD,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,MAAM,CAAC,IAAI,yBAAyB,EAAE,CAAC,CAAC;YAC1C,CAAC,EAAE,aAAa,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC,CAAC;YACtD,OAAO;gBACL,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe;gBAC5C,OAAO,EAAE,GAAG,EAAE;oBACZ,kBAAkB,EAAE,CAAC;oBACrB,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,aAAa,EAAE,CAAC;wBAC3D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC1C,CAAC;gBACH,CAAC;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,iEAAiE;YACjE,kBAAkB,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,aAAa,EAAE,CAAC;gBAC3D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC1C,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,aAAa,EAAE,CAAC;gBAClB,YAAY,CAAC,aAAa,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;CACF;AA5DD,oDA4DC;AAEY,QAAA,oBAAoB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
/**
|
|
8
|
+
* Stateless HTTP MCP transport.
|
|
9
|
+
*
|
|
10
|
+
* Every POST creates a fresh transport, connects the MCP server to it,
|
|
11
|
+
* handles the request, and closes. No session store, no queue, no TTL
|
|
12
|
+
* cleanup service. Horizontal scaling (MaxSize > 1) is safe because there
|
|
13
|
+
* is no shared in-process state between requests.
|
|
14
|
+
*
|
|
15
|
+
* Why stateless fixes the 120 s timeout cascade:
|
|
16
|
+
* In the session-based transport, all requests for the same session are
|
|
17
|
+
* serialized through a per-session queue. If Cursor fires several RPCs
|
|
18
|
+
* concurrently (initialize + tools/list + tools/call), each one queues
|
|
19
|
+
* behind the previous one. A 40 s tool call in slot 1 pushes slot 3 to
|
|
20
|
+
* ~120 s total wait → client timeout → MCP_TRANSPORT_SEND_ERROR cascade.
|
|
21
|
+
* In stateless mode every request runs concurrently at its natural speed.
|
|
22
|
+
*
|
|
23
|
+
* What is lost vs the session transport:
|
|
24
|
+
* • SSE server-to-client push (GET /) — not used by this server today.
|
|
25
|
+
* • Per-session request serialization — was causing the timeout cascade,
|
|
26
|
+
* so losing it is the desired outcome.
|
|
27
|
+
*/
|
|
28
|
+
const fs_1 = __importDefault(require("fs"));
|
|
29
|
+
const path_1 = __importDefault(require("path"));
|
|
30
|
+
const cors_1 = __importDefault(require("cors"));
|
|
31
|
+
const express_1 = __importDefault(require("express"));
|
|
32
|
+
const helmet_1 = __importDefault(require("helmet"));
|
|
33
|
+
const promises_1 = require("node:stream/promises");
|
|
34
|
+
const serve_favicon_1 = __importDefault(require("serve-favicon"));
|
|
35
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
36
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
37
|
+
const constants_1 = require("./constants");
|
|
38
|
+
const middleware_1 = require("./middleware");
|
|
39
|
+
const request_context_1 = require("./utils/request-context");
|
|
40
|
+
const auth_1 = require("../../auth");
|
|
41
|
+
const config_1 = require("../../config");
|
|
42
|
+
const cv_api_1 = require("../../cv-api");
|
|
43
|
+
const server_1 = require("../../server");
|
|
44
|
+
const utils_1 = require("../../utils");
|
|
45
|
+
const app = (0, express_1.default)();
|
|
46
|
+
app.set('x-powered-by', false);
|
|
47
|
+
// Trust proxy for rate limiting — only localhost and private networks
|
|
48
|
+
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);
|
|
49
|
+
const faviconPath = path_1.default.join(process.cwd(), 'public', 'favicon.ico');
|
|
50
|
+
if (fs_1.default.existsSync(faviconPath)) {
|
|
51
|
+
app.use((0, serve_favicon_1.default)(faviconPath));
|
|
52
|
+
}
|
|
53
|
+
app.use((0, cors_1.default)());
|
|
54
|
+
app.use((0, helmet_1.default)());
|
|
55
|
+
app.use(middleware_1.rateLimitMiddleware);
|
|
56
|
+
app.use(express_1.default.json({ limit: '1mb' }));
|
|
57
|
+
app.use(middleware_1.addRequestIdMiddleware);
|
|
58
|
+
app.use(middleware_1.logRequest);
|
|
59
|
+
let carbonVoiceApiHealth = {
|
|
60
|
+
isHealthy: (0, config_1.isTestEnvironment)() ? true : false,
|
|
61
|
+
lastChecked: new Date().toISOString(),
|
|
62
|
+
apiUrl: config_1.env.CARBON_VOICE_BASE_URL,
|
|
63
|
+
};
|
|
64
|
+
const resourceMetadataUrl = config_1.env.MCP_RESOURCE_METADATA_URL;
|
|
65
|
+
const oauthTokenVerifier = (0, auth_1.createOAuthTokenVerifier)();
|
|
66
|
+
const authWithAbsoluteMetadata = (0, middleware_1.requireBearerAuthWithAbsoluteMetadata)({
|
|
67
|
+
verifier: oauthTokenVerifier,
|
|
68
|
+
requiredScopes: constants_1.REQUIRED_SCOPES,
|
|
69
|
+
resourceMetadataUrl,
|
|
70
|
+
});
|
|
71
|
+
// ── Health / info ─────────────────────────────────────────────────────────────
|
|
72
|
+
app.get('/health', (req, res) => {
|
|
73
|
+
const response = {
|
|
74
|
+
status: carbonVoiceApiHealth.isHealthy ? 'healthy' : 'degraded',
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
uptime: (0, utils_1.getProcessUptime)(),
|
|
77
|
+
dependencies: {
|
|
78
|
+
carbonVoiceApi: {
|
|
79
|
+
status: carbonVoiceApiHealth.isHealthy ? 'healthy' : 'unhealthy',
|
|
80
|
+
lastChecked: carbonVoiceApiHealth.lastChecked,
|
|
81
|
+
...(carbonVoiceApiHealth.error && { error: carbonVoiceApiHealth.error }),
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const logLevel = carbonVoiceApiHealth.isHealthy ? 'info' : 'warn';
|
|
86
|
+
utils_1.logger[logLevel]('Health check', response);
|
|
87
|
+
res.status(carbonVoiceApiHealth.isHealthy ? 200 : 503).json(response);
|
|
88
|
+
});
|
|
89
|
+
app.get('/info', (req, res) => {
|
|
90
|
+
utils_1.logger.info('Info', {
|
|
91
|
+
ENV_VARS: {
|
|
92
|
+
CARBON_VOICE_BASE_URL: config_1.env.CARBON_VOICE_BASE_URL,
|
|
93
|
+
LOG_LEVEL: config_1.env.LOG_LEVEL,
|
|
94
|
+
PORT: config_1.env.PORT,
|
|
95
|
+
ENVIRONMENT: config_1.env.ENVIRONMENT,
|
|
96
|
+
LOG_TRANSPORT: config_1.env.LOG_TRANSPORT,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
res.status(200).send('OK');
|
|
100
|
+
});
|
|
101
|
+
// ── OAuth well-known ──────────────────────────────────────────────────────────
|
|
102
|
+
app.get('/.well-known/oauth-protected-resource', middleware_1.wellKnownCorsHeaders, middleware_1.oauthProtectedResource);
|
|
103
|
+
app.get('/.well-known/oauth-authorization-server', middleware_1.wellKnownCorsHeaders, middleware_1.oauthAuthorizationServer);
|
|
104
|
+
// ── HEAD — capability discovery without auth ──────────────────────────────────
|
|
105
|
+
app.head('/', (req, res) => {
|
|
106
|
+
const mcpProtocolVersion = req.headers['mcp-protocol-version'] || types_js_1.LATEST_PROTOCOL_VERSION;
|
|
107
|
+
res
|
|
108
|
+
.status(200)
|
|
109
|
+
.set('Content-Type', 'application/json')
|
|
110
|
+
.set('MCP-Protocol-Version', String(mcpProtocolVersion))
|
|
111
|
+
.end();
|
|
112
|
+
});
|
|
113
|
+
// ── POST — stateless MCP handler (one transport per request) ──────────────────
|
|
114
|
+
app.post('/', middleware_1.authErrorLogger, authWithAbsoluteMetadata, async (req, res) => {
|
|
115
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
116
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
117
|
+
sessionIdGenerator: undefined, // stateless: no mcp-session-id header emitted
|
|
118
|
+
enableJsonResponse: true,
|
|
119
|
+
});
|
|
120
|
+
(0, request_context_1.updateRequestContext)({ userId: (_c = (_b = (_a = req.auth) === null || _a === void 0 ? void 0 : _a.extra) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id });
|
|
121
|
+
const jsonRpcMethod = (_d = req.body) === null || _d === void 0 ? void 0 : _d.method;
|
|
122
|
+
const jsonRpcId = (_e = req.body) === null || _e === void 0 ? void 0 : _e.id;
|
|
123
|
+
const requestStartedAt = Date.now();
|
|
124
|
+
utils_1.logger.info('MCP_REQUEST_START', {
|
|
125
|
+
event: 'MCP_REQUEST_START',
|
|
126
|
+
jsonRpcMethod,
|
|
127
|
+
jsonRpcId,
|
|
128
|
+
toolName: (_g = (_f = req.body) === null || _f === void 0 ? void 0 : _f.params) === null || _g === void 0 ? void 0 : _g.name,
|
|
129
|
+
traceId: (0, request_context_1.getTraceId)(),
|
|
130
|
+
userId: (_k = (_j = (_h = req.auth) === null || _h === void 0 ? void 0 : _h.extra) === null || _j === void 0 ? void 0 : _j.user) === null || _k === void 0 ? void 0 : _k.id,
|
|
131
|
+
});
|
|
132
|
+
// Single-fire close guard so transport.close() is never called twice.
|
|
133
|
+
let transportClosed = false;
|
|
134
|
+
const closeTransport = () => {
|
|
135
|
+
if (!transportClosed) {
|
|
136
|
+
transportClosed = true;
|
|
137
|
+
transport.close();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
// If the client disconnects before the response is ready (e.g. its own
|
|
141
|
+
// 120 s timeout fires), close the transport immediately so the in-flight
|
|
142
|
+
// tool call is aborted rather than continuing to completion and then
|
|
143
|
+
// failing with MCP_TRANSPORT_SEND_ERROR.
|
|
144
|
+
const onClientClose = () => {
|
|
145
|
+
var _a, _b, _c;
|
|
146
|
+
if (!res.headersSent) {
|
|
147
|
+
utils_1.logger.warn('MCP_CLIENT_DISCONNECTED', {
|
|
148
|
+
event: 'MCP_CLIENT_DISCONNECTED',
|
|
149
|
+
jsonRpcMethod,
|
|
150
|
+
jsonRpcId,
|
|
151
|
+
elapsedMs: Date.now() - requestStartedAt,
|
|
152
|
+
traceId: (0, request_context_1.getTraceId)(),
|
|
153
|
+
userId: (_c = (_b = (_a = req.auth) === null || _a === void 0 ? void 0 : _a.extra) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id,
|
|
154
|
+
});
|
|
155
|
+
closeTransport();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
req.on('close', onClientClose);
|
|
159
|
+
const requestServer = (0, server_1.createMcpServer)();
|
|
160
|
+
try {
|
|
161
|
+
await requestServer.connect(transport);
|
|
162
|
+
await transport.handleRequest(req, res, req.body);
|
|
163
|
+
utils_1.logger.info('MCP_REQUEST_DONE', {
|
|
164
|
+
event: 'MCP_REQUEST_DONE',
|
|
165
|
+
jsonRpcMethod,
|
|
166
|
+
jsonRpcId,
|
|
167
|
+
elapsedMs: Date.now() - requestStartedAt,
|
|
168
|
+
traceId: (0, request_context_1.getTraceId)(),
|
|
169
|
+
userId: (_o = (_m = (_l = req.auth) === null || _l === void 0 ? void 0 : _l.extra) === null || _m === void 0 ? void 0 : _m.user) === null || _o === void 0 ? void 0 : _o.id,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
utils_1.logger.error('❌ Error handling MCP request (stateless)', {
|
|
174
|
+
error: {
|
|
175
|
+
message: error instanceof Error ? error.message : String(error),
|
|
176
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
177
|
+
},
|
|
178
|
+
jsonRpcMethod,
|
|
179
|
+
jsonRpcId,
|
|
180
|
+
userId: (_r = (_q = (_p = req.auth) === null || _p === void 0 ? void 0 : _p.extra) === null || _q === void 0 ? void 0 : _q.user) === null || _r === void 0 ? void 0 : _r.id,
|
|
181
|
+
traceId: (0, request_context_1.getTraceId)(),
|
|
182
|
+
});
|
|
183
|
+
if (!res.headersSent) {
|
|
184
|
+
res.status(500).json({
|
|
185
|
+
jsonrpc: '2.0',
|
|
186
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
187
|
+
id: jsonRpcId !== null && jsonRpcId !== void 0 ? jsonRpcId : null,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
req.off('close', onClientClose);
|
|
193
|
+
// StreamableHTTPServerTransport.handlePostRequest() returns before the MCP
|
|
194
|
+
// server calls transport.send(). enableJsonResponse mode sets Content-Type
|
|
195
|
+
// inside send(). Closing the transport here immediately would end res early
|
|
196
|
+
// with no body / no Content-Type → Cursor: "Unexpected content type: null".
|
|
197
|
+
try {
|
|
198
|
+
await (0, promises_1.finished)(res);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Client may have aborted; response may already be torn down.
|
|
202
|
+
}
|
|
203
|
+
closeTransport();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
// ── GET / DELETE — not applicable in stateless mode ───────────────────────────
|
|
207
|
+
const sseNotSupported = (req, res) => {
|
|
208
|
+
res.status(405).json({
|
|
209
|
+
jsonrpc: '2.0',
|
|
210
|
+
error: {
|
|
211
|
+
code: -32000,
|
|
212
|
+
message: 'This server runs in stateless mode. ' +
|
|
213
|
+
'SSE and session termination are not supported. Use POST for all MCP requests.',
|
|
214
|
+
},
|
|
215
|
+
id: null,
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
app.get('/', middleware_1.authErrorLogger, authWithAbsoluteMetadata, sseNotSupported);
|
|
219
|
+
app.delete('/', middleware_1.authErrorLogger, authWithAbsoluteMetadata, sseNotSupported);
|
|
220
|
+
// ── Shutdown ──────────────────────────────────────────────────────────────────
|
|
221
|
+
let heartbeatInterval;
|
|
222
|
+
function shutdown() {
|
|
223
|
+
utils_1.logger.info('🛑 Shutting down HTTP MCP Server (stateless)...');
|
|
224
|
+
if (heartbeatInterval)
|
|
225
|
+
clearInterval(heartbeatInterval);
|
|
226
|
+
process.exit(0);
|
|
227
|
+
}
|
|
228
|
+
process.on('SIGINT', shutdown);
|
|
229
|
+
process.on('SIGTERM', shutdown);
|
|
230
|
+
process.once('SIGUSR2', () => {
|
|
231
|
+
utils_1.logger.info('SIGUSR2 received, shutting down...');
|
|
232
|
+
shutdown();
|
|
233
|
+
process.kill(process.pid, 'SIGUSR2');
|
|
234
|
+
});
|
|
235
|
+
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
236
|
+
if (!(0, config_1.isTestEnvironment)()) {
|
|
237
|
+
const PORT = config_1.env.PORT || 3005;
|
|
238
|
+
const serverInstance = app.listen(PORT, async () => {
|
|
239
|
+
const status = await (0, cv_api_1.getCarbonVoiceApiStatus)();
|
|
240
|
+
carbonVoiceApiHealth = {
|
|
241
|
+
...status,
|
|
242
|
+
lastChecked: new Date().toISOString(),
|
|
243
|
+
};
|
|
244
|
+
utils_1.logger.info('🚀 HTTP MCP Server started (stateless mode)', {
|
|
245
|
+
port: PORT,
|
|
246
|
+
mode: 'stateless',
|
|
247
|
+
carbonVoiceApiHealth,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
serverInstance.on('error', (error) => {
|
|
251
|
+
utils_1.logger.error('❌ Error on MCP HTTP Server', { error });
|
|
252
|
+
});
|
|
253
|
+
process.on('uncaughtException', (error) => {
|
|
254
|
+
utils_1.logger.error('🚨 Uncaught Exception detected', {
|
|
255
|
+
error: error.message,
|
|
256
|
+
stack: error.stack,
|
|
257
|
+
name: error.name,
|
|
258
|
+
processId: process.pid,
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
262
|
+
utils_1.logger.error('🚨 Unhandled Promise Rejection detected', {
|
|
263
|
+
reason: reason instanceof Error ? reason.message : String(reason),
|
|
264
|
+
stack: reason instanceof Error ? reason.stack : undefined,
|
|
265
|
+
promise: promise.toString(),
|
|
266
|
+
processId: process.pid,
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
heartbeatInterval = setInterval(async () => {
|
|
270
|
+
const status = await (0, cv_api_1.getCarbonVoiceApiStatus)();
|
|
271
|
+
carbonVoiceApiHealth = {
|
|
272
|
+
isHealthy: status.isHealthy,
|
|
273
|
+
apiUrl: status.apiUrl,
|
|
274
|
+
lastChecked: new Date().toISOString(),
|
|
275
|
+
...(status.error && { error: status.error }),
|
|
276
|
+
};
|
|
277
|
+
const icon = carbonVoiceApiHealth.isHealthy ? '🟢' : '🔴';
|
|
278
|
+
utils_1.logger.info(`💓 Server heartbeat ${icon} (stateless)`, {
|
|
279
|
+
isCarbonVoiceApiWorking: carbonVoiceApiHealth.isHealthy,
|
|
280
|
+
uptime: (0, utils_1.getProcessUptime)(),
|
|
281
|
+
memoryUsage: process.memoryUsage(),
|
|
282
|
+
carbonVoiceApiHealth,
|
|
283
|
+
mode: 'stateless',
|
|
284
|
+
});
|
|
285
|
+
}, 30000);
|
|
286
|
+
}
|
|
287
|
+
exports.default = app;
|
|
288
|
+
//# sourceMappingURL=streamable-stateless.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamable-stateless.js","sourceRoot":"","sources":["../../../src/transports/http/streamable-stateless.ts"],"names":[],"mappings":"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"}
|