@j0hanz/fetch-url-mcp 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/dist/cli.d.ts +2 -3
  2. package/dist/cli.js +1 -2
  3. package/dist/http/auth.d.ts +5 -3
  4. package/dist/http/auth.js +64 -15
  5. package/dist/http/health.d.ts +1 -2
  6. package/dist/http/health.js +7 -18
  7. package/dist/http/helpers.d.ts +3 -4
  8. package/dist/http/helpers.js +21 -21
  9. package/dist/http/native.d.ts +0 -1
  10. package/dist/http/native.js +34 -26
  11. package/dist/http/rate-limit.d.ts +0 -1
  12. package/dist/http/rate-limit.js +3 -4
  13. package/dist/index.d.ts +0 -1
  14. package/dist/index.js +17 -18
  15. package/dist/lib/{markdown-cleanup.d.ts → content.d.ts} +4 -2
  16. package/dist/lib/content.js +1356 -0
  17. package/dist/lib/core.d.ts +253 -0
  18. package/dist/lib/core.js +1228 -0
  19. package/dist/lib/{tool-pipeline.d.ts → fetch-pipeline.d.ts} +1 -2
  20. package/dist/lib/{tool-pipeline.js → fetch-pipeline.js} +10 -19
  21. package/dist/lib/{fetch.d.ts → http.d.ts} +7 -9
  22. package/dist/lib/{fetch.js → http.js} +706 -944
  23. package/dist/lib/mcp-tools.d.ts +28 -0
  24. package/dist/lib/mcp-tools.js +107 -0
  25. package/dist/lib/{tool-progress.d.ts → progress.d.ts} +0 -1
  26. package/dist/lib/{tool-progress.js → progress.js} +8 -13
  27. package/dist/lib/task-handlers.d.ts +5 -0
  28. package/dist/lib/{mcp.js → task-handlers.js} +56 -12
  29. package/dist/lib/url.d.ts +70 -0
  30. package/dist/lib/url.js +686 -0
  31. package/dist/lib/utils.d.ts +58 -0
  32. package/dist/lib/utils.js +304 -0
  33. package/dist/prompts/index.d.ts +0 -1
  34. package/dist/prompts/index.js +0 -1
  35. package/dist/resources/index.d.ts +0 -1
  36. package/dist/resources/index.js +74 -33
  37. package/dist/resources/instructions.d.ts +0 -1
  38. package/dist/resources/instructions.js +2 -2
  39. package/dist/schemas/inputs.d.ts +0 -1
  40. package/dist/schemas/inputs.js +2 -3
  41. package/dist/schemas/outputs.d.ts +0 -1
  42. package/dist/schemas/outputs.js +1 -2
  43. package/dist/server.d.ts +0 -1
  44. package/dist/server.js +16 -26
  45. package/dist/tasks/execution.d.ts +0 -1
  46. package/dist/tasks/execution.js +27 -24
  47. package/dist/tasks/manager.d.ts +7 -3
  48. package/dist/tasks/manager.js +53 -34
  49. package/dist/tasks/owner.d.ts +1 -2
  50. package/dist/tasks/owner.js +1 -2
  51. package/dist/tasks/tool-registry.d.ts +1 -2
  52. package/dist/tasks/tool-registry.js +0 -1
  53. package/dist/tools/fetch-url.d.ts +1 -2
  54. package/dist/tools/fetch-url.js +39 -31
  55. package/dist/tools/index.d.ts +0 -1
  56. package/dist/tools/index.js +0 -1
  57. package/dist/transform/html-translators.d.ts +1 -0
  58. package/dist/transform/html-translators.js +454 -0
  59. package/dist/transform/metadata.d.ts +4 -0
  60. package/dist/transform/metadata.js +183 -0
  61. package/dist/transform/transform.d.ts +0 -1
  62. package/dist/transform/transform.js +24 -641
  63. package/dist/transform/types.d.ts +9 -11
  64. package/dist/transform/types.js +0 -1
  65. package/dist/transform/worker-pool.d.ts +0 -1
  66. package/dist/transform/worker-pool.js +7 -16
  67. package/dist/transform/workers/shared.d.ts +0 -1
  68. package/dist/transform/workers/shared.js +1 -2
  69. package/dist/transform/workers/transform-child.d.ts +0 -1
  70. package/dist/transform/workers/transform-child.js +0 -1
  71. package/dist/transform/workers/transform-worker.d.ts +0 -1
  72. package/dist/transform/workers/transform-worker.js +0 -1
  73. package/package.json +6 -3
  74. package/dist/cli.d.ts.map +0 -1
  75. package/dist/cli.js.map +0 -1
  76. package/dist/http/auth.d.ts.map +0 -1
  77. package/dist/http/auth.js.map +0 -1
  78. package/dist/http/health.d.ts.map +0 -1
  79. package/dist/http/health.js.map +0 -1
  80. package/dist/http/helpers.d.ts.map +0 -1
  81. package/dist/http/helpers.js.map +0 -1
  82. package/dist/http/native.d.ts.map +0 -1
  83. package/dist/http/native.js.map +0 -1
  84. package/dist/http/rate-limit.d.ts.map +0 -1
  85. package/dist/http/rate-limit.js.map +0 -1
  86. package/dist/index.d.ts.map +0 -1
  87. package/dist/index.js.map +0 -1
  88. package/dist/lib/cache.d.ts +0 -54
  89. package/dist/lib/cache.d.ts.map +0 -1
  90. package/dist/lib/cache.js +0 -264
  91. package/dist/lib/cache.js.map +0 -1
  92. package/dist/lib/config.d.ts +0 -143
  93. package/dist/lib/config.d.ts.map +0 -1
  94. package/dist/lib/config.js +0 -476
  95. package/dist/lib/config.js.map +0 -1
  96. package/dist/lib/crypto.d.ts +0 -4
  97. package/dist/lib/crypto.d.ts.map +0 -1
  98. package/dist/lib/crypto.js +0 -56
  99. package/dist/lib/crypto.js.map +0 -1
  100. package/dist/lib/dom-noise-removal.d.ts +0 -2
  101. package/dist/lib/dom-noise-removal.d.ts.map +0 -1
  102. package/dist/lib/dom-noise-removal.js +0 -494
  103. package/dist/lib/dom-noise-removal.js.map +0 -1
  104. package/dist/lib/download.d.ts +0 -4
  105. package/dist/lib/download.d.ts.map +0 -1
  106. package/dist/lib/download.js +0 -106
  107. package/dist/lib/download.js.map +0 -1
  108. package/dist/lib/errors.d.ts +0 -14
  109. package/dist/lib/errors.d.ts.map +0 -1
  110. package/dist/lib/errors.js +0 -72
  111. package/dist/lib/errors.js.map +0 -1
  112. package/dist/lib/fetch-content.d.ts +0 -5
  113. package/dist/lib/fetch-content.d.ts.map +0 -1
  114. package/dist/lib/fetch-content.js +0 -164
  115. package/dist/lib/fetch-content.js.map +0 -1
  116. package/dist/lib/fetch-stream.d.ts +0 -5
  117. package/dist/lib/fetch-stream.d.ts.map +0 -1
  118. package/dist/lib/fetch-stream.js +0 -29
  119. package/dist/lib/fetch-stream.js.map +0 -1
  120. package/dist/lib/fetch.d.ts.map +0 -1
  121. package/dist/lib/fetch.js.map +0 -1
  122. package/dist/lib/host-normalization.d.ts +0 -2
  123. package/dist/lib/host-normalization.d.ts.map +0 -1
  124. package/dist/lib/host-normalization.js +0 -91
  125. package/dist/lib/host-normalization.js.map +0 -1
  126. package/dist/lib/ip-blocklist.d.ts +0 -9
  127. package/dist/lib/ip-blocklist.d.ts.map +0 -1
  128. package/dist/lib/ip-blocklist.js +0 -79
  129. package/dist/lib/ip-blocklist.js.map +0 -1
  130. package/dist/lib/json.d.ts +0 -2
  131. package/dist/lib/json.d.ts.map +0 -1
  132. package/dist/lib/json.js +0 -45
  133. package/dist/lib/json.js.map +0 -1
  134. package/dist/lib/language-detection.d.ts +0 -3
  135. package/dist/lib/language-detection.d.ts.map +0 -1
  136. package/dist/lib/language-detection.js +0 -355
  137. package/dist/lib/language-detection.js.map +0 -1
  138. package/dist/lib/markdown-cleanup.d.ts.map +0 -1
  139. package/dist/lib/markdown-cleanup.js +0 -532
  140. package/dist/lib/markdown-cleanup.js.map +0 -1
  141. package/dist/lib/mcp-lifecycle.d.ts +0 -5
  142. package/dist/lib/mcp-lifecycle.d.ts.map +0 -1
  143. package/dist/lib/mcp-lifecycle.js +0 -51
  144. package/dist/lib/mcp-lifecycle.js.map +0 -1
  145. package/dist/lib/mcp-validator.d.ts +0 -17
  146. package/dist/lib/mcp-validator.d.ts.map +0 -1
  147. package/dist/lib/mcp-validator.js +0 -45
  148. package/dist/lib/mcp-validator.js.map +0 -1
  149. package/dist/lib/mcp.d.ts +0 -4
  150. package/dist/lib/mcp.d.ts.map +0 -1
  151. package/dist/lib/mcp.js.map +0 -1
  152. package/dist/lib/observability.d.ts +0 -23
  153. package/dist/lib/observability.d.ts.map +0 -1
  154. package/dist/lib/observability.js +0 -238
  155. package/dist/lib/observability.js.map +0 -1
  156. package/dist/lib/server-tuning.d.ts +0 -15
  157. package/dist/lib/server-tuning.d.ts.map +0 -1
  158. package/dist/lib/server-tuning.js +0 -49
  159. package/dist/lib/server-tuning.js.map +0 -1
  160. package/dist/lib/session.d.ts +0 -45
  161. package/dist/lib/session.d.ts.map +0 -1
  162. package/dist/lib/session.js +0 -263
  163. package/dist/lib/session.js.map +0 -1
  164. package/dist/lib/timer-utils.d.ts +0 -13
  165. package/dist/lib/timer-utils.d.ts.map +0 -1
  166. package/dist/lib/timer-utils.js +0 -44
  167. package/dist/lib/timer-utils.js.map +0 -1
  168. package/dist/lib/tool-errors.d.ts +0 -12
  169. package/dist/lib/tool-errors.d.ts.map +0 -1
  170. package/dist/lib/tool-errors.js +0 -55
  171. package/dist/lib/tool-errors.js.map +0 -1
  172. package/dist/lib/tool-pipeline.d.ts.map +0 -1
  173. package/dist/lib/tool-pipeline.js.map +0 -1
  174. package/dist/lib/tool-progress.d.ts.map +0 -1
  175. package/dist/lib/tool-progress.js.map +0 -1
  176. package/dist/lib/type-guards.d.ts +0 -16
  177. package/dist/lib/type-guards.d.ts.map +0 -1
  178. package/dist/lib/type-guards.js +0 -13
  179. package/dist/lib/type-guards.js.map +0 -1
  180. package/dist/prompts/index.d.ts.map +0 -1
  181. package/dist/prompts/index.js.map +0 -1
  182. package/dist/resources/index.d.ts.map +0 -1
  183. package/dist/resources/index.js.map +0 -1
  184. package/dist/resources/instructions.d.ts.map +0 -1
  185. package/dist/resources/instructions.js.map +0 -1
  186. package/dist/schemas/inputs.d.ts.map +0 -1
  187. package/dist/schemas/inputs.js.map +0 -1
  188. package/dist/schemas/outputs.d.ts.map +0 -1
  189. package/dist/schemas/outputs.js.map +0 -1
  190. package/dist/server.d.ts.map +0 -1
  191. package/dist/server.js.map +0 -1
  192. package/dist/tasks/execution.d.ts.map +0 -1
  193. package/dist/tasks/execution.js.map +0 -1
  194. package/dist/tasks/manager.d.ts.map +0 -1
  195. package/dist/tasks/manager.js.map +0 -1
  196. package/dist/tasks/owner.d.ts.map +0 -1
  197. package/dist/tasks/owner.js.map +0 -1
  198. package/dist/tasks/tool-registry.d.ts.map +0 -1
  199. package/dist/tasks/tool-registry.js.map +0 -1
  200. package/dist/tools/fetch-url.d.ts.map +0 -1
  201. package/dist/tools/fetch-url.js.map +0 -1
  202. package/dist/tools/index.d.ts.map +0 -1
  203. package/dist/tools/index.js.map +0 -1
  204. package/dist/transform/transform.d.ts.map +0 -1
  205. package/dist/transform/transform.js.map +0 -1
  206. package/dist/transform/types.d.ts.map +0 -1
  207. package/dist/transform/types.js.map +0 -1
  208. package/dist/transform/worker-pool.d.ts.map +0 -1
  209. package/dist/transform/worker-pool.js.map +0 -1
  210. package/dist/transform/workers/shared.d.ts.map +0 -1
  211. package/dist/transform/workers/shared.js.map +0 -1
  212. package/dist/transform/workers/transform-child.d.ts.map +0 -1
  213. package/dist/transform/workers/transform-child.js.map +0 -1
  214. package/dist/transform/workers/transform-worker.d.ts.map +0 -1
  215. package/dist/transform/workers/transform-worker.js.map +0 -1
@@ -0,0 +1,28 @@
1
+ import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export type JsonRpcId = string | number | null;
3
+ interface McpRequestParams {
4
+ _meta?: Record<string, unknown>;
5
+ [key: string]: unknown;
6
+ }
7
+ interface McpRequestBody {
8
+ jsonrpc: '2.0';
9
+ method: string;
10
+ id?: JsonRpcId;
11
+ params?: McpRequestParams;
12
+ }
13
+ export declare function isJsonRpcBatchRequest(body: unknown): boolean;
14
+ export declare function isMcpRequestBody(body: unknown): body is McpRequestBody;
15
+ export declare function acceptsEventStream(header: string | null | undefined): boolean;
16
+ export declare function acceptsJsonAndEventStream(header: string | null | undefined): boolean;
17
+ type ToolErrorResponse = CallToolResult & {
18
+ isError: true;
19
+ };
20
+ export declare function createToolErrorResponse(message: string, url: string, extra?: {
21
+ code?: string;
22
+ statusCode?: number;
23
+ details?: Record<string, unknown>;
24
+ }): ToolErrorResponse;
25
+ export declare function handleToolError(error: unknown, url: string, fallbackMessage?: string): ToolErrorResponse;
26
+ export { registerServerLifecycleCleanup, registerTaskHandlers, cancelTasksForOwner, abortAllTaskExecutions, } from './task-handlers.js';
27
+ export { readString, readNestedRecord, withSignal, TRUNCATION_MARKER, type InlineContentResult, appendTruncationMarker, type PipelineResult, executeFetchPipeline, type MarkdownPipelineResult, parseCachedMarkdownResult, markdownTransform, serializeMarkdownResult, performSharedFetch, } from './fetch-pipeline.js';
28
+ export { type ProgressNotificationParams, type ProgressNotification, type ToolHandlerExtra, type ProgressReporter, createProgressReporter, } from './progress.js';
@@ -0,0 +1,107 @@
1
+ import {} from '@modelcontextprotocol/sdk/types.js';
2
+ import { z } from 'zod';
3
+ import { FetchError, isAbortError, isSystemError } from './utils.js';
4
+ const paramsSchema = z.looseObject({});
5
+ const mcpRequestSchema = z.strictObject({
6
+ jsonrpc: z.literal('2.0'),
7
+ method: z.string().min(1),
8
+ id: z.union([z.string(), z.number(), z.null()]).optional(),
9
+ params: paramsSchema.optional(),
10
+ });
11
+ export function isJsonRpcBatchRequest(body) {
12
+ return Array.isArray(body);
13
+ }
14
+ export function isMcpRequestBody(body) {
15
+ return mcpRequestSchema.safeParse(body).success;
16
+ }
17
+ function parseAcceptMediaTypes(header) {
18
+ if (!header)
19
+ return [];
20
+ return header
21
+ .split(',')
22
+ .map((value) => extractAcceptMediaType(value.trim()))
23
+ .filter((value) => value.length > 0);
24
+ }
25
+ function extractAcceptMediaType(value) {
26
+ return value.split(';', 1)[0]?.trim().toLowerCase() ?? '';
27
+ }
28
+ export function acceptsEventStream(header) {
29
+ const mediaTypes = parseAcceptMediaTypes(header);
30
+ return mediaTypes.some((mediaType) => mediaType === 'text/event-stream');
31
+ }
32
+ function hasAcceptedMediaType(mediaTypes, exact, wildcardPrefix) {
33
+ return mediaTypes.some((mediaType) => typeof mediaType === 'string' &&
34
+ mediaType.length > 0 &&
35
+ (mediaType === '*/*' ||
36
+ mediaType === exact ||
37
+ mediaType === wildcardPrefix));
38
+ }
39
+ export function acceptsJsonAndEventStream(header) {
40
+ const mediaTypes = parseAcceptMediaTypes(header);
41
+ const acceptsJson = hasAcceptedMediaType(mediaTypes, 'application/json', 'application/*');
42
+ if (!acceptsJson)
43
+ return false;
44
+ return hasAcceptedMediaType(mediaTypes, 'text/event-stream', 'text/*');
45
+ }
46
+ export function createToolErrorResponse(message, url, extra) {
47
+ const errorContent = {
48
+ error: message,
49
+ ...(extra?.code ? { code: extra.code } : {}),
50
+ url,
51
+ ...(extra?.statusCode !== undefined
52
+ ? { statusCode: extra.statusCode }
53
+ : {}),
54
+ ...(extra?.details ? { details: extra.details } : {}),
55
+ };
56
+ return {
57
+ content: [{ type: 'text', text: JSON.stringify(errorContent) }],
58
+ isError: true,
59
+ };
60
+ }
61
+ function isValidationError(error) {
62
+ return (error instanceof Error &&
63
+ isSystemError(error) &&
64
+ error.code === 'VALIDATION_ERROR');
65
+ }
66
+ function isHandledToolError(error) {
67
+ return error instanceof FetchError || isValidationError(error);
68
+ }
69
+ function resolveToolErrorMessage(error, fallbackMessage) {
70
+ if (isHandledToolError(error)) {
71
+ return error.message;
72
+ }
73
+ if (error instanceof Error) {
74
+ return `${fallbackMessage}: ${error.message}`;
75
+ }
76
+ return `${fallbackMessage}: Unknown error`;
77
+ }
78
+ function resolveToolErrorCode(error) {
79
+ if (error instanceof FetchError)
80
+ return error.code;
81
+ if (isValidationError(error))
82
+ return 'VALIDATION_ERROR';
83
+ if (isAbortError(error))
84
+ return 'ABORTED';
85
+ return 'FETCH_ERROR';
86
+ }
87
+ export function handleToolError(error, url, fallbackMessage = 'Operation failed') {
88
+ const message = resolveToolErrorMessage(error, fallbackMessage);
89
+ const code = resolveToolErrorCode(error);
90
+ if (error instanceof FetchError) {
91
+ return createToolErrorResponse(message, url, {
92
+ code,
93
+ statusCode: error.statusCode,
94
+ details: error.details,
95
+ });
96
+ }
97
+ return createToolErrorResponse(message, url, { code });
98
+ }
99
+ /* -------------------------------------------------------------------------------------------------
100
+ * Re-exports from split modules
101
+ *
102
+ * Preserves backward compatibility — consumers import from 'lib/mcp-tools.js'
103
+ * without changes. Direct imports from the sub-modules are preferred for new code.
104
+ * ------------------------------------------------------------------------------------------------- */
105
+ export { registerServerLifecycleCleanup, registerTaskHandlers, cancelTasksForOwner, abortAllTaskExecutions, } from './task-handlers.js';
106
+ export { readString, readNestedRecord, withSignal, TRUNCATION_MARKER, appendTruncationMarker, executeFetchPipeline, parseCachedMarkdownResult, markdownTransform, serializeMarkdownResult, performSharedFetch, } from './fetch-pipeline.js';
107
+ export { createProgressReporter, } from './progress.js';
@@ -28,4 +28,3 @@ export interface ProgressReporter {
28
28
  }
29
29
  export declare function createProgressReporter(extra?: ToolHandlerExtra): ProgressReporter;
30
30
  export {};
31
- //# sourceMappingURL=tool-progress.d.ts.map
@@ -1,14 +1,7 @@
1
- import { getErrorMessage } from './errors.js';
2
- import { logWarn } from './observability.js';
3
- import { isObject } from './type-guards.js';
4
- /* -------------------------------------------------------------------------------------------------
5
- * Constants
6
- * ------------------------------------------------------------------------------------------------- */
1
+ import { logWarn } from './core.js';
2
+ import { getErrorMessage, isObject } from './utils.js';
7
3
  const FETCH_PROGRESS_TOTAL = 4;
8
4
  const PROGRESS_NOTIFICATION_TIMEOUT_MS = 5000;
9
- /* -------------------------------------------------------------------------------------------------
10
- * Helpers
11
- * ------------------------------------------------------------------------------------------------- */
12
5
  function resolveRelatedTaskMeta(meta) {
13
6
  if (!meta)
14
7
  return undefined;
@@ -18,9 +11,6 @@ function resolveRelatedTaskMeta(meta) {
18
11
  const { taskId } = related;
19
12
  return typeof taskId === 'string' ? { taskId } : undefined;
20
13
  }
21
- /* -------------------------------------------------------------------------------------------------
22
- * Progress reporter
23
- * ------------------------------------------------------------------------------------------------- */
24
14
  class ToolProgressReporter {
25
15
  token;
26
16
  sendNotification;
@@ -45,6 +35,12 @@ class ToolProgressReporter {
45
35
  }
46
36
  return new ToolProgressReporter(token, sendNotification, relatedTaskMeta, onProgress);
47
37
  }
38
+ /**
39
+ * Report progress toward completion. Steps are monotonic (never decrease)
40
+ * and may be skipped under normal conditions (e.g., fast responses skip
41
+ * intermediate steps). Clients should treat progress as "at least this far"
42
+ * rather than expecting every step to fire sequentially.
43
+ */
48
44
  report(progress, message) {
49
45
  if (this.isTerminal)
50
46
  return;
@@ -126,4 +122,3 @@ class ToolProgressReporter {
126
122
  export function createProgressReporter(extra) {
127
123
  return ToolProgressReporter.create(extra);
128
124
  }
129
- //# sourceMappingURL=tool-progress.js.map
@@ -0,0 +1,5 @@
1
+ import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ type CleanupCallback = () => void;
3
+ export declare function registerServerLifecycleCleanup(server: McpServer, callback: CleanupCallback): void;
4
+ export { cancelTasksForOwner, abortAllTaskExecutions, } from '../tasks/execution.js';
5
+ export declare function registerTaskHandlers(server: McpServer): void;
@@ -1,15 +1,59 @@
1
- import { CallToolRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
2
1
  import { randomUUID } from 'node:crypto';
2
+ import {} from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { CallToolRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
3
4
  import { z } from 'zod';
4
5
  import { abortTaskExecution, emitTaskStatusNotification, handleToolCallRequest, throwTaskNotFound, toTaskSummary, withRelatedTaskMeta, } from '../tasks/execution.js';
5
6
  import { taskManager } from '../tasks/manager.js';
6
7
  import { isServerResult, parseHandlerExtra, resolveTaskOwnerKey, resolveToolCallContext, } from '../tasks/owner.js';
7
8
  import { hasTaskCapableTool } from '../tasks/tool-registry.js';
8
- import { runWithRequestContext } from './observability.js';
9
- // Re-export public API so existing consumers (tests, other modules) keep working.
9
+ import { logWarn, runWithRequestContext } from './core.js';
10
+ const patchedCleanupServers = new WeakSet();
11
+ const serverCleanupCallbacks = new WeakMap();
12
+ function getServerCleanupCallbackSet(server) {
13
+ let callbacks = serverCleanupCallbacks.get(server);
14
+ if (!callbacks) {
15
+ callbacks = new Set();
16
+ serverCleanupCallbacks.set(server, callbacks);
17
+ }
18
+ return callbacks;
19
+ }
20
+ function drainServerCleanupCallbacks(server) {
21
+ const callbacks = serverCleanupCallbacks.get(server);
22
+ if (!callbacks || callbacks.size === 0)
23
+ return;
24
+ const pending = [...callbacks];
25
+ callbacks.clear();
26
+ for (const callback of pending) {
27
+ try {
28
+ callback();
29
+ }
30
+ catch (error) {
31
+ logWarn('Server cleanup callback failed', { error });
32
+ }
33
+ }
34
+ }
35
+ function ensureServerCleanupHooks(server) {
36
+ if (patchedCleanupServers.has(server))
37
+ return;
38
+ patchedCleanupServers.add(server);
39
+ const originalOnClose = server.server.onclose;
40
+ server.server.onclose = () => {
41
+ drainServerCleanupCallbacks(server);
42
+ originalOnClose?.();
43
+ };
44
+ const originalClose = server.close.bind(server);
45
+ server.close = async () => {
46
+ drainServerCleanupCallbacks(server);
47
+ await originalClose();
48
+ };
49
+ }
50
+ export function registerServerLifecycleCleanup(server, callback) {
51
+ ensureServerCleanupHooks(server);
52
+ getServerCleanupCallbackSet(server).add(callback);
53
+ }
10
54
  export { cancelTasksForOwner, abortAllTaskExecutions, } from '../tasks/execution.js';
11
55
  /* -------------------------------------------------------------------------------------------------
12
- * Tasks API schemas
56
+ * Task handler schemas and registration
13
57
  * ------------------------------------------------------------------------------------------------- */
14
58
  const TaskGetSchema = z
15
59
  .object({
@@ -40,9 +84,6 @@ const TaskResultSchema = z
40
84
  params: z.object({ taskId: z.string() }).loose(),
41
85
  })
42
86
  .loose();
43
- /* -------------------------------------------------------------------------------------------------
44
- * Tool call interception (tools/call) with task support
45
- * ------------------------------------------------------------------------------------------------- */
46
87
  const MIN_TASK_TTL_MS = 1_000;
47
88
  const MAX_TASK_TTL_MS = 86_400_000;
48
89
  const ExtendedCallToolRequestSchema = z
@@ -81,7 +122,11 @@ function parseExtendedCallToolRequest(request) {
81
122
  const parsed = ExtendedCallToolRequestSchema.safeParse(request);
82
123
  if (parsed.success)
83
124
  return parsed.data;
84
- throw new McpError(ErrorCode.InvalidParams, 'Invalid tool request');
125
+ const flat = z.flattenError(parsed.error);
126
+ const details = Object.entries(flat.fieldErrors)
127
+ .map(([k, v]) => `${k}: ${(v ?? []).join(', ')}`)
128
+ .join('; ') || flat.formErrors.join('; ');
129
+ throw new McpError(ErrorCode.InvalidParams, `Invalid tool request params: ${details}`);
85
130
  }
86
131
  function resolveOwnerScopedExtra(extra) {
87
132
  const parsedExtra = parseHandlerExtra(extra);
@@ -97,11 +142,11 @@ function getSdkCallToolHandler(server) {
97
142
  const handler = maybeHandlers.get('tools/call');
98
143
  return typeof handler === 'function' ? handler : null;
99
144
  }
100
- /* -------------------------------------------------------------------------------------------------
101
- * Register handlers
102
- * ------------------------------------------------------------------------------------------------- */
103
145
  export function registerTaskHandlers(server) {
104
146
  const sdkCallToolHandler = getSdkCallToolHandler(server);
147
+ if (!sdkCallToolHandler) {
148
+ logWarn('Task call interception disabled: SDK tools/call handler unavailable; task-capable tools require MCP SDK compatibility update', { sdkVersion: 'unknown' });
149
+ }
105
150
  if (sdkCallToolHandler) {
106
151
  server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
107
152
  const parsedExtra = parseHandlerExtra(extra);
@@ -192,4 +237,3 @@ export function registerTaskHandlers(server) {
192
237
  return toTaskSummary(task);
193
238
  });
194
239
  }
195
- //# sourceMappingURL=mcp.js.map
@@ -0,0 +1,70 @@
1
+ import { BlockList } from 'node:net';
2
+ import { type config } from './core.js';
3
+ export declare class SafeDnsResolver {
4
+ private readonly ipBlocker;
5
+ private readonly security;
6
+ private readonly blockedHostSuffixes;
7
+ constructor(ipBlocker: IpBlocker, security: SecurityConfig, blockedHostSuffixes: readonly string[]);
8
+ resolveAndValidate(hostname: string, signal?: AbortSignal): Promise<string>;
9
+ private isBlockedHostname;
10
+ private assertNoBlockedCname;
11
+ private resolveCname;
12
+ }
13
+ type HostnamePreflight = (url: string, signal?: AbortSignal) => Promise<string>;
14
+ export declare function createDnsPreflight(dnsResolver: SafeDnsResolver): HostnamePreflight;
15
+ export declare function normalizeHost(value: string): string | null;
16
+ type IpFamily = 'ipv4' | 'ipv6';
17
+ export declare function createDefaultBlockList(): BlockList;
18
+ export declare function normalizeIpForBlockList(input: string): {
19
+ ip: string;
20
+ family: IpFamily;
21
+ } | null;
22
+ export interface TransformResult {
23
+ readonly url: string;
24
+ readonly transformed: boolean;
25
+ readonly platform?: string;
26
+ }
27
+ export declare class RawUrlTransformer {
28
+ private readonly logger;
29
+ constructor(logger: Logger);
30
+ transformToRawUrl(url: string): TransformResult;
31
+ isRawTextContentUrl(urlString: string): boolean;
32
+ private isRawUrl;
33
+ private splitParams;
34
+ private tryTransformWithUrl;
35
+ private transformGithubBlob;
36
+ private transformGithubGist;
37
+ private transformGitLab;
38
+ private transformBitbucket;
39
+ }
40
+ export interface Logger {
41
+ debug(message: string, data?: Record<string, unknown>): void;
42
+ warn(message: string, data?: Record<string, unknown>): void;
43
+ error(message: string, data?: Record<string, unknown>): void;
44
+ }
45
+ export declare const VALIDATION_ERROR_CODE = "VALIDATION_ERROR";
46
+ export declare const BLOCKED_HOST_SUFFIXES: readonly string[];
47
+ type SecurityConfig = typeof config.security;
48
+ export declare class IpBlocker {
49
+ private readonly security;
50
+ private readonly blockList;
51
+ constructor(security: SecurityConfig);
52
+ isBlockedIp(candidate: string): boolean;
53
+ }
54
+ type ConstantsConfig = typeof config.constants;
55
+ export declare class UrlNormalizer {
56
+ private readonly constants;
57
+ private readonly security;
58
+ private readonly ipBlocker;
59
+ private readonly blockedHostSuffixes;
60
+ constructor(constants: ConstantsConfig, security: SecurityConfig, ipBlocker: IpBlocker, blockedHostSuffixes: readonly string[]);
61
+ normalize(urlString: string): {
62
+ normalizedUrl: string;
63
+ hostname: string;
64
+ };
65
+ validateAndNormalize(urlString: string): string;
66
+ private requireTrimmedUrl;
67
+ private normalizeHostname;
68
+ private assertHostnameAllowed;
69
+ }
70
+ export {};