@j0hanz/fetch-url-mcp 1.2.0 → 1.3.1
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/cache.d.ts +9 -3
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +54 -119
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -4
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +2 -3
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +19 -27
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +1 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +7 -3
- package/dist/crypto.js.map +1 -0
- package/dist/dom-noise-removal.d.ts +2 -1
- package/dist/dom-noise-removal.d.ts.map +1 -0
- package/dist/dom-noise-removal.js +9 -6
- package/dist/dom-noise-removal.js.map +1 -0
- package/dist/download.d.ts +4 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +106 -0
- package/dist/download.js.map +1 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -1
- package/dist/errors.js.map +1 -0
- package/dist/examples/mcp-fetch-url-client.js +19 -3
- package/dist/examples/mcp-fetch-url-client.js.map +1 -1
- package/dist/fetch-content.d.ts +1 -0
- package/dist/fetch-content.d.ts.map +1 -0
- package/dist/fetch-content.js +15 -14
- package/dist/fetch-content.js.map +1 -0
- package/dist/fetch-stream.d.ts +1 -0
- package/dist/fetch-stream.d.ts.map +1 -0
- package/dist/fetch-stream.js +1 -0
- package/dist/fetch-stream.js.map +1 -0
- package/dist/fetch.d.ts +1 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +123 -54
- package/dist/fetch.js.map +1 -0
- package/dist/host-normalization.d.ts +1 -0
- package/dist/host-normalization.d.ts.map +1 -0
- package/dist/host-normalization.js +22 -9
- package/dist/host-normalization.js.map +1 -0
- package/dist/http/auth.d.ts +51 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +344 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/health.d.ts +7 -0
- package/dist/http/health.d.ts.map +1 -0
- package/dist/http/health.js +156 -0
- package/dist/http/health.js.map +1 -0
- package/dist/http/helpers.d.ts +58 -0
- package/dist/http/helpers.d.ts.map +1 -0
- package/dist/http/helpers.js +370 -0
- package/dist/http/helpers.js.map +1 -0
- package/dist/{http-native.d.ts → http/native.d.ts} +1 -0
- package/dist/http/native.d.ts.map +1 -0
- package/dist/http/native.js +618 -0
- package/dist/http/native.js.map +1 -0
- package/dist/http/rate-limit.d.ts +13 -0
- package/dist/http/rate-limit.d.ts.map +1 -0
- package/dist/http/rate-limit.js +92 -0
- package/dist/http/rate-limit.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -14
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +2 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +41 -0
- package/dist/instructions.js.map +1 -0
- package/dist/ip-blocklist.d.ts +1 -0
- package/dist/ip-blocklist.d.ts.map +1 -0
- package/dist/ip-blocklist.js +13 -8
- package/dist/ip-blocklist.js.map +1 -0
- package/dist/json.d.ts +2 -1
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +16 -6
- package/dist/json.js.map +1 -0
- package/dist/language-detection.d.ts +1 -0
- package/dist/language-detection.d.ts.map +1 -0
- package/dist/language-detection.js +2 -7
- package/dist/language-detection.js.map +1 -0
- package/dist/markdown-cleanup.d.ts +2 -1
- package/dist/markdown-cleanup.d.ts.map +1 -0
- package/dist/markdown-cleanup.js +52 -54
- package/dist/markdown-cleanup.js.map +1 -0
- package/dist/mcp-validator.d.ts +1 -0
- package/dist/mcp-validator.d.ts.map +1 -0
- package/dist/mcp-validator.js +20 -18
- package/dist/mcp-validator.js.map +1 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +35 -344
- package/dist/mcp.js.map +1 -0
- package/dist/observability.d.ts +2 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +32 -6
- package/dist/observability.js.map +1 -0
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +15 -3
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +1 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +46 -25
- package/dist/resources.js.map +1 -0
- package/dist/server-tuning.d.ts +1 -0
- package/dist/server-tuning.d.ts.map +1 -0
- package/dist/server-tuning.js +14 -17
- package/dist/server-tuning.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +29 -35
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +2 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +58 -29
- package/dist/session.js.map +1 -0
- package/dist/tasks/execution.d.ts +42 -0
- package/dist/tasks/execution.d.ts.map +1 -0
- package/dist/tasks/execution.js +241 -0
- package/dist/tasks/execution.js.map +1 -0
- package/dist/{tasks.d.ts → tasks/manager.d.ts} +12 -0
- package/dist/tasks/manager.d.ts.map +1 -0
- package/dist/{tasks.js → tasks/manager.js} +95 -43
- package/dist/tasks/manager.js.map +1 -0
- package/dist/tasks/owner.d.ts +32 -0
- package/dist/tasks/owner.d.ts.map +1 -0
- package/dist/tasks/owner.js +92 -0
- package/dist/tasks/owner.js.map +1 -0
- package/dist/timer-utils.d.ts +1 -0
- package/dist/timer-utils.d.ts.map +1 -0
- package/dist/timer-utils.js +8 -4
- package/dist/timer-utils.js.map +1 -0
- package/dist/tool-errors.d.ts +12 -0
- package/dist/tool-errors.d.ts.map +1 -0
- package/dist/tool-errors.js +55 -0
- package/dist/tool-errors.js.map +1 -0
- package/dist/tool-pipeline.d.ts +72 -0
- package/dist/tool-pipeline.d.ts.map +1 -0
- package/dist/tool-pipeline.js +408 -0
- package/dist/tool-pipeline.js.map +1 -0
- package/dist/tool-progress.d.ts +32 -0
- package/dist/tool-progress.d.ts.map +1 -0
- package/dist/tool-progress.js +129 -0
- package/dist/tool-progress.js.map +1 -0
- package/dist/tools.d.ts +35 -111
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +150 -610
- package/dist/tools.js.map +1 -0
- package/dist/{transform.d.ts → transform/transform.d.ts} +2 -1
- package/dist/transform/transform.d.ts.map +1 -0
- package/dist/{transform.js → transform/transform.js} +81 -771
- package/dist/transform/transform.js.map +1 -0
- package/dist/{transform-types.d.ts → transform/types.d.ts} +2 -0
- package/dist/transform/types.d.ts.map +1 -0
- package/dist/{transform-types.js → transform/types.js} +1 -0
- package/dist/transform/types.js.map +1 -0
- package/dist/transform/worker-pool.d.ts +93 -0
- package/dist/transform/worker-pool.d.ts.map +1 -0
- package/dist/transform/worker-pool.js +757 -0
- package/dist/transform/worker-pool.js.map +1 -0
- package/dist/transform/workers/transform-child.d.ts +2 -0
- package/dist/transform/workers/transform-child.d.ts.map +1 -0
- package/dist/{workers → transform/workers}/transform-child.js +17 -13
- package/dist/transform/workers/transform-child.js.map +1 -0
- package/dist/transform/workers/transform-worker.d.ts +2 -0
- package/dist/transform/workers/transform-worker.d.ts.map +1 -0
- package/dist/{workers → transform/workers}/transform-worker.js +16 -13
- package/dist/transform/workers/transform-worker.js.map +1 -0
- package/dist/type-guards.d.ts +1 -0
- package/dist/type-guards.d.ts.map +1 -0
- package/dist/type-guards.js +4 -4
- package/dist/type-guards.js.map +1 -0
- package/package.json +6 -7
- package/dist/AGENTS.md +0 -152
- package/dist/http-native.js +0 -1320
- package/dist/instructions.md +0 -113
- package/dist/workers/transform-child.d.ts +0 -1
- package/dist/workers/transform-worker.d.ts +0 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { InvalidTokenError, ServerError, } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
import { config } from '../config.js';
|
|
5
|
+
import { hmacSha256Hex, timingSafeEqualUtf8 } from '../crypto.js';
|
|
6
|
+
import { normalizeHost } from '../host-normalization.js';
|
|
7
|
+
import { isObject } from '../type-guards.js';
|
|
8
|
+
import { getHeaderValue, sendEmpty, sendError, sendJson, } from './helpers.js';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// CORS
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
class CorsPolicy {
|
|
13
|
+
// NOTE: CorsPolicy.handle() is invoked only AFTER hostOriginPolicy.validate() in
|
|
14
|
+
// HttpRequestPipeline. The Origin header is reflected only when it matches an
|
|
15
|
+
// allowlisted host — arbitrary/unauthenticated origins are never reflected.
|
|
16
|
+
handle(ctx) {
|
|
17
|
+
const { req, res } = ctx;
|
|
18
|
+
const origin = getHeaderValue(req, 'origin');
|
|
19
|
+
if (origin) {
|
|
20
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
21
|
+
res.setHeader('Vary', 'Origin');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
25
|
+
}
|
|
26
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE');
|
|
27
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key, MCP-Protocol-Version, MCP-Session-ID, X-MCP-Session-ID, Last-Event-ID');
|
|
28
|
+
if (req.method !== 'OPTIONS')
|
|
29
|
+
return false;
|
|
30
|
+
sendEmpty(res, 204);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const corsPolicy = new CorsPolicy();
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Host / Origin validation
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
|
|
39
|
+
const WILDCARD_HOSTS = new Set(['0.0.0.0', '::']);
|
|
40
|
+
function hasConstantTimeMatch(candidates, input) {
|
|
41
|
+
// Avoid leaking match index via early-return.
|
|
42
|
+
let matched = 0;
|
|
43
|
+
for (const candidate of candidates) {
|
|
44
|
+
matched |= timingSafeEqualUtf8(candidate, input) ? 1 : 0;
|
|
45
|
+
}
|
|
46
|
+
return matched === 1;
|
|
47
|
+
}
|
|
48
|
+
function isWildcardHost(host) {
|
|
49
|
+
return WILDCARD_HOSTS.has(host);
|
|
50
|
+
}
|
|
51
|
+
function addNormalizedHost(target, value) {
|
|
52
|
+
const normalized = normalizeHost(value);
|
|
53
|
+
if (normalized)
|
|
54
|
+
target.add(normalized);
|
|
55
|
+
}
|
|
56
|
+
function buildAllowedHosts() {
|
|
57
|
+
const allowed = new Set(LOOPBACK_HOSTS);
|
|
58
|
+
const configuredHost = normalizeHost(config.server.host);
|
|
59
|
+
if (configuredHost && !isWildcardHost(configuredHost)) {
|
|
60
|
+
allowed.add(configuredHost);
|
|
61
|
+
}
|
|
62
|
+
for (const host of config.security.allowedHosts) {
|
|
63
|
+
addNormalizedHost(allowed, host);
|
|
64
|
+
}
|
|
65
|
+
return allowed;
|
|
66
|
+
}
|
|
67
|
+
const ALLOWED_HOSTS = buildAllowedHosts();
|
|
68
|
+
class HostOriginPolicy {
|
|
69
|
+
validate(ctx) {
|
|
70
|
+
const { req, res } = ctx;
|
|
71
|
+
const host = this.resolveHostHeader(req);
|
|
72
|
+
if (!host)
|
|
73
|
+
return this.reject(res, 400, 'Missing or invalid Host header');
|
|
74
|
+
if (!ALLOWED_HOSTS.has(host))
|
|
75
|
+
return this.reject(res, 403, 'Host not allowed');
|
|
76
|
+
const originHeader = getHeaderValue(req, 'origin');
|
|
77
|
+
if (!originHeader)
|
|
78
|
+
return true;
|
|
79
|
+
const originHost = this.resolveOriginHost(originHeader);
|
|
80
|
+
if (!originHost)
|
|
81
|
+
return this.reject(res, 403, 'Invalid Origin header');
|
|
82
|
+
if (!ALLOWED_HOSTS.has(originHost))
|
|
83
|
+
return this.reject(res, 403, 'Origin not allowed');
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
resolveHostHeader(req) {
|
|
87
|
+
const host = getHeaderValue(req, 'host');
|
|
88
|
+
if (!host)
|
|
89
|
+
return null;
|
|
90
|
+
return normalizeHost(host);
|
|
91
|
+
}
|
|
92
|
+
resolveOriginHost(origin) {
|
|
93
|
+
if (origin === 'null')
|
|
94
|
+
return null;
|
|
95
|
+
try {
|
|
96
|
+
const parsed = new URL(origin);
|
|
97
|
+
return normalizeHost(parsed.host);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
reject(res, status, message) {
|
|
104
|
+
sendJson(res, status, { error: message });
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export const hostOriginPolicy = new HostOriginPolicy();
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// HTTP mode configuration guard
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
export function assertHttpModeConfiguration() {
|
|
113
|
+
const configuredHost = normalizeHost(config.server.host);
|
|
114
|
+
const isLoopback = configuredHost !== null && LOOPBACK_HOSTS.has(configuredHost);
|
|
115
|
+
const isRemoteBinding = !isLoopback;
|
|
116
|
+
if (isRemoteBinding && !config.security.allowRemote) {
|
|
117
|
+
throw new Error('ALLOW_REMOTE must be true to bind to non-loopback interfaces');
|
|
118
|
+
}
|
|
119
|
+
if (isRemoteBinding && config.auth.mode !== 'oauth') {
|
|
120
|
+
throw new Error('OAuth authentication is required for remote bindings');
|
|
121
|
+
}
|
|
122
|
+
if (config.auth.mode === 'static' && config.auth.staticTokens.length === 0) {
|
|
123
|
+
throw new Error('Static auth requires ACCESS_TOKENS or API_KEY to be configured');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// MCP protocol version
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
const DEFAULT_MCP_PROTOCOL_VERSION = '2025-11-25';
|
|
130
|
+
const LEGACY_MCP_PROTOCOL_VERSION = '2025-03-26';
|
|
131
|
+
export const SUPPORTED_MCP_PROTOCOL_VERSIONS = new Set([
|
|
132
|
+
DEFAULT_MCP_PROTOCOL_VERSION,
|
|
133
|
+
LEGACY_MCP_PROTOCOL_VERSION,
|
|
134
|
+
]);
|
|
135
|
+
export function resolveMcpProtocolVersion(req) {
|
|
136
|
+
const versionHeader = getHeaderValue(req, 'mcp-protocol-version');
|
|
137
|
+
if (!versionHeader)
|
|
138
|
+
return undefined;
|
|
139
|
+
const version = versionHeader.trim();
|
|
140
|
+
return version.length > 0 ? version : undefined;
|
|
141
|
+
}
|
|
142
|
+
export function ensureMcpProtocolVersion(req, res, options) {
|
|
143
|
+
const version = resolveMcpProtocolVersion(req);
|
|
144
|
+
const requireHeader = options?.requireHeader ?? false;
|
|
145
|
+
if (!version) {
|
|
146
|
+
if (!requireHeader) {
|
|
147
|
+
// Permissive backward-compat fallback: clients predating MCP 2025-03-26 do not
|
|
148
|
+
// send MCP-Protocol-Version. Accepting requests without the header keeps older
|
|
149
|
+
// integrations working. Pass requireHeader: true to enforce strict version checking.
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
sendError(res, -32600, 'Missing MCP-Protocol-Version header');
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
if (!SUPPORTED_MCP_PROTOCOL_VERSIONS.has(version)) {
|
|
156
|
+
sendError(res, -32600, `Unsupported MCP-Protocol-Version: ${version}`);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
const expectedVersion = options?.expectedVersion;
|
|
160
|
+
if (expectedVersion && version !== expectedVersion) {
|
|
161
|
+
sendError(res, -32600, `MCP-Protocol-Version mismatch: expected ${expectedVersion}, got ${version}`);
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Auth fingerprint
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
const SESSION_AUTH_FINGERPRINT_KEY = randomBytes(32);
|
|
170
|
+
export function buildAuthFingerprint(auth) {
|
|
171
|
+
if (!auth)
|
|
172
|
+
return null;
|
|
173
|
+
const safeClientId = typeof auth.clientId === 'string' ? auth.clientId : '';
|
|
174
|
+
const safeToken = typeof auth.token === 'string' ? auth.token : '';
|
|
175
|
+
if (!safeClientId && !safeToken)
|
|
176
|
+
return null;
|
|
177
|
+
return hmacSha256Hex(SESSION_AUTH_FINGERPRINT_KEY, `${safeClientId}:${safeToken}`);
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Auth service
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
const STATIC_TOKEN_TTL_SECONDS = 60 * 60 * 24;
|
|
183
|
+
const STATIC_TOKEN_HMAC_KEY = randomBytes(32);
|
|
184
|
+
class AuthService {
|
|
185
|
+
staticTokenDigests = config.auth.staticTokens.map((token) => hmacSha256Hex(STATIC_TOKEN_HMAC_KEY, token));
|
|
186
|
+
async authenticate(req, signal) {
|
|
187
|
+
const authHeader = getHeaderValue(req, 'authorization');
|
|
188
|
+
if (!authHeader) {
|
|
189
|
+
return this.authenticateWithApiKey(req);
|
|
190
|
+
}
|
|
191
|
+
const token = this.resolveBearerToken(authHeader);
|
|
192
|
+
return this.authenticateWithToken(token, signal);
|
|
193
|
+
}
|
|
194
|
+
authenticateWithToken(token, signal) {
|
|
195
|
+
return config.auth.mode === 'oauth'
|
|
196
|
+
? this.verifyWithIntrospection(token, signal)
|
|
197
|
+
: Promise.resolve(this.verifyStaticToken(token));
|
|
198
|
+
}
|
|
199
|
+
authenticateWithApiKey(req) {
|
|
200
|
+
const apiKey = getHeaderValue(req, 'x-api-key');
|
|
201
|
+
if (apiKey && config.auth.mode === 'static') {
|
|
202
|
+
return this.verifyStaticToken(apiKey);
|
|
203
|
+
}
|
|
204
|
+
if (apiKey && config.auth.mode === 'oauth') {
|
|
205
|
+
throw new InvalidTokenError('X-API-Key not supported for OAuth');
|
|
206
|
+
}
|
|
207
|
+
throw new InvalidTokenError('Missing Authorization header');
|
|
208
|
+
}
|
|
209
|
+
resolveBearerToken(authHeader) {
|
|
210
|
+
if (!authHeader.startsWith('Bearer ')) {
|
|
211
|
+
throw new InvalidTokenError('Invalid Authorization header format');
|
|
212
|
+
}
|
|
213
|
+
const token = authHeader.substring(7);
|
|
214
|
+
if (!token) {
|
|
215
|
+
throw new InvalidTokenError('Invalid Authorization header format');
|
|
216
|
+
}
|
|
217
|
+
return token;
|
|
218
|
+
}
|
|
219
|
+
buildStaticAuthInfo(token) {
|
|
220
|
+
return {
|
|
221
|
+
token,
|
|
222
|
+
clientId: 'static-token',
|
|
223
|
+
scopes: config.auth.requiredScopes,
|
|
224
|
+
expiresAt: Math.floor(Date.now() / 1000) + STATIC_TOKEN_TTL_SECONDS,
|
|
225
|
+
resource: config.auth.resourceUrl,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
verifyStaticToken(token) {
|
|
229
|
+
if (this.staticTokenDigests.length === 0) {
|
|
230
|
+
throw new InvalidTokenError('No static tokens configured');
|
|
231
|
+
}
|
|
232
|
+
const tokenDigest = hmacSha256Hex(STATIC_TOKEN_HMAC_KEY, token);
|
|
233
|
+
const matched = hasConstantTimeMatch(this.staticTokenDigests, tokenDigest);
|
|
234
|
+
if (!matched)
|
|
235
|
+
throw new InvalidTokenError('Invalid token');
|
|
236
|
+
return this.buildStaticAuthInfo(token);
|
|
237
|
+
}
|
|
238
|
+
stripHash(url) {
|
|
239
|
+
const clean = new URL(url);
|
|
240
|
+
clean.hash = '';
|
|
241
|
+
return clean.href;
|
|
242
|
+
}
|
|
243
|
+
buildBasicAuthHeader(clientId, clientSecret) {
|
|
244
|
+
// Base64 is only an encoding for header transport; it is NOT encryption.
|
|
245
|
+
const credentials = `${clientId}:${clientSecret ?? ''}`;
|
|
246
|
+
return `Basic ${Buffer.from(credentials, 'utf8').toString('base64')}`;
|
|
247
|
+
}
|
|
248
|
+
buildIntrospectionRequest(token, resourceUrl, clientId, clientSecret) {
|
|
249
|
+
const body = new URLSearchParams({
|
|
250
|
+
token,
|
|
251
|
+
token_type_hint: 'access_token',
|
|
252
|
+
resource: this.stripHash(resourceUrl),
|
|
253
|
+
}).toString();
|
|
254
|
+
const headers = {
|
|
255
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
256
|
+
};
|
|
257
|
+
if (clientId) {
|
|
258
|
+
headers['authorization'] = this.buildBasicAuthHeader(clientId, clientSecret);
|
|
259
|
+
}
|
|
260
|
+
return { body, headers };
|
|
261
|
+
}
|
|
262
|
+
async requestIntrospection(url, request, timeoutMs, signal) {
|
|
263
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
264
|
+
const combinedSignal = signal
|
|
265
|
+
? AbortSignal.any([signal, timeoutSignal])
|
|
266
|
+
: timeoutSignal;
|
|
267
|
+
const response = await fetch(url, {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
headers: request.headers,
|
|
270
|
+
body: request.body,
|
|
271
|
+
signal: combinedSignal,
|
|
272
|
+
});
|
|
273
|
+
if (!response.ok) {
|
|
274
|
+
if (response.body) {
|
|
275
|
+
await response.body.cancel();
|
|
276
|
+
}
|
|
277
|
+
throw new ServerError(`Token introspection failed: ${response.status}`);
|
|
278
|
+
}
|
|
279
|
+
return response.json();
|
|
280
|
+
}
|
|
281
|
+
buildIntrospectionAuthInfo(token, payload) {
|
|
282
|
+
const { exp, client_id: clientIdRaw, scope: scopeRaw } = payload;
|
|
283
|
+
const expiresAt = typeof exp === 'number' ? exp : undefined;
|
|
284
|
+
const clientId = typeof clientIdRaw === 'string' ? clientIdRaw : 'unknown';
|
|
285
|
+
const info = {
|
|
286
|
+
token,
|
|
287
|
+
clientId,
|
|
288
|
+
scopes: typeof scopeRaw === 'string' ? scopeRaw.split(' ') : [],
|
|
289
|
+
resource: config.auth.resourceUrl,
|
|
290
|
+
};
|
|
291
|
+
if (expiresAt !== undefined)
|
|
292
|
+
info.expiresAt = expiresAt;
|
|
293
|
+
return info;
|
|
294
|
+
}
|
|
295
|
+
async verifyWithIntrospection(token, signal) {
|
|
296
|
+
if (!config.auth.introspectionUrl) {
|
|
297
|
+
throw new ServerError('Introspection not configured');
|
|
298
|
+
}
|
|
299
|
+
const req = this.buildIntrospectionRequest(token, config.auth.resourceUrl, config.auth.clientId, config.auth.clientSecret);
|
|
300
|
+
const payload = await this.requestIntrospection(config.auth.introspectionUrl, req, config.auth.introspectionTimeoutMs, signal);
|
|
301
|
+
if (!isObject(payload) || payload['active'] !== true) {
|
|
302
|
+
throw new InvalidTokenError('Token is inactive');
|
|
303
|
+
}
|
|
304
|
+
return this.buildIntrospectionAuthInfo(token, payload);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function resolvePublicOrigin(req) {
|
|
308
|
+
const host = getHeaderValue(req, 'host');
|
|
309
|
+
if (host) {
|
|
310
|
+
const protocol = config.server.https.enabled ? 'https' : 'http';
|
|
311
|
+
return `${protocol}://${host}`;
|
|
312
|
+
}
|
|
313
|
+
return config.auth.resourceUrl.origin;
|
|
314
|
+
}
|
|
315
|
+
function resolveResourceMetadataPath() {
|
|
316
|
+
return '/.well-known/oauth-protected-resource/mcp';
|
|
317
|
+
}
|
|
318
|
+
export function buildResourceMetadataUrl(req) {
|
|
319
|
+
const origin = resolvePublicOrigin(req);
|
|
320
|
+
const path = resolveResourceMetadataPath();
|
|
321
|
+
return new URL(path, `${origin}/`).href;
|
|
322
|
+
}
|
|
323
|
+
export function applyUnauthorizedAuthHeaders(req, res) {
|
|
324
|
+
const resourceMetadata = buildResourceMetadataUrl(req);
|
|
325
|
+
res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${resourceMetadata}"`);
|
|
326
|
+
}
|
|
327
|
+
export function buildProtectedResourceMetadataDocument(req) {
|
|
328
|
+
const metadataUrl = buildResourceMetadataUrl(req);
|
|
329
|
+
return {
|
|
330
|
+
resource: config.auth.resourceUrl.href,
|
|
331
|
+
resource_metadata: metadataUrl,
|
|
332
|
+
authorization_servers: config.auth.issuerUrl
|
|
333
|
+
? [config.auth.issuerUrl.href]
|
|
334
|
+
: [],
|
|
335
|
+
bearer_methods_supported: ['header'],
|
|
336
|
+
scopes_supported: config.auth.requiredScopes,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
export function isProtectedResourceMetadataPath(pathname) {
|
|
340
|
+
return (pathname === '/.well-known/oauth-protected-resource' ||
|
|
341
|
+
pathname === '/.well-known/oauth-protected-resource/mcp');
|
|
342
|
+
}
|
|
343
|
+
export const authService = new AuthService();
|
|
344
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/http/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SessionStore } from '../session.js';
|
|
2
|
+
import { type RequestContext } from './helpers.js';
|
|
3
|
+
export declare function resetEventLoopMonitoring(): void;
|
|
4
|
+
export declare function disableEventLoopMonitoring(): void;
|
|
5
|
+
export declare function shouldHandleHealthRoute(ctx: RequestContext): boolean;
|
|
6
|
+
export declare function sendHealthRouteResponse(store: SessionStore, ctx: RequestContext, authPresent: boolean): boolean;
|
|
7
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/http/health.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,KAAK,cAAc,EAAY,MAAM,cAAc,CAAC;AAY7D,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAwMD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAEpE;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,cAAc,EACnB,WAAW,EAAE,OAAO,GACnB,OAAO,CAOT"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { freemem, hostname, totalmem } from 'node:os';
|
|
2
|
+
import { monitorEventLoopDelay, performance } from 'node:perf_hooks';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { keys as cacheKeys } from '../cache.js';
|
|
5
|
+
import { config, serverVersion } from '../config.js';
|
|
6
|
+
import { getTransformPoolStats } from '../transform/transform.js';
|
|
7
|
+
import { sendJson } from './helpers.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Event-loop monitoring
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const EVENT_LOOP_DELAY_RESOLUTION_MS = 20;
|
|
12
|
+
const eventLoopDelay = monitorEventLoopDelay({
|
|
13
|
+
resolution: EVENT_LOOP_DELAY_RESOLUTION_MS,
|
|
14
|
+
});
|
|
15
|
+
let lastEventLoopUtilization = performance.eventLoopUtilization();
|
|
16
|
+
export function resetEventLoopMonitoring() {
|
|
17
|
+
lastEventLoopUtilization = performance.eventLoopUtilization();
|
|
18
|
+
eventLoopDelay.reset();
|
|
19
|
+
eventLoopDelay.enable();
|
|
20
|
+
}
|
|
21
|
+
export function disableEventLoopMonitoring() {
|
|
22
|
+
eventLoopDelay.disable();
|
|
23
|
+
}
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Stats helpers
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
function roundTo(value, precision) {
|
|
28
|
+
const factor = 10 ** precision;
|
|
29
|
+
return Math.round(value * factor) / factor;
|
|
30
|
+
}
|
|
31
|
+
function formatEventLoopUtilization(snapshot) {
|
|
32
|
+
return {
|
|
33
|
+
utilization: roundTo(snapshot.utilization, 4),
|
|
34
|
+
activeMs: Math.round(snapshot.active),
|
|
35
|
+
idleMs: Math.round(snapshot.idle),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function toMs(valueNs) {
|
|
39
|
+
return roundTo(valueNs / 1_000_000, 3);
|
|
40
|
+
}
|
|
41
|
+
function getEventLoopStats() {
|
|
42
|
+
const current = performance.eventLoopUtilization();
|
|
43
|
+
const delta = performance.eventLoopUtilization(current, lastEventLoopUtilization);
|
|
44
|
+
lastEventLoopUtilization = current;
|
|
45
|
+
return {
|
|
46
|
+
utilization: {
|
|
47
|
+
total: formatEventLoopUtilization(current),
|
|
48
|
+
sinceLast: formatEventLoopUtilization(delta),
|
|
49
|
+
},
|
|
50
|
+
delay: {
|
|
51
|
+
minMs: toMs(eventLoopDelay.min),
|
|
52
|
+
maxMs: toMs(eventLoopDelay.max),
|
|
53
|
+
meanMs: toMs(eventLoopDelay.mean),
|
|
54
|
+
stddevMs: toMs(eventLoopDelay.stddev),
|
|
55
|
+
p50Ms: toMs(eventLoopDelay.percentile(50)),
|
|
56
|
+
p95Ms: toMs(eventLoopDelay.percentile(95)),
|
|
57
|
+
p99Ms: toMs(eventLoopDelay.percentile(99)),
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function buildHealthResponse(store, includeDiagnostics) {
|
|
62
|
+
const base = {
|
|
63
|
+
status: 'ok',
|
|
64
|
+
version: serverVersion,
|
|
65
|
+
uptime: Math.floor(process.uptime()),
|
|
66
|
+
timestamp: new Date().toISOString(),
|
|
67
|
+
};
|
|
68
|
+
if (!includeDiagnostics)
|
|
69
|
+
return base;
|
|
70
|
+
const poolStats = getTransformPoolStats();
|
|
71
|
+
return {
|
|
72
|
+
...base,
|
|
73
|
+
os: {
|
|
74
|
+
hostname: hostname(),
|
|
75
|
+
platform: process.platform,
|
|
76
|
+
arch: process.arch,
|
|
77
|
+
memoryFree: freemem(),
|
|
78
|
+
memoryTotal: totalmem(),
|
|
79
|
+
},
|
|
80
|
+
process: {
|
|
81
|
+
pid: process.pid,
|
|
82
|
+
ppid: process.ppid,
|
|
83
|
+
memory: process.memoryUsage(),
|
|
84
|
+
cpu: process.cpuUsage(),
|
|
85
|
+
resource: process.resourceUsage(),
|
|
86
|
+
},
|
|
87
|
+
perf: getEventLoopStats(),
|
|
88
|
+
stats: {
|
|
89
|
+
activeSessions: store.size(),
|
|
90
|
+
cacheKeys: cacheKeys().length,
|
|
91
|
+
workerPool: poolStats ?? {
|
|
92
|
+
queueDepth: 0,
|
|
93
|
+
activeWorkers: 0,
|
|
94
|
+
capacity: 0,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function sendHealth(store, res, includeDiagnostics) {
|
|
100
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
101
|
+
sendJson(res, 200, buildHealthResponse(store, includeDiagnostics));
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Health route helpers
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
function isVerboseHealthRequest(ctx) {
|
|
107
|
+
const value = ctx.url.searchParams.get('verbose');
|
|
108
|
+
if (!value)
|
|
109
|
+
return false;
|
|
110
|
+
const normalized = value.trim().toLowerCase();
|
|
111
|
+
return normalized === '1' || normalized === 'true';
|
|
112
|
+
}
|
|
113
|
+
function isGetHealthRoute(ctx) {
|
|
114
|
+
return ctx.method === 'GET' && ctx.url.pathname === '/health';
|
|
115
|
+
}
|
|
116
|
+
function isVerboseHealthRoute(ctx) {
|
|
117
|
+
return isGetHealthRoute(ctx) && isVerboseHealthRequest(ctx);
|
|
118
|
+
}
|
|
119
|
+
function isHealthRoute(ctx) {
|
|
120
|
+
return isGetHealthRoute(ctx);
|
|
121
|
+
}
|
|
122
|
+
function ensureHealthAuthIfNeeded(ctx, authPresent) {
|
|
123
|
+
if (!isHealthRoute(ctx))
|
|
124
|
+
return true;
|
|
125
|
+
const isVerbose = isVerboseHealthRequest(ctx);
|
|
126
|
+
if (!isVerbose)
|
|
127
|
+
return true;
|
|
128
|
+
if (!config.security.allowRemote)
|
|
129
|
+
return true;
|
|
130
|
+
if (authPresent)
|
|
131
|
+
return true;
|
|
132
|
+
sendJson(ctx.res, 401, {
|
|
133
|
+
error: 'Authentication required for verbose health metrics',
|
|
134
|
+
});
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
function resolveHealthDiagnosticsMode(ctx, authPresent) {
|
|
138
|
+
if (!isVerboseHealthRoute(ctx))
|
|
139
|
+
return false;
|
|
140
|
+
if (authPresent)
|
|
141
|
+
return true;
|
|
142
|
+
return !config.security.allowRemote;
|
|
143
|
+
}
|
|
144
|
+
export function shouldHandleHealthRoute(ctx) {
|
|
145
|
+
return isGetHealthRoute(ctx);
|
|
146
|
+
}
|
|
147
|
+
export function sendHealthRouteResponse(store, ctx, authPresent) {
|
|
148
|
+
if (!shouldHandleHealthRoute(ctx))
|
|
149
|
+
return false;
|
|
150
|
+
if (!ensureHealthAuthIfNeeded(ctx, authPresent))
|
|
151
|
+
return true;
|
|
152
|
+
const includeDiagnostics = resolveHealthDiagnosticsMode(ctx, authPresent);
|
|
153
|
+
sendHealth(store, ctx.res, includeDiagnostics);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/http/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
2
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
5
|
+
import type { IncomingMessage, Server, ServerResponse } from 'node:http';
|
|
6
|
+
import type { Server as HttpsServer } from 'node:https';
|
|
7
|
+
import type { JsonRpcId } from '../mcp-validator.js';
|
|
8
|
+
export type NetworkServer = Server | HttpsServer;
|
|
9
|
+
export interface RequestContext {
|
|
10
|
+
req: IncomingMessage;
|
|
11
|
+
res: ServerResponse;
|
|
12
|
+
url: URL;
|
|
13
|
+
method: string | undefined;
|
|
14
|
+
ip: string | null;
|
|
15
|
+
body: unknown;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
export interface AuthenticatedContext extends RequestContext {
|
|
19
|
+
auth: AuthInfo;
|
|
20
|
+
}
|
|
21
|
+
export declare function setNoStoreHeaders(res: ServerResponse): void;
|
|
22
|
+
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
23
|
+
export declare function sendText(res: ServerResponse, status: number, body: string): void;
|
|
24
|
+
export declare function sendEmpty(res: ServerResponse, status: number): void;
|
|
25
|
+
export declare function sendError(res: ServerResponse, code: number, message: string, status?: number, id?: JsonRpcId): void;
|
|
26
|
+
export declare function getHeaderValue(req: IncomingMessage, name: string): string | null;
|
|
27
|
+
export declare function getMcpSessionId(req: IncomingMessage): string | null;
|
|
28
|
+
export declare function findDuplicateSingleValueHeader(req: IncomingMessage): string | null;
|
|
29
|
+
export declare function drainRequest(req: IncomingMessage): void;
|
|
30
|
+
export declare function createRequestAbortSignal(req: IncomingMessage): {
|
|
31
|
+
signal: AbortSignal;
|
|
32
|
+
cleanup: () => void;
|
|
33
|
+
};
|
|
34
|
+
export declare function normalizeRemoteAddress(address: string | undefined): string | null;
|
|
35
|
+
export declare function registerInboundBlockList(server: NetworkServer): void;
|
|
36
|
+
export declare function buildRequestContext(req: IncomingMessage, res: ServerResponse, signal?: AbortSignal): RequestContext | null;
|
|
37
|
+
export declare function closeTransportBestEffort(transport: {
|
|
38
|
+
close: () => Promise<unknown>;
|
|
39
|
+
}, context: string): Promise<void>;
|
|
40
|
+
export declare function closeMcpServerBestEffort(server: McpServer, context: string): Promise<void>;
|
|
41
|
+
export declare function createTransportAdapter(transportImpl: StreamableHTTPServerTransport): Transport;
|
|
42
|
+
type JsonBodyErrorKind = 'payload-too-large' | 'invalid-json' | 'read-failed';
|
|
43
|
+
export declare class JsonBodyError extends Error {
|
|
44
|
+
readonly kind: JsonBodyErrorKind;
|
|
45
|
+
constructor(kind: JsonBodyErrorKind, message: string);
|
|
46
|
+
}
|
|
47
|
+
export declare const DEFAULT_BODY_LIMIT_BYTES: number;
|
|
48
|
+
declare class JsonBodyReader {
|
|
49
|
+
read(req: IncomingMessage, limit?: number, signal?: AbortSignal): Promise<unknown>;
|
|
50
|
+
private readBody;
|
|
51
|
+
private attachAbortListener;
|
|
52
|
+
private detachAbortListener;
|
|
53
|
+
private collectChunks;
|
|
54
|
+
private normalizeChunk;
|
|
55
|
+
}
|
|
56
|
+
export declare const jsonBodyReader: JsonBodyReader;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/http/helpers.ts"],"names":[],"mappings":"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"}
|