@j0hanz/fetch-url-mcp 1.12.6 → 1.12.7
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/http/auth.d.ts.map +1 -1
- package/dist/http/auth.js +12 -12
- package/dist/http/helpers.d.ts +1 -1
- package/dist/http/helpers.d.ts.map +1 -1
- package/dist/http/helpers.js +8 -10
- package/dist/http/native.d.ts.map +1 -1
- package/dist/http/native.js +32 -53
- package/dist/http/rate-limit.d.ts.map +1 -1
- package/dist/http/rate-limit.js +3 -3
- package/dist/index.js +3 -3
- package/dist/lib/core.d.ts.map +1 -1
- package/dist/lib/core.js +8 -8
- package/dist/lib/error-codes.d.ts +12 -10
- package/dist/lib/error-codes.d.ts.map +1 -1
- package/dist/lib/error-codes.js +12 -15
- package/dist/lib/error-messages.d.ts.map +1 -1
- package/dist/lib/error-messages.js +12 -12
- package/dist/lib/fetch-pipeline.d.ts.map +1 -1
- package/dist/lib/fetch-pipeline.js +5 -5
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +9 -9
- package/dist/lib/logger-names.d.ts +12 -10
- package/dist/lib/logger-names.d.ts.map +1 -1
- package/dist/lib/logger-names.js +12 -10
- package/dist/lib/mcp-interop.d.ts +1 -0
- package/dist/lib/mcp-interop.d.ts.map +1 -1
- package/dist/lib/mcp-interop.js +15 -5
- package/dist/lib/tool-errors.d.ts.map +1 -1
- package/dist/lib/tool-errors.js +22 -21
- package/dist/lib/url.d.ts +1 -1
- package/dist/lib/url.d.ts.map +1 -1
- package/dist/lib/url.js +5 -5
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +8 -5
- package/dist/resources/index.js +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +6 -6
- package/dist/tasks/execution.js +9 -9
- package/dist/tasks/handlers.js +7 -7
- package/dist/tasks/manager.d.ts.map +1 -1
- package/dist/tasks/manager.js +9 -9
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +10 -25
- package/dist/transform/dom-prep.d.ts.map +1 -1
- package/dist/transform/dom-prep.js +7 -7
- package/dist/transform/transform.d.ts.map +1 -1
- package/dist/transform/transform.js +18 -17
- package/dist/transform/worker-pool.js +11 -11
- package/package.json +1 -1
package/dist/http/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/http/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EACL,iBAAiB,EAElB,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAa/E,OAAO,EAEL,KAAK,cAAc,EAIpB,MAAM,cAAc,CAAC;AAMtB,cAAM,UAAU;IAId,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO;CAuBrC;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC;AAS3C,cAAM,sBAAuB,SAAQ,iBAAiB;IAElD,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE;gBAAjC,cAAc,EAAE,SAAS,MAAM,EAAE,EAC1C,OAAO,SAAuB;CAKjC;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,sBAAsB,CAEjC;AAwCD,cAAM,gBAAgB;IACpB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO;IA6BtC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,MAAM;CAoBf;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC;AAMvD,wBAAgB,2BAA2B,IAAI,IAAI,CAyBlD;AAMD,eAAO,MAAM,4BAA4B,eAAe,CAAC;AACzD,eAAO,MAAM,+BAA+B,aAE1C,CAAC;AAEH,UAAU,8BAA8B;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAUD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CA2DT;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAQD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,MAAM,GAAG,IAAI,CAWf;AAiBD,cAAM,WAAW;IACf,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAEjC;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA0C;IAEvE,YAAY,CAChB,GAAG,EAAE,eAAe,EACpB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,QAAQ,CAAC;IAwBpB,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,sBAAsB;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/http/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/http/auth.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
2
|
import { InvalidTokenError, ServerError, } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
3
3
|
import { config, logDebug, logWarn } from '../lib/core.js';
|
|
4
|
-
import {
|
|
4
|
+
import { Loggers } from '../lib/logger-names.js';
|
|
5
5
|
import { normalizeHost } from '../lib/url.js';
|
|
6
6
|
import { composeAbortSignal, hmacSha256Hex, isObject, parseUrlOrNull, timingSafeEqualUtf8, } from '../lib/utils.js';
|
|
7
7
|
import { getHeaderValue, sendEmpty, sendError, sendJson, } from './helpers.js';
|
|
@@ -261,7 +261,7 @@ class AuthService {
|
|
|
261
261
|
source,
|
|
262
262
|
clientId: info.clientId,
|
|
263
263
|
scopeCount: info.scopes.length,
|
|
264
|
-
}, LOG_AUTH);
|
|
264
|
+
}, Loggers.LOG_AUTH);
|
|
265
265
|
return info;
|
|
266
266
|
}
|
|
267
267
|
authenticateWithToken(token, signal) {
|
|
@@ -275,11 +275,11 @@ class AuthService {
|
|
|
275
275
|
return this.verifyStaticToken(apiKey);
|
|
276
276
|
}
|
|
277
277
|
if (apiKey && config.auth.mode === 'oauth') {
|
|
278
|
-
logWarn('Auth failed: X-API-Key not supported for OAuth', {}, LOG_AUTH);
|
|
278
|
+
logWarn('Auth failed: X-API-Key not supported for OAuth', {}, Loggers.LOG_AUTH);
|
|
279
279
|
const error = new InvalidTokenError('X-API-Key not supported for OAuth');
|
|
280
280
|
throw error;
|
|
281
281
|
}
|
|
282
|
-
logWarn('Auth failed: missing credentials', { authMode: config.auth.mode }, LOG_AUTH);
|
|
282
|
+
logWarn('Auth failed: missing credentials', { authMode: config.auth.mode }, Loggers.LOG_AUTH);
|
|
283
283
|
const error = new InvalidTokenError(config.auth.mode === 'static'
|
|
284
284
|
? 'Missing Authorization or X-API-Key header'
|
|
285
285
|
: 'Missing Authorization header');
|
|
@@ -314,7 +314,7 @@ class AuthService {
|
|
|
314
314
|
const tokenDigest = hmacSha256Hex(STATIC_TOKEN_HMAC_KEY, token);
|
|
315
315
|
const matched = hasConstantTimeMatch(this.staticTokenDigests, tokenDigest);
|
|
316
316
|
if (!matched) {
|
|
317
|
-
logWarn('Auth failed: invalid static token', {}, LOG_AUTH);
|
|
317
|
+
logWarn('Auth failed: invalid static token', {}, Loggers.LOG_AUTH);
|
|
318
318
|
const error = new InvalidTokenError('Invalid token');
|
|
319
319
|
throw error;
|
|
320
320
|
}
|
|
@@ -362,12 +362,12 @@ class AuthService {
|
|
|
362
362
|
.map((value) => this.canonicalizeResourceUri(value))
|
|
363
363
|
.filter((value) => value !== null);
|
|
364
364
|
if (audiences.length === 0) {
|
|
365
|
-
logWarn('Auth failed: token missing audience binding', {}, LOG_AUTH);
|
|
365
|
+
logWarn('Auth failed: token missing audience binding', {}, Loggers.LOG_AUTH);
|
|
366
366
|
const error = new InvalidTokenError('Token missing audience binding');
|
|
367
367
|
throw error;
|
|
368
368
|
}
|
|
369
369
|
if (!audiences.includes(expected)) {
|
|
370
|
-
logWarn('Auth failed: audience mismatch', {}, LOG_AUTH);
|
|
370
|
+
logWarn('Auth failed: audience mismatch', {}, Loggers.LOG_AUTH);
|
|
371
371
|
const error = new InvalidTokenError('Token audience does not match this MCP server');
|
|
372
372
|
throw error;
|
|
373
373
|
}
|
|
@@ -403,7 +403,7 @@ class AuthService {
|
|
|
403
403
|
if (response.body) {
|
|
404
404
|
await response.body.cancel();
|
|
405
405
|
}
|
|
406
|
-
logWarn('Token introspection HTTP error', { status: response.status }, LOG_AUTH);
|
|
406
|
+
logWarn('Token introspection HTTP error', { status: response.status }, Loggers.LOG_AUTH);
|
|
407
407
|
const error = new ServerError(`Token introspection failed: ${response.status}`);
|
|
408
408
|
throw error;
|
|
409
409
|
}
|
|
@@ -430,7 +430,7 @@ class AuthService {
|
|
|
430
430
|
const tokenScopeSet = new Set(tokenScopes);
|
|
431
431
|
const missing = requiredScopes.filter((s) => !tokenScopeSet.has(s));
|
|
432
432
|
if (missing.length > 0) {
|
|
433
|
-
logWarn('Auth failed: insufficient scopes', { missingCount: missing.length }, LOG_AUTH);
|
|
433
|
+
logWarn('Auth failed: insufficient scopes', { missingCount: missing.length }, Loggers.LOG_AUTH);
|
|
434
434
|
const error = new InsufficientScopeError(missing);
|
|
435
435
|
throw error;
|
|
436
436
|
}
|
|
@@ -445,21 +445,21 @@ class AuthService {
|
|
|
445
445
|
if (cached && cached.expiresAt > Date.now()) {
|
|
446
446
|
this.introspectionCache.delete(cacheKey);
|
|
447
447
|
this.introspectionCache.set(cacheKey, cached);
|
|
448
|
-
logDebug('Token introspection cache hit', {}, LOG_AUTH);
|
|
448
|
+
logDebug('Token introspection cache hit', {}, Loggers.LOG_AUTH);
|
|
449
449
|
return cached.info;
|
|
450
450
|
}
|
|
451
451
|
const req = this.buildIntrospectionRequest(token, config.auth.resourceUrl, config.auth.clientId, config.auth.clientSecret);
|
|
452
452
|
const payload = await this.requestIntrospection(config.auth.introspectionUrl, req, config.auth.introspectionTimeoutMs, signal);
|
|
453
453
|
if (!isObject(payload) || payload['active'] !== true) {
|
|
454
454
|
this.introspectionCache.delete(cacheKey);
|
|
455
|
-
logWarn('Auth failed: token inactive', {}, LOG_AUTH);
|
|
455
|
+
logWarn('Auth failed: token inactive', {}, Loggers.LOG_AUTH);
|
|
456
456
|
const error = new InvalidTokenError('Token is inactive');
|
|
457
457
|
throw error;
|
|
458
458
|
}
|
|
459
459
|
this.assertTokenAudience(payload);
|
|
460
460
|
const info = this.buildIntrospectionAuthInfo(token, payload);
|
|
461
461
|
this.assertRequiredScopes(info.scopes);
|
|
462
|
-
logDebug('Token introspection successful', { clientId: info.clientId }, LOG_AUTH);
|
|
462
|
+
logDebug('Token introspection successful', { clientId: info.clientId }, Loggers.LOG_AUTH);
|
|
463
463
|
this.evictStaleEntries();
|
|
464
464
|
this.introspectionCache.set(cacheKey, {
|
|
465
465
|
info,
|
package/dist/http/helpers.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface AuthenticatedContext extends RequestContext {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
22
22
|
export declare function sendEmpty(res: ServerResponse, status: number): void;
|
|
23
|
-
export declare function sendError(res: ServerResponse,
|
|
23
|
+
export declare function sendError(res: ServerResponse, _code: number, message: string, status?: number, _id?: JsonRpcId | null): void;
|
|
24
24
|
export declare function getHeaderValue(req: IncomingMessage, name: string): string | null;
|
|
25
25
|
export declare function getMcpSessionId(req: IncomingMessage): string | null;
|
|
26
26
|
export declare function findDuplicateSingleValueHeader(req: IncomingMessage): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/http/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,YAAY,CAAC;AAKxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACxG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAS/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQvD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;AAcjD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,IAAI,EAAE,QAAQ,CAAC;CAChB;AAWD,wBAAgB,QAAQ,CACtB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,IAAI,CAKN;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAInE;AAED,wBAAgB,SAAS,CACvB,GAAG,EAAE,cAAc,EACnB,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/http/helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/http/helpers.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Writable } from 'node:stream';
|
|
|
2
2
|
import { pipeline } from 'node:stream/promises';
|
|
3
3
|
import { composeCloseHandlers, config, logWarn } from '../lib/core.js';
|
|
4
4
|
import { resolveMcpSessionIdByServer, unregisterMcpSessionServer, unregisterMcpSessionServerByServer, } from '../lib/core.js';
|
|
5
|
-
import {
|
|
5
|
+
import { Loggers } from '../lib/logger-names.js';
|
|
6
6
|
import { createDefaultBlockList, normalizeIpForBlockList } from '../lib/url.js';
|
|
7
7
|
import { getErrorMessage, toError } from '../lib/utils.js';
|
|
8
8
|
function abortControllerBestEffort(controller) {
|
|
@@ -35,12 +35,10 @@ export function sendEmpty(res, status) {
|
|
|
35
35
|
res.setHeader('Content-Length', '0');
|
|
36
36
|
res.end();
|
|
37
37
|
}
|
|
38
|
-
export function sendError(res,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
id,
|
|
43
|
-
});
|
|
38
|
+
export function sendError(res, _code, message, status = 400,
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
40
|
+
_id = null) {
|
|
41
|
+
sendJson(res, status, { error: message });
|
|
44
42
|
}
|
|
45
43
|
// ---------------------------------------------------------------------------
|
|
46
44
|
// Request helpers
|
|
@@ -155,7 +153,7 @@ export function registerInboundBlockList(server) {
|
|
|
155
153
|
logWarn('Blocked inbound connection', {
|
|
156
154
|
remoteAddress: normalized.ip,
|
|
157
155
|
family: normalized.family,
|
|
158
|
-
}, LOG_HTTP);
|
|
156
|
+
}, Loggers.LOG_HTTP);
|
|
159
157
|
socket.destroy();
|
|
160
158
|
}
|
|
161
159
|
});
|
|
@@ -187,7 +185,7 @@ export async function closeTransportBestEffort(transport, context) {
|
|
|
187
185
|
await transport.close();
|
|
188
186
|
}
|
|
189
187
|
catch (error) {
|
|
190
|
-
logWarn('Transport close failed', { context, error }, LOG_HTTP);
|
|
188
|
+
logWarn('Transport close failed', { context, error }, Loggers.LOG_HTTP);
|
|
191
189
|
}
|
|
192
190
|
}
|
|
193
191
|
export async function closeMcpServerBestEffort(server, context) {
|
|
@@ -195,7 +193,7 @@ export async function closeMcpServerBestEffort(server, context) {
|
|
|
195
193
|
await server.close();
|
|
196
194
|
}
|
|
197
195
|
catch (error) {
|
|
198
|
-
logWarn('MCP server close failed', { context, error }, LOG_HTTP);
|
|
196
|
+
logWarn('MCP server close failed', { context, error }, Loggers.LOG_HTTP);
|
|
199
197
|
}
|
|
200
198
|
}
|
|
201
199
|
export function createTransportAdapter(transportImpl) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/http/native.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/http/native.ts"],"names":[],"mappings":"AAy8CA,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CA2DD"}
|
package/dist/http/native.js
CHANGED
|
@@ -8,8 +8,8 @@ import process from 'node:process';
|
|
|
8
8
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
9
9
|
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
10
10
|
import { composeCloseHandlers, config, createSessionStore, createSlotTracker, enableHttpMode, ensureSessionCapacity, logDebug, logError, logInfo, logWarn, registerMcpSessionOwnerKey, registerMcpSessionServer, reserveSessionSlot, runWithRequestContext, startSessionCleanupLoop, } from '../lib/core.js';
|
|
11
|
-
import {
|
|
12
|
-
import { acceptsEventStream, acceptsJsonAndEventStream,
|
|
11
|
+
import { Loggers } from '../lib/logger-names.js';
|
|
12
|
+
import { acceptsEventStream, acceptsJsonAndEventStream, isMcpRequestBody, } from '../lib/mcp-interop.js';
|
|
13
13
|
import { applyHttpServerTuning, drainConnectionsOnShutdown, isObject, toError, } from '../lib/utils.js';
|
|
14
14
|
import { createMcpServerForHttpSession } from '../server.js';
|
|
15
15
|
import { buildAuthenticatedOwnerKey } from '../tasks/owner.js';
|
|
@@ -56,7 +56,7 @@ function logGatewayRejection(params) {
|
|
|
56
56
|
...rest,
|
|
57
57
|
...(rpcId === null || rpcId === undefined ? {} : { rpcId }),
|
|
58
58
|
...(details ?? {}),
|
|
59
|
-
}, LOG_HTTP);
|
|
59
|
+
}, Loggers.LOG_HTTP);
|
|
60
60
|
}
|
|
61
61
|
function resolveRequestPath(req) {
|
|
62
62
|
return URL.parse(req.url ?? '', 'http://localhost')?.pathname ?? '/';
|
|
@@ -71,14 +71,14 @@ function logRequestCompletion(params) {
|
|
|
71
71
|
...(params.sessionId ? { sessionId: params.sessionId } : {}),
|
|
72
72
|
};
|
|
73
73
|
if (params.statusCode >= 500) {
|
|
74
|
-
logError('HTTP request failed with server error', meta, LOG_HTTP);
|
|
74
|
+
logError('HTTP request failed with server error', meta, Loggers.LOG_HTTP);
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
if (params.statusCode >= 400) {
|
|
78
|
-
logWarn('HTTP client error', meta, LOG_HTTP);
|
|
78
|
+
logWarn('HTTP client error', meta, Loggers.LOG_HTTP);
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
logDebug('HTTP request completed', meta, LOG_HTTP);
|
|
81
|
+
logDebug('HTTP request completed', meta, Loggers.LOG_HTTP);
|
|
82
82
|
}
|
|
83
83
|
function createSessionTeardownOptions(mode, context) {
|
|
84
84
|
switch (mode) {
|
|
@@ -137,7 +137,7 @@ class McpSessionGateway {
|
|
|
137
137
|
method: method ?? 'response',
|
|
138
138
|
rpcId: body.id,
|
|
139
139
|
sessionId,
|
|
140
|
-
}, LOG_HTTP);
|
|
140
|
+
}, Loggers.LOG_HTTP);
|
|
141
141
|
const transport = await this.getOrCreateTransport(ctx, requestId);
|
|
142
142
|
if (!transport)
|
|
143
143
|
return;
|
|
@@ -165,7 +165,7 @@ class McpSessionGateway {
|
|
|
165
165
|
});
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
|
-
logDebug('MCP GET received', { sessionId }, LOG_HTTP);
|
|
168
|
+
logDebug('MCP GET received', { sessionId }, Loggers.LOG_HTTP);
|
|
169
169
|
this.store.touch(sessionId);
|
|
170
170
|
await session.transport.handleRequest(ctx.req, ctx.res);
|
|
171
171
|
}
|
|
@@ -177,7 +177,7 @@ class McpSessionGateway {
|
|
|
177
177
|
return;
|
|
178
178
|
const { sessionId, session } = sessionState;
|
|
179
179
|
await session.transport.close();
|
|
180
|
-
logDebug('MCP DELETE received', { sessionId }, LOG_HTTP);
|
|
180
|
+
logDebug('MCP DELETE received', { sessionId }, Loggers.LOG_HTTP);
|
|
181
181
|
this.cleanupSessionRecord(sessionId, createSessionTeardownOptions('ended', 'session-delete'));
|
|
182
182
|
sendJson(ctx.res, 200, { status: 'closed' });
|
|
183
183
|
}
|
|
@@ -196,31 +196,10 @@ class McpSessionGateway {
|
|
|
196
196
|
return null;
|
|
197
197
|
}
|
|
198
198
|
const { body } = ctx;
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
message: 'Rejected MCP POST request',
|
|
202
|
-
method: ctx.method,
|
|
203
|
-
path: ctx.url.pathname,
|
|
204
|
-
reason: 'batch_request_not_supported',
|
|
205
|
-
status: 400,
|
|
206
|
-
mcpCode: -32600,
|
|
207
|
-
});
|
|
208
|
-
sendError(ctx.res, -32600, "We don't support batch requests yet. Please send one request at a time.");
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
if (!isMcpMessageBody(body)) {
|
|
212
|
-
logGatewayRejection({
|
|
213
|
-
message: 'Rejected MCP POST request',
|
|
214
|
-
method: ctx.method,
|
|
215
|
-
path: ctx.url.pathname,
|
|
216
|
-
reason: 'invalid_request_body',
|
|
217
|
-
status: 400,
|
|
218
|
-
mcpCode: -32600,
|
|
219
|
-
});
|
|
220
|
-
sendError(ctx.res, -32600, "The request body isn't quite right. Please check the format and try again.");
|
|
221
|
-
return null;
|
|
199
|
+
if (isObject(body) && !Array.isArray(body)) {
|
|
200
|
+
return body;
|
|
222
201
|
}
|
|
223
|
-
return
|
|
202
|
+
return { id: undefined, method: undefined };
|
|
224
203
|
}
|
|
225
204
|
resolvePostRequestState(ctx, body) {
|
|
226
205
|
const requestId = body.id ?? null;
|
|
@@ -444,7 +423,7 @@ class McpSessionGateway {
|
|
|
444
423
|
this.clearSessionInitTimeout(sessionId);
|
|
445
424
|
if (sessionId)
|
|
446
425
|
this.store.touch(sessionId);
|
|
447
|
-
logDebug('Session initialized', { sessionId }, LOG_SESSION);
|
|
426
|
+
logDebug('Session initialized', { sessionId }, Loggers.LOG_SESSION);
|
|
448
427
|
}
|
|
449
428
|
createSessionInitTimeout(sessionId, tracker, unpublishedSession) {
|
|
450
429
|
const initTimeout = setTimeout(() => {
|
|
@@ -454,11 +433,11 @@ class McpSessionGateway {
|
|
|
454
433
|
this.clearSessionInitTimeout(sessionId);
|
|
455
434
|
return;
|
|
456
435
|
}
|
|
457
|
-
logWarn('Session init timeout', { sessionId }, LOG_SESSION);
|
|
436
|
+
logWarn('Session init timeout', { sessionId }, Loggers.LOG_SESSION);
|
|
458
437
|
this.cleanupSessionRecord(sessionId, createSessionTeardownOptions('init-timeout'));
|
|
459
438
|
return;
|
|
460
439
|
}
|
|
461
|
-
logWarn('Session init timeout before registration completed', { sessionId }, LOG_SESSION);
|
|
440
|
+
logWarn('Session init timeout before registration completed', { sessionId }, Loggers.LOG_SESSION);
|
|
462
441
|
tracker.releaseSlot();
|
|
463
442
|
void teardownUnregisteredSessionResources(unpublishedSession, 'session-init-timeout');
|
|
464
443
|
}, config.server.sessionInitTimeoutMs);
|
|
@@ -481,7 +460,7 @@ class McpSessionGateway {
|
|
|
481
460
|
logWarn('Session transport connect failed', {
|
|
482
461
|
sessionId,
|
|
483
462
|
error: toError(err).message,
|
|
484
|
-
}, LOG_SESSION);
|
|
463
|
+
}, Loggers.LOG_SESSION);
|
|
485
464
|
clearTimeout(initTimeout);
|
|
486
465
|
tracker.releaseSlot();
|
|
487
466
|
void teardownUnregisteredSessionResources(unpublishedSession, 'session-connect-failed');
|
|
@@ -495,7 +474,7 @@ class McpSessionGateway {
|
|
|
495
474
|
logError('Session creation failed: missing auth context', {
|
|
496
475
|
path: ctx.url.pathname,
|
|
497
476
|
method: ctx.method,
|
|
498
|
-
}, LOG_SESSION);
|
|
477
|
+
}, Loggers.LOG_SESSION);
|
|
499
478
|
sendError(ctx.res, -32603, "We're missing some authorization details to process this request.", 500, requestId);
|
|
500
479
|
return null;
|
|
501
480
|
}
|
|
@@ -504,7 +483,7 @@ class McpSessionGateway {
|
|
|
504
483
|
logError('Session creation failed: missing task owner context', {
|
|
505
484
|
path: ctx.url.pathname,
|
|
506
485
|
method: ctx.method,
|
|
507
|
-
}, LOG_SESSION);
|
|
486
|
+
}, Loggers.LOG_SESSION);
|
|
508
487
|
sendError(ctx.res, -32603, "We're missing the owner information needed to authorize this request.", 500, requestId);
|
|
509
488
|
return null;
|
|
510
489
|
}
|
|
@@ -517,7 +496,7 @@ class McpSessionGateway {
|
|
|
517
496
|
sessionServer = await this.createSessionServer();
|
|
518
497
|
}
|
|
519
498
|
catch (error) {
|
|
520
|
-
logError('Session server creation failed', { sessionId: newSessionId, error: toError(error).message }, LOG_SESSION);
|
|
499
|
+
logError('Session server creation failed', { sessionId: newSessionId, error: toError(error).message }, Loggers.LOG_SESSION);
|
|
521
500
|
tracker.releaseSlot();
|
|
522
501
|
throw error;
|
|
523
502
|
}
|
|
@@ -532,7 +511,7 @@ class McpSessionGateway {
|
|
|
532
511
|
const isConnected = await this.connectTransport(sessionServer, transportImpl, initTimeout, tracker, unpublishedSession, newSessionId);
|
|
533
512
|
tracker.releaseSlot();
|
|
534
513
|
if (!isConnected) {
|
|
535
|
-
logWarn('Session closed before registration completed', { sessionId: newSessionId }, LOG_SESSION);
|
|
514
|
+
logWarn('Session closed before registration completed', { sessionId: newSessionId }, Loggers.LOG_SESSION);
|
|
536
515
|
void teardownUnregisteredSessionResources(unpublishedSession, 'session-closed-during-connect');
|
|
537
516
|
return null;
|
|
538
517
|
}
|
|
@@ -548,7 +527,7 @@ class McpSessionGateway {
|
|
|
548
527
|
this.sessionInitTimeouts.set(newSessionId, initTimeout);
|
|
549
528
|
registerMcpSessionOwnerKey(newSessionId, ownerKey);
|
|
550
529
|
registerMcpSessionServer(newSessionId, sessionServer);
|
|
551
|
-
logInfo('Session created', { sessionId: newSessionId, negotiatedProtocolVersion }, LOG_SESSION);
|
|
530
|
+
logInfo('Session created', { sessionId: newSessionId, negotiatedProtocolVersion }, Loggers.LOG_SESSION);
|
|
552
531
|
transportImpl.onclose = composeCloseHandlers(transportImpl.onclose, () => {
|
|
553
532
|
this.cleanupSessionRecord(newSessionId, createSessionTeardownOptions('ended', 'session-close'));
|
|
554
533
|
});
|
|
@@ -558,7 +537,7 @@ class McpSessionGateway {
|
|
|
558
537
|
const context = teardownOptions.closeTransportReason ??
|
|
559
538
|
teardownOptions.closeServerReason ??
|
|
560
539
|
'session';
|
|
561
|
-
logDebug('Session cleanup', { sessionId, context }, LOG_SESSION);
|
|
540
|
+
logDebug('Session cleanup', { sessionId, context }, Loggers.LOG_SESSION);
|
|
562
541
|
this.clearSessionInitTimeout(sessionId);
|
|
563
542
|
const session = this.store.remove(sessionId);
|
|
564
543
|
if (!session)
|
|
@@ -588,13 +567,13 @@ class McpSessionGateway {
|
|
|
588
567
|
},
|
|
589
568
|
});
|
|
590
569
|
if (!allowed) {
|
|
591
|
-
logWarn('Session capacity exhausted', { maxSessions: config.server.maxSessions }, LOG_SESSION);
|
|
570
|
+
logWarn('Session capacity exhausted', { maxSessions: config.server.maxSessions }, Loggers.LOG_SESSION);
|
|
592
571
|
sendError(res, -32000, 'The server is currently too busy to handle your request. Please try again in a little while.', 503, requestId);
|
|
593
572
|
return false;
|
|
594
573
|
}
|
|
595
574
|
// Double-check: capacity may have changed during the async eviction window above.
|
|
596
575
|
if (!reserveSessionSlot(this.store, config.server.maxSessions)) {
|
|
597
|
-
logWarn('Session capacity exhausted (post-eviction)', { maxSessions: config.server.maxSessions }, LOG_SESSION);
|
|
576
|
+
logWarn('Session capacity exhausted (post-eviction)', { maxSessions: config.server.maxSessions }, Loggers.LOG_SESSION);
|
|
598
577
|
sendError(res, -32000, 'The server is currently too busy to handle your request. Please try again in a little while.', 503, requestId);
|
|
599
578
|
return false;
|
|
600
579
|
}
|
|
@@ -662,7 +641,7 @@ class HttpDispatcher {
|
|
|
662
641
|
}
|
|
663
642
|
catch (err) {
|
|
664
643
|
const error = toError(err);
|
|
665
|
-
logError('Request failed', error, LOG_HTTP);
|
|
644
|
+
logError('Request failed', error, Loggers.LOG_HTTP);
|
|
666
645
|
if (!ctx.res.writableEnded) {
|
|
667
646
|
sendJson(ctx.res, 500, {
|
|
668
647
|
error: "Something went wrong on our end. We're looking into it!",
|
|
@@ -691,7 +670,7 @@ class HttpDispatcher {
|
|
|
691
670
|
}
|
|
692
671
|
catch (err) {
|
|
693
672
|
const message = err instanceof Error ? err.message : 'Unauthorized';
|
|
694
|
-
logWarn('Authentication failed', { message, method: ctx.method, path: ctx.url.pathname }, LOG_AUTH);
|
|
673
|
+
logWarn('Authentication failed', { message, method: ctx.method, path: ctx.url.pathname }, Loggers.LOG_AUTH);
|
|
695
674
|
if (isInsufficientScopeError(err)) {
|
|
696
675
|
applyInsufficientScopeAuthHeaders(ctx.req, ctx.res, err.requiredScopes, message);
|
|
697
676
|
sendError(ctx.res, -32000, message, 403);
|
|
@@ -839,10 +818,10 @@ class HttpRequestPipeline {
|
|
|
839
818
|
catch (error) {
|
|
840
819
|
const bodyErrorKind = isJsonBodyError(error) ? error.kind : null;
|
|
841
820
|
if (bodyErrorKind === 'payload-too-large') {
|
|
842
|
-
logWarn('The request body is too large. Please send a smaller payload.', { method: ctx.method, path: ctx.url.pathname }, LOG_HTTP);
|
|
821
|
+
logWarn('The request body is too large. Please send a smaller payload.', { method: ctx.method, path: ctx.url.pathname }, Loggers.LOG_HTTP);
|
|
843
822
|
}
|
|
844
823
|
else if (bodyErrorKind === 'read-failed' || bodyErrorKind === null) {
|
|
845
|
-
logError('Request body parsing failed', toError(error), LOG_HTTP);
|
|
824
|
+
logError('Request body parsing failed', toError(error), Loggers.LOG_HTTP);
|
|
846
825
|
}
|
|
847
826
|
sendBodyParseError(ctx, bodyErrorKind, rawReq);
|
|
848
827
|
return false;
|
|
@@ -864,7 +843,7 @@ class HttpRequestPipeline {
|
|
|
864
843
|
// Server bootstrap
|
|
865
844
|
// ---------------------------------------------------------------------------
|
|
866
845
|
function handlePipelineError(error, res) {
|
|
867
|
-
logError('Request pipeline failed', toError(error), LOG_HTTP);
|
|
846
|
+
logError('Request pipeline failed', toError(error), Loggers.LOG_HTTP);
|
|
868
847
|
if (res.writableEnded)
|
|
869
848
|
return;
|
|
870
849
|
if (!res.headersSent) {
|
|
@@ -912,7 +891,7 @@ function resolveListeningPort(server, fallback) {
|
|
|
912
891
|
function createShutdownHandler(options) {
|
|
913
892
|
const closeBatchSize = 10;
|
|
914
893
|
return async (signal) => {
|
|
915
|
-
logInfo(`Stopping HTTP server (${signal})...`, undefined, LOG_HTTP);
|
|
894
|
+
logInfo(`Stopping HTTP server (${signal})...`, undefined, Loggers.LOG_HTTP);
|
|
916
895
|
options.rateLimiter.stop();
|
|
917
896
|
options.sessionCleanup.abort();
|
|
918
897
|
drainConnectionsOnShutdown(options.server);
|
|
@@ -925,7 +904,7 @@ function createShutdownHandler(options) {
|
|
|
925
904
|
}));
|
|
926
905
|
for (const r of results) {
|
|
927
906
|
if (r.status === 'rejected') {
|
|
928
|
-
logError('Session teardown failed during shutdown', r.reason instanceof Error ? r.reason : undefined, LOG_HTTP);
|
|
907
|
+
logError('Session teardown failed during shutdown', r.reason instanceof Error ? r.reason : undefined, Loggers.LOG_HTTP);
|
|
929
908
|
}
|
|
930
909
|
}
|
|
931
910
|
}
|
|
@@ -961,7 +940,7 @@ export async function startHttpServer() {
|
|
|
961
940
|
arch: process.arch,
|
|
962
941
|
hostname: hostname(),
|
|
963
942
|
nodeVersion: process.version,
|
|
964
|
-
}, LOG_HTTP);
|
|
943
|
+
}, Loggers.LOG_HTTP);
|
|
965
944
|
return {
|
|
966
945
|
port,
|
|
967
946
|
host: config.server.host,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,cAAc,EAAY,MAAM,cAAc,CAAC;AAY7D,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IACpC,IAAI,IAAI,IAAI,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,cAAc,EAAY,MAAM,cAAc,CAAC;AAY7D,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IACpC,IAAI,IAAI,IAAI,CAAC;CACd;AA+FD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,eAAe,GACvB,oBAAoB,CAGtB"}
|
package/dist/http/rate-limit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logWarn } from '../lib/core.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Loggers } from '../lib/logger-names.js';
|
|
3
3
|
import { isAbortError } from '../lib/utils.js';
|
|
4
4
|
import { startAbortableIntervalLoop } from '../lib/utils.js';
|
|
5
5
|
import { sendJson } from './helpers.js';
|
|
@@ -22,7 +22,7 @@ class RateLimiter {
|
|
|
22
22
|
},
|
|
23
23
|
onError: (err) => {
|
|
24
24
|
if (!isAbortError(err)) {
|
|
25
|
-
logWarn('Rate limit cleanup failed', { error: err }, LOG_RATE_LIMIT);
|
|
25
|
+
logWarn('Rate limit cleanup failed', { error: err }, Loggers.LOG_RATE_LIMIT);
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
});
|
|
@@ -72,7 +72,7 @@ class RateLimiter {
|
|
|
72
72
|
this.store.set(key, entry);
|
|
73
73
|
}
|
|
74
74
|
if (entry.count > this.options.maxRequests) {
|
|
75
|
-
logWarn('Rate limit exceeded', { ip: key }, LOG_RATE_LIMIT);
|
|
75
|
+
logWarn('Rate limit exceeded', { ip: key }, Loggers.LOG_RATE_LIMIT);
|
|
76
76
|
const retryAfter = Math.max(1, Math.ceil((entry.resetTime - now) / 1000));
|
|
77
77
|
ctx.res.setHeader('Retry-After', String(retryAfter));
|
|
78
78
|
sendJson(ctx.res, 429, { error: 'Rate limit exceeded', retryAfter });
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import process from 'node:process';
|
|
3
3
|
import { serverVersion } from './lib/core.js';
|
|
4
4
|
import { logError } from './lib/core.js';
|
|
5
|
-
import {
|
|
5
|
+
import { Loggers } from './lib/logger-names.js';
|
|
6
6
|
import { toError } from './lib/utils.js';
|
|
7
7
|
import { parseCliArgs, renderCliUsage } from './cli.js';
|
|
8
8
|
import { startHttpServer } from './http/native.js';
|
|
@@ -61,13 +61,13 @@ function registerHttpSignalHandlers() {
|
|
|
61
61
|
registerSignalHandlers(['SIGINT', 'SIGTERM'], tryShutdown);
|
|
62
62
|
}
|
|
63
63
|
function writeStartupError(error) {
|
|
64
|
-
logError('Failed to start server', error, LOG_SERVER);
|
|
64
|
+
logError('Failed to start server', error, Loggers.LOG_SERVER);
|
|
65
65
|
process.stderr.write(`Failed to start server: ${error.message}\n`);
|
|
66
66
|
process.exitCode = 1;
|
|
67
67
|
scheduleForcedExit('Startup failure');
|
|
68
68
|
}
|
|
69
69
|
function handleFatalError(label, error, signal) {
|
|
70
|
-
logError(label, error, LOG_SERVER);
|
|
70
|
+
logError(label, error, Loggers.LOG_SERVER);
|
|
71
71
|
process.stderr.write(`${label}: ${error.message}\n`);
|
|
72
72
|
process.exitCode = 1;
|
|
73
73
|
if (shouldAttemptShutdown()) {
|
package/dist/lib/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/lib/core.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAOjD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYpE,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,UAAU,cAAc;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AA6BD,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAKpD;AACD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,GAChB,IAAI,CAGN;AACD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI,CAGN;AACD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAKlE;AACD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAO1E;AACD,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAEpB;AACD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,GAChB,MAAM,GAAG,SAAS,CAKpB;AACD,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAEH;AAID,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAGjD;AACD,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AACD,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAEnD;AAscD,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAEN;AACD,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAEN;AACD,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAEN;AACD,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAEN;AAcD,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,GAAG,WAAW,EAC3B,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAIN;AACD,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,GAAG,WAAW,EAC3B,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAIN;AACD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAUnE;AACD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQhD;AACD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/lib/core.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/core.js
CHANGED
|
@@ -3,7 +3,7 @@ import process from 'node:process';
|
|
|
3
3
|
import { getSystemErrorMessage, inspect, stripVTControlCharacters, } from 'node:util';
|
|
4
4
|
import {} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
5
|
import { config } from './config.js';
|
|
6
|
-
import {
|
|
6
|
+
import { Loggers } from './logger-names.js';
|
|
7
7
|
import { getErrorMessage, isAbortError, startAbortableIntervalLoop, } from './utils.js';
|
|
8
8
|
export { config, enableHttpMode, serverVersion } from './config.js';
|
|
9
9
|
const requestContext = new AsyncLocalStorage({
|
|
@@ -513,12 +513,12 @@ function getCleanupIntervalMs(sessionTtlMs) {
|
|
|
513
513
|
function handleSessionCleanupError(error) {
|
|
514
514
|
if (isAbortError(error))
|
|
515
515
|
return;
|
|
516
|
-
logWarn('Session cleanup loop failed', { error: getErrorMessage(error) }, LOG_SESSION);
|
|
516
|
+
logWarn('Session cleanup loop failed', { error: getErrorMessage(error) }, Loggers.LOG_SESSION);
|
|
517
517
|
}
|
|
518
518
|
function logRejectedSettledResults(results, message) {
|
|
519
519
|
for (const result of results) {
|
|
520
520
|
if (result.status === 'rejected') {
|
|
521
|
-
logWarn(message, { error: getErrorMessage(result.reason) }, LOG_SESSION);
|
|
521
|
+
logWarn(message, { error: getErrorMessage(result.reason) }, Loggers.LOG_SESSION);
|
|
522
522
|
}
|
|
523
523
|
}
|
|
524
524
|
}
|
|
@@ -558,7 +558,7 @@ class SessionCleanupLoop {
|
|
|
558
558
|
logInfo('Expired sessions evicted', {
|
|
559
559
|
evicted: evicted.length,
|
|
560
560
|
timestamp: new Date(now).toISOString(),
|
|
561
|
-
}, LOG_SESSION);
|
|
561
|
+
}, Loggers.LOG_SESSION);
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
async closeExpiredSession(sessionId, session) {
|
|
@@ -569,7 +569,7 @@ class SessionCleanupLoop {
|
|
|
569
569
|
catch (error) {
|
|
570
570
|
logWarn('Expired session pre-close hook failed', {
|
|
571
571
|
error: getErrorMessage(error),
|
|
572
|
-
}, LOG_SESSION);
|
|
572
|
+
}, Loggers.LOG_SESSION);
|
|
573
573
|
}
|
|
574
574
|
}
|
|
575
575
|
const closePromise = Promise.allSettled([
|
|
@@ -598,7 +598,7 @@ class SessionCleanupLoop {
|
|
|
598
598
|
catch (error) {
|
|
599
599
|
logWarn('Session close operation failed or timed out', {
|
|
600
600
|
error: getErrorMessage(error),
|
|
601
|
-
}, LOG_SESSION);
|
|
601
|
+
}, Loggers.LOG_SESSION);
|
|
602
602
|
}
|
|
603
603
|
finally {
|
|
604
604
|
if (timeoutId) {
|
|
@@ -611,7 +611,7 @@ class SessionCleanupLoop {
|
|
|
611
611
|
catch (error) {
|
|
612
612
|
logWarn('Failed to unregister session server', {
|
|
613
613
|
error: getErrorMessage(error),
|
|
614
|
-
}, LOG_SESSION);
|
|
614
|
+
}, Loggers.LOG_SESSION);
|
|
615
615
|
}
|
|
616
616
|
}
|
|
617
617
|
logCloseFailure(target, error) {
|
|
@@ -619,7 +619,7 @@ class SessionCleanupLoop {
|
|
|
619
619
|
return;
|
|
620
620
|
logWarn(`Failed to close expired session ${target}`, {
|
|
621
621
|
error: getErrorMessage(error),
|
|
622
|
-
}, LOG_SESSION);
|
|
622
|
+
}, Loggers.LOG_SESSION);
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
625
|
export function startSessionCleanupLoop(store, sessionTtlMs, options) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
export declare const SystemErrors: {
|
|
2
|
+
readonly EBLOCKED: "EBLOCKED";
|
|
3
|
+
readonly ETIMEOUT: "ETIMEOUT";
|
|
4
|
+
readonly EINVAL: "EINVAL";
|
|
5
|
+
readonly ENODATA: "ENODATA";
|
|
6
|
+
readonly EBADREDIRECT: "EBADREDIRECT";
|
|
7
|
+
readonly EUNSUPPORTEDPROTOCOL: "EUNSUPPORTEDPROTOCOL";
|
|
8
|
+
readonly FETCH_ERROR: "FETCH_ERROR";
|
|
9
|
+
readonly ABORTED: "ABORTED";
|
|
10
|
+
readonly QUEUE_FULL: "queue_full";
|
|
11
|
+
readonly VALIDATION_ERROR: "VALIDATION_ERROR";
|
|
12
|
+
};
|
|
11
13
|
//# sourceMappingURL=error-codes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/lib/error-codes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/lib/error-codes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC"}
|