@j0hanz/fetch-url-mcp 1.11.2 → 1.11.4
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/helpers.d.ts +1 -1
- package/dist/http/helpers.d.ts.map +1 -1
- package/dist/http/helpers.js +1 -1
- package/dist/http/native.js +1 -1
- package/dist/lib/config.d.ts +152 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +478 -0
- package/dist/lib/core.d.ts +1 -150
- package/dist/lib/core.d.ts.map +1 -1
- package/dist/lib/core.js +3 -459
- package/dist/lib/{mcp-tools.d.ts → mcp-interop.d.ts} +49 -1
- package/dist/lib/mcp-interop.d.ts.map +1 -0
- package/dist/lib/mcp-interop.js +354 -0
- package/dist/lib/task-handlers.js +1 -1
- package/dist/resources/index.js +1 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/server.js +2 -2
- package/dist/tasks/handlers.d.ts +11 -0
- package/dist/tasks/handlers.d.ts.map +1 -0
- package/dist/tasks/handlers.js +151 -0
- package/dist/tasks/owner.d.ts +1 -2
- package/dist/tasks/owner.d.ts.map +1 -1
- package/dist/tasks/registry.d.ts +1 -1
- package/dist/tasks/registry.d.ts.map +1 -1
- package/dist/tools/fetch-url.d.ts +2 -3
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +3 -4
- package/dist/{lib → transform}/dom-prep.d.ts +1 -1
- package/dist/transform/dom-prep.d.ts.map +1 -0
- package/dist/{lib → transform}/dom-prep.js +2 -2
- package/dist/transform/html-translators.d.ts.map +1 -1
- package/dist/transform/html-translators.js +1 -1
- package/dist/transform/metadata.d.ts +8 -0
- package/dist/transform/metadata.d.ts.map +1 -1
- package/dist/transform/metadata.js +66 -0
- package/dist/transform/transform.d.ts.map +1 -1
- package/dist/transform/transform.js +2 -3
- package/package.json +1 -1
- package/dist/lib/dom-prep.d.ts.map +0 -1
- package/dist/lib/mcp-tools.d.ts.map +0 -1
- package/dist/lib/mcp-tools.js +0 -129
- package/dist/lib/progress.d.ts +0 -32
- package/dist/lib/progress.d.ts.map +0 -1
- package/dist/lib/progress.js +0 -143
- package/dist/lib/sdk-interop.d.ts +0 -20
- package/dist/lib/sdk-interop.d.ts.map +0 -1
- package/dist/lib/sdk-interop.js +0 -85
- package/dist/transform/title-policy.d.ts +0 -9
- package/dist/transform/title-policy.d.ts.map +0 -1
- package/dist/transform/title-policy.js +0 -67
package/dist/lib/core.d.ts
CHANGED
|
@@ -1,157 +1,8 @@
|
|
|
1
1
|
import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { SessionEntry } from './session.js';
|
|
3
3
|
import type { SessionStore } from './session.js';
|
|
4
|
-
export
|
|
5
|
-
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
4
|
+
export { config, enableHttpMode, serverVersion } from './config.js';
|
|
6
5
|
type McpLogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';
|
|
7
|
-
type TransformWorkerMode = 'threads' | 'process';
|
|
8
|
-
type AuthMode = 'oauth' | 'static';
|
|
9
|
-
interface WorkerResourceLimits {
|
|
10
|
-
maxOldGenerationSizeMb?: number;
|
|
11
|
-
maxYoungGenerationSizeMb?: number;
|
|
12
|
-
codeRangeSizeMb?: number;
|
|
13
|
-
stackSizeMb?: number;
|
|
14
|
-
}
|
|
15
|
-
interface AuthConfig {
|
|
16
|
-
mode: AuthMode;
|
|
17
|
-
issuerUrl: URL | undefined;
|
|
18
|
-
authorizationUrl: URL | undefined;
|
|
19
|
-
tokenUrl: URL | undefined;
|
|
20
|
-
revocationUrl: URL | undefined;
|
|
21
|
-
registrationUrl: URL | undefined;
|
|
22
|
-
introspectionUrl: URL | undefined;
|
|
23
|
-
resourceUrl: URL;
|
|
24
|
-
requiredScopes: string[];
|
|
25
|
-
clientId: string | undefined;
|
|
26
|
-
clientSecret: string | undefined;
|
|
27
|
-
introspectionTimeoutMs: number;
|
|
28
|
-
staticTokens: string[];
|
|
29
|
-
}
|
|
30
|
-
interface HttpsConfig {
|
|
31
|
-
enabled: boolean;
|
|
32
|
-
keyFile: string | undefined;
|
|
33
|
-
certFile: string | undefined;
|
|
34
|
-
caFile: string | undefined;
|
|
35
|
-
}
|
|
36
|
-
interface RuntimeState {
|
|
37
|
-
httpMode: boolean;
|
|
38
|
-
}
|
|
39
|
-
interface AppServerHttpConfig {
|
|
40
|
-
headersTimeoutMs: number | undefined;
|
|
41
|
-
requestTimeoutMs: number | undefined;
|
|
42
|
-
keepAliveTimeoutMs: number | undefined;
|
|
43
|
-
keepAliveTimeoutBufferMs: number | undefined;
|
|
44
|
-
maxHeadersCount: number | undefined;
|
|
45
|
-
maxConnections: number;
|
|
46
|
-
blockPrivateConnections: boolean;
|
|
47
|
-
shutdownCloseIdleConnections: boolean;
|
|
48
|
-
shutdownCloseAllConnections: boolean;
|
|
49
|
-
}
|
|
50
|
-
interface AppServerConfig {
|
|
51
|
-
name: string;
|
|
52
|
-
version: string;
|
|
53
|
-
port: number;
|
|
54
|
-
host: string;
|
|
55
|
-
https: HttpsConfig;
|
|
56
|
-
sessionTtlMs: number;
|
|
57
|
-
sessionInitTimeoutMs: number;
|
|
58
|
-
maxSessions: number;
|
|
59
|
-
http: AppServerHttpConfig;
|
|
60
|
-
}
|
|
61
|
-
interface AppFetcherConfig {
|
|
62
|
-
timeout: number;
|
|
63
|
-
maxRedirects: number;
|
|
64
|
-
userAgent: string;
|
|
65
|
-
maxContentLength: number;
|
|
66
|
-
}
|
|
67
|
-
interface AppTransformConfig {
|
|
68
|
-
timeoutMs: number;
|
|
69
|
-
stageWarnRatio: number;
|
|
70
|
-
metadataFormat: string;
|
|
71
|
-
maxWorkerScale: number;
|
|
72
|
-
cancelAckTimeoutMs: number;
|
|
73
|
-
workerMode: TransformWorkerMode;
|
|
74
|
-
workerResourceLimits: WorkerResourceLimits | undefined;
|
|
75
|
-
}
|
|
76
|
-
interface AppTasksConfig {
|
|
77
|
-
maxTotal: number;
|
|
78
|
-
maxPerOwner: number;
|
|
79
|
-
emitStatusNotifications: boolean;
|
|
80
|
-
requireInterception: boolean;
|
|
81
|
-
}
|
|
82
|
-
interface AppCacheConfig {
|
|
83
|
-
enabled: boolean;
|
|
84
|
-
ttl: number;
|
|
85
|
-
maxKeys: number;
|
|
86
|
-
maxSizeBytes: number;
|
|
87
|
-
}
|
|
88
|
-
interface AppNoiseRemovalConfig {
|
|
89
|
-
extraTokens: string[];
|
|
90
|
-
extraSelectors: string[];
|
|
91
|
-
enabledCategories: string[];
|
|
92
|
-
debug: boolean;
|
|
93
|
-
aggressiveMode: boolean;
|
|
94
|
-
preserveSvgCanvas: boolean;
|
|
95
|
-
weights: {
|
|
96
|
-
hidden: number;
|
|
97
|
-
structural: number;
|
|
98
|
-
promo: number;
|
|
99
|
-
stickyFixed: number;
|
|
100
|
-
threshold: number;
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
interface AppMarkdownCleanupConfig {
|
|
104
|
-
promoteOrphanHeadings: boolean;
|
|
105
|
-
removeSkipLinks: boolean;
|
|
106
|
-
removeTocBlocks: boolean;
|
|
107
|
-
removeTypeDocComments: boolean;
|
|
108
|
-
headingKeywords: string[];
|
|
109
|
-
}
|
|
110
|
-
export declare const config: {
|
|
111
|
-
server: AppServerConfig;
|
|
112
|
-
fetcher: AppFetcherConfig;
|
|
113
|
-
transform: AppTransformConfig;
|
|
114
|
-
tools: {
|
|
115
|
-
enabled: string[];
|
|
116
|
-
timeoutMs: number;
|
|
117
|
-
};
|
|
118
|
-
tasks: AppTasksConfig;
|
|
119
|
-
cache: AppCacheConfig;
|
|
120
|
-
extraction: {
|
|
121
|
-
maxBlockLength: number;
|
|
122
|
-
minParagraphLength: number;
|
|
123
|
-
};
|
|
124
|
-
noiseRemoval: AppNoiseRemovalConfig;
|
|
125
|
-
markdownCleanup: AppMarkdownCleanupConfig;
|
|
126
|
-
i18n: {
|
|
127
|
-
locale: string | undefined;
|
|
128
|
-
};
|
|
129
|
-
logging: {
|
|
130
|
-
level: LogLevel;
|
|
131
|
-
format: string;
|
|
132
|
-
};
|
|
133
|
-
constants: {
|
|
134
|
-
maxHtmlBytes: number;
|
|
135
|
-
maxUrlLength: number;
|
|
136
|
-
maxInlineContentChars: number;
|
|
137
|
-
};
|
|
138
|
-
security: {
|
|
139
|
-
blockedHosts: Set<string>;
|
|
140
|
-
allowedHosts: Set<string>;
|
|
141
|
-
apiKey: string | undefined;
|
|
142
|
-
allowRemote: boolean;
|
|
143
|
-
allowLocalFetch: boolean;
|
|
144
|
-
};
|
|
145
|
-
auth: AuthConfig;
|
|
146
|
-
rateLimit: {
|
|
147
|
-
enabled: boolean;
|
|
148
|
-
maxRequests: number;
|
|
149
|
-
windowMs: number;
|
|
150
|
-
cleanupIntervalMs: number;
|
|
151
|
-
};
|
|
152
|
-
runtime: RuntimeState;
|
|
153
|
-
};
|
|
154
|
-
export declare function enableHttpMode(): void;
|
|
155
6
|
interface CacheEntry {
|
|
156
7
|
url: string;
|
|
157
8
|
title?: string;
|
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":"
|
|
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,449 +1,13 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
4
|
-
import { findPackageJSON } from 'node:module';
|
|
5
3
|
import process from 'node:process';
|
|
6
4
|
import { getSystemErrorMessage, inspect, stripVTControlCharacters, } from 'node:util';
|
|
7
5
|
import {} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
-
import {
|
|
9
|
-
import { buildIpv4, isIP, normalizeHostname, stripTrailingDots, } from './url.js';
|
|
6
|
+
import { config } from './config.js';
|
|
10
7
|
import { getErrorMessage, isAbortError, sha256Hex, stableStringify as stableJsonStringify, startAbortableIntervalLoop, } from './utils.js';
|
|
11
|
-
export
|
|
12
|
-
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
13
|
-
const ALLOWED_LOG_LEVELS = new Set(LOG_LEVELS);
|
|
14
|
-
const DEFAULT_HEADING_KEYWORDS = [
|
|
15
|
-
'overview',
|
|
16
|
-
'introduction',
|
|
17
|
-
'summary',
|
|
18
|
-
'conclusion',
|
|
19
|
-
'prerequisites',
|
|
20
|
-
'requirements',
|
|
21
|
-
'installation',
|
|
22
|
-
'configuration',
|
|
23
|
-
'usage',
|
|
24
|
-
'features',
|
|
25
|
-
'limitations',
|
|
26
|
-
'troubleshooting',
|
|
27
|
-
'faq',
|
|
28
|
-
'resources',
|
|
29
|
-
'references',
|
|
30
|
-
'changelog',
|
|
31
|
-
'license',
|
|
32
|
-
'acknowledgments',
|
|
33
|
-
'appendix',
|
|
34
|
-
];
|
|
35
|
-
class ConfigError extends Error {
|
|
36
|
-
name = 'ConfigError';
|
|
37
|
-
}
|
|
38
|
-
function isMissingEnvFileError(error) {
|
|
39
|
-
if (!error || typeof error !== 'object')
|
|
40
|
-
return false;
|
|
41
|
-
const { code } = error;
|
|
42
|
-
return code === 'ENOENT' || code === 'ERR_ENV_FILE_NOT_FOUND';
|
|
43
|
-
}
|
|
44
|
-
function loadEnvFileIfAvailable() {
|
|
45
|
-
if (typeof process.loadEnvFile !== 'function')
|
|
46
|
-
return;
|
|
47
|
-
try {
|
|
48
|
-
process.loadEnvFile();
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
if (isMissingEnvFileError(error))
|
|
52
|
-
return;
|
|
53
|
-
throw error;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
loadEnvFileIfAvailable();
|
|
57
|
-
const { env } = process;
|
|
58
|
-
const ENV_BOOLEAN_SCHEMA = z.stringbool({
|
|
59
|
-
truthy: ['true', '1', 'yes', 'on'],
|
|
60
|
-
falsy: ['false', '0', 'no', 'off'],
|
|
61
|
-
});
|
|
62
|
-
function tryParseUrlHost(raw) {
|
|
63
|
-
if (raw.includes('://')) {
|
|
64
|
-
const hostname = URL.parse(raw)?.hostname;
|
|
65
|
-
if (hostname)
|
|
66
|
-
return normalizeHostname(hostname);
|
|
67
|
-
}
|
|
68
|
-
const candidateHostname = URL.parse(`http://${raw}`)?.hostname;
|
|
69
|
-
if (candidateHostname)
|
|
70
|
-
return normalizeHostname(candidateHostname);
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
function tryParseIpv6Bracket(lowered) {
|
|
74
|
-
if (!lowered.startsWith('['))
|
|
75
|
-
return undefined;
|
|
76
|
-
const end = lowered.indexOf(']');
|
|
77
|
-
return end === -1 ? null : normalizeHostname(lowered.slice(1, end));
|
|
78
|
-
}
|
|
79
|
-
function tryParseHostPort(lowered) {
|
|
80
|
-
const firstColon = lowered.indexOf(':');
|
|
81
|
-
if (firstColon === -1)
|
|
82
|
-
return normalizeHostname(lowered);
|
|
83
|
-
if (lowered.includes(':', firstColon + 1))
|
|
84
|
-
return null;
|
|
85
|
-
const host = lowered.slice(0, firstColon);
|
|
86
|
-
return host ? normalizeHostname(host) : null;
|
|
87
|
-
}
|
|
88
|
-
const EnvParser = {
|
|
89
|
-
integerValue(envValue, opts) {
|
|
90
|
-
if (!envValue)
|
|
91
|
-
return null;
|
|
92
|
-
const parsed = Number.parseInt(envValue, 10);
|
|
93
|
-
if (Number.isNaN(parsed)) {
|
|
94
|
-
if (opts?.envName)
|
|
95
|
-
process.stderr.write(`Warning: ignoring invalid ${opts.envName} value "${envValue}" (not an integer)\n`);
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
if ((opts?.min !== undefined && parsed < opts.min) ||
|
|
99
|
-
(opts?.max !== undefined && parsed > opts.max)) {
|
|
100
|
-
if (opts.envName)
|
|
101
|
-
process.stderr.write(`Warning: ignoring out-of-range ${opts.envName} value ${parsed} (allowed: ${opts.min ?? '-∞'}..${opts.max ?? '∞'})\n`);
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
return parsed;
|
|
105
|
-
},
|
|
106
|
-
optionalInteger(envValue, opts) {
|
|
107
|
-
return EnvParser.integerValue(envValue, opts) ?? undefined;
|
|
108
|
-
},
|
|
109
|
-
integer(envValue, defaultValue, opts) {
|
|
110
|
-
return EnvParser.integerValue(envValue, opts) ?? defaultValue;
|
|
111
|
-
},
|
|
112
|
-
boolean(envValue, defaultValue, envName) {
|
|
113
|
-
const trimmed = envValue?.trim();
|
|
114
|
-
if (!trimmed)
|
|
115
|
-
return defaultValue;
|
|
116
|
-
const parsed = ENV_BOOLEAN_SCHEMA.safeParse(trimmed);
|
|
117
|
-
if (!parsed.success) {
|
|
118
|
-
if (envName)
|
|
119
|
-
process.stderr.write(`Warning: ignoring invalid ${envName} value "${envValue ?? ''}" (expected true/false, 1/0, yes/no, or on/off)\n`);
|
|
120
|
-
return defaultValue;
|
|
121
|
-
}
|
|
122
|
-
return parsed.data;
|
|
123
|
-
},
|
|
124
|
-
list(envValue, defaultValue) {
|
|
125
|
-
if (!envValue)
|
|
126
|
-
return defaultValue ? [...defaultValue] : [];
|
|
127
|
-
const parsed = envValue
|
|
128
|
-
.split(/[\s,]+/)
|
|
129
|
-
.map((e) => e.trim())
|
|
130
|
-
.filter(Boolean);
|
|
131
|
-
return parsed.length > 0 || !defaultValue ? parsed : [...defaultValue];
|
|
132
|
-
},
|
|
133
|
-
locale(value) {
|
|
134
|
-
const lowered = value?.trim().toLowerCase();
|
|
135
|
-
return !lowered || lowered === 'system' || lowered === 'default'
|
|
136
|
-
? undefined
|
|
137
|
-
: lowered;
|
|
138
|
-
},
|
|
139
|
-
logLevel(envValue) {
|
|
140
|
-
const level = envValue?.toLowerCase();
|
|
141
|
-
if (!level || !ALLOWED_LOG_LEVELS.has(level)) {
|
|
142
|
-
if (envValue)
|
|
143
|
-
process.stderr.write(`Warning: ignoring invalid LOG_LEVEL value "${envValue}", using default "info"\n`);
|
|
144
|
-
return 'info';
|
|
145
|
-
}
|
|
146
|
-
return level;
|
|
147
|
-
},
|
|
148
|
-
transformWorkerMode(envValue) {
|
|
149
|
-
const normalized = envValue?.trim().toLowerCase();
|
|
150
|
-
return normalized === 'process' || normalized === 'fork'
|
|
151
|
-
? 'process'
|
|
152
|
-
: 'threads';
|
|
153
|
-
},
|
|
154
|
-
url(value, name) {
|
|
155
|
-
if (!value)
|
|
156
|
-
return undefined;
|
|
157
|
-
const parsed = URL.parse(value);
|
|
158
|
-
if (!parsed)
|
|
159
|
-
throw new ConfigError(`Invalid ${name} value: ${value}`);
|
|
160
|
-
return parsed;
|
|
161
|
-
},
|
|
162
|
-
allowedHosts(envValue) {
|
|
163
|
-
return new Set(EnvParser.list(envValue)
|
|
164
|
-
.map((h) => EnvParser.normalizeHostValue(h))
|
|
165
|
-
.filter((h) => h !== null));
|
|
166
|
-
},
|
|
167
|
-
optionalFilePath(value) {
|
|
168
|
-
const trimmed = value?.trim();
|
|
169
|
-
return trimmed === '' ? undefined : trimmed;
|
|
170
|
-
},
|
|
171
|
-
normalizeHostValue(value) {
|
|
172
|
-
const raw = value.trim();
|
|
173
|
-
if (!raw)
|
|
174
|
-
return null;
|
|
175
|
-
const fromUrl = tryParseUrlHost(raw);
|
|
176
|
-
if (fromUrl !== undefined)
|
|
177
|
-
return fromUrl;
|
|
178
|
-
const lowered = raw.toLowerCase();
|
|
179
|
-
const fromBracket = tryParseIpv6Bracket(lowered);
|
|
180
|
-
if (fromBracket !== undefined)
|
|
181
|
-
return fromBracket;
|
|
182
|
-
if (isIP(lowered) === 6)
|
|
183
|
-
return stripTrailingDots(lowered);
|
|
184
|
-
return tryParseHostPort(lowered);
|
|
185
|
-
},
|
|
186
|
-
formatHostForUrl(hostname) {
|
|
187
|
-
if (hostname.includes(':') && !hostname.startsWith('['))
|
|
188
|
-
return `[${hostname}]`;
|
|
189
|
-
return hostname;
|
|
190
|
-
},
|
|
191
|
-
};
|
|
8
|
+
export { config, enableHttpMode, serverVersion } from './config.js';
|
|
192
9
|
const PRIMARY_HASH_LENGTH = 32;
|
|
193
10
|
const VARY_HASH_LENGTH = 16;
|
|
194
|
-
const MAX_HTML_BYTES = 10 * 1024 * 1024;
|
|
195
|
-
const MAX_INLINE_CONTENT_CHARS = EnvParser.integer(env['MAX_INLINE_CONTENT_CHARS'], 0, { min: 0, max: MAX_HTML_BYTES, envName: 'MAX_INLINE_CONTENT_CHARS' });
|
|
196
|
-
const DEFAULT_SESSION_TTL_MS = 30 * 60 * 1000;
|
|
197
|
-
const DEFAULT_SESSION_INIT_TIMEOUT_MS = 10000;
|
|
198
|
-
const DEFAULT_MAX_SESSIONS = 200;
|
|
199
|
-
const DEFAULT_USER_AGENT = `fetch-url-mcp/${serverVersion}`;
|
|
200
|
-
const DEFAULT_TOOL_TIMEOUT_PADDING_MS = 5000;
|
|
201
|
-
const DEFAULT_TRANSFORM_TIMEOUT_MS = 30000;
|
|
202
|
-
const DEFAULT_FETCH_TIMEOUT_MS = EnvParser.integer(env['FETCH_TIMEOUT_MS'], 15000, { min: 1000, max: 60000, envName: 'FETCH_TIMEOUT_MS' });
|
|
203
|
-
const DEFAULT_TOOL_TIMEOUT_MS = DEFAULT_FETCH_TIMEOUT_MS +
|
|
204
|
-
DEFAULT_TRANSFORM_TIMEOUT_MS +
|
|
205
|
-
DEFAULT_TOOL_TIMEOUT_PADDING_MS;
|
|
206
|
-
const DEFAULT_TASKS_MAX_TOTAL = EnvParser.integer(env['TASKS_MAX_TOTAL'], 5000, { min: 1, envName: 'TASKS_MAX_TOTAL' });
|
|
207
|
-
const DEFAULT_TASKS_MAX_PER_OWNER = EnvParser.integer(env['TASKS_MAX_PER_OWNER'], 1000, { min: 1, envName: 'TASKS_MAX_PER_OWNER' });
|
|
208
|
-
const RESOLVED_TASKS_MAX_PER_OWNER = Math.min(DEFAULT_TASKS_MAX_PER_OWNER, DEFAULT_TASKS_MAX_TOTAL);
|
|
209
|
-
function resolveWorkerResourceLimits() {
|
|
210
|
-
const limits = {};
|
|
211
|
-
const keys = {
|
|
212
|
-
maxOldGenerationSizeMb: 'TRANSFORM_WORKER_MAX_OLD_GENERATION_MB',
|
|
213
|
-
maxYoungGenerationSizeMb: 'TRANSFORM_WORKER_MAX_YOUNG_GENERATION_MB',
|
|
214
|
-
codeRangeSizeMb: 'TRANSFORM_WORKER_CODE_RANGE_MB',
|
|
215
|
-
stackSizeMb: 'TRANSFORM_WORKER_STACK_MB',
|
|
216
|
-
};
|
|
217
|
-
let hasLimits = false;
|
|
218
|
-
for (const [prop, envKey] of Object.entries(keys)) {
|
|
219
|
-
const val = EnvParser.optionalInteger(env[envKey], {
|
|
220
|
-
min: 1,
|
|
221
|
-
envName: envKey,
|
|
222
|
-
});
|
|
223
|
-
if (val !== undefined) {
|
|
224
|
-
limits[prop] = val;
|
|
225
|
-
hasLimits = true;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return hasLimits ? limits : undefined;
|
|
229
|
-
}
|
|
230
|
-
function buildAuthConfig(baseUrl) {
|
|
231
|
-
const parseUrl = (key) => EnvParser.url(env[key], key);
|
|
232
|
-
const issuerUrl = parseUrl('OAUTH_ISSUER_URL');
|
|
233
|
-
const authorizationUrl = parseUrl('OAUTH_AUTHORIZATION_URL');
|
|
234
|
-
const tokenUrl = parseUrl('OAUTH_TOKEN_URL');
|
|
235
|
-
const revocationUrl = parseUrl('OAUTH_REVOCATION_URL');
|
|
236
|
-
const registrationUrl = parseUrl('OAUTH_REGISTRATION_URL');
|
|
237
|
-
const introspectionUrl = parseUrl('OAUTH_INTROSPECTION_URL');
|
|
238
|
-
const resourceUrl = new URL('/mcp', baseUrl);
|
|
239
|
-
const oauthConfigured = issuerUrl !== undefined ||
|
|
240
|
-
authorizationUrl !== undefined ||
|
|
241
|
-
tokenUrl !== undefined ||
|
|
242
|
-
introspectionUrl !== undefined;
|
|
243
|
-
const tokens = EnvParser.list(env['ACCESS_TOKENS']);
|
|
244
|
-
if (env['API_KEY'])
|
|
245
|
-
tokens.push(env['API_KEY']);
|
|
246
|
-
return {
|
|
247
|
-
mode: oauthConfigured ? 'oauth' : 'static',
|
|
248
|
-
issuerUrl,
|
|
249
|
-
authorizationUrl,
|
|
250
|
-
tokenUrl,
|
|
251
|
-
revocationUrl,
|
|
252
|
-
registrationUrl,
|
|
253
|
-
introspectionUrl,
|
|
254
|
-
resourceUrl,
|
|
255
|
-
requiredScopes: EnvParser.list(env['OAUTH_REQUIRED_SCOPES']),
|
|
256
|
-
clientId: env['OAUTH_CLIENT_ID'],
|
|
257
|
-
clientSecret: env['OAUTH_CLIENT_SECRET'],
|
|
258
|
-
introspectionTimeoutMs: 5000,
|
|
259
|
-
staticTokens: [...new Set(tokens)],
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function buildHttpsConfig() {
|
|
263
|
-
const keyFile = EnvParser.optionalFilePath(env['SERVER_TLS_KEY_FILE']);
|
|
264
|
-
const certFile = EnvParser.optionalFilePath(env['SERVER_TLS_CERT_FILE']);
|
|
265
|
-
const caFile = EnvParser.optionalFilePath(env['SERVER_TLS_CA_FILE']);
|
|
266
|
-
if ((keyFile && !certFile) || (!keyFile && certFile)) {
|
|
267
|
-
throw new ConfigError('Both SERVER_TLS_KEY_FILE and SERVER_TLS_CERT_FILE must be set together');
|
|
268
|
-
}
|
|
269
|
-
return {
|
|
270
|
-
enabled: Boolean(keyFile && certFile),
|
|
271
|
-
keyFile,
|
|
272
|
-
certFile,
|
|
273
|
-
caFile,
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
const LOOPBACK_V4 = buildIpv4([127, 0, 0, 1]);
|
|
277
|
-
const ANY_V4 = buildIpv4([0, 0, 0, 0]);
|
|
278
|
-
const METADATA_V4_AWS = buildIpv4([169, 254, 169, 254]);
|
|
279
|
-
const METADATA_V4_AZURE = buildIpv4([100, 100, 100, 200]);
|
|
280
|
-
const BLOCKED_HOSTS = new Set([
|
|
281
|
-
'localhost',
|
|
282
|
-
LOOPBACK_V4,
|
|
283
|
-
ANY_V4,
|
|
284
|
-
'::1',
|
|
285
|
-
METADATA_V4_AWS,
|
|
286
|
-
'metadata.google.internal',
|
|
287
|
-
'metadata.azure.com',
|
|
288
|
-
METADATA_V4_AZURE,
|
|
289
|
-
'instance-data',
|
|
290
|
-
]);
|
|
291
|
-
const host = (env['HOST'] ?? LOOPBACK_V4).trim();
|
|
292
|
-
const port = env['PORT']?.trim() === '0'
|
|
293
|
-
? 0
|
|
294
|
-
: EnvParser.integer(env['PORT'], 3000, {
|
|
295
|
-
min: 1024,
|
|
296
|
-
max: 65535,
|
|
297
|
-
envName: 'PORT',
|
|
298
|
-
});
|
|
299
|
-
const httpsConfig = buildHttpsConfig();
|
|
300
|
-
const allowRemote = EnvParser.boolean(env['ALLOW_REMOTE'], false, 'ALLOW_REMOTE');
|
|
301
|
-
const baseUrl = new URL(`${httpsConfig.enabled ? 'https' : 'http'}://${EnvParser.formatHostForUrl(host)}:${port}`);
|
|
302
|
-
const runtimeState = {
|
|
303
|
-
httpMode: false,
|
|
304
|
-
};
|
|
305
|
-
function buildServerConfig() {
|
|
306
|
-
const parseOptInt = (key, min = 1) => EnvParser.optionalInteger(env[key], { min, envName: key });
|
|
307
|
-
return {
|
|
308
|
-
name: 'fetch-url-mcp',
|
|
309
|
-
version: serverVersion,
|
|
310
|
-
port,
|
|
311
|
-
host,
|
|
312
|
-
https: httpsConfig,
|
|
313
|
-
sessionTtlMs: DEFAULT_SESSION_TTL_MS,
|
|
314
|
-
sessionInitTimeoutMs: DEFAULT_SESSION_INIT_TIMEOUT_MS,
|
|
315
|
-
maxSessions: DEFAULT_MAX_SESSIONS,
|
|
316
|
-
http: {
|
|
317
|
-
headersTimeoutMs: parseOptInt('SERVER_HEADERS_TIMEOUT_MS'),
|
|
318
|
-
requestTimeoutMs: parseOptInt('SERVER_REQUEST_TIMEOUT_MS', 0),
|
|
319
|
-
keepAliveTimeoutMs: parseOptInt('SERVER_KEEP_ALIVE_TIMEOUT_MS'),
|
|
320
|
-
keepAliveTimeoutBufferMs: parseOptInt('SERVER_KEEP_ALIVE_TIMEOUT_BUFFER_MS', 0),
|
|
321
|
-
maxHeadersCount: parseOptInt('SERVER_MAX_HEADERS_COUNT'),
|
|
322
|
-
maxConnections: EnvParser.integer(env['SERVER_MAX_CONNECTIONS'], 0, {
|
|
323
|
-
min: 0,
|
|
324
|
-
envName: 'SERVER_MAX_CONNECTIONS',
|
|
325
|
-
}),
|
|
326
|
-
blockPrivateConnections: EnvParser.boolean(env['SERVER_BLOCK_PRIVATE_CONNECTIONS'], false, 'SERVER_BLOCK_PRIVATE_CONNECTIONS'),
|
|
327
|
-
shutdownCloseIdleConnections: true,
|
|
328
|
-
shutdownCloseAllConnections: false,
|
|
329
|
-
},
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
function buildFetcherConfig() {
|
|
333
|
-
return {
|
|
334
|
-
timeout: DEFAULT_FETCH_TIMEOUT_MS,
|
|
335
|
-
maxRedirects: 5,
|
|
336
|
-
userAgent: env['USER_AGENT'] ?? DEFAULT_USER_AGENT,
|
|
337
|
-
maxContentLength: MAX_HTML_BYTES,
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
function buildTransformConfig() {
|
|
341
|
-
return {
|
|
342
|
-
timeoutMs: DEFAULT_TRANSFORM_TIMEOUT_MS,
|
|
343
|
-
stageWarnRatio: 0.5,
|
|
344
|
-
metadataFormat: 'markdown',
|
|
345
|
-
maxWorkerScale: 4,
|
|
346
|
-
cancelAckTimeoutMs: EnvParser.integer(env['TRANSFORM_CANCEL_ACK_TIMEOUT_MS'], 200, { min: 50, max: 5000, envName: 'TRANSFORM_CANCEL_ACK_TIMEOUT_MS' }),
|
|
347
|
-
workerMode: EnvParser.transformWorkerMode(env['TRANSFORM_WORKER_MODE']),
|
|
348
|
-
workerResourceLimits: resolveWorkerResourceLimits(),
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
function buildTasksConfig() {
|
|
352
|
-
return {
|
|
353
|
-
maxTotal: DEFAULT_TASKS_MAX_TOTAL,
|
|
354
|
-
maxPerOwner: RESOLVED_TASKS_MAX_PER_OWNER,
|
|
355
|
-
emitStatusNotifications: EnvParser.boolean(env['TASKS_STATUS_NOTIFICATIONS'], false, 'TASKS_STATUS_NOTIFICATIONS'),
|
|
356
|
-
requireInterception: EnvParser.boolean(env['TASKS_REQUIRE_INTERCEPTION'], true, 'TASKS_REQUIRE_INTERCEPTION'),
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
function buildCacheConfig() {
|
|
360
|
-
return {
|
|
361
|
-
enabled: EnvParser.boolean(env['CACHE_ENABLED'], true, 'CACHE_ENABLED'),
|
|
362
|
-
ttl: 86400,
|
|
363
|
-
maxKeys: 100,
|
|
364
|
-
maxSizeBytes: 50 * 1024 * 1024,
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
function buildNoiseRemovalConfig() {
|
|
368
|
-
return {
|
|
369
|
-
extraTokens: EnvParser.list(env['FETCH_URL_MCP_EXTRA_NOISE_TOKENS']),
|
|
370
|
-
extraSelectors: EnvParser.list(env['FETCH_URL_MCP_EXTRA_NOISE_SELECTORS']),
|
|
371
|
-
enabledCategories: [
|
|
372
|
-
'cookie-banners',
|
|
373
|
-
'newsletters',
|
|
374
|
-
'social-share',
|
|
375
|
-
'nav-footer',
|
|
376
|
-
'author-blocks',
|
|
377
|
-
'related-content',
|
|
378
|
-
],
|
|
379
|
-
debug: false,
|
|
380
|
-
aggressiveMode: false,
|
|
381
|
-
preserveSvgCanvas: false,
|
|
382
|
-
weights: {
|
|
383
|
-
hidden: 50,
|
|
384
|
-
structural: 50,
|
|
385
|
-
promo: 35,
|
|
386
|
-
stickyFixed: 30,
|
|
387
|
-
threshold: 50,
|
|
388
|
-
},
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
function buildMarkdownCleanupConfig() {
|
|
392
|
-
return {
|
|
393
|
-
promoteOrphanHeadings: true,
|
|
394
|
-
removeSkipLinks: true,
|
|
395
|
-
removeTocBlocks: true,
|
|
396
|
-
removeTypeDocComments: true,
|
|
397
|
-
headingKeywords: EnvParser.list(env['MARKDOWN_HEADING_KEYWORDS'], DEFAULT_HEADING_KEYWORDS),
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
export const config = {
|
|
401
|
-
server: buildServerConfig(),
|
|
402
|
-
fetcher: buildFetcherConfig(),
|
|
403
|
-
transform: buildTransformConfig(),
|
|
404
|
-
tools: {
|
|
405
|
-
enabled: ['fetch-url'],
|
|
406
|
-
timeoutMs: DEFAULT_TOOL_TIMEOUT_MS,
|
|
407
|
-
},
|
|
408
|
-
tasks: buildTasksConfig(),
|
|
409
|
-
cache: buildCacheConfig(),
|
|
410
|
-
extraction: {
|
|
411
|
-
maxBlockLength: 5000,
|
|
412
|
-
minParagraphLength: 10,
|
|
413
|
-
},
|
|
414
|
-
noiseRemoval: buildNoiseRemovalConfig(),
|
|
415
|
-
markdownCleanup: buildMarkdownCleanupConfig(),
|
|
416
|
-
i18n: {
|
|
417
|
-
locale: EnvParser.locale(env['FETCH_URL_MCP_LOCALE']),
|
|
418
|
-
},
|
|
419
|
-
logging: {
|
|
420
|
-
level: EnvParser.logLevel(env['LOG_LEVEL']),
|
|
421
|
-
format: env['LOG_FORMAT']?.toLowerCase() === 'json' ? 'json' : 'text',
|
|
422
|
-
},
|
|
423
|
-
constants: {
|
|
424
|
-
maxHtmlBytes: MAX_HTML_BYTES,
|
|
425
|
-
maxUrlLength: 2048,
|
|
426
|
-
maxInlineContentChars: MAX_INLINE_CONTENT_CHARS,
|
|
427
|
-
},
|
|
428
|
-
security: {
|
|
429
|
-
blockedHosts: BLOCKED_HOSTS,
|
|
430
|
-
allowedHosts: EnvParser.allowedHosts(env['ALLOWED_HOSTS']),
|
|
431
|
-
apiKey: env['API_KEY'],
|
|
432
|
-
allowRemote,
|
|
433
|
-
allowLocalFetch: EnvParser.boolean(env['ALLOW_LOCAL_FETCH'], false, 'ALLOW_LOCAL_FETCH'),
|
|
434
|
-
},
|
|
435
|
-
auth: buildAuthConfig(baseUrl),
|
|
436
|
-
rateLimit: {
|
|
437
|
-
enabled: true,
|
|
438
|
-
maxRequests: 100,
|
|
439
|
-
windowMs: 60000,
|
|
440
|
-
cleanupIntervalMs: 60000,
|
|
441
|
-
},
|
|
442
|
-
runtime: runtimeState,
|
|
443
|
-
};
|
|
444
|
-
export function enableHttpMode() {
|
|
445
|
-
runtimeState.httpMode = true;
|
|
446
|
-
}
|
|
447
11
|
export function createCacheKey(namespace, url, vary) {
|
|
448
12
|
if (!namespace || !url)
|
|
449
13
|
return null;
|
|
@@ -673,27 +237,6 @@ export function getEntryMeta(cacheKey) {
|
|
|
673
237
|
export function isEnabled() {
|
|
674
238
|
return store.isEnabled();
|
|
675
239
|
}
|
|
676
|
-
function hasPackageJsonVersion(value) {
|
|
677
|
-
return (typeof value === 'object' &&
|
|
678
|
-
value !== null &&
|
|
679
|
-
typeof value.version === 'string');
|
|
680
|
-
}
|
|
681
|
-
function readServerVersion(moduleUrl) {
|
|
682
|
-
const packageJsonPath = findPackageJSON(moduleUrl);
|
|
683
|
-
if (!packageJsonPath)
|
|
684
|
-
throw new Error('package.json not found');
|
|
685
|
-
let packageJson;
|
|
686
|
-
try {
|
|
687
|
-
packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
688
|
-
}
|
|
689
|
-
catch (error) {
|
|
690
|
-
throw new Error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, { cause: error });
|
|
691
|
-
}
|
|
692
|
-
if (!hasPackageJsonVersion(packageJson)) {
|
|
693
|
-
throw new Error(`package.json version is missing at ${packageJsonPath}`);
|
|
694
|
-
}
|
|
695
|
-
return packageJson.version;
|
|
696
|
-
}
|
|
697
240
|
const requestContext = new AsyncLocalStorage({
|
|
698
241
|
name: 'requestContext',
|
|
699
242
|
});
|
|
@@ -837,6 +380,7 @@ const LOG_LEVEL_ALIASES = {
|
|
|
837
380
|
function normalizeLogLevel(level) {
|
|
838
381
|
return LOG_LEVEL_ALIASES[level.toLowerCase()];
|
|
839
382
|
}
|
|
383
|
+
// Map internal log levels to standard RFC 5424 severities
|
|
840
384
|
function toMcpLogLevel(level) {
|
|
841
385
|
return level === 'warn' ? 'warning' : level;
|
|
842
386
|
}
|