@j0hanz/fetch-url-mcp 1.12.9 → 1.12.11
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/README.md +2 -0
- package/dist/http/auth.d.ts +4 -9
- package/dist/http/auth.d.ts.map +1 -1
- package/dist/http/auth.js +18 -26
- package/dist/http/native.d.ts +4 -1
- package/dist/http/native.d.ts.map +1 -1
- package/dist/http/native.js +127 -97
- package/dist/http/rate-limit.d.ts +12 -9
- package/dist/http/rate-limit.d.ts.map +1 -1
- package/dist/http/rate-limit.js +12 -9
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +4 -2
- package/dist/lib/core.d.ts +11 -1
- package/dist/lib/core.d.ts.map +1 -1
- package/dist/lib/core.js +166 -86
- package/dist/lib/error/classes.d.ts.map +1 -1
- package/dist/lib/error/classes.js +4 -2
- package/dist/lib/error/classify.d.ts.map +1 -1
- package/dist/lib/error/classify.js +20 -16
- package/dist/lib/mcp-interop.d.ts +12 -0
- package/dist/lib/mcp-interop.d.ts.map +1 -1
- package/dist/lib/mcp-interop.js +20 -2
- package/dist/lib/net/pipeline.d.ts.map +1 -1
- package/dist/lib/net/pipeline.js +8 -8
- package/dist/lib/net/url.d.ts +0 -1
- package/dist/lib/net/url.d.ts.map +1 -1
- package/dist/lib/net/url.js +7 -5
- package/dist/lib/utils.d.ts +0 -2
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +3 -8
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +46 -21
- package/dist/schemas.d.ts +9 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/tasks/manager.d.ts +9 -106
- package/dist/tasks/manager.d.ts.map +1 -1
- package/dist/tasks/manager.js +189 -553
- package/dist/tasks/store.d.ts +104 -0
- package/dist/tasks/store.d.ts.map +1 -0
- package/dist/tasks/store.js +480 -0
- package/dist/tools/index.js +3 -3
- package/dist/transform/index.d.ts +1 -85
- package/dist/transform/index.d.ts.map +1 -1
- package/dist/transform/index.js +310 -941
- package/dist/transform/worker-pool.d.ts +19 -0
- package/dist/transform/worker-pool.d.ts.map +1 -0
- package/dist/transform/worker-pool.js +716 -0
- package/package.json +3 -1
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RequestContext } from './native.js';
|
|
2
2
|
interface RateLimitConfig {
|
|
3
3
|
maxRequests: number;
|
|
4
4
|
windowMs: number;
|
|
5
5
|
cleanupIntervalMs: number;
|
|
6
6
|
enabled: boolean;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
export declare class RateLimiter {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly cleanup;
|
|
12
|
+
constructor(options: RateLimitConfig);
|
|
13
|
+
private startCleanupLoop;
|
|
14
|
+
private cleanupEntries;
|
|
15
|
+
private resetEntry;
|
|
16
|
+
private incrementEntry;
|
|
17
|
+
private createEntry;
|
|
18
|
+
check(ctx: RequestContext): boolean;
|
|
15
19
|
stop(): void;
|
|
16
20
|
}
|
|
17
|
-
export declare function createRateLimitManagerImpl(options: RateLimitConfig): RateLimitManagerImpl;
|
|
18
21
|
export {};
|
|
19
22
|
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAYlD,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAcD,qBAAa,WAAW;IAIV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAEpB,OAAO,EAAE,eAAe;IAIrD,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,WAAW;IAQnB,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO;IAyCnC,IAAI,IAAI,IAAI;CAGb"}
|
package/dist/http/rate-limit.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
1
2
|
import { Loggers, logWarn } from '../lib/core.js';
|
|
2
3
|
import { isAbortError } from '../lib/error/index.js';
|
|
4
|
+
import { sendJsonRpcError } from '../lib/mcp-interop.js';
|
|
3
5
|
import { startAbortableIntervalLoop } from '../lib/utils.js';
|
|
4
6
|
function sendJson(res, status, body) {
|
|
5
7
|
res.statusCode = status;
|
|
@@ -8,10 +10,10 @@ function sendJson(res, status, body) {
|
|
|
8
10
|
res.setHeader('Cache-Control', 'no-store');
|
|
9
11
|
res.end(JSON.stringify(body));
|
|
10
12
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class RateLimiter {
|
|
13
|
+
function isMcpEndpoint(pathname) {
|
|
14
|
+
return pathname === '/mcp' || pathname === '/mcp/';
|
|
15
|
+
}
|
|
16
|
+
export class RateLimiter {
|
|
15
17
|
options;
|
|
16
18
|
store = new Map();
|
|
17
19
|
cleanup = new AbortController();
|
|
@@ -80,7 +82,12 @@ class RateLimiter {
|
|
|
80
82
|
logWarn('Rate limit exceeded', { ip: key }, Loggers.LOG_RATE_LIMIT);
|
|
81
83
|
const retryAfter = Math.max(1, Math.ceil((entry.resetTime - now) / 1000));
|
|
82
84
|
ctx.res.setHeader('Retry-After', String(retryAfter));
|
|
83
|
-
|
|
85
|
+
if (isMcpEndpoint(ctx.url.pathname)) {
|
|
86
|
+
sendJsonRpcError(ctx.res, 429, ErrorCode.InvalidRequest, 'Rate limit exceeded', null, { retryAfter });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
sendJson(ctx.res, 429, { error: 'Rate limit exceeded', retryAfter });
|
|
90
|
+
}
|
|
84
91
|
return false;
|
|
85
92
|
}
|
|
86
93
|
return true;
|
|
@@ -89,7 +96,3 @@ class RateLimiter {
|
|
|
89
96
|
this.cleanup.abort();
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
|
-
export function createRateLimitManagerImpl(options) {
|
|
93
|
-
const limiter = new RateLimiter(options);
|
|
94
|
-
return limiter;
|
|
95
|
-
}
|
package/dist/lib/config.d.ts
CHANGED
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AA4CA,eAAO,MAAM,aAAa,EAAE,MAA2C,CAAC;AAIxE,MAAM,MAAM,QAAQ,GAChB,OAAO,GACP,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,CAAC;AAkCf,KAAK,mBAAmB,GAAG,SAAS,GAAG,SAAS,CAAC;AACjD,KAAK,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAqQnC,UAAU,oBAAoB;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyCD,UAAU,UAAU;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,GAAG,GAAG,SAAS,CAAC;IAC3B,gBAAgB,EAAE,GAAG,GAAG,SAAS,CAAC;IAClC,QAAQ,EAAE,GAAG,GAAG,SAAS,CAAC;IAC1B,aAAa,EAAE,GAAG,GAAG,SAAS,CAAC;IAC/B,eAAe,EAAE,GAAG,GAAG,SAAS,CAAC;IACjC,gBAAgB,EAAE,GAAG,GAAG,SAAS,CAAC;IAClC,WAAW,EAAE,GAAG,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -4,7 +4,7 @@ import { isIP } from 'node:net';
|
|
|
4
4
|
import process from 'node:process';
|
|
5
5
|
import { domainToASCII } from 'node:url';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import { getErrorMessage } from './error/
|
|
7
|
+
import { getErrorMessage } from './error/classes.js';
|
|
8
8
|
// ── Version ─────────────────────────────────────────────────────────
|
|
9
9
|
function getObjectProperty(value, key) {
|
|
10
10
|
return value[key];
|
|
@@ -297,7 +297,8 @@ function buildAuthConfig(baseUrl) {
|
|
|
297
297
|
const revocationUrl = parseUrl('OAUTH_REVOCATION_URL');
|
|
298
298
|
const registrationUrl = parseUrl('OAUTH_REGISTRATION_URL');
|
|
299
299
|
const introspectionUrl = parseUrl('OAUTH_INTROSPECTION_URL');
|
|
300
|
-
const
|
|
300
|
+
const publicBaseUrl = parseUrl('PUBLIC_BASE_URL');
|
|
301
|
+
const resourceUrl = new URL('/mcp', publicBaseUrl ?? baseUrl);
|
|
301
302
|
const oauthConfigured = issuerUrl !== undefined ||
|
|
302
303
|
authorizationUrl !== undefined ||
|
|
303
304
|
tokenUrl !== undefined ||
|
|
@@ -313,6 +314,7 @@ function buildAuthConfig(baseUrl) {
|
|
|
313
314
|
revocationUrl,
|
|
314
315
|
registrationUrl,
|
|
315
316
|
introspectionUrl,
|
|
317
|
+
publicBaseUrl,
|
|
316
318
|
resourceUrl,
|
|
317
319
|
requiredScopes: EnvParser.list(env['OAUTH_REQUIRED_SCOPES']),
|
|
318
320
|
clientId: env['OAUTH_CLIENT_ID'],
|
package/dist/lib/core.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
3
|
type LogMetadata = Record<string, unknown>;
|
|
4
|
+
export interface TraceContext {
|
|
5
|
+
readonly traceparent?: string;
|
|
6
|
+
readonly tracestate?: string;
|
|
7
|
+
readonly baggage?: string;
|
|
8
|
+
}
|
|
4
9
|
interface RequestContext {
|
|
5
10
|
readonly requestId: string;
|
|
6
11
|
readonly sessionId?: string;
|
|
7
12
|
readonly operationId?: string;
|
|
13
|
+
readonly traceparent?: string;
|
|
14
|
+
readonly tracestate?: string;
|
|
15
|
+
readonly baggage?: string;
|
|
8
16
|
}
|
|
9
17
|
export declare function setMcpServer(server: McpServer): void;
|
|
10
18
|
export declare function registerMcpSessionServer(sessionId: string, server: McpServer): void;
|
|
@@ -14,15 +22,17 @@ export declare function unregisterMcpSessionServerByServer(server: McpServer): v
|
|
|
14
22
|
export declare function resolveMcpSessionOwnerKey(sessionId: string): string | undefined;
|
|
15
23
|
export declare function resolveMcpSessionIdByServer(server: McpServer): string | undefined;
|
|
16
24
|
export declare function runWithRequestContext<T>(context: RequestContext, fn: () => T): T;
|
|
25
|
+
export declare function extractTraceContext(meta: unknown): TraceContext | undefined;
|
|
26
|
+
export declare function runWithTraceContext<T>(meta: unknown, fn: () => T): T;
|
|
17
27
|
export declare function getRequestId(): string | undefined;
|
|
18
28
|
export declare function getSessionId(): string | undefined;
|
|
19
29
|
export declare function getOperationId(): string | undefined;
|
|
30
|
+
export declare function getTraceContext(): TraceContext | undefined;
|
|
20
31
|
export declare function logInfo(message: string, meta?: LogMetadata, logger?: string): void;
|
|
21
32
|
export declare function logDebug(message: string, meta?: LogMetadata, logger?: string): void;
|
|
22
33
|
export declare function logNotice(message: string, meta?: LogMetadata, logger?: string): void;
|
|
23
34
|
export declare function logWarn(message: string, meta?: LogMetadata, logger?: string): void;
|
|
24
35
|
export declare function logError(message: string, error?: Error | LogMetadata, logger?: string): void;
|
|
25
|
-
export declare function logCritical(message: string, error?: Error | LogMetadata, logger?: string): void;
|
|
26
36
|
export declare function setLogLevel(level: string, sessionId?: string): void;
|
|
27
37
|
export declare function redactUrl(rawUrl: string): string;
|
|
28
38
|
export declare function startSessionCleanupLoop(store: SessionStore, sessionTtlMs: number, options?: {
|
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":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,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
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
3
4
|
import process from 'node:process';
|
|
4
5
|
import { getSystemErrorMessage, inspect, stripVTControlCharacters, } from 'node:util';
|
|
5
6
|
import { config } from './config.js';
|
|
6
|
-
import { getErrorMessage, isAbortError } from './error/
|
|
7
|
+
import { getErrorMessage, isAbortError } from './error/classes.js';
|
|
7
8
|
import { startAbortableIntervalLoop } from './utils.js';
|
|
8
9
|
const requestContext = new AsyncLocalStorage({
|
|
9
10
|
name: 'requestContext',
|
|
@@ -33,6 +34,18 @@ process.stderr.on('error', () => {
|
|
|
33
34
|
}
|
|
34
35
|
}, 5_000).unref();
|
|
35
36
|
});
|
|
37
|
+
function clearSessionTracking(sessionId) {
|
|
38
|
+
sessionServers.delete(sessionId);
|
|
39
|
+
sessionOwnerKeys.delete(sessionId);
|
|
40
|
+
sessionMcpLogLevels.delete(sessionId);
|
|
41
|
+
}
|
|
42
|
+
function findSessionIdByServer(server) {
|
|
43
|
+
for (const [sessionId, mappedServer] of sessionServers.entries()) {
|
|
44
|
+
if (mappedServer === server)
|
|
45
|
+
return sessionId;
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
36
49
|
export function setMcpServer(server) {
|
|
37
50
|
if (mcpServer) {
|
|
38
51
|
logWarn('setMcpServer called when server already set — overwriting');
|
|
@@ -52,32 +65,61 @@ export function registerMcpSessionOwnerKey(sessionId, ownerKey) {
|
|
|
52
65
|
export function unregisterMcpSessionServer(sessionId) {
|
|
53
66
|
if (!sessionId)
|
|
54
67
|
return;
|
|
55
|
-
|
|
56
|
-
sessionOwnerKeys.delete(sessionId);
|
|
57
|
-
sessionMcpLogLevels.delete(sessionId);
|
|
68
|
+
clearSessionTracking(sessionId);
|
|
58
69
|
}
|
|
59
70
|
export function unregisterMcpSessionServerByServer(server) {
|
|
60
71
|
for (const [sessionId, mappedServer] of sessionServers.entries()) {
|
|
61
72
|
if (mappedServer !== server)
|
|
62
73
|
continue;
|
|
63
|
-
|
|
64
|
-
sessionOwnerKeys.delete(sessionId);
|
|
65
|
-
sessionMcpLogLevels.delete(sessionId);
|
|
74
|
+
clearSessionTracking(sessionId);
|
|
66
75
|
}
|
|
67
76
|
}
|
|
68
77
|
export function resolveMcpSessionOwnerKey(sessionId) {
|
|
69
78
|
return sessionOwnerKeys.get(sessionId);
|
|
70
79
|
}
|
|
71
80
|
export function resolveMcpSessionIdByServer(server) {
|
|
72
|
-
|
|
73
|
-
if (mappedServer === server)
|
|
74
|
-
return sessionId;
|
|
75
|
-
}
|
|
76
|
-
return undefined;
|
|
81
|
+
return findSessionIdByServer(server);
|
|
77
82
|
}
|
|
78
83
|
export function runWithRequestContext(context, fn) {
|
|
79
84
|
return requestContext.run(context, fn);
|
|
80
85
|
}
|
|
86
|
+
function isTraceContextValue(value) {
|
|
87
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
88
|
+
}
|
|
89
|
+
export function extractTraceContext(meta) {
|
|
90
|
+
if (meta === null || typeof meta !== 'object' || Array.isArray(meta)) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const traceMeta = meta;
|
|
94
|
+
const traceparent = isTraceContextValue(traceMeta['traceparent'])
|
|
95
|
+
? traceMeta['traceparent']
|
|
96
|
+
: undefined;
|
|
97
|
+
const tracestate = isTraceContextValue(traceMeta['tracestate'])
|
|
98
|
+
? traceMeta['tracestate']
|
|
99
|
+
: undefined;
|
|
100
|
+
const baggage = isTraceContextValue(traceMeta['baggage'])
|
|
101
|
+
? traceMeta['baggage']
|
|
102
|
+
: undefined;
|
|
103
|
+
if (!traceparent && !tracestate && !baggage)
|
|
104
|
+
return undefined;
|
|
105
|
+
return {
|
|
106
|
+
...(traceparent ? { traceparent } : {}),
|
|
107
|
+
...(tracestate ? { tracestate } : {}),
|
|
108
|
+
...(baggage ? { baggage } : {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export function runWithTraceContext(meta, fn) {
|
|
112
|
+
const traceContext = extractTraceContext(meta);
|
|
113
|
+
if (!traceContext)
|
|
114
|
+
return fn();
|
|
115
|
+
const existing = getRequestContext();
|
|
116
|
+
return runWithRequestContext({
|
|
117
|
+
requestId: existing?.requestId ?? randomUUID(),
|
|
118
|
+
...(existing?.sessionId ? { sessionId: existing.sessionId } : {}),
|
|
119
|
+
...(existing?.operationId ? { operationId: existing.operationId } : {}),
|
|
120
|
+
...traceContext,
|
|
121
|
+
}, fn);
|
|
122
|
+
}
|
|
81
123
|
function getRequestContext() {
|
|
82
124
|
return requestContext.getStore();
|
|
83
125
|
}
|
|
@@ -91,18 +133,29 @@ export function getSessionId() {
|
|
|
91
133
|
export function getOperationId() {
|
|
92
134
|
return getRequestContext()?.operationId;
|
|
93
135
|
}
|
|
136
|
+
export function getTraceContext() {
|
|
137
|
+
const context = getRequestContext();
|
|
138
|
+
if (!context)
|
|
139
|
+
return undefined;
|
|
140
|
+
const { traceparent, tracestate, baggage } = context;
|
|
141
|
+
if (!traceparent && !tracestate && !baggage)
|
|
142
|
+
return undefined;
|
|
143
|
+
return {
|
|
144
|
+
...(traceparent ? { traceparent } : {}),
|
|
145
|
+
...(tracestate ? { tracestate } : {}),
|
|
146
|
+
...(baggage ? { baggage } : {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
94
149
|
function isDebugEnabled() {
|
|
95
150
|
return config.logging.level === 'debug';
|
|
96
151
|
}
|
|
97
|
-
function
|
|
98
|
-
const ctx = requestContext.getStore();
|
|
99
|
-
const hasMeta = meta && Object.keys(meta).length > 0;
|
|
152
|
+
function buildContextMetadata(ctx) {
|
|
100
153
|
if (!ctx)
|
|
101
|
-
return
|
|
154
|
+
return undefined;
|
|
102
155
|
const { requestId, operationId, sessionId } = ctx;
|
|
103
156
|
const includeSession = sessionId && isDebugEnabled();
|
|
104
157
|
if (!requestId && !operationId && !includeSession)
|
|
105
|
-
return
|
|
158
|
+
return undefined;
|
|
106
159
|
const contextMeta = {};
|
|
107
160
|
if (requestId)
|
|
108
161
|
contextMeta['requestId'] = requestId;
|
|
@@ -110,7 +163,16 @@ function mergeMetadata(meta) {
|
|
|
110
163
|
contextMeta['operationId'] = operationId;
|
|
111
164
|
if (includeSession)
|
|
112
165
|
contextMeta['sessionId'] = sessionId;
|
|
113
|
-
return
|
|
166
|
+
return contextMeta;
|
|
167
|
+
}
|
|
168
|
+
function mergeMetadata(meta) {
|
|
169
|
+
const ctxMeta = buildContextMetadata(getRequestContext());
|
|
170
|
+
const hasMeta = meta && Object.keys(meta).length > 0;
|
|
171
|
+
if (!ctxMeta)
|
|
172
|
+
return hasMeta ? meta : undefined;
|
|
173
|
+
if (!hasMeta)
|
|
174
|
+
return ctxMeta;
|
|
175
|
+
return { ...ctxMeta, ...meta };
|
|
114
176
|
}
|
|
115
177
|
function isUrlLikeKey(key) {
|
|
116
178
|
const normalized = key
|
|
@@ -134,11 +196,61 @@ function redactUrlValue(value) {
|
|
|
134
196
|
}
|
|
135
197
|
return redactUrl(value);
|
|
136
198
|
}
|
|
137
|
-
function
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
199
|
+
function extractErrorCode(value, sanitized) {
|
|
200
|
+
if (!('code' in value))
|
|
201
|
+
return;
|
|
202
|
+
const errorCode = value.code;
|
|
203
|
+
if (typeof errorCode === 'string' || typeof errorCode === 'number') {
|
|
204
|
+
sanitized['code'] = errorCode;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function extractSysError(value, sanitized) {
|
|
208
|
+
if (!('errno' in value) || typeof value.errno !== 'number')
|
|
209
|
+
return;
|
|
210
|
+
try {
|
|
211
|
+
const sysMsg = getSystemErrorMessage(value.errno);
|
|
212
|
+
if (sysMsg)
|
|
213
|
+
sanitized['sysError'] = sysMsg;
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// ignore
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function sanitizeErrorForLog(value, includeStack) {
|
|
220
|
+
const sanitized = {
|
|
221
|
+
error: value.message,
|
|
222
|
+
...(value.name && value.name !== 'Error' ? { errorName: value.name } : {}),
|
|
223
|
+
};
|
|
224
|
+
extractErrorCode(value, sanitized);
|
|
225
|
+
extractSysError(value, sanitized);
|
|
226
|
+
if (includeStack && value.stack) {
|
|
227
|
+
sanitized['stack'] = value.stack;
|
|
228
|
+
}
|
|
229
|
+
return sanitized;
|
|
230
|
+
}
|
|
231
|
+
function sanitizeObjectForLog(value, options) {
|
|
232
|
+
if (options.seen.has(value))
|
|
233
|
+
return '[circular]';
|
|
234
|
+
options.seen.add(value);
|
|
235
|
+
const sanitized = {};
|
|
236
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
237
|
+
if (isSensitiveKey(entryKey) &&
|
|
238
|
+
(!options.includeStack || entryKey.toLowerCase() !== 'stack')) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const normalized = sanitizeLogValue(entryValue, {
|
|
242
|
+
includeStack: options.includeStack,
|
|
243
|
+
depth: options.depth + 1,
|
|
244
|
+
seen: options.seen,
|
|
245
|
+
key: entryKey,
|
|
246
|
+
});
|
|
247
|
+
if (normalized !== undefined) {
|
|
248
|
+
sanitized[entryKey] = normalized;
|
|
249
|
+
}
|
|
141
250
|
}
|
|
251
|
+
return sanitized;
|
|
252
|
+
}
|
|
253
|
+
function sanitizePrimitiveOrString(value, key) {
|
|
142
254
|
if (value === null ||
|
|
143
255
|
typeof value === 'number' ||
|
|
144
256
|
typeof value === 'boolean') {
|
|
@@ -147,37 +259,16 @@ function sanitizeLogValue(value, options) {
|
|
|
147
259
|
if (typeof value === 'string') {
|
|
148
260
|
return key && isUrlLikeKey(key) ? redactUrlValue(value) : value;
|
|
149
261
|
}
|
|
262
|
+
return undefined; // Not a primitive/string we handle directly here
|
|
263
|
+
}
|
|
264
|
+
function sanitizeComplexValue(value, options) {
|
|
265
|
+
const { includeStack, depth = 0, seen = new WeakSet() } = options;
|
|
150
266
|
if (typeof value === 'bigint')
|
|
151
267
|
return value.toString();
|
|
152
268
|
if (value instanceof URL)
|
|
153
269
|
return redactUrl(value.toString());
|
|
154
270
|
if (value instanceof Error) {
|
|
155
|
-
|
|
156
|
-
error: value.message,
|
|
157
|
-
...(value.name && value.name !== 'Error'
|
|
158
|
-
? { errorName: value.name }
|
|
159
|
-
: {}),
|
|
160
|
-
};
|
|
161
|
-
if ('code' in value) {
|
|
162
|
-
const errorCode = value.code;
|
|
163
|
-
if (typeof errorCode === 'string' || typeof errorCode === 'number') {
|
|
164
|
-
sanitized['code'] = errorCode;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if ('errno' in value && typeof value.errno === 'number') {
|
|
168
|
-
try {
|
|
169
|
-
const sysMsg = getSystemErrorMessage(value.errno);
|
|
170
|
-
if (sysMsg)
|
|
171
|
-
sanitized['sysError'] = sysMsg;
|
|
172
|
-
}
|
|
173
|
-
catch {
|
|
174
|
-
// ignore
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (includeStack && value.stack) {
|
|
178
|
-
sanitized['stack'] = value.stack;
|
|
179
|
-
}
|
|
180
|
-
return sanitized;
|
|
271
|
+
return sanitizeErrorForLog(value, includeStack);
|
|
181
272
|
}
|
|
182
273
|
if (Array.isArray(value)) {
|
|
183
274
|
return value
|
|
@@ -185,29 +276,22 @@ function sanitizeLogValue(value, options) {
|
|
|
185
276
|
.filter((entry) => entry !== undefined);
|
|
186
277
|
}
|
|
187
278
|
if (isPlainLogObject(value)) {
|
|
188
|
-
|
|
189
|
-
return '[circular]';
|
|
190
|
-
seen.add(value);
|
|
191
|
-
const sanitized = {};
|
|
192
|
-
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
193
|
-
if (isSensitiveKey(entryKey) &&
|
|
194
|
-
(!includeStack || entryKey.toLowerCase() !== 'stack')) {
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
const normalized = sanitizeLogValue(entryValue, {
|
|
198
|
-
includeStack,
|
|
199
|
-
depth: depth + 1,
|
|
200
|
-
seen,
|
|
201
|
-
key: entryKey,
|
|
202
|
-
});
|
|
203
|
-
if (normalized !== undefined) {
|
|
204
|
-
sanitized[entryKey] = normalized;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return sanitized;
|
|
279
|
+
return sanitizeObjectForLog(value, { includeStack, depth, seen });
|
|
208
280
|
}
|
|
209
281
|
return undefined;
|
|
210
282
|
}
|
|
283
|
+
function sanitizeLogValue(value, options) {
|
|
284
|
+
const { depth = 0, key } = options;
|
|
285
|
+
if (depth >= LOG_METADATA_MAX_DEPTH) {
|
|
286
|
+
return '[truncated]';
|
|
287
|
+
}
|
|
288
|
+
const primitive = sanitizePrimitiveOrString(value, key);
|
|
289
|
+
if (primitive !== undefined || value === undefined)
|
|
290
|
+
return primitive;
|
|
291
|
+
if (value === null)
|
|
292
|
+
return null;
|
|
293
|
+
return sanitizeComplexValue(value, options);
|
|
294
|
+
}
|
|
211
295
|
function sanitizeLogMetadata(meta, options) {
|
|
212
296
|
if (!meta || Object.keys(meta).length === 0)
|
|
213
297
|
return undefined;
|
|
@@ -297,23 +381,23 @@ function shouldForwardMcpLog(level, sessionId) {
|
|
|
297
381
|
return (MCP_LOG_LEVEL_PRIORITY[emittedLevel] <=
|
|
298
382
|
MCP_LOG_LEVEL_PRIORITY[configuredLevel]);
|
|
299
383
|
}
|
|
300
|
-
function
|
|
301
|
-
if (err
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (sysMsg)
|
|
306
|
-
return `${err.message} (${sysMsg})`;
|
|
307
|
-
}
|
|
308
|
-
catch {
|
|
309
|
-
// ignore
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return err.message;
|
|
384
|
+
function resolveErrorSysMsg(err) {
|
|
385
|
+
if (!('errno' in err) || typeof err.errno !== 'number')
|
|
386
|
+
return undefined;
|
|
387
|
+
try {
|
|
388
|
+
return getSystemErrorMessage(err.errno);
|
|
313
389
|
}
|
|
390
|
+
catch {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function resolveErrorText(err) {
|
|
314
395
|
if (typeof err === 'string')
|
|
315
396
|
return err;
|
|
316
|
-
|
|
397
|
+
if (!(err instanceof Error))
|
|
398
|
+
return 'unknown error';
|
|
399
|
+
const sysMsg = resolveErrorSysMsg(err);
|
|
400
|
+
return sysMsg ? `${err.message} (${sysMsg})` : err.message;
|
|
317
401
|
}
|
|
318
402
|
const MCP_LOG_SENSITIVE_PATTERNS = [
|
|
319
403
|
'password',
|
|
@@ -477,10 +561,6 @@ export function logError(message, error, logger) {
|
|
|
477
561
|
const errorMeta = error instanceof Error ? formatErrorMeta(error) : (error ?? {});
|
|
478
562
|
writeLog('error', message, errorMeta, logger);
|
|
479
563
|
}
|
|
480
|
-
export function logCritical(message, error, logger) {
|
|
481
|
-
const errorMeta = error instanceof Error ? formatErrorMeta(error) : (error ?? {});
|
|
482
|
-
writeLog('critical', message, errorMeta, logger);
|
|
483
|
-
}
|
|
484
564
|
export function setLogLevel(level, sessionId) {
|
|
485
565
|
const normalized = normalizeLogLevel(level);
|
|
486
566
|
if (!normalized)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classes.ts"],"names":[],"mappings":"AAcA,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAQtD;AAMD,qBAAa,UAAW,SAAQ,KAAK;IAOjC,QAAQ,CAAC,GAAG,EAAE,MAAM;IANtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAGlD,OAAO,EAAE,MAAM,EACN,GAAG,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,OAAO,CAAC,EAAE,YAAY;CAezB;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKlE;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAK5E;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsBtD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE7C;AAID,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,IAAI,CAYN;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAMvE"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
|
-
import { isObject } from '../utils.js';
|
|
3
2
|
import { SystemErrors } from './codes.js';
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
4
6
|
export function isError(value) {
|
|
5
7
|
const maybeIsError = Error.isError;
|
|
6
8
|
if (typeof maybeIsError === 'function') {
|
|
@@ -62,7 +64,7 @@ export function getErrorMessage(error) {
|
|
|
62
64
|
return error.message;
|
|
63
65
|
if (typeof error === 'string' && error.length > 0)
|
|
64
66
|
return error;
|
|
65
|
-
if (
|
|
67
|
+
if (isRecord(error) &&
|
|
66
68
|
typeof error['message'] === 'string' &&
|
|
67
69
|
error['message'].length > 0) {
|
|
68
70
|
return error['message'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classify.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../../src/lib/error/classify.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AA+JtB,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,MAAM,EACX,eAAe,SAAqB,GACnC,iBAAiB,CAInB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GACtB,iBAAiB,CAuCnB"}
|
|
@@ -18,17 +18,20 @@ function buildUpstreamHttpMessage(error) {
|
|
|
18
18
|
}
|
|
19
19
|
return `An error occurred when communicating with the target URL.`;
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function resolveFetchErrorCode(error) {
|
|
22
22
|
const { code: detailsCode, reason } = error.details;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
if (typeof detailsCode === 'string')
|
|
24
|
+
return detailsCode;
|
|
25
|
+
if (reason === SystemErrors.QUEUE_FULL)
|
|
26
|
+
return SystemErrors.QUEUE_FULL;
|
|
27
|
+
return error.code;
|
|
28
|
+
}
|
|
29
|
+
function mapFetchToolError(error, fallbackUrl) {
|
|
30
|
+
const { reason } = error.details;
|
|
31
|
+
const code = resolveFetchErrorCode(error);
|
|
30
32
|
const url = error.url || fallbackUrl;
|
|
31
33
|
const details = sanitizeToolErrorDetails(error.details);
|
|
34
|
+
const detailsSpread = details ? { details } : {};
|
|
32
35
|
if (reason === 'timeout') {
|
|
33
36
|
return {
|
|
34
37
|
error: 'The request to the target timed out.',
|
|
@@ -37,7 +40,7 @@ function mapFetchToolError(error, fallbackUrl) {
|
|
|
37
40
|
code,
|
|
38
41
|
statusCode: error.statusCode,
|
|
39
42
|
upstreamMessage: error.message,
|
|
40
|
-
...
|
|
43
|
+
...detailsSpread,
|
|
41
44
|
};
|
|
42
45
|
}
|
|
43
46
|
if (reason === 'aborted') {
|
|
@@ -48,7 +51,7 @@ function mapFetchToolError(error, fallbackUrl) {
|
|
|
48
51
|
code,
|
|
49
52
|
statusCode: error.statusCode,
|
|
50
53
|
upstreamMessage: error.message,
|
|
51
|
-
...
|
|
54
|
+
...detailsSpread,
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
if (reason === SystemErrors.QUEUE_FULL) {
|
|
@@ -58,21 +61,22 @@ function mapFetchToolError(error, fallbackUrl) {
|
|
|
58
61
|
category: ErrorCategory.QUEUE_FULL,
|
|
59
62
|
code,
|
|
60
63
|
statusCode: error.statusCode,
|
|
61
|
-
...
|
|
64
|
+
...detailsSpread,
|
|
62
65
|
};
|
|
63
66
|
}
|
|
64
67
|
const isRealHttpError = typeof error.details['httpStatus'] === 'number';
|
|
65
68
|
if (isRealHttpError && error.statusCode >= 400) {
|
|
69
|
+
const category = error.statusCode === 429
|
|
70
|
+
? ErrorCategory.UPSTREAM_RATE_LIMITED
|
|
71
|
+
: ErrorCategory.UPSTREAM_HTTP_ERROR;
|
|
66
72
|
return {
|
|
67
73
|
error: buildUpstreamHttpMessage(error),
|
|
68
74
|
url,
|
|
69
|
-
category
|
|
70
|
-
? ErrorCategory.UPSTREAM_RATE_LIMITED
|
|
71
|
-
: ErrorCategory.UPSTREAM_HTTP_ERROR,
|
|
75
|
+
category,
|
|
72
76
|
code,
|
|
73
77
|
statusCode: error.statusCode,
|
|
74
78
|
upstreamMessage: error.message,
|
|
75
|
-
...
|
|
79
|
+
...detailsSpread,
|
|
76
80
|
};
|
|
77
81
|
}
|
|
78
82
|
return {
|
|
@@ -81,7 +85,7 @@ function mapFetchToolError(error, fallbackUrl) {
|
|
|
81
85
|
category: ErrorCategory.FETCH_ERROR,
|
|
82
86
|
code,
|
|
83
87
|
statusCode: error.statusCode,
|
|
84
|
-
...
|
|
88
|
+
...detailsSpread,
|
|
85
89
|
};
|
|
86
90
|
}
|
|
87
91
|
function mapGenericToolError(error, url, fallbackMessage) {
|