@zuplo/cli 7.8.6 → 7.8.7
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/node_modules/@modelcontextprotocol/client/dist/{index-CHhhk6PQ.d.cts → index-BCtJi0p5.d.mts} +38 -6
- package/node_modules/@modelcontextprotocol/client/dist/index-BCtJi0p5.d.mts.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/{index-D4xIIEF6.d.mts → index-CEk3qkZM.d.cts} +41 -3
- package/node_modules/@modelcontextprotocol/client/dist/index-CEk3qkZM.d.cts.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/index.cjs +375 -60
- package/node_modules/@modelcontextprotocol/client/dist/index.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.d.cts +227 -11
- package/node_modules/@modelcontextprotocol/client/dist/index.d.cts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.d.mts +227 -11
- package/node_modules/@modelcontextprotocol/client/dist/index.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.mjs +369 -61
- package/node_modules/@modelcontextprotocol/client/dist/index.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.cjs +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.mjs +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/{src-NAgB4Mp8.cjs → src-D0qEN74R.cjs} +111 -38
- package/node_modules/@modelcontextprotocol/client/dist/src-D0qEN74R.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/{src-D_zzAWoS.mjs → src-DDAAhLnO.mjs} +106 -33
- package/node_modules/@modelcontextprotocol/client/dist/src-DDAAhLnO.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs +8 -2
- package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs +8 -2
- package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/package.json +4 -4
- package/node_modules/@modelcontextprotocol/core/dist/{auth-BWdKR39I.d.mts → auth--n_Yzytt.d.cts} +6 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-BWdKR39I.d.mts.map → auth--n_Yzytt.d.cts.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CfDMXiII.cjs → auth-4-zilcqg.cjs} +3 -2
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CfDMXiII.cjs.map → auth-4-zilcqg.cjs.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CUe6YdwF.mjs → auth-CGP0BDVq.mjs} +3 -2
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CUe6YdwF.mjs.map → auth-CGP0BDVq.mjs.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-hYtaIUZm.d.cts → auth-YUQV3RRv.d.mts} +6 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-hYtaIUZm.d.cts.map → auth-YUQV3RRv.d.mts.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.mjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.mjs +1 -1
- package/node_modules/@modelcontextprotocol/core/package.json +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts +15 -4
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js +22 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.js +3 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.d.ts +25 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.js +64 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts +10 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js +13 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts +15 -4
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js +22 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.js +3 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.d.ts +25 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.d.ts.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js +58 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js.map +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts +10 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js +13 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/package.json +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-dBHMsxwf.d.cts → createMcpHandler-BLVe3qmU.d.cts} +110 -7
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-BLVe3qmU.d.cts.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-CLhGwQTn.d.mts → createMcpHandler-Bt6U_Fqb.d.mts} +110 -7
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-Bt6U_Fqb.d.mts.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/index.cjs +144 -248
- package/node_modules/@modelcontextprotocol/server/dist/index.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.d.cts +38 -3
- package/node_modules/@modelcontextprotocol/server/dist/index.d.cts.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.d.mts +38 -3
- package/node_modules/@modelcontextprotocol/server/dist/index.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.mjs +136 -243
- package/node_modules/@modelcontextprotocol/server/dist/index.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{mcp-D7GmuPnv.cjs → mcp-DUcCQSTW.cjs} +426 -21
- package/node_modules/@modelcontextprotocol/server/dist/mcp-DUcCQSTW.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{mcp-DXXb3Vv3.mjs → mcp-Dw2OlZ1f.mjs} +367 -22
- package/node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.cjs +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.mjs +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{src-STyD_Vvf.cjs → src-CgFsfg3E.cjs} +114 -36
- package/node_modules/@modelcontextprotocol/server/dist/src-CgFsfg3E.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{src-CX2iR2pK.mjs → src-D-y6h4N7.mjs} +114 -36
- package/node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs +30 -3
- package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts +9 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts +9 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs +30 -3
- package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/package.json +3 -3
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/package.json +11 -11
- package/node_modules/@modelcontextprotocol/client/dist/index-CHhhk6PQ.d.cts.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/index-D4xIIEF6.d.mts.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/src-D_zzAWoS.mjs.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/src-NAgB4Mp8.cjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-CLhGwQTn.d.mts.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-dBHMsxwf.d.cts.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/mcp-D7GmuPnv.cjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/mcp-DXXb3Vv3.mjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/src-STyD_Vvf.cjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as seedClientIdentityFromEnvelope, d as
|
|
2
|
-
import { $ as isTaskAugmentedRequestParams, At as LATEST_PROTOCOL_VERSION, B as scanXMcpHeaderDeclarations, Bt as TRACESTATE_META_KEY, Ct as CLIENT_CAPABILITIES_META_KEY, D as acceptedContent, Dt as INVALID_PARAMS, Et as INTERNAL_ERROR, Ft as RELATED_TASK_META_KEY, G as isInitializeRequest, Gt as resourceUrlFromServerUrl, H as assertCompleteRequestPrompt, I as classifyInboundRequest, It as SERVER_INFO_META_KEY, J as isJSONRPCErrorResponse, Jt as SdkHttpError, K as isInitializedNotification, Kt as SdkError, L as httpStatusForErrorCode, Lt as SUBSCRIPTION_ID_META_KEY, Mt as METHOD_NOT_FOUND, Nt as PARSE_ERROR, O as inputRequired, Ot as INVALID_REQUEST, P as LADDER_ERROR_HTTP_STATUS, Pt as PROTOCOL_VERSION_META_KEY, Q as isJSONRPCResultResponse, R as modernOnlyStrictRejection, Rt as SUPPORTED_PROTOCOL_VERSIONS, S as specTypeSchemas, St as BAGGAGE_META_KEY, Tt as DEFAULT_NEGOTIATED_PROTOCOL_VERSION, U as assertCompleteRequestResourceTemplate, Ut as requiredClientCapabilitiesForRequest, V as validateMcpParamHeaders, Vt as missingClientCapabilities, W as isCallToolResult, Wt as checkResourceAllowed, X as isJSONRPCRequest, Xt as OAuthErrorCode, Y as isJSONRPCNotification, Yt as OAuthError, Z as isJSONRPCResponse, _ as mergeCapabilities, a as UriTemplate, at as requestMetaOf, c as ReadBuffer, d as serializeMessage, dt as ResourceNotFoundError, et as parseJSONRPCMessage, f as getDisplayName, ft as UnsupportedProtocolVersionError, g as Protocol, h as DEFAULT_REQUEST_TIMEOUT_MSEC, i as InMemoryTransport, jt as LOG_LEVEL_META_KEY, k as inputResponse, kt as JSONRPC_VERSION, l as STDIO_DEFAULT_MAX_BUFFER_SIZE, lt as MissingRequiredClientCapabilityError, m as mediaTypeEssence, mt as ProtocolErrorCode, n as preloadSchemas, o as createFetchWithInit, p as isJsonContentType, pt as UrlElicitationRequiredError, q as isInputRequiredResult, qt as SdkErrorCode, t as fromJsonSchema$1, tt as JSONRPCMessageSchema, u as deserializeMessage, ut as ProtocolError, vt as SUPPORTED_MODERN_PROTOCOL_VERSIONS, wt as CLIENT_INFO_META_KEY, x as isSpecType, y as setNegotiatedProtocolVersion, z as validateStandardRequestHeaders, zt as TRACEPARENT_META_KEY } from "./src-
|
|
1
|
+
import { C as armSseKeepAlive, S as DEFAULT_SSE_KEEP_ALIVE_MS, T as isCompletable, _ as DEFAULT_MAX_SUBSCRIPTIONS, a as seedClientIdentityFromEnvelope, b as InMemoryServerEventBus, c as findScopeChallenge, d as buildOAuthProtectedResourceMetadata, f as getOAuthProtectedResourceMetadataUrl, g as verifyBearerToken, h as requireBearerAuth, i as installModernOnlyHandlers, l as requireScopes, m as bearerAuthChallengeResponse, n as ResourceTemplate, o as serverIdentityOf, p as oauthMetadataResponse, r as Server, s as createScopeChallengeResponse, t as McpServer, u as scopeChallengeResourceMetadataUrl, w as completable, x as createServerNotifier, y as createListenRouter } from "./mcp-Dw2OlZ1f.mjs";
|
|
2
|
+
import { $ as isTaskAugmentedRequestParams, At as LATEST_PROTOCOL_VERSION, B as scanXMcpHeaderDeclarations, Bt as TRACESTATE_META_KEY, Ct as CLIENT_CAPABILITIES_META_KEY, D as acceptedContent, Dt as INVALID_PARAMS, Et as INTERNAL_ERROR, Ft as RELATED_TASK_META_KEY, G as isInitializeRequest, Gt as resourceUrlFromServerUrl, H as assertCompleteRequestPrompt, I as classifyInboundRequest, It as SERVER_INFO_META_KEY, J as isJSONRPCErrorResponse, Jt as SdkHttpError, K as isInitializedNotification, Kt as SdkError, L as httpStatusForErrorCode, Lt as SUBSCRIPTION_ID_META_KEY, Mt as METHOD_NOT_FOUND, Nt as PARSE_ERROR, O as inputRequired, Ot as INVALID_REQUEST, P as LADDER_ERROR_HTTP_STATUS, Pt as PROTOCOL_VERSION_META_KEY, Q as isJSONRPCResultResponse, R as modernOnlyStrictRejection, Rt as SUPPORTED_PROTOCOL_VERSIONS, S as specTypeSchemas, St as BAGGAGE_META_KEY, Tt as DEFAULT_NEGOTIATED_PROTOCOL_VERSION, U as assertCompleteRequestResourceTemplate, Ut as requiredClientCapabilitiesForRequest, V as validateMcpParamHeaders, Vt as missingClientCapabilities, W as isCallToolResult, Wt as checkResourceAllowed, X as isJSONRPCRequest, Xt as OAuthErrorCode, Y as isJSONRPCNotification, Yt as OAuthError, Z as isJSONRPCResponse, _ as mergeCapabilities, a as UriTemplate, at as requestMetaOf, c as ReadBuffer, d as serializeMessage, dt as ResourceNotFoundError, et as parseJSONRPCMessage, f as getDisplayName, ft as UnsupportedProtocolVersionError, g as Protocol, h as DEFAULT_REQUEST_TIMEOUT_MSEC, i as InMemoryTransport, jt as LOG_LEVEL_META_KEY, k as inputResponse, kt as JSONRPC_VERSION, l as STDIO_DEFAULT_MAX_BUFFER_SIZE, lt as MissingRequiredClientCapabilityError, m as mediaTypeEssence, mt as ProtocolErrorCode, n as preloadSchemas, o as createFetchWithInit, p as isJsonContentType, pt as UrlElicitationRequiredError, q as isInputRequiredResult, qt as SdkErrorCode, t as fromJsonSchema$1, tt as JSONRPCMessageSchema, u as deserializeMessage, ut as ProtocolError, vt as SUPPORTED_MODERN_PROTOCOL_VERSIONS, wt as CLIENT_INFO_META_KEY, x as isSpecType, y as setNegotiatedProtocolVersion, z as validateStandardRequestHeaders, zt as TRACEPARENT_META_KEY } from "./src-D-y6h4N7.mjs";
|
|
3
3
|
import { DefaultJsonSchemaValidator } from "@modelcontextprotocol/server/_shims";
|
|
4
4
|
|
|
5
5
|
//#region src/server/perRequestTransport.ts
|
|
@@ -246,6 +246,59 @@ async function invoke(server, message, ctx) {
|
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/server/requestBody.ts
|
|
251
|
+
/** Default upper bound, in bytes, on a request body read by the HTTP entry points (4 MiB). */
|
|
252
|
+
const DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
|
|
253
|
+
/** Upper bound on the number of messages accepted in one JSON-RPC batch array. */
|
|
254
|
+
const MAX_BATCH_SIZE = 100;
|
|
255
|
+
/** The message answered with 413 for a request body over `maxBytes`. */
|
|
256
|
+
function requestBodyTooLargeMessage(maxBytes) {
|
|
257
|
+
return `Payload Too Large: Request body must not exceed ${maxBytes} bytes`;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Resolves a `maxRequestBodySize` option to the bound to apply: the default when
|
|
261
|
+
* omitted, otherwise the value itself, which must be a positive finite number of
|
|
262
|
+
* bytes (a `RangeError` is thrown at configuration time for anything else).
|
|
263
|
+
*/
|
|
264
|
+
function resolveMaxRequestBodySize(value) {
|
|
265
|
+
if (value === void 0) return DEFAULT_MAX_REQUEST_BODY_SIZE;
|
|
266
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new RangeError(`maxRequestBodySize must be a positive number of bytes, got ${String(value)}`);
|
|
267
|
+
return value;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Reads a request body as text, up to `maxBytes` (default
|
|
271
|
+
* {@linkcode DEFAULT_MAX_REQUEST_BODY_SIZE}). A declared `Content-Length` over the
|
|
272
|
+
* limit is refused without reading anything; otherwise the read stops as soon as
|
|
273
|
+
* more than the limit has arrived. Stream failures propagate.
|
|
274
|
+
*/
|
|
275
|
+
async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE) {
|
|
276
|
+
if (Number(request.headers.get("content-length")) > maxBytes) return { tooLarge: true };
|
|
277
|
+
if (request.body === null) return {
|
|
278
|
+
tooLarge: false,
|
|
279
|
+
text: ""
|
|
280
|
+
};
|
|
281
|
+
const reader = request.body.getReader();
|
|
282
|
+
const decoder = new TextDecoder();
|
|
283
|
+
let received = 0;
|
|
284
|
+
let text = "";
|
|
285
|
+
try {
|
|
286
|
+
for (;;) {
|
|
287
|
+
const { done, value } = await reader.read();
|
|
288
|
+
if (done) break;
|
|
289
|
+
received += value.byteLength;
|
|
290
|
+
if (received > maxBytes) return { tooLarge: true };
|
|
291
|
+
text += decoder.decode(value, { stream: true });
|
|
292
|
+
}
|
|
293
|
+
} finally {
|
|
294
|
+
reader.releaseLock();
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
tooLarge: false,
|
|
298
|
+
text: text + decoder.decode()
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
249
302
|
//#endregion
|
|
250
303
|
//#region src/server/streamableHttp.ts
|
|
251
304
|
/**
|
|
@@ -318,6 +371,8 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
318
371
|
_retryInterval;
|
|
319
372
|
_supportedProtocolVersions;
|
|
320
373
|
_keepAliveMs;
|
|
374
|
+
_maxRequestBodySize;
|
|
375
|
+
_scopeChallengeResolver;
|
|
321
376
|
sessionId;
|
|
322
377
|
onclose;
|
|
323
378
|
onerror;
|
|
@@ -334,6 +389,7 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
334
389
|
this._retryInterval = options.retryInterval;
|
|
335
390
|
this._supportedProtocolVersions = options.supportedProtocolVersions ?? SUPPORTED_PROTOCOL_VERSIONS;
|
|
336
391
|
this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;
|
|
392
|
+
this._maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
|
|
337
393
|
}
|
|
338
394
|
startKeepAlive(controller, encoder) {
|
|
339
395
|
if (this._closed) return void 0;
|
|
@@ -346,6 +402,10 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
346
402
|
});
|
|
347
403
|
return timer;
|
|
348
404
|
}
|
|
405
|
+
/** Sets the scope challenge resolver for parsed JSON-RPC requests. */
|
|
406
|
+
setScopeChallengeResolver(resolver) {
|
|
407
|
+
this._scopeChallengeResolver = resolver;
|
|
408
|
+
}
|
|
349
409
|
/**
|
|
350
410
|
* Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
|
|
351
411
|
* for the Streamable HTTP transport as connections are managed per-request.
|
|
@@ -382,6 +442,11 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
382
442
|
}
|
|
383
443
|
});
|
|
384
444
|
}
|
|
445
|
+
async _checkScopeChallenge(messages, authInfo) {
|
|
446
|
+
if (!this._scopeChallengeResolver) return;
|
|
447
|
+
const challenge = await findScopeChallenge(messages.filter((message) => isJSONRPCRequest(message)), authInfo, this._scopeChallengeResolver);
|
|
448
|
+
return challenge === void 0 ? void 0 : createScopeChallengeResponse(challenge, scopeChallengeResourceMetadataUrl(authInfo));
|
|
449
|
+
}
|
|
385
450
|
/**
|
|
386
451
|
* Validates request headers for DNS rebinding protection.
|
|
387
452
|
* @returns Error response if validation fails, `undefined` if validation passes.
|
|
@@ -639,12 +704,22 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
639
704
|
const request = req;
|
|
640
705
|
let rawMessage;
|
|
641
706
|
if (options?.parsedBody === void 0) try {
|
|
642
|
-
|
|
707
|
+
const body = await readRequestBody(req, this._maxRequestBodySize);
|
|
708
|
+
if (body.tooLarge) {
|
|
709
|
+
const message = requestBodyTooLargeMessage(this._maxRequestBodySize);
|
|
710
|
+
this.onerror?.(new Error(message));
|
|
711
|
+
return this.createJsonErrorResponse(413, -32e3, message);
|
|
712
|
+
}
|
|
713
|
+
rawMessage = JSON.parse(body.text);
|
|
643
714
|
} catch (error) {
|
|
644
715
|
this.onerror?.(error);
|
|
645
716
|
return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
|
|
646
717
|
}
|
|
647
718
|
else rawMessage = options.parsedBody;
|
|
719
|
+
if (Array.isArray(rawMessage) && rawMessage.length > MAX_BATCH_SIZE) {
|
|
720
|
+
this.onerror?.(/* @__PURE__ */ new Error(`Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`));
|
|
721
|
+
return this.createJsonErrorResponse(400, -32600, `Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`);
|
|
722
|
+
}
|
|
648
723
|
let messages;
|
|
649
724
|
try {
|
|
650
725
|
messages = Array.isArray(rawMessage) ? rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(rawMessage)];
|
|
@@ -674,6 +749,14 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
674
749
|
if (protocolError) return protocolError;
|
|
675
750
|
}
|
|
676
751
|
if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
|
|
752
|
+
let scopeChallengeResponse;
|
|
753
|
+
try {
|
|
754
|
+
scopeChallengeResponse = await this._checkScopeChallenge(messages, options?.authInfo);
|
|
755
|
+
} catch (error) {
|
|
756
|
+
this.onerror?.(error);
|
|
757
|
+
return this.createJsonErrorResponse(500, -32603, "Internal server error");
|
|
758
|
+
}
|
|
759
|
+
if (scopeChallengeResponse) return scopeChallengeResponse;
|
|
677
760
|
if (!messages.some((element) => isJSONRPCRequest(element))) {
|
|
678
761
|
for (const message of messages) this.onmessage?.(message, {
|
|
679
762
|
authInfo: options?.authInfo,
|
|
@@ -963,7 +1046,7 @@ function internalServerErrorResponse(id = null) {
|
|
|
963
1046
|
* The entry passes its own `onerror` here when expanding the default, so
|
|
964
1047
|
* legacy-leg failures are never silently swallowed.
|
|
965
1048
|
*/
|
|
966
|
-
function createLegacyStatelessFallback(factory, onerror, keepAliveMs) {
|
|
1049
|
+
function createLegacyStatelessFallback(factory, onerror, keepAliveMs, maxRequestBodySize) {
|
|
967
1050
|
return async (request, options) => {
|
|
968
1051
|
if (request.method.toUpperCase() !== "POST") return jsonRpcErrorResponse(405, -32e3, "Method not allowed.");
|
|
969
1052
|
try {
|
|
@@ -974,7 +1057,8 @@ function createLegacyStatelessFallback(factory, onerror, keepAliveMs) {
|
|
|
974
1057
|
});
|
|
975
1058
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
976
1059
|
sessionIdGenerator: void 0,
|
|
977
|
-
...keepAliveMs !== void 0 && { keepAliveMs }
|
|
1060
|
+
...keepAliveMs !== void 0 && { keepAliveMs },
|
|
1061
|
+
...maxRequestBodySize !== void 0 && { maxRequestBodySize }
|
|
978
1062
|
});
|
|
979
1063
|
await product.connect(transport);
|
|
980
1064
|
const teardown = () => {
|
|
@@ -1031,8 +1115,26 @@ function createLegacyStatelessFallback(factory, onerror, keepAliveMs) {
|
|
|
1031
1115
|
}
|
|
1032
1116
|
};
|
|
1033
1117
|
}
|
|
1034
|
-
function legacyStatelessFallback(factory, onerror) {
|
|
1035
|
-
return createLegacyStatelessFallback(factory, onerror);
|
|
1118
|
+
function legacyStatelessFallback(factory, onerror, options) {
|
|
1119
|
+
return createLegacyStatelessFallback(factory, onerror, void 0, resolveMaxRequestBodySize(options?.maxRequestBodySize));
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Read the SEP-2243 standard request headers off the inbound request.
|
|
1123
|
+
*
|
|
1124
|
+
* Both halves of the standard-header story need them — the body-primary
|
|
1125
|
+
* classifier for its cross-check cells, and
|
|
1126
|
+
* {@linkcode validateStandardRequestHeaders} for the presence half — and a
|
|
1127
|
+
* header read at one site but not the other is precisely how a required header
|
|
1128
|
+
* goes unenforced: that divergence is what let a modern POST omitting
|
|
1129
|
+
* `MCP-Protocol-Version` be served. Read them here once so a header added to
|
|
1130
|
+
* {@linkcode InboundHttpRequest} reaches both sites together.
|
|
1131
|
+
*/
|
|
1132
|
+
function standardHeadersOf(request) {
|
|
1133
|
+
return {
|
|
1134
|
+
protocolVersionHeader: request.headers.get("mcp-protocol-version") ?? void 0,
|
|
1135
|
+
mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
|
|
1136
|
+
mcpNameHeader: request.headers.get("mcp-name") ?? void 0
|
|
1137
|
+
};
|
|
1036
1138
|
}
|
|
1037
1139
|
/**
|
|
1038
1140
|
* The entry's classification step: read the request body exactly once (unless
|
|
@@ -1045,7 +1147,7 @@ function legacyStatelessFallback(factory, onerror) {
|
|
|
1045
1147
|
* the body-preserving clone is then skipped and `forwardRequest` is the
|
|
1046
1148
|
* (consumed) input request.
|
|
1047
1149
|
*/
|
|
1048
|
-
async function classifyEntryRequest(request, providedParsedBody, needsForward = true) {
|
|
1150
|
+
async function classifyEntryRequest(request, providedParsedBody, needsForward = true, maxRequestBodySize = DEFAULT_MAX_REQUEST_BODY_SIZE) {
|
|
1049
1151
|
const httpMethod = request.method.toUpperCase();
|
|
1050
1152
|
let body;
|
|
1051
1153
|
let parsedBody = providedParsedBody;
|
|
@@ -1056,7 +1158,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
|
|
|
1056
1158
|
if (needsForward) forwardRequest = request.clone();
|
|
1057
1159
|
let bodyText;
|
|
1058
1160
|
try {
|
|
1059
|
-
|
|
1161
|
+
const read = await readRequestBody(request, maxRequestBodySize);
|
|
1162
|
+
if (read.tooLarge) return { step: "body-too-large" };
|
|
1163
|
+
bodyText = read.text;
|
|
1060
1164
|
} catch {
|
|
1061
1165
|
return { step: "unreadable-body" };
|
|
1062
1166
|
}
|
|
@@ -1076,9 +1180,7 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
|
|
|
1076
1180
|
step: "classified",
|
|
1077
1181
|
outcome: classifyInboundRequest({
|
|
1078
1182
|
httpMethod,
|
|
1079
|
-
|
|
1080
|
-
mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
|
|
1081
|
-
mcpNameHeader: request.headers.get("mcp-name") ?? void 0,
|
|
1183
|
+
...standardHeadersOf(request),
|
|
1082
1184
|
...body !== void 0 && { body }
|
|
1083
1185
|
}),
|
|
1084
1186
|
body,
|
|
@@ -1146,7 +1248,8 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
|
|
|
1146
1248
|
* answers it with the unsupported-protocol-version error), a malformed
|
|
1147
1249
|
* envelope behind a present claim (answered `-32602`), a request whose
|
|
1148
1250
|
* `MCP-Protocol-Version` header names a modern revision but that lacks the
|
|
1149
|
-
* envelope (`-32602`),
|
|
1251
|
+
* envelope (`-32602`), header/body mismatches (`-32020`), and a POST body
|
|
1252
|
+
* over the size limit (413). Consumers
|
|
1150
1253
|
* routing on the predicate must send `false` traffic to the modern handler,
|
|
1151
1254
|
* never to a legacy handler — the modern path owns those error answers.
|
|
1152
1255
|
* - `server/discover` probes sent by negotiating clients always carry the
|
|
@@ -1154,8 +1257,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
|
|
|
1154
1257
|
* a method named `server/discover` has no claim and classifies legacy,
|
|
1155
1258
|
* exactly as the entry itself routes it.
|
|
1156
1259
|
*/
|
|
1157
|
-
async function isLegacyRequest(request, parsedBody) {
|
|
1158
|
-
const
|
|
1260
|
+
async function isLegacyRequest(request, parsedBody, options) {
|
|
1261
|
+
const maxRequestBodySize = resolveMaxRequestBodySize(options?.maxRequestBodySize);
|
|
1262
|
+
const classified = await classifyEntryRequest(parsedBody === void 0 && request.method.toUpperCase() === "POST" ? request.clone() : request, parsedBody, false, maxRequestBodySize);
|
|
1159
1263
|
return classified.step === "no-json-body" || classified.step === "classified" && classified.outcome.kind === "legacy";
|
|
1160
1264
|
}
|
|
1161
1265
|
/**
|
|
@@ -1204,6 +1308,7 @@ async function isLegacyRequest(request, parsedBody) {
|
|
|
1204
1308
|
*/
|
|
1205
1309
|
function createMcpHandler(factory, options = {}) {
|
|
1206
1310
|
const { legacy, onerror, responseMode } = options;
|
|
1311
|
+
const maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
|
|
1207
1312
|
if (typeof legacy === "function") throw new TypeError("The 'legacy' option only accepts 'stateless' or 'reject', not a handler function. To serve 2025-era traffic with your own handler, route in user land with the exported isLegacyRequest(request) predicate in front of a strict (legacy: 'reject') handler.");
|
|
1208
1313
|
/** Modern per-request instances with an exchange still in flight (close() tears these down). */
|
|
1209
1314
|
const inflight = /* @__PURE__ */ new Set();
|
|
@@ -1222,7 +1327,7 @@ function createMcpHandler(factory, options = {}) {
|
|
|
1222
1327
|
onerror: reportError
|
|
1223
1328
|
});
|
|
1224
1329
|
if (responseMode === "json") console.warn("responseMode: 'json' drops mid-call notifications. subscriptions/listen streams are always served over SSE regardless; other notifications emitted before a result are dropped.");
|
|
1225
|
-
const legacyHandler = legacy === "reject" ? void 0 : createLegacyStatelessFallback(factory, reportError, options.keepAliveMs);
|
|
1330
|
+
const legacyHandler = legacy === "reject" ? void 0 : createLegacyStatelessFallback(factory, reportError, options.keepAliveMs, maxRequestBodySize);
|
|
1226
1331
|
async function serveModern(route, request, authInfo) {
|
|
1227
1332
|
const claimedRevision = route.classification.revision;
|
|
1228
1333
|
if (claimedRevision === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedRevision)) {
|
|
@@ -1235,8 +1340,7 @@ function createMcpHandler(factory, options = {}) {
|
|
|
1235
1340
|
}
|
|
1236
1341
|
const stdHeaderRejection = validateStandardRequestHeaders({
|
|
1237
1342
|
httpMethod: request.method,
|
|
1238
|
-
|
|
1239
|
-
mcpNameHeader: request.headers.get("mcp-name") ?? void 0
|
|
1343
|
+
...standardHeadersOf(request)
|
|
1240
1344
|
}, route);
|
|
1241
1345
|
if (stdHeaderRejection !== void 0) {
|
|
1242
1346
|
reportError(/* @__PURE__ */ new Error(`Rejected inbound request (${stdHeaderRejection.cell}): ${stdHeaderRejection.message}`));
|
|
@@ -1283,6 +1387,17 @@ function createMcpHandler(factory, options = {}) {
|
|
|
1283
1387
|
}
|
|
1284
1388
|
}
|
|
1285
1389
|
}
|
|
1390
|
+
if (route.messageKind === "request" && product instanceof McpServer) try {
|
|
1391
|
+
const challenge = await findScopeChallenge([route.message], authInfo, (context) => product.resolveScopeChallenge(context));
|
|
1392
|
+
if (challenge !== void 0) {
|
|
1393
|
+
product.close().catch(reportError);
|
|
1394
|
+
return createScopeChallengeResponse(challenge, scopeChallengeResourceMetadataUrl(authInfo));
|
|
1395
|
+
}
|
|
1396
|
+
} catch (error) {
|
|
1397
|
+
product.close().catch(reportError);
|
|
1398
|
+
reportError(toError(error));
|
|
1399
|
+
return internalServerErrorResponse(route.message.id);
|
|
1400
|
+
}
|
|
1286
1401
|
setNegotiatedProtocolVersion(server, claimedRevision);
|
|
1287
1402
|
installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
1288
1403
|
if (meta !== void 0) seedClientIdentityFromEnvelope(server, {
|
|
@@ -1329,8 +1444,9 @@ function createMcpHandler(factory, options = {}) {
|
|
|
1329
1444
|
reportError(/* @__PURE__ */ new Error("Unsupported Media Type: Content-Type must be application/json"));
|
|
1330
1445
|
return jsonRpcErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
|
|
1331
1446
|
}
|
|
1332
|
-
const classified = await classifyEntryRequest(request, requestOptions?.parsedBody);
|
|
1447
|
+
const classified = await classifyEntryRequest(request, requestOptions?.parsedBody, true, maxRequestBodySize);
|
|
1333
1448
|
if (classified.step === "unreadable-body") return jsonRpcErrorResponse(400, -32700, "Parse error: the request body could not be read");
|
|
1449
|
+
if (classified.step === "body-too-large") return jsonRpcErrorResponse(413, -32e3, requestBodyTooLargeMessage(maxRequestBodySize));
|
|
1334
1450
|
if (classified.step === "no-json-body") {
|
|
1335
1451
|
if (legacyHandler !== void 0) return legacyHandler(classified.forwardRequest, { ...authInfo !== void 0 && { authInfo } });
|
|
1336
1452
|
return jsonRpcErrorResponse(400, -32700, "Parse error: the request body is not valid JSON");
|
|
@@ -1372,115 +1488,6 @@ function createMcpHandler(factory, options = {}) {
|
|
|
1372
1488
|
};
|
|
1373
1489
|
}
|
|
1374
1490
|
|
|
1375
|
-
//#endregion
|
|
1376
|
-
//#region src/server/middleware/bearerAuth.ts
|
|
1377
|
-
function headerQuotedValue(value) {
|
|
1378
|
-
return value.replaceAll(/[\\"]/g, String.raw`\$&`).replaceAll(/[^\u0020-\u007E]/g, " ");
|
|
1379
|
-
}
|
|
1380
|
-
function buildWwwAuthenticateHeader(errorCode, description, requiredScopes, resourceMetadataUrl) {
|
|
1381
|
-
let header = `Bearer error="${headerQuotedValue(errorCode)}", error_description="${headerQuotedValue(description)}"`;
|
|
1382
|
-
if (requiredScopes.length > 0) header += `, scope="${requiredScopes.join(" ")}"`;
|
|
1383
|
-
if (resourceMetadataUrl) header += `, resource_metadata="${resourceMetadataUrl}"`;
|
|
1384
|
-
return header;
|
|
1385
|
-
}
|
|
1386
|
-
/**
|
|
1387
|
-
* Validate a raw `Authorization` header value as a Bearer token and return
|
|
1388
|
-
* the verified {@link AuthInfo}.
|
|
1389
|
-
*
|
|
1390
|
-
* The runtime-neutral core of Bearer authentication: it parses the header,
|
|
1391
|
-
* runs the verifier, enforces `requiredScopes`, and rejects tokens without an
|
|
1392
|
-
* expiration or past it. On any failure it throws an {@link OAuthError} —
|
|
1393
|
-
* pass that to {@link bearerAuthChallengeResponse} for the matching HTTP
|
|
1394
|
-
* answer, or use {@link requireBearerAuth} to get both steps as one call.
|
|
1395
|
-
*
|
|
1396
|
-
* Framework adapters build on this: `requireBearerAuth` from
|
|
1397
|
-
* `@modelcontextprotocol/express` feeds it `req.headers.authorization`.
|
|
1398
|
-
*/
|
|
1399
|
-
async function verifyBearerToken(authorizationHeader, options) {
|
|
1400
|
-
const { verifier, requiredScopes = [] } = options;
|
|
1401
|
-
if (!authorizationHeader) throw new OAuthError(OAuthErrorCode.InvalidToken, "Missing Authorization header");
|
|
1402
|
-
const [type, token] = authorizationHeader.split(" ");
|
|
1403
|
-
if (type?.toLowerCase() !== "bearer" || !token) throw new OAuthError(OAuthErrorCode.InvalidToken, "Invalid Authorization header format, expected 'Bearer TOKEN'");
|
|
1404
|
-
const authInfo = await verifier.verifyAccessToken(token);
|
|
1405
|
-
if (requiredScopes.length > 0) {
|
|
1406
|
-
if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new OAuthError(OAuthErrorCode.InsufficientScope, "Insufficient scope");
|
|
1407
|
-
}
|
|
1408
|
-
if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has no expiration time");
|
|
1409
|
-
else if (authInfo.expiresAt < Date.now() / 1e3) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has expired");
|
|
1410
|
-
return authInfo;
|
|
1411
|
-
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Build the HTTP answer for a Bearer authentication failure.
|
|
1414
|
-
*
|
|
1415
|
-
* Maps an {@link OAuthError} to its status — `401` for `invalid_token` and
|
|
1416
|
-
* `403` for `insufficient_scope` (both carrying the `WWW-Authenticate: Bearer …`
|
|
1417
|
-
* challenge, with `resource_metadata` when configured so clients can discover
|
|
1418
|
-
* the Authorization Server), `500` for `server_error`, `400` for anything
|
|
1419
|
-
* else. A non-`OAuthError` value answers `500 server_error`. The body is the
|
|
1420
|
-
* OAuth error JSON.
|
|
1421
|
-
*/
|
|
1422
|
-
function bearerAuthChallengeResponse(error, options) {
|
|
1423
|
-
const { requiredScopes = [], resourceMetadataUrl } = options ?? {};
|
|
1424
|
-
if (!(error instanceof OAuthError)) {
|
|
1425
|
-
const serverError = new OAuthError(OAuthErrorCode.ServerError, "Internal Server Error");
|
|
1426
|
-
return Response.json(serverError.toResponseObject(), { status: 500 });
|
|
1427
|
-
}
|
|
1428
|
-
switch (error.code) {
|
|
1429
|
-
case OAuthErrorCode.InvalidToken: {
|
|
1430
|
-
const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
|
|
1431
|
-
return Response.json(error.toResponseObject(), {
|
|
1432
|
-
status: 401,
|
|
1433
|
-
headers: { "WWW-Authenticate": challenge }
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
case OAuthErrorCode.InsufficientScope: {
|
|
1437
|
-
const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
|
|
1438
|
-
return Response.json(error.toResponseObject(), {
|
|
1439
|
-
status: 403,
|
|
1440
|
-
headers: { "WWW-Authenticate": challenge }
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
|
-
case OAuthErrorCode.ServerError: return Response.json(error.toResponseObject(), { status: 500 });
|
|
1444
|
-
default: return Response.json(error.toResponseObject(), { status: 400 });
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
/**
|
|
1448
|
-
* Require a valid Bearer token on web-standard requests.
|
|
1449
|
-
*
|
|
1450
|
-
* The framework-free counterpart of `requireBearerAuth` from
|
|
1451
|
-
* `@modelcontextprotocol/express`, for hosts whose HTTP surface is a
|
|
1452
|
-
* `fetch(request)` handler — Cloudflare Workers, Deno, Bun, Hono. The
|
|
1453
|
-
* returned gate resolves to the verified {@link AuthInfo}, or to the
|
|
1454
|
-
* ready-to-return challenge `Response` when the request must be refused.
|
|
1455
|
-
*
|
|
1456
|
-
* @example
|
|
1457
|
-
* ```ts source="./bearerAuth.examples.ts#requireBearerAuth_fetchGate"
|
|
1458
|
-
* const gate = requireBearerAuth({ verifier, requiredScopes: ['mcp'] });
|
|
1459
|
-
*
|
|
1460
|
-
* async function fetchHandler(request: Request): Promise<Response> {
|
|
1461
|
-
* const auth: AuthInfo | Response = await gate(request);
|
|
1462
|
-
* if (auth instanceof Response) return auth;
|
|
1463
|
-
* return handler.fetch(request, { authInfo: auth });
|
|
1464
|
-
* }
|
|
1465
|
-
* ```
|
|
1466
|
-
*/
|
|
1467
|
-
function requireBearerAuth(options) {
|
|
1468
|
-
const { verifier, requiredScopes = [], resourceMetadataUrl } = options;
|
|
1469
|
-
const resolved = {
|
|
1470
|
-
verifier,
|
|
1471
|
-
requiredScopes,
|
|
1472
|
-
resourceMetadataUrl
|
|
1473
|
-
};
|
|
1474
|
-
return async (request) => {
|
|
1475
|
-
const [authorizationHeader] = (request.headers.get("authorization") ?? "").split(",");
|
|
1476
|
-
try {
|
|
1477
|
-
return await verifyBearerToken(authorizationHeader || void 0, resolved);
|
|
1478
|
-
} catch (error) {
|
|
1479
|
-
return bearerAuthChallengeResponse(error, resolved);
|
|
1480
|
-
}
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
1491
|
//#endregion
|
|
1485
1492
|
//#region src/server/middleware/hostHeaderValidation.ts
|
|
1486
1493
|
/**
|
|
@@ -1551,120 +1558,6 @@ function hostHeaderValidationResponse(req, allowedHostnames) {
|
|
|
1551
1558
|
});
|
|
1552
1559
|
}
|
|
1553
1560
|
|
|
1554
|
-
//#endregion
|
|
1555
|
-
//#region src/server/middleware/oauthMetadata.ts
|
|
1556
|
-
function checkIssuerUrl(issuer, allowInsecure) {
|
|
1557
|
-
if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1" && !allowInsecure) throw new Error("Issuer URL must be HTTPS");
|
|
1558
|
-
if (issuer.hash) throw new Error(`Issuer URL must not have a fragment: ${issuer}`);
|
|
1559
|
-
if (issuer.search) throw new Error(`Issuer URL must not have a query string: ${issuer}`);
|
|
1560
|
-
}
|
|
1561
|
-
/**
|
|
1562
|
-
* Derive the RFC 9728 Protected Resource Metadata document from
|
|
1563
|
-
* {@link AuthMetadataOptions}, validating the Authorization Server issuer URL
|
|
1564
|
-
* (HTTPS required outside localhost) in the process.
|
|
1565
|
-
*
|
|
1566
|
-
* `oauthMetadataResponse` and the Express `mcpAuthMetadataRouter` both build
|
|
1567
|
-
* on this; use it directly when serving the document through your own
|
|
1568
|
-
* routing — or call it once at startup to fail fast on a misconfigured
|
|
1569
|
-
* issuer before any request arrives.
|
|
1570
|
-
*/
|
|
1571
|
-
function buildOAuthProtectedResourceMetadata(options) {
|
|
1572
|
-
checkIssuerUrl(new URL(options.oauthMetadata.issuer), options.dangerouslyAllowInsecureIssuerUrl);
|
|
1573
|
-
return {
|
|
1574
|
-
resource: options.resourceServerUrl.href,
|
|
1575
|
-
authorization_servers: [options.oauthMetadata.issuer],
|
|
1576
|
-
scopes_supported: options.scopesSupported,
|
|
1577
|
-
resource_name: options.resourceName,
|
|
1578
|
-
resource_documentation: options.serviceDocumentationUrl?.href
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
/**
|
|
1582
|
-
* Builds the RFC 9728 Protected Resource Metadata URL for a given MCP server
|
|
1583
|
-
* URL by inserting `/.well-known/oauth-protected-resource` ahead of the path.
|
|
1584
|
-
*
|
|
1585
|
-
* @example
|
|
1586
|
-
* ```ts
|
|
1587
|
-
* getOAuthProtectedResourceMetadataUrl(new URL('https://api.example.com/mcp'))
|
|
1588
|
-
* // → 'https://api.example.com/.well-known/oauth-protected-resource/mcp'
|
|
1589
|
-
* ```
|
|
1590
|
-
*/
|
|
1591
|
-
function getOAuthProtectedResourceMetadataUrl(serverUrl) {
|
|
1592
|
-
return new URL(protectedResourceMetadataPath(serverUrl), serverUrl).href;
|
|
1593
|
-
}
|
|
1594
|
-
/** The RFC 9728 path-aware well-known path for a resource URL. */
|
|
1595
|
-
function protectedResourceMetadataPath(resourceServerUrl) {
|
|
1596
|
-
const rsPath = stripTrailingSlash(resourceServerUrl.pathname);
|
|
1597
|
-
return `/.well-known/oauth-protected-resource${rsPath === "/" ? "" : rsPath}`;
|
|
1598
|
-
}
|
|
1599
|
-
function stripTrailingSlash(path) {
|
|
1600
|
-
return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
1601
|
-
}
|
|
1602
|
-
const ALLOWED_METHODS = "GET, HEAD, OPTIONS";
|
|
1603
|
-
function metadataDocumentResponse(request, metadata) {
|
|
1604
|
-
if (request.method === "OPTIONS") {
|
|
1605
|
-
const requestedHeaders = request.headers.get("access-control-request-headers");
|
|
1606
|
-
return new Response(null, {
|
|
1607
|
-
status: 204,
|
|
1608
|
-
headers: {
|
|
1609
|
-
"Access-Control-Allow-Origin": "*",
|
|
1610
|
-
"Access-Control-Allow-Methods": ALLOWED_METHODS,
|
|
1611
|
-
...requestedHeaders === null ? {} : {
|
|
1612
|
-
"Access-Control-Allow-Headers": requestedHeaders,
|
|
1613
|
-
Vary: "Access-Control-Request-Headers"
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
});
|
|
1617
|
-
}
|
|
1618
|
-
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
1619
|
-
const error = new OAuthError(OAuthErrorCode.MethodNotAllowed, `The method ${request.method} is not allowed for this endpoint`);
|
|
1620
|
-
return Response.json(error.toResponseObject(), {
|
|
1621
|
-
status: 405,
|
|
1622
|
-
headers: {
|
|
1623
|
-
Allow: ALLOWED_METHODS,
|
|
1624
|
-
"Access-Control-Allow-Origin": "*"
|
|
1625
|
-
}
|
|
1626
|
-
});
|
|
1627
|
-
}
|
|
1628
|
-
const response = Response.json(metadata, { headers: { "Access-Control-Allow-Origin": "*" } });
|
|
1629
|
-
return request.method === "HEAD" ? new Response(null, {
|
|
1630
|
-
status: response.status,
|
|
1631
|
-
headers: response.headers
|
|
1632
|
-
}) : response;
|
|
1633
|
-
}
|
|
1634
|
-
/**
|
|
1635
|
-
* Serve the two OAuth discovery documents an MCP server acting as a Resource
|
|
1636
|
-
* Server exposes, from a web-standard `fetch(request)` handler:
|
|
1637
|
-
*
|
|
1638
|
-
* - `/.well-known/oauth-protected-resource[/<path>]` — RFC 9728 Protected
|
|
1639
|
-
* Resource Metadata, derived from the supplied options (path-aware: the
|
|
1640
|
-
* resource URL's path is reflected in the route).
|
|
1641
|
-
* - `/.well-known/oauth-authorization-server` — RFC 8414 Authorization
|
|
1642
|
-
* Server Metadata, passed through verbatim.
|
|
1643
|
-
*
|
|
1644
|
-
* Returns the matched document `Response` (JSON with permissive CORS, `405`
|
|
1645
|
-
* with an `Allow` header for non-GET methods, `204` for CORS preflight), or
|
|
1646
|
-
* `undefined` when the request path is neither well-known route — fall
|
|
1647
|
-
* through to your own routing. The framework-free counterpart of
|
|
1648
|
-
* `mcpAuthMetadataRouter` from `@modelcontextprotocol/express`; pair it with
|
|
1649
|
-
* `requireBearerAuth` and `getOAuthProtectedResourceMetadataUrl` so
|
|
1650
|
-
* unauthenticated clients can discover the AS from the `401` challenge.
|
|
1651
|
-
*
|
|
1652
|
-
* @example
|
|
1653
|
-
* ```ts source="./oauthMetadata.examples.ts#oauthMetadataResponse_fetchHandler"
|
|
1654
|
-
* async function fetchHandler(request: Request): Promise<Response> {
|
|
1655
|
-
* return oauthMetadataResponse(request, options) ?? serveMcp(request);
|
|
1656
|
-
* }
|
|
1657
|
-
* ```
|
|
1658
|
-
*/
|
|
1659
|
-
function oauthMetadataResponse(request, options) {
|
|
1660
|
-
const requestPath = stripTrailingSlash(new URL(request.url).pathname);
|
|
1661
|
-
if (requestPath === protectedResourceMetadataPath(options.resourceServerUrl)) return metadataDocumentResponse(request, buildOAuthProtectedResourceMetadata(options));
|
|
1662
|
-
if (requestPath === "/.well-known/oauth-authorization-server") {
|
|
1663
|
-
buildOAuthProtectedResourceMetadata(options);
|
|
1664
|
-
return metadataDocumentResponse(request, options.oauthMetadata);
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
1561
|
//#endregion
|
|
1669
1562
|
//#region src/server/middleware/originValidation.ts
|
|
1670
1563
|
/**
|
|
@@ -1866,5 +1759,5 @@ function fromJsonSchema(schema, validator) {
|
|
|
1866
1759
|
}
|
|
1867
1760
|
|
|
1868
1761
|
//#endregion
|
|
1869
|
-
export { BAGGAGE_META_KEY, CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, DEFAULT_REQUEST_TIMEOUT_MSEC, INTERNAL_ERROR, INVALID_PARAMS, INVALID_REQUEST, InMemoryServerEventBus, InMemoryTransport, JSONRPC_VERSION, LATEST_PROTOCOL_VERSION, LOG_LEVEL_META_KEY, METHOD_NOT_FOUND, McpServer, MissingRequiredClientCapabilityError, OAuthError, OAuthErrorCode, PARSE_ERROR, PROTOCOL_VERSION_META_KEY, PerRequestHTTPServerTransport, Protocol, ProtocolError, ProtocolErrorCode, RELATED_TASK_META_KEY, ReadBuffer, ResourceNotFoundError, ResourceTemplate, SERVER_INFO_META_KEY, STDIO_DEFAULT_MAX_BUFFER_SIZE, SUBSCRIPTION_ID_META_KEY, SUPPORTED_PROTOCOL_VERSIONS, SdkError, SdkErrorCode, SdkHttpError, Server, TRACEPARENT_META_KEY, TRACESTATE_META_KEY, UnsupportedProtocolVersionError, UriTemplate, UrlElicitationRequiredError, WebStandardStreamableHTTPServerTransport, acceptedContent, assertCompleteRequestPrompt, assertCompleteRequestResourceTemplate, bearerAuthChallengeResponse, buildOAuthProtectedResourceMetadata, checkResourceAllowed, classifyInboundRequest, completable, createFetchWithInit, createMcpHandler, createRequestStateCodec, deserializeMessage, fromJsonSchema, getDisplayName, getOAuthProtectedResourceMetadataUrl, hostHeaderValidationResponse, inputRequired, inputResponse, isCallToolResult, isCompletable, isInitializeRequest, isInitializedNotification, isInputRequiredResult, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isJsonContentType, isLegacyRequest, isSpecType, isTaskAugmentedRequestParams, legacyStatelessFallback, localhostAllowedHostnames, localhostAllowedOrigins, mergeCapabilities, oauthMetadataResponse, originValidationResponse, parseJSONRPCMessage, preloadSchemas, requireBearerAuth, resourceUrlFromServerUrl, serializeMessage, specTypeSchemas, validateHostHeader, validateOriginHeader, verifyBearerToken };
|
|
1762
|
+
export { BAGGAGE_META_KEY, CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, DEFAULT_MAX_REQUEST_BODY_SIZE, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, DEFAULT_REQUEST_TIMEOUT_MSEC, INTERNAL_ERROR, INVALID_PARAMS, INVALID_REQUEST, InMemoryServerEventBus, InMemoryTransport, JSONRPC_VERSION, LATEST_PROTOCOL_VERSION, LOG_LEVEL_META_KEY, METHOD_NOT_FOUND, McpServer, MissingRequiredClientCapabilityError, OAuthError, OAuthErrorCode, PARSE_ERROR, PROTOCOL_VERSION_META_KEY, PerRequestHTTPServerTransport, Protocol, ProtocolError, ProtocolErrorCode, RELATED_TASK_META_KEY, ReadBuffer, ResourceNotFoundError, ResourceTemplate, SERVER_INFO_META_KEY, STDIO_DEFAULT_MAX_BUFFER_SIZE, SUBSCRIPTION_ID_META_KEY, SUPPORTED_PROTOCOL_VERSIONS, SdkError, SdkErrorCode, SdkHttpError, Server, TRACEPARENT_META_KEY, TRACESTATE_META_KEY, UnsupportedProtocolVersionError, UriTemplate, UrlElicitationRequiredError, WebStandardStreamableHTTPServerTransport, acceptedContent, assertCompleteRequestPrompt, assertCompleteRequestResourceTemplate, bearerAuthChallengeResponse, buildOAuthProtectedResourceMetadata, checkResourceAllowed, classifyInboundRequest, completable, createFetchWithInit, createMcpHandler, createRequestStateCodec, deserializeMessage, fromJsonSchema, getDisplayName, getOAuthProtectedResourceMetadataUrl, hostHeaderValidationResponse, inputRequired, inputResponse, isCallToolResult, isCompletable, isInitializeRequest, isInitializedNotification, isInputRequiredResult, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isJsonContentType, isLegacyRequest, isSpecType, isTaskAugmentedRequestParams, legacyStatelessFallback, localhostAllowedHostnames, localhostAllowedOrigins, mergeCapabilities, oauthMetadataResponse, originValidationResponse, parseJSONRPCMessage, preloadSchemas, readRequestBody, requireBearerAuth, requireScopes, resourceUrlFromServerUrl, serializeMessage, specTypeSchemas, validateHostHeader, validateOriginHeader, verifyBearerToken };
|
|
1870
1763
|
//# sourceMappingURL=index.mjs.map
|