@j0hanz/fetch-url-mcp 1.6.0 → 1.7.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.
- package/README.md +507 -403
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/http/auth.d.ts +12 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +85 -6
- package/dist/http/health.d.ts +1 -0
- package/dist/http/health.d.ts.map +1 -0
- package/dist/http/helpers.d.ts +1 -0
- package/dist/http/helpers.d.ts.map +1 -0
- package/dist/http/native.d.ts +1 -0
- package/dist/http/native.d.ts.map +1 -0
- package/dist/http/native.js +80 -63
- package/dist/http/rate-limit.d.ts +1 -0
- package/dist/http/rate-limit.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/content.d.ts +3 -0
- package/dist/lib/content.d.ts.map +1 -0
- package/dist/lib/content.js +16 -11
- package/dist/lib/core.d.ts +6 -8
- package/dist/lib/core.d.ts.map +1 -0
- package/dist/lib/core.js +111 -97
- package/dist/lib/fetch-pipeline.d.ts +1 -1
- package/dist/lib/fetch-pipeline.d.ts.map +1 -0
- package/dist/lib/fetch-pipeline.js +54 -44
- package/dist/lib/http.d.ts +1 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/mcp-tools.d.ts +45 -7
- package/dist/lib/mcp-tools.d.ts.map +1 -0
- package/dist/lib/mcp-tools.js +37 -6
- package/dist/lib/net-utils.d.ts +1 -0
- package/dist/lib/net-utils.d.ts.map +1 -0
- package/dist/lib/progress.d.ts +1 -0
- package/dist/lib/progress.d.ts.map +1 -0
- package/dist/lib/task-handlers.d.ts +9 -1
- package/dist/lib/task-handlers.d.ts.map +1 -0
- package/dist/lib/task-handlers.js +30 -38
- package/dist/lib/types.d.ts +4 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +12 -1
- package/dist/lib/url.d.ts +3 -0
- package/dist/lib/url.d.ts.map +1 -0
- package/dist/lib/url.js +78 -151
- package/dist/lib/utils.d.ts +2 -2
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +60 -94
- package/dist/lib/zod.d.ts +3 -0
- package/dist/lib/zod.d.ts.map +1 -0
- package/dist/lib/zod.js +33 -0
- package/dist/prompts/index.d.ts +2 -1
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +2 -13
- package/dist/resources/index.d.ts +2 -1
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +5 -19
- package/dist/resources/instructions.d.ts +1 -0
- package/dist/resources/instructions.d.ts.map +1 -0
- package/dist/resources/instructions.js +2 -0
- package/dist/schemas/cache.d.ts +18 -0
- package/dist/schemas/cache.d.ts.map +1 -0
- package/dist/schemas/cache.js +19 -0
- package/dist/schemas/inputs.d.ts +1 -0
- package/dist/schemas/inputs.d.ts.map +1 -0
- package/dist/schemas/outputs.d.ts +6 -5
- package/dist/schemas/outputs.d.ts.map +1 -0
- package/dist/schemas/outputs.js +5 -9
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +9 -7
- package/dist/tasks/execution.d.ts +1 -0
- package/dist/tasks/execution.d.ts.map +1 -0
- package/dist/tasks/execution.js +3 -21
- package/dist/tasks/manager.d.ts +2 -6
- package/dist/tasks/manager.d.ts.map +1 -0
- package/dist/tasks/manager.js +2 -4
- package/dist/tasks/owner.d.ts +1 -0
- package/dist/tasks/owner.d.ts.map +1 -0
- package/dist/tasks/tool-registry.d.ts +2 -0
- package/dist/tasks/tool-registry.d.ts.map +1 -0
- package/dist/tasks/tool-registry.js +3 -0
- package/dist/tools/fetch-url.d.ts +4 -6
- package/dist/tools/fetch-url.d.ts.map +1 -0
- package/dist/tools/fetch-url.js +61 -59
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/transform/html-translators.d.ts +1 -0
- package/dist/transform/html-translators.d.ts.map +1 -0
- package/dist/transform/html-translators.js +5 -2
- package/dist/transform/metadata.d.ts +1 -0
- package/dist/transform/metadata.d.ts.map +1 -0
- package/dist/transform/metadata.js +1 -0
- package/dist/transform/{workers/shared.d.ts → shared.d.ts} +2 -1
- package/dist/transform/shared.d.ts.map +1 -0
- package/dist/transform/{workers/shared.js → shared.js} +1 -1
- package/dist/transform/transform.d.ts +1 -0
- package/dist/transform/transform.d.ts.map +1 -0
- package/dist/transform/transform.js +21 -14
- package/dist/transform/types.d.ts +1 -4
- package/dist/transform/types.d.ts.map +1 -0
- package/dist/transform/worker-pool.d.ts +3 -18
- package/dist/transform/worker-pool.d.ts.map +1 -0
- package/dist/transform/worker-pool.js +51 -167
- package/package.json +9 -6
- package/dist/transform/workers/transform-child.d.ts +0 -1
- package/dist/transform/workers/transform-child.js +0 -15
- package/dist/transform/workers/transform-worker.d.ts +0 -1
- package/dist/transform/workers/transform-worker.js +0 -13
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks';
|
|
2
2
|
import { Buffer } from 'node:buffer';
|
|
3
|
-
import { fork } from 'node:child_process';
|
|
4
3
|
import { availableParallelism } from 'node:os';
|
|
5
|
-
import
|
|
4
|
+
import process from 'node:process';
|
|
6
5
|
import { isSharedArrayBuffer } from 'node:util/types';
|
|
7
|
-
import { Worker, } from 'node:worker_threads';
|
|
6
|
+
import { isMainThread, parentPort, Worker, } from 'node:worker_threads';
|
|
8
7
|
import { config } from '../lib/core.js';
|
|
9
8
|
import { logWarn } from '../lib/core.js';
|
|
10
9
|
import { createAbortError } from '../lib/utils.js';
|
|
11
10
|
import { FetchError, getErrorMessage } from '../lib/utils.js';
|
|
12
11
|
import { createUnrefTimeout } from '../lib/utils.js';
|
|
13
12
|
import { isObject } from '../lib/utils.js';
|
|
14
|
-
|
|
13
|
+
import { createTransformMessageHandler } from './shared.js';
|
|
14
|
+
import { transformHtmlToMarkdownInProcess } from './transform.js';
|
|
15
15
|
// Worker message validation
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
16
|
function isWorkerResultPayload(value) {
|
|
18
17
|
if (!isObject(value))
|
|
19
18
|
return false;
|
|
@@ -91,7 +90,7 @@ function ensureTightBuffer(buffer) {
|
|
|
91
90
|
}
|
|
92
91
|
return Buffer.from(buffer);
|
|
93
92
|
}
|
|
94
|
-
function buildWorkerDispatchPayload(task
|
|
93
|
+
function buildWorkerDispatchPayload(task) {
|
|
95
94
|
const message = {
|
|
96
95
|
type: 'transform',
|
|
97
96
|
id: task.id,
|
|
@@ -105,12 +104,6 @@ function buildWorkerDispatchPayload(task, supportsTransferList) {
|
|
|
105
104
|
return { message };
|
|
106
105
|
}
|
|
107
106
|
const htmlBuffer = ensureTightBuffer(task.htmlBuffer);
|
|
108
|
-
if (!supportsTransferList) {
|
|
109
|
-
message.htmlBuffer = htmlBuffer;
|
|
110
|
-
if (task.encoding)
|
|
111
|
-
message.encoding = task.encoding;
|
|
112
|
-
return { message };
|
|
113
|
-
}
|
|
114
107
|
const transferableHtmlBuffer = Uint8Array.from(htmlBuffer);
|
|
115
108
|
message.htmlBuffer = transferableHtmlBuffer;
|
|
116
109
|
if (task.encoding)
|
|
@@ -120,139 +113,15 @@ function buildWorkerDispatchPayload(task, supportsTransferList) {
|
|
|
120
113
|
return { message };
|
|
121
114
|
return { message, transferList: [backingBuffer] };
|
|
122
115
|
}
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
116
|
// Pool sizing & constants
|
|
125
|
-
//
|
|
126
|
-
/**
|
|
127
|
-
* Worker Pool Sizing Configuration
|
|
128
|
-
*
|
|
129
|
-
* Default: min(4, floor(availableParallelism() / 2)), constrained to [2, N]
|
|
130
|
-
*
|
|
131
|
-
* Tuning Guidance:
|
|
132
|
-
* - **Default behavior**: Appropriate for most deployments. Uses half of available
|
|
133
|
-
* CPU threads (capped at 4) to balance throughput with system resource availability.
|
|
134
|
-
*
|
|
135
|
-
* - **CPU-limited containers**: If running in a container with strict CPU limits
|
|
136
|
-
* (e.g., Docker with --cpus=2), the default may over-subscribe. Consider setting
|
|
137
|
-
* maxWorkerScale to match the container's CPU limit.
|
|
138
|
-
*
|
|
139
|
-
* - **High-concurrency workloads**: For dedicated servers handling many concurrent
|
|
140
|
-
* fetch requests, increasing maxWorkerScale to (availableParallelism() + 2) may
|
|
141
|
-
* improve throughput by overlapping I/O wait with computation.
|
|
142
|
-
*
|
|
143
|
-
* - **Memory-constrained environments**: Each worker allocates ~50-100MB for DOM
|
|
144
|
-
* parsing. If memory is limited, reduce maxWorkerScale to (availableParallelism() / 2)
|
|
145
|
-
* or lower to prevent OOM errors.
|
|
146
|
-
*
|
|
147
|
-
* - **Shared hosting**: On shared systems where CPU is contested, reducing the pool
|
|
148
|
-
* size prevents starving other processes. Consider maxWorkerScale = 2 or using
|
|
149
|
-
* process-based workers (TRANSFORM_WORKER_MODE=process) for better isolation.
|
|
150
|
-
*
|
|
151
|
-
* Configuration:
|
|
152
|
-
* - TRANSFORM_MAX_WORKER_SCALE env var (default: availableParallelism())
|
|
153
|
-
* - TRANSFORM_WORKER_MODE env var: 'threads' (default) or 'process'
|
|
154
|
-
*
|
|
155
|
-
* See config.ts for full worker configuration options.
|
|
156
|
-
*/
|
|
117
|
+
// Core tuning: ~half of available CPUs as baseline, capped by config limits.
|
|
157
118
|
const POOL_MIN_WORKERS = Math.max(2, Math.min(4, Math.floor(availableParallelism() / 2)));
|
|
158
119
|
const POOL_MAX_WORKERS = config.transform.maxWorkerScale;
|
|
159
120
|
const POOL_SCALE_THRESHOLD = 0.5;
|
|
160
121
|
const WORKER_NAME_PREFIX = 'fetch-url-mcp-transform';
|
|
161
122
|
const DEFAULT_TIMEOUT_MS = config.transform.timeoutMs;
|
|
162
|
-
const
|
|
163
|
-
// ---------------------------------------------------------------------------
|
|
164
|
-
// Worker host spawners
|
|
165
|
-
// ---------------------------------------------------------------------------
|
|
166
|
-
function createThreadWorkerHost(_workerIndex, name) {
|
|
167
|
-
const resourceLimits = config.transform.workerResourceLimits;
|
|
168
|
-
const worker = new Worker(new URL('./workers/transform-worker.js', import.meta.url), {
|
|
169
|
-
name,
|
|
170
|
-
...(resourceLimits ? { resourceLimits } : {}),
|
|
171
|
-
});
|
|
172
|
-
return {
|
|
173
|
-
kind: 'thread',
|
|
174
|
-
supportsTransferList: true,
|
|
175
|
-
threadId: worker.threadId,
|
|
176
|
-
postMessage: (message, transferList) => {
|
|
177
|
-
worker.postMessage(message, transferList);
|
|
178
|
-
},
|
|
179
|
-
terminate: async () => {
|
|
180
|
-
await worker.terminate();
|
|
181
|
-
},
|
|
182
|
-
unref: () => {
|
|
183
|
-
worker.unref();
|
|
184
|
-
},
|
|
185
|
-
onMessage: (handler) => {
|
|
186
|
-
worker.on('message', handler);
|
|
187
|
-
},
|
|
188
|
-
onError: (handler) => {
|
|
189
|
-
worker.on('error', handler);
|
|
190
|
-
worker.on('messageerror', handler);
|
|
191
|
-
},
|
|
192
|
-
onExit: (handler) => {
|
|
193
|
-
worker.on('exit', (code) => {
|
|
194
|
-
handler(code, null);
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
function createProcessWorkerHost(workerIndex, name) {
|
|
200
|
-
const child = fork(TRANSFORM_CHILD_PATH, [], {
|
|
201
|
-
stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
|
|
202
|
-
serialization: 'advanced',
|
|
203
|
-
env: {
|
|
204
|
-
...process.env,
|
|
205
|
-
FETCH_URL_MCP_WORKER_INDEX: String(workerIndex),
|
|
206
|
-
FETCH_URL_MCP_WORKER_NAME: name,
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
if (child.pid === undefined) {
|
|
210
|
-
throw new Error('Failed to fork process');
|
|
211
|
-
}
|
|
212
|
-
return {
|
|
213
|
-
kind: 'process',
|
|
214
|
-
supportsTransferList: false,
|
|
215
|
-
pid: child.pid,
|
|
216
|
-
postMessage: (message) => {
|
|
217
|
-
if (!child.connected) {
|
|
218
|
-
throw new Error('Transform worker IPC channel is closed');
|
|
219
|
-
}
|
|
220
|
-
child.send(message);
|
|
221
|
-
},
|
|
222
|
-
terminate: () => new Promise((resolve) => {
|
|
223
|
-
if (child.exitCode !== null || child.killed) {
|
|
224
|
-
resolve();
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
child.once('exit', () => {
|
|
228
|
-
resolve();
|
|
229
|
-
});
|
|
230
|
-
try {
|
|
231
|
-
child.kill();
|
|
232
|
-
}
|
|
233
|
-
catch {
|
|
234
|
-
resolve();
|
|
235
|
-
}
|
|
236
|
-
}),
|
|
237
|
-
unref: () => {
|
|
238
|
-
child.unref();
|
|
239
|
-
},
|
|
240
|
-
onMessage: (handler) => {
|
|
241
|
-
child.on('message', handler);
|
|
242
|
-
},
|
|
243
|
-
onError: (handler) => {
|
|
244
|
-
child.on('error', handler);
|
|
245
|
-
},
|
|
246
|
-
onExit: (handler) => {
|
|
247
|
-
child.on('exit', (code, signal) => {
|
|
248
|
-
handler(code, signal);
|
|
249
|
-
});
|
|
250
|
-
},
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
// ---------------------------------------------------------------------------
|
|
123
|
+
const TRANSFORM_WORKER_PATH = new URL(import.meta.url);
|
|
254
124
|
// WorkerPool
|
|
255
|
-
// ---------------------------------------------------------------------------
|
|
256
125
|
class WorkerPool {
|
|
257
126
|
static CLOSED_MESSAGE = 'Transform worker pool closed';
|
|
258
127
|
workers = [];
|
|
@@ -265,17 +134,15 @@ class WorkerPool {
|
|
|
265
134
|
cancelAcks = new Map();
|
|
266
135
|
timeoutMs;
|
|
267
136
|
queueMax;
|
|
268
|
-
spawnWorkerImpl;
|
|
269
137
|
closed = false;
|
|
270
138
|
taskIdSeq = 0;
|
|
271
|
-
constructor(size, timeoutMs
|
|
139
|
+
constructor(size, timeoutMs) {
|
|
272
140
|
this.capacity =
|
|
273
141
|
size === 0
|
|
274
142
|
? 0
|
|
275
143
|
: Math.max(this.minCapacity, Math.min(size, this.maxCapacity));
|
|
276
144
|
this.timeoutMs = timeoutMs;
|
|
277
145
|
this.queueMax = this.maxCapacity * 4;
|
|
278
|
-
this.spawnWorkerImpl = spawnWorker;
|
|
279
146
|
}
|
|
280
147
|
async transform(htmlOrBuffer, url, options) {
|
|
281
148
|
this.ensureOpen();
|
|
@@ -315,7 +182,7 @@ class WorkerPool {
|
|
|
315
182
|
return;
|
|
316
183
|
this.closed = true;
|
|
317
184
|
const terminations = this.workers
|
|
318
|
-
.map((slot) => slot?.
|
|
185
|
+
.map((slot) => slot?.worker.terminate().catch(() => undefined))
|
|
319
186
|
.filter((p) => p !== undefined);
|
|
320
187
|
this.workers.fill(undefined);
|
|
321
188
|
this.workers.length = 0;
|
|
@@ -442,7 +309,7 @@ class WorkerPool {
|
|
|
442
309
|
}
|
|
443
310
|
if (slot) {
|
|
444
311
|
try {
|
|
445
|
-
slot.
|
|
312
|
+
slot.worker.postMessage({ type: 'cancel', id });
|
|
446
313
|
}
|
|
447
314
|
catch {
|
|
448
315
|
// Worker may be unavailable; failure is acceptable during abort
|
|
@@ -465,19 +332,25 @@ class WorkerPool {
|
|
|
465
332
|
}
|
|
466
333
|
spawnWorker(workerIndex) {
|
|
467
334
|
const name = `${WORKER_NAME_PREFIX}-${workerIndex + 1}`;
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
335
|
+
const resourceLimits = config.transform.workerResourceLimits;
|
|
336
|
+
const worker = new Worker(TRANSFORM_WORKER_PATH, {
|
|
337
|
+
name,
|
|
338
|
+
...(resourceLimits ? { resourceLimits } : {}),
|
|
339
|
+
});
|
|
340
|
+
worker.unref();
|
|
341
|
+
worker.on('message', (raw) => {
|
|
471
342
|
this.onWorkerMessage(workerIndex, raw);
|
|
472
343
|
});
|
|
473
|
-
|
|
344
|
+
worker.on('error', (error) => {
|
|
345
|
+
this.onWorkerBroken(workerIndex, `Transform worker error: ${getErrorMessage(error)}`);
|
|
346
|
+
});
|
|
347
|
+
worker.on('messageerror', (error) => {
|
|
474
348
|
this.onWorkerBroken(workerIndex, `Transform worker error: ${getErrorMessage(error)}`);
|
|
475
349
|
});
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
this.onWorkerBroken(workerIndex, `Transform worker exited (${suffix})`);
|
|
350
|
+
worker.on('exit', (code) => {
|
|
351
|
+
this.onWorkerBroken(workerIndex, `Transform worker exited (code ${code ?? 'unknown'})`);
|
|
479
352
|
});
|
|
480
|
-
return {
|
|
353
|
+
return { worker, busy: false, currentTaskId: null, name };
|
|
481
354
|
}
|
|
482
355
|
onWorkerBroken(workerIndex, message) {
|
|
483
356
|
if (this.closed)
|
|
@@ -488,11 +361,8 @@ class WorkerPool {
|
|
|
488
361
|
logWarn('Transform worker unavailable; restarting', {
|
|
489
362
|
reason: message,
|
|
490
363
|
workerIndex,
|
|
491
|
-
workerKind: slot.host.kind,
|
|
492
364
|
workerName: slot.name,
|
|
493
|
-
|
|
494
|
-
? { pid: slot.host.pid }
|
|
495
|
-
: { threadId: slot.host.threadId }),
|
|
365
|
+
threadId: slot.worker.threadId,
|
|
496
366
|
});
|
|
497
367
|
if (slot.busy && slot.currentTaskId) {
|
|
498
368
|
this.failTask(slot.currentTaskId, new FetchError(message, '', 503, { reason: 'worker_exit' }));
|
|
@@ -504,7 +374,7 @@ class WorkerPool {
|
|
|
504
374
|
return;
|
|
505
375
|
const target = slot ?? this.workers[workerIndex];
|
|
506
376
|
if (target) {
|
|
507
|
-
target.
|
|
377
|
+
target.worker.terminate().catch(() => undefined);
|
|
508
378
|
}
|
|
509
379
|
this.workers[workerIndex] = this.spawnWorker(workerIndex);
|
|
510
380
|
this.drainQueue();
|
|
@@ -645,7 +515,7 @@ class WorkerPool {
|
|
|
645
515
|
void timeout.promise
|
|
646
516
|
.then(() => {
|
|
647
517
|
try {
|
|
648
|
-
slot.
|
|
518
|
+
slot.worker.postMessage({ type: 'cancel', id: task.id });
|
|
649
519
|
}
|
|
650
520
|
catch {
|
|
651
521
|
// Worker may be unavailable; proceed with timeout handling
|
|
@@ -675,8 +545,8 @@ class WorkerPool {
|
|
|
675
545
|
cancelPending: false,
|
|
676
546
|
});
|
|
677
547
|
try {
|
|
678
|
-
const { message, transferList } = buildWorkerDispatchPayload(task
|
|
679
|
-
slot.
|
|
548
|
+
const { message, transferList } = buildWorkerDispatchPayload(task);
|
|
549
|
+
slot.worker.postMessage(message, transferList);
|
|
680
550
|
}
|
|
681
551
|
catch (error) {
|
|
682
552
|
timeout.cancel();
|
|
@@ -717,18 +587,11 @@ class WorkerPool {
|
|
|
717
587
|
}
|
|
718
588
|
}
|
|
719
589
|
}
|
|
720
|
-
// ---------------------------------------------------------------------------
|
|
721
590
|
// Pool singleton management
|
|
722
|
-
// ---------------------------------------------------------------------------
|
|
723
591
|
let workerPool = null;
|
|
724
|
-
function resolveWorkerSpawner() {
|
|
725
|
-
return config.transform.workerMode === 'process'
|
|
726
|
-
? createProcessWorkerHost
|
|
727
|
-
: createThreadWorkerHost;
|
|
728
|
-
}
|
|
729
592
|
export function getOrCreateWorkerPool() {
|
|
730
593
|
const size = config.transform.maxWorkerScale === 0 ? 0 : POOL_MIN_WORKERS;
|
|
731
|
-
workerPool ??= new WorkerPool(size, DEFAULT_TIMEOUT_MS
|
|
594
|
+
workerPool ??= new WorkerPool(size, DEFAULT_TIMEOUT_MS);
|
|
732
595
|
return workerPool;
|
|
733
596
|
}
|
|
734
597
|
export function getWorkerPoolStats() {
|
|
@@ -746,3 +609,24 @@ export async function shutdownWorkerPool() {
|
|
|
746
609
|
await workerPool.close();
|
|
747
610
|
workerPool = null;
|
|
748
611
|
}
|
|
612
|
+
// Worker thread message handling
|
|
613
|
+
if (!isMainThread && parentPort) {
|
|
614
|
+
const port = parentPort;
|
|
615
|
+
const onMessage = createTransformMessageHandler({
|
|
616
|
+
sendMessage: (message) => {
|
|
617
|
+
port.postMessage(message);
|
|
618
|
+
},
|
|
619
|
+
runTransform: transformHtmlToMarkdownInProcess,
|
|
620
|
+
});
|
|
621
|
+
port.on('message', onMessage);
|
|
622
|
+
}
|
|
623
|
+
else if (process.send) {
|
|
624
|
+
const send = process.send.bind(process);
|
|
625
|
+
const onMessage = createTransformMessageHandler({
|
|
626
|
+
sendMessage: (message) => {
|
|
627
|
+
send(message);
|
|
628
|
+
},
|
|
629
|
+
runTransform: transformHtmlToMarkdownInProcess,
|
|
630
|
+
});
|
|
631
|
+
process.on('message', onMessage);
|
|
632
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j0hanz/fetch-url-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"mcpName": "io.github.j0hanz/fetch-url-mcp",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "A web content fetcher MCP server that converts HTML to clean, AI and human readable markdown.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -33,12 +33,15 @@
|
|
|
33
33
|
"keywords": [
|
|
34
34
|
"mcp",
|
|
35
35
|
"mcp-server",
|
|
36
|
+
"model-context-protocol",
|
|
36
37
|
"web-fetching",
|
|
37
38
|
"content-extraction",
|
|
38
39
|
"readability",
|
|
39
40
|
"markdown",
|
|
41
|
+
"html-to-markdown",
|
|
42
|
+
"web-scraper",
|
|
43
|
+
"llm-context",
|
|
40
44
|
"ai-tools",
|
|
41
|
-
"model-context-protocol",
|
|
42
45
|
"fetch-url-mcp"
|
|
43
46
|
],
|
|
44
47
|
"scripts": {
|
|
@@ -78,16 +81,16 @@
|
|
|
78
81
|
"@eslint/js": "^10.0.1",
|
|
79
82
|
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
|
80
83
|
"@types/node": "^24",
|
|
81
|
-
"eslint": "^10.0.
|
|
84
|
+
"eslint": "^10.0.3",
|
|
82
85
|
"eslint-config-prettier": "^10.1.8",
|
|
83
86
|
"eslint-plugin-de-morgan": "^2.1.1",
|
|
84
87
|
"eslint-plugin-depend": "^1.5.0",
|
|
85
88
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
86
|
-
"knip": "^5.
|
|
89
|
+
"knip": "^5.86.0",
|
|
87
90
|
"prettier": "^3.8.1",
|
|
88
91
|
"tsx": "^4.21.0",
|
|
89
92
|
"typescript": "^5.9.3",
|
|
90
|
-
"typescript-eslint": "^8.
|
|
93
|
+
"typescript-eslint": "^8.57.0"
|
|
91
94
|
},
|
|
92
95
|
"engines": {
|
|
93
96
|
"node": ">=24"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import process from 'node:process';
|
|
2
|
-
import { transformHtmlToMarkdownInProcess } from '../transform.js';
|
|
3
|
-
import { createTransformMessageHandler } from './shared.js';
|
|
4
|
-
const send = process.send?.bind(process);
|
|
5
|
-
if (!send)
|
|
6
|
-
throw new Error('transform-child started without IPC channel');
|
|
7
|
-
const sendMessage = send;
|
|
8
|
-
function postMessage(message) {
|
|
9
|
-
sendMessage(message);
|
|
10
|
-
}
|
|
11
|
-
const onMessage = createTransformMessageHandler({
|
|
12
|
-
sendMessage: postMessage,
|
|
13
|
-
runTransform: transformHtmlToMarkdownInProcess,
|
|
14
|
-
});
|
|
15
|
-
process.on('message', onMessage);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { parentPort } from 'node:worker_threads';
|
|
2
|
-
import { transformHtmlToMarkdownInProcess } from '../transform.js';
|
|
3
|
-
import { createTransformMessageHandler } from './shared.js';
|
|
4
|
-
if (!parentPort)
|
|
5
|
-
throw new Error('transform-worker started without parentPort');
|
|
6
|
-
const port = parentPort;
|
|
7
|
-
const onMessage = createTransformMessageHandler({
|
|
8
|
-
sendMessage: (message) => {
|
|
9
|
-
port.postMessage(message);
|
|
10
|
-
},
|
|
11
|
-
runTransform: transformHtmlToMarkdownInProcess,
|
|
12
|
-
});
|
|
13
|
-
port.on('message', onMessage);
|