@j0hanz/fetch-url-mcp 1.12.4 → 1.12.6
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 +44 -29
- package/dist/http/helpers.d.ts.map +1 -1
- package/dist/http/helpers.js +22 -12
- package/dist/http/native.d.ts.map +1 -1
- package/dist/http/native.js +30 -29
- package/dist/http/rate-limit.d.ts.map +1 -1
- package/dist/http/rate-limit.js +5 -3
- package/dist/index.js +3 -2
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -7
- package/dist/lib/core.d.ts.map +1 -1
- package/dist/lib/core.js +12 -9
- package/dist/lib/error-codes.d.ts +11 -0
- package/dist/lib/error-codes.d.ts.map +1 -0
- package/dist/lib/error-codes.js +15 -0
- package/dist/lib/error-messages.d.ts +13 -0
- package/dist/lib/error-messages.d.ts.map +1 -0
- package/dist/lib/error-messages.js +51 -0
- package/dist/lib/fetch-pipeline.d.ts.map +1 -1
- package/dist/lib/fetch-pipeline.js +5 -4
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +74 -41
- package/dist/lib/logger-names.d.ts +14 -0
- package/dist/lib/logger-names.d.ts.map +1 -0
- package/dist/lib/logger-names.js +13 -0
- package/dist/lib/mcp-interop.d.ts +1 -11
- package/dist/lib/mcp-interop.d.ts.map +1 -1
- package/dist/lib/mcp-interop.js +10 -73
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/session.js +2 -1
- package/dist/lib/tool-errors.d.ts +39 -0
- package/dist/lib/tool-errors.d.ts.map +1 -0
- package/dist/lib/tool-errors.js +252 -0
- package/dist/lib/url.d.ts.map +1 -1
- package/dist/lib/url.js +18 -15
- package/dist/lib/utils.d.ts +4 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +18 -9
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +7 -6
- package/dist/tasks/call-contract.d.ts.map +1 -1
- package/dist/tasks/call-contract.js +8 -10
- package/dist/tasks/execution.d.ts.map +1 -1
- package/dist/tasks/execution.js +17 -14
- package/dist/tasks/handlers.d.ts.map +1 -1
- package/dist/tasks/handlers.js +9 -8
- package/dist/tasks/manager.d.ts.map +1 -1
- package/dist/tasks/manager.js +14 -13
- package/dist/tasks/owner.d.ts +0 -1
- package/dist/tasks/owner.d.ts.map +1 -1
- package/dist/tasks/owner.js +0 -25
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +14 -26
- package/dist/transform/dom-prep.d.ts.map +1 -1
- package/dist/transform/dom-prep.js +10 -8
- package/dist/transform/shared.d.ts.map +1 -1
- package/dist/transform/shared.js +2 -1
- package/dist/transform/transform.d.ts.map +1 -1
- package/dist/transform/transform.js +29 -21
- package/dist/transform/worker-pool.d.ts.map +1 -1
- package/dist/transform/worker-pool.js +16 -12
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-interop.d.ts","sourceRoot":"","sources":["../../src/lib/mcp-interop.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-interop.d.ts","sourceRoot":"","sources":["../../src/lib/mcp-interop.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/mcp-interop.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { setTimeout as setTimeoutPromise } from 'node:timers/promises';
|
|
2
|
-
import { ListToolsRequestSchema, ListToolsResultSchema,
|
|
2
|
+
import { ListToolsRequestSchema, ListToolsResultSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { logError, logWarn } from './core.js';
|
|
5
|
-
import {
|
|
6
|
+
import { LOG_MCP } from './logger-names.js';
|
|
7
|
+
import { getErrorMessage, isObject } from './utils.js';
|
|
6
8
|
export function createMcpError(code, message, data) {
|
|
7
9
|
const error = new McpError(code, message, data);
|
|
8
10
|
error.message = message;
|
|
@@ -71,72 +73,6 @@ export function acceptsJsonAndEventStream(header) {
|
|
|
71
73
|
return false;
|
|
72
74
|
return mediaTypes.some((m) => m === '*/*' || m === 'text/event-stream' || m === 'text/*');
|
|
73
75
|
}
|
|
74
|
-
const PUBLIC_ERROR_REASONS = new Set(['aborted', 'queue_full', 'timeout']);
|
|
75
|
-
function sanitizeToolErrorDetails(details) {
|
|
76
|
-
const sanitized = {};
|
|
77
|
-
const { retryAfter, timeout, reason } = details;
|
|
78
|
-
if (typeof retryAfter === 'number' ||
|
|
79
|
-
typeof retryAfter === 'string' ||
|
|
80
|
-
retryAfter === null) {
|
|
81
|
-
sanitized['retryAfter'] = retryAfter;
|
|
82
|
-
}
|
|
83
|
-
if (typeof timeout === 'number' && Number.isFinite(timeout) && timeout >= 0) {
|
|
84
|
-
sanitized['timeout'] = timeout;
|
|
85
|
-
}
|
|
86
|
-
if (typeof reason === 'string' && PUBLIC_ERROR_REASONS.has(reason)) {
|
|
87
|
-
sanitized['reason'] = reason;
|
|
88
|
-
}
|
|
89
|
-
return Object.keys(sanitized).length > 0 ? sanitized : undefined;
|
|
90
|
-
}
|
|
91
|
-
export function createToolErrorResponse(message, url, extra) {
|
|
92
|
-
const errorContent = {
|
|
93
|
-
error: message,
|
|
94
|
-
...(extra?.code !== undefined ? { code: extra.code } : {}),
|
|
95
|
-
url,
|
|
96
|
-
...(extra?.statusCode !== undefined
|
|
97
|
-
? { statusCode: extra.statusCode }
|
|
98
|
-
: {}),
|
|
99
|
-
...(extra?.details ? { details: extra.details } : {}),
|
|
100
|
-
...(extra?.data !== undefined ? { data: extra.data } : {}),
|
|
101
|
-
};
|
|
102
|
-
return {
|
|
103
|
-
content: [{ type: 'text', text: JSON.stringify(errorContent) }],
|
|
104
|
-
isError: true,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function isValidationError(error) {
|
|
108
|
-
return (error instanceof Error &&
|
|
109
|
-
isSystemError(error) &&
|
|
110
|
-
error.code === 'VALIDATION_ERROR');
|
|
111
|
-
}
|
|
112
|
-
export function handleToolError(error, url, fallbackMessage = 'Operation failed') {
|
|
113
|
-
if (error instanceof FetchError) {
|
|
114
|
-
const { code: detailsCode, reason } = error.details;
|
|
115
|
-
let { code } = error;
|
|
116
|
-
if (typeof detailsCode === 'string') {
|
|
117
|
-
code = detailsCode;
|
|
118
|
-
}
|
|
119
|
-
else if (reason === 'queue_full') {
|
|
120
|
-
code = 'queue_full';
|
|
121
|
-
}
|
|
122
|
-
const details = sanitizeToolErrorDetails(error.details);
|
|
123
|
-
return createToolErrorResponse(error.message, url, {
|
|
124
|
-
code,
|
|
125
|
-
statusCode: error.statusCode,
|
|
126
|
-
...(details ? { details } : {}),
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
if (isValidationError(error)) {
|
|
130
|
-
return createToolErrorResponse(error.message, url, {
|
|
131
|
-
code: 'VALIDATION_ERROR',
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
const code = isAbortError(error) ? 'ABORTED' : 'FETCH_ERROR';
|
|
135
|
-
const message = error instanceof Error
|
|
136
|
-
? error.message
|
|
137
|
-
: `${fallbackMessage}: unknown error`;
|
|
138
|
-
return createToolErrorResponse(message, url, { code });
|
|
139
|
-
}
|
|
140
76
|
function getNestedRecord(value, key) {
|
|
141
77
|
const nested = value[key];
|
|
142
78
|
return isObject(nested) ? nested : undefined;
|
|
@@ -162,7 +98,7 @@ function drainServerCleanupCallbacks(server) {
|
|
|
162
98
|
callback();
|
|
163
99
|
}
|
|
164
100
|
catch (error) {
|
|
165
|
-
logWarn('Server cleanup callback failed', { error },
|
|
101
|
+
logWarn('Server cleanup callback failed', { error }, LOG_MCP);
|
|
166
102
|
}
|
|
167
103
|
}
|
|
168
104
|
}
|
|
@@ -303,11 +239,12 @@ class ToolProgressReporter {
|
|
|
303
239
|
if (token === null && !onProgress) {
|
|
304
240
|
return { report: () => { } };
|
|
305
241
|
}
|
|
306
|
-
|
|
242
|
+
const reporter = new ToolProgressReporter(token, {
|
|
307
243
|
send: extra.sendNotification,
|
|
308
244
|
onProgress,
|
|
309
245
|
canReport: extra.canReportProgress,
|
|
310
246
|
}, extra.progressState, resolveRelatedTaskMeta(extra._meta));
|
|
247
|
+
return reporter;
|
|
311
248
|
}
|
|
312
249
|
/**
|
|
313
250
|
* Report progress toward completion. Steps are monotonic (never decrease)
|
|
@@ -337,7 +274,7 @@ class ToolProgressReporter {
|
|
|
337
274
|
error: getErrorMessage(error),
|
|
338
275
|
progress: effectiveProgress,
|
|
339
276
|
message,
|
|
340
|
-
},
|
|
277
|
+
}, LOG_MCP);
|
|
341
278
|
}
|
|
342
279
|
}
|
|
343
280
|
if (!isIncreasing || this.token === null || !this.handlers.send)
|
|
@@ -399,7 +336,7 @@ class ToolProgressReporter {
|
|
|
399
336
|
logWarn('Progress notification timed out', {
|
|
400
337
|
progress: notification.params.progress,
|
|
401
338
|
message: notification.params.message,
|
|
402
|
-
},
|
|
339
|
+
}, LOG_MCP);
|
|
403
340
|
}
|
|
404
341
|
}
|
|
405
342
|
catch (error) {
|
|
@@ -407,7 +344,7 @@ class ToolProgressReporter {
|
|
|
407
344
|
error: getErrorMessage(error),
|
|
408
345
|
progress: notification.params.progress,
|
|
409
346
|
message: notification.params.message,
|
|
410
|
-
},
|
|
347
|
+
}, LOG_MCP);
|
|
411
348
|
}
|
|
412
349
|
}
|
|
413
350
|
createProgressNotification(params) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAMxG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,6BAA6B,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACrD,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACtD,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACxD,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,YAAY,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,EAAE,CAAC;IAC1D,WAAW,EAAE,MAAM,YAAY,GAAG,SAAS,CAAC;CAC7C;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC;CACvC;AAMD,KAAK,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;AAE7C,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,YAAY,CAWd;AA0FD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAMxG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,6BAA6B,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACrD,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACtD,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACxD,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,YAAY,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,EAAE,CAAC;IAC1D,WAAW,EAAE,MAAM,YAAY,GAAG,SAAS,CAAC;CAC7C;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC;CACvC;AAMD,KAAK,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;AAE7C,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,YAAY,CAWd;AA0FD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAGrE;AAMD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,CAiBlE;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAMT;AAED,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,WAAW,EACX,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;CAC/C,GAAG,OAAO,CAUV"}
|
package/dist/lib/session.js
CHANGED
|
@@ -93,7 +93,8 @@ class InMemorySessionStore {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
export function createSessionStore(sessionTtlMs) {
|
|
96
|
-
|
|
96
|
+
const store = new InMemorySessionStore(sessionTtlMs);
|
|
97
|
+
return store;
|
|
97
98
|
}
|
|
98
99
|
/* -------------------------------------------------------------------------------------------------
|
|
99
100
|
* Slot tracking and capacity
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
export type ToolErrorResponse = CallToolResult & {
|
|
3
|
+
isError: true;
|
|
4
|
+
};
|
|
5
|
+
export interface ToolErrorLogMeta {
|
|
6
|
+
url: string;
|
|
7
|
+
durationMs: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ToolErrorPayload extends Record<string, unknown> {
|
|
10
|
+
error: string;
|
|
11
|
+
url: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
code?: string | number;
|
|
14
|
+
statusCode?: number;
|
|
15
|
+
upstreamMessage?: string;
|
|
16
|
+
details?: Record<string, unknown>;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export declare function createToolErrorResponse(message: string, url: string, extra?: {
|
|
20
|
+
category?: string;
|
|
21
|
+
code?: string | number;
|
|
22
|
+
statusCode?: number;
|
|
23
|
+
upstreamMessage?: string;
|
|
24
|
+
details?: Record<string, unknown>;
|
|
25
|
+
data?: unknown;
|
|
26
|
+
}): ToolErrorResponse;
|
|
27
|
+
export declare function createToolErrorPayload(message: string, url: string, extra?: {
|
|
28
|
+
category?: string;
|
|
29
|
+
code?: string | number;
|
|
30
|
+
statusCode?: number;
|
|
31
|
+
upstreamMessage?: string;
|
|
32
|
+
details?: Record<string, unknown>;
|
|
33
|
+
data?: unknown;
|
|
34
|
+
}): ToolErrorPayload;
|
|
35
|
+
export declare function tryReadToolErrorPayload(value: unknown): ToolErrorPayload | undefined;
|
|
36
|
+
export declare function tryReadToolErrorMessage(value: unknown): string | undefined;
|
|
37
|
+
export declare function handleToolError(error: unknown, url: string, fallbackMessage?: string): ToolErrorResponse;
|
|
38
|
+
export declare function classifyAndLogToolError(error: unknown, meta: ToolErrorLogMeta, loggerName: string, toolName: string, fallbackMessage: string): ToolErrorResponse;
|
|
39
|
+
//# sourceMappingURL=tool-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-errors.d.ts","sourceRoot":"","sources":["../../src/lib/tool-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,oCAAoC,CAAC;AAY5C,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG;IAC/C,OAAO,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAmDD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE;IACN,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,iBAAiB,CAOnB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE;IACN,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,gBAAgB,CAgBlB;AAiBD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,gBAAgB,GAAG,SAAS,CA2B9B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE1E;AAkKD,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,CA+BnB"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { logError, logWarn } from './core.js';
|
|
4
|
+
import { ABORTED, FETCH_ERROR, QUEUE_FULL, VALIDATION_ERROR, } from './error-codes.js';
|
|
5
|
+
import { FetchError, isAbortError, isObject, isSystemError } from './utils.js';
|
|
6
|
+
const toolErrorPayloadSchema = z.strictObject({
|
|
7
|
+
error: z.string(),
|
|
8
|
+
url: z.string(),
|
|
9
|
+
category: z.string().optional(),
|
|
10
|
+
code: z.union([z.string(), z.number()]).optional(),
|
|
11
|
+
statusCode: z.number().int().optional(),
|
|
12
|
+
upstreamMessage: z.string().optional(),
|
|
13
|
+
details: z.record(z.string(), z.unknown()).optional(),
|
|
14
|
+
data: z.unknown().optional(),
|
|
15
|
+
});
|
|
16
|
+
const PUBLIC_ERROR_REASONS = new Set(['aborted', QUEUE_FULL, 'timeout']);
|
|
17
|
+
function sanitizeToolErrorDetails(details) {
|
|
18
|
+
const sanitized = {};
|
|
19
|
+
const { retryAfter, timeout, reason } = details;
|
|
20
|
+
if (typeof retryAfter === 'number' ||
|
|
21
|
+
typeof retryAfter === 'string' ||
|
|
22
|
+
retryAfter === null) {
|
|
23
|
+
sanitized['retryAfter'] = retryAfter;
|
|
24
|
+
}
|
|
25
|
+
if (typeof timeout === 'number' && Number.isFinite(timeout) && timeout >= 0) {
|
|
26
|
+
sanitized['timeout'] = timeout;
|
|
27
|
+
}
|
|
28
|
+
if (typeof reason === 'string' && PUBLIC_ERROR_REASONS.has(reason)) {
|
|
29
|
+
sanitized['reason'] = reason;
|
|
30
|
+
}
|
|
31
|
+
return Object.keys(sanitized).length > 0 ? sanitized : undefined;
|
|
32
|
+
}
|
|
33
|
+
export function createToolErrorResponse(message, url, extra) {
|
|
34
|
+
const errorContent = createToolErrorPayload(message, url, extra);
|
|
35
|
+
return {
|
|
36
|
+
content: [{ type: 'text', text: JSON.stringify(errorContent) }],
|
|
37
|
+
isError: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function createToolErrorPayload(message, url, extra) {
|
|
41
|
+
const payload = {
|
|
42
|
+
error: message,
|
|
43
|
+
url,
|
|
44
|
+
};
|
|
45
|
+
if (extra?.category !== undefined)
|
|
46
|
+
payload.category = extra.category;
|
|
47
|
+
if (extra?.code !== undefined)
|
|
48
|
+
payload.code = extra.code;
|
|
49
|
+
if (extra?.statusCode !== undefined)
|
|
50
|
+
payload.statusCode = extra.statusCode;
|
|
51
|
+
if (extra?.upstreamMessage !== undefined) {
|
|
52
|
+
payload.upstreamMessage = extra.upstreamMessage;
|
|
53
|
+
}
|
|
54
|
+
if (extra?.details)
|
|
55
|
+
payload.details = extra.details;
|
|
56
|
+
if (extra?.data !== undefined)
|
|
57
|
+
payload.data = extra.data;
|
|
58
|
+
return payload;
|
|
59
|
+
}
|
|
60
|
+
function normalizeToolErrorPayload(value) {
|
|
61
|
+
return createToolErrorPayload(value.error, value.url, {
|
|
62
|
+
...(value.category !== undefined ? { category: value.category } : {}),
|
|
63
|
+
...(value.code !== undefined ? { code: value.code } : {}),
|
|
64
|
+
...(value.statusCode !== undefined ? { statusCode: value.statusCode } : {}),
|
|
65
|
+
...(value.upstreamMessage !== undefined
|
|
66
|
+
? { upstreamMessage: value.upstreamMessage }
|
|
67
|
+
: {}),
|
|
68
|
+
...(value.details ? { details: value.details } : {}),
|
|
69
|
+
...(value.data !== undefined ? { data: value.data } : {}),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export function tryReadToolErrorPayload(value) {
|
|
73
|
+
if (!isObject(value))
|
|
74
|
+
return undefined;
|
|
75
|
+
const structuredContent = toolErrorPayloadSchema.safeParse(value['structuredContent']);
|
|
76
|
+
if (structuredContent.success) {
|
|
77
|
+
return normalizeToolErrorPayload(structuredContent.data);
|
|
78
|
+
}
|
|
79
|
+
const { content } = value;
|
|
80
|
+
if (!Array.isArray(content) || content.length === 0)
|
|
81
|
+
return undefined;
|
|
82
|
+
const firstBlock = content[0];
|
|
83
|
+
if (!isObject(firstBlock))
|
|
84
|
+
return undefined;
|
|
85
|
+
if (firstBlock['type'] !== 'text')
|
|
86
|
+
return undefined;
|
|
87
|
+
if (typeof firstBlock['text'] !== 'string')
|
|
88
|
+
return undefined;
|
|
89
|
+
try {
|
|
90
|
+
const payload = toolErrorPayloadSchema.safeParse(JSON.parse(firstBlock['text']));
|
|
91
|
+
return payload.success
|
|
92
|
+
? normalizeToolErrorPayload(payload.data)
|
|
93
|
+
: undefined;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function tryReadToolErrorMessage(value) {
|
|
100
|
+
return tryReadToolErrorPayload(value)?.error;
|
|
101
|
+
}
|
|
102
|
+
function renderToolErrorResponse(presentation) {
|
|
103
|
+
return createToolErrorResponse(presentation.message, presentation.url, {
|
|
104
|
+
...(presentation.category !== undefined
|
|
105
|
+
? { category: presentation.category }
|
|
106
|
+
: {}),
|
|
107
|
+
...(presentation.code !== undefined ? { code: presentation.code } : {}),
|
|
108
|
+
...(presentation.statusCode !== undefined
|
|
109
|
+
? { statusCode: presentation.statusCode }
|
|
110
|
+
: {}),
|
|
111
|
+
...(presentation.upstreamMessage !== undefined
|
|
112
|
+
? { upstreamMessage: presentation.upstreamMessage }
|
|
113
|
+
: {}),
|
|
114
|
+
...(presentation.details ? { details: presentation.details } : {}),
|
|
115
|
+
...(presentation.data !== undefined ? { data: presentation.data } : {}),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function isValidationError(error) {
|
|
119
|
+
return (error instanceof Error &&
|
|
120
|
+
isSystemError(error) &&
|
|
121
|
+
error.code === VALIDATION_ERROR);
|
|
122
|
+
}
|
|
123
|
+
function extractHttpStatusText(message, statusCode) {
|
|
124
|
+
const prefix = `HTTP ${statusCode}:`;
|
|
125
|
+
if (!message.startsWith(prefix))
|
|
126
|
+
return '';
|
|
127
|
+
return message.slice(prefix.length).trim();
|
|
128
|
+
}
|
|
129
|
+
function buildUpstreamHttpMessage(error) {
|
|
130
|
+
const { statusCode } = error;
|
|
131
|
+
const statusText = extractHttpStatusText(error.message, statusCode);
|
|
132
|
+
const suffix = statusText ? ` ${statusText}` : '';
|
|
133
|
+
if (statusCode === 404) {
|
|
134
|
+
return `The target page returned 404${suffix}.`;
|
|
135
|
+
}
|
|
136
|
+
return `The target server returned ${statusCode}${suffix}.`;
|
|
137
|
+
}
|
|
138
|
+
function mapFetchToolError(error, fallbackUrl) {
|
|
139
|
+
const { code: detailsCode, reason } = error.details;
|
|
140
|
+
let { code } = error;
|
|
141
|
+
if (typeof detailsCode === 'string') {
|
|
142
|
+
code = detailsCode;
|
|
143
|
+
}
|
|
144
|
+
else if (reason === QUEUE_FULL) {
|
|
145
|
+
code = QUEUE_FULL;
|
|
146
|
+
}
|
|
147
|
+
const url = error.url || fallbackUrl;
|
|
148
|
+
const details = sanitizeToolErrorDetails(error.details);
|
|
149
|
+
if (reason === 'timeout') {
|
|
150
|
+
return {
|
|
151
|
+
message: 'The request to the target timed out.',
|
|
152
|
+
url,
|
|
153
|
+
category: 'upstream_timeout',
|
|
154
|
+
code,
|
|
155
|
+
statusCode: error.statusCode,
|
|
156
|
+
upstreamMessage: error.message,
|
|
157
|
+
...(details ? { details } : {}),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (reason === 'aborted') {
|
|
161
|
+
return {
|
|
162
|
+
message: 'The request to the target was cancelled.',
|
|
163
|
+
url,
|
|
164
|
+
category: 'upstream_aborted',
|
|
165
|
+
code,
|
|
166
|
+
statusCode: error.statusCode,
|
|
167
|
+
upstreamMessage: error.message,
|
|
168
|
+
...(details ? { details } : {}),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (reason === QUEUE_FULL) {
|
|
172
|
+
return {
|
|
173
|
+
message: error.message,
|
|
174
|
+
url,
|
|
175
|
+
category: 'queue_full',
|
|
176
|
+
code,
|
|
177
|
+
statusCode: error.statusCode,
|
|
178
|
+
...(details ? { details } : {}),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const isRealHttpError = typeof error.details['httpStatus'] === 'number';
|
|
182
|
+
if (isRealHttpError && error.statusCode >= 400) {
|
|
183
|
+
return {
|
|
184
|
+
message: buildUpstreamHttpMessage(error),
|
|
185
|
+
url,
|
|
186
|
+
category: error.statusCode === 429
|
|
187
|
+
? 'upstream_rate_limited'
|
|
188
|
+
: 'upstream_http_error',
|
|
189
|
+
code,
|
|
190
|
+
statusCode: error.statusCode,
|
|
191
|
+
upstreamMessage: error.message,
|
|
192
|
+
...(details ? { details } : {}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
message: error.message,
|
|
197
|
+
url,
|
|
198
|
+
category: 'fetch_error',
|
|
199
|
+
code,
|
|
200
|
+
statusCode: error.statusCode,
|
|
201
|
+
...(details ? { details } : {}),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function mapGenericToolError(error, url, fallbackMessage) {
|
|
205
|
+
if (isValidationError(error)) {
|
|
206
|
+
return {
|
|
207
|
+
message: error.message,
|
|
208
|
+
url,
|
|
209
|
+
category: 'validation_error',
|
|
210
|
+
code: VALIDATION_ERROR,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const isAborted = isAbortError(error);
|
|
214
|
+
return {
|
|
215
|
+
message: error instanceof Error
|
|
216
|
+
? error.message
|
|
217
|
+
: `${fallbackMessage}: unknown error`,
|
|
218
|
+
url,
|
|
219
|
+
category: isAborted ? 'upstream_aborted' : 'fetch_error',
|
|
220
|
+
code: isAborted ? ABORTED : FETCH_ERROR,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function resolveToolErrorPresentation(error, url, fallbackMessage) {
|
|
224
|
+
if (error instanceof FetchError) {
|
|
225
|
+
return mapFetchToolError(error, url);
|
|
226
|
+
}
|
|
227
|
+
return mapGenericToolError(error, url, fallbackMessage);
|
|
228
|
+
}
|
|
229
|
+
export function handleToolError(error, url, fallbackMessage = 'Operation failed') {
|
|
230
|
+
return renderToolErrorResponse(resolveToolErrorPresentation(error, url, fallbackMessage));
|
|
231
|
+
}
|
|
232
|
+
export function classifyAndLogToolError(error, meta, loggerName, toolName, fallbackMessage) {
|
|
233
|
+
if (error instanceof McpError) {
|
|
234
|
+
logError(`${toolName} tool failed`, { url: meta.url, durationMs: meta.durationMs, error }, loggerName);
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
if (error instanceof FetchError || isAbortError(error)) {
|
|
238
|
+
logWarn(`${toolName} request failed`, {
|
|
239
|
+
url: meta.url,
|
|
240
|
+
error: error instanceof Error ? error.message : String(error),
|
|
241
|
+
durationMs: meta.durationMs,
|
|
242
|
+
}, loggerName);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
logError(`${toolName} request failed unexpectedly`, {
|
|
246
|
+
url: meta.url,
|
|
247
|
+
error: error instanceof Error ? error.message : String(error),
|
|
248
|
+
durationMs: meta.durationMs,
|
|
249
|
+
}, loggerName);
|
|
250
|
+
}
|
|
251
|
+
return handleToolError(error, meta.url, fallbackMessage);
|
|
252
|
+
}
|
package/dist/lib/url.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/lib/url.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAiB,MAAM,UAAU,CAAC;AAG1D,OAAO,EAAE,MAAM,EAAY,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/lib/url.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/url.js
CHANGED
|
@@ -2,7 +2,10 @@ import dns from 'node:dns';
|
|
|
2
2
|
import { BlockList, isIP, SocketAddress } from 'node:net';
|
|
3
3
|
import { domainToASCII } from 'node:url';
|
|
4
4
|
import { config, logDebug } from './core.js';
|
|
5
|
-
import {
|
|
5
|
+
import { VALIDATION_ERROR } from './error-codes.js';
|
|
6
|
+
import { blockedCnameError, blockedHostError, blockedIpError, dnsNoResultsError, dnsTimeoutError, invalidAddressFamilyError, invalidHostnameError, invalidUrlError, } from './error-messages.js';
|
|
7
|
+
import { LOG_FETCH } from './logger-names.js';
|
|
8
|
+
import { CodedError, composeAbortSignal, isError, isSystemError, } from './utils.js';
|
|
6
9
|
const DNS_LOOKUP_TIMEOUT_MS = 5000;
|
|
7
10
|
const CNAME_LOOKUP_MAX_DEPTH = 5;
|
|
8
11
|
async function withTimeout(promise, timeoutMs, onTimeout, signal, onAbort) {
|
|
@@ -14,7 +17,7 @@ async function withTimeout(promise, timeoutMs, onTimeout, signal, onAbort) {
|
|
|
14
17
|
: onTimeout();
|
|
15
18
|
if (raceSignal.aborted)
|
|
16
19
|
throw classifyError();
|
|
17
|
-
|
|
20
|
+
const racePromise = new Promise((resolve, reject) => {
|
|
18
21
|
const handleAbort = () => {
|
|
19
22
|
reject(classifyError());
|
|
20
23
|
};
|
|
@@ -23,6 +26,7 @@ async function withTimeout(promise, timeoutMs, onTimeout, signal, onAbort) {
|
|
|
23
26
|
raceSignal.removeEventListener('abort', handleAbort);
|
|
24
27
|
});
|
|
25
28
|
});
|
|
29
|
+
return racePromise;
|
|
26
30
|
}
|
|
27
31
|
function createAbortSignalError() {
|
|
28
32
|
const err = new Error('Request was canceled');
|
|
@@ -47,20 +51,18 @@ export class SafeDnsResolver {
|
|
|
47
51
|
if (!result)
|
|
48
52
|
return;
|
|
49
53
|
const errorTarget = context ?? ip;
|
|
50
|
-
throw
|
|
51
|
-
? `Blocked IP range: ${errorTarget}. Cloud metadata endpoints are not allowed`
|
|
52
|
-
: `Blocked IP range: ${errorTarget}. Private IPs are not allowed`, 'EBLOCKED');
|
|
54
|
+
throw blockedIpError(errorTarget, result.reason === 'cloud-metadata' ? 'cloud-metadata' : 'private');
|
|
53
55
|
}
|
|
54
56
|
async resolveAndValidate(hostname, signal) {
|
|
55
57
|
const normalizedHostname = normalizeHostname(hostname.replace(/^\[|\]$/g, ''));
|
|
56
58
|
if (!normalizedHostname) {
|
|
57
|
-
throw
|
|
59
|
+
throw invalidHostnameError();
|
|
58
60
|
}
|
|
59
61
|
if (signal?.aborted) {
|
|
60
62
|
throw createAbortSignalError();
|
|
61
63
|
}
|
|
62
64
|
if (this.isBlockedHostname(normalizedHostname)) {
|
|
63
|
-
throw
|
|
65
|
+
throw blockedHostError(normalizedHostname);
|
|
64
66
|
}
|
|
65
67
|
if (isIP(normalizedHostname)) {
|
|
66
68
|
this.assertIpAllowed(normalizedHostname);
|
|
@@ -71,13 +73,13 @@ export class SafeDnsResolver {
|
|
|
71
73
|
all: true,
|
|
72
74
|
order: 'verbatim',
|
|
73
75
|
});
|
|
74
|
-
const addresses = await withTimeout(resultPromise, DNS_LOOKUP_TIMEOUT_MS, () =>
|
|
76
|
+
const addresses = await withTimeout(resultPromise, DNS_LOOKUP_TIMEOUT_MS, () => dnsTimeoutError(normalizedHostname), signal, createAbortSignalError);
|
|
75
77
|
if (addresses.length === 0 || !addresses[0]) {
|
|
76
|
-
throw
|
|
78
|
+
throw dnsNoResultsError(normalizedHostname);
|
|
77
79
|
}
|
|
78
80
|
for (const addr of addresses) {
|
|
79
81
|
if (addr.family !== 4 && addr.family !== 6) {
|
|
80
|
-
throw
|
|
82
|
+
throw invalidAddressFamilyError(normalizedHostname);
|
|
81
83
|
}
|
|
82
84
|
this.assertIpAllowed(addr.address, normalizedHostname);
|
|
83
85
|
}
|
|
@@ -98,7 +100,7 @@ export class SafeDnsResolver {
|
|
|
98
100
|
return;
|
|
99
101
|
for (const cname of cnames) {
|
|
100
102
|
if (this.isBlockedHostname(cname)) {
|
|
101
|
-
throw
|
|
103
|
+
throw blockedCnameError(hostname, cname);
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
current = cnames[0] ?? '';
|
|
@@ -127,7 +129,7 @@ export class SafeDnsResolver {
|
|
|
127
129
|
logDebug('DNS CNAME lookup failed; continuing with address lookup', {
|
|
128
130
|
hostname,
|
|
129
131
|
...(isSystemError(error) ? { code: error.code } : {}),
|
|
130
|
-
},
|
|
132
|
+
}, LOG_FETCH);
|
|
131
133
|
return [];
|
|
132
134
|
}
|
|
133
135
|
}
|
|
@@ -135,7 +137,7 @@ export class SafeDnsResolver {
|
|
|
135
137
|
function extractHostname(url) {
|
|
136
138
|
const parsed = URL.parse(url);
|
|
137
139
|
if (!parsed)
|
|
138
|
-
throw
|
|
140
|
+
throw invalidUrlError();
|
|
139
141
|
return parsed.hostname;
|
|
140
142
|
}
|
|
141
143
|
export function createDnsPreflight(dnsResolver) {
|
|
@@ -439,9 +441,10 @@ export class RawUrlTransformer {
|
|
|
439
441
|
});
|
|
440
442
|
}
|
|
441
443
|
}
|
|
442
|
-
export const VALIDATION_ERROR_CODE =
|
|
444
|
+
export const VALIDATION_ERROR_CODE = VALIDATION_ERROR;
|
|
443
445
|
function createValidationError(message) {
|
|
444
|
-
|
|
446
|
+
const error = new CodedError(message, VALIDATION_ERROR);
|
|
447
|
+
return error;
|
|
445
448
|
}
|
|
446
449
|
export const BLOCKED_HOST_SUFFIXES = ['.local', '.internal'];
|
|
447
450
|
function isLocalFetchAllowed() {
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -14,7 +14,10 @@ export declare class FetchError extends Error {
|
|
|
14
14
|
export declare function getErrorMessage(error: unknown): string;
|
|
15
15
|
export declare function toError(error: unknown): Error;
|
|
16
16
|
export declare function isAbortError(error: unknown): boolean;
|
|
17
|
-
export declare
|
|
17
|
+
export declare class CodedError extends Error {
|
|
18
|
+
readonly code: string;
|
|
19
|
+
constructor(message: string, code: string, options?: ErrorOptions);
|
|
20
|
+
}
|
|
18
21
|
export declare function isSystemError(error: unknown): error is NodeJS.ErrnoException;
|
|
19
22
|
interface TunableHttpServer {
|
|
20
23
|
headersTimeout?: number;
|
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"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"}
|