ostacky 0.9.4 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +27 -25
  2. package/assets/agents/ostacky.md +3 -3
  3. package/assets/commands/install-stack.md +2 -2
  4. package/assets/mcp/ostacky-controller/bun.lock +20 -0
  5. package/assets/mcp/ostacky-controller/index.js +80 -19
  6. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-B2Q9_Vxp.d.cts → auth--n_Yzytt.d.cts} +14 -9
  7. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-CVhIKulL.d.mts.map → auth--n_Yzytt.d.cts.map} +1 -1
  8. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-CfDMXiII.cjs → auth-4-zilcqg.cjs} +3 -2
  9. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/auth-4-zilcqg.cjs.map +1 -0
  10. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-CUe6YdwF.mjs → auth-CGP0BDVq.mjs} +3 -2
  11. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/auth-CGP0BDVq.mjs.map +1 -0
  12. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-CVhIKulL.d.mts → auth-YUQV3RRv.d.mts} +14 -9
  13. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/{auth-B2Q9_Vxp.d.cts.map → auth-YUQV3RRv.d.mts.map} +1 -1
  14. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/index.cjs +1 -1
  15. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/index.d.cts +1 -1
  16. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/index.d.mts +1 -1
  17. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/index.mjs +1 -1
  18. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/internal.cjs +1 -1
  19. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/internal.d.cts +1 -1
  20. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/internal.d.mts +1 -1
  21. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/internal.mjs +1 -1
  22. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/package.json +1 -1
  23. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/README.md +3 -3
  24. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-CplOkyLC.mjs → ajvProvider-CEoC__sr.mjs} +483 -38
  25. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/ajvProvider-CEoC__sr.mjs.map +1 -0
  26. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-BdSo9BII.d.mts → ajvProvider-CgI-5L6O.d.mts} +25 -8
  27. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-BdSo9BII.d.mts.map → ajvProvider-CgI-5L6O.d.mts.map} +1 -1
  28. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-B_4czhCS.d.cts → ajvProvider-FOQRM7up.d.cts} +24 -7
  29. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-B_4czhCS.d.cts.map → ajvProvider-FOQRM7up.d.cts.map} +1 -1
  30. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{ajvProvider-Brn-Q2J_.cjs → ajvProvider-ZaoO9afR.cjs} +483 -38
  31. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/ajvProvider-ZaoO9afR.cjs.map +1 -0
  32. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{cfWorkerProvider-ojcZaap3.cjs → cfWorkerProvider-BwbPzsdI.cjs} +25 -15
  33. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-BwbPzsdI.cjs.map +1 -0
  34. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{cfWorkerProvider-BYRW5af5.d.mts → cfWorkerProvider-C03CSigr.d.mts} +21 -6
  35. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-C03CSigr.d.mts.map +1 -0
  36. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{cfWorkerProvider-D9GAttn8.d.cts → cfWorkerProvider-doTkZbTr.d.cts} +20 -5
  37. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-doTkZbTr.d.cts.map +1 -0
  38. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{cfWorkerProvider-Bd-iTHAF.mjs → cfWorkerProvider-p3WaZPqB.mjs} +26 -15
  39. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-p3WaZPqB.mjs.map +1 -0
  40. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-DzBzpE4_.d.cts → createMcpHandler-BLVe3qmU.d.cts} +137 -32
  41. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-BLVe3qmU.d.cts.map +1 -0
  42. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-CEckaSEs.d.mts → createMcpHandler-Bt6U_Fqb.d.mts} +138 -33
  43. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-Bt6U_Fqb.d.mts.map +1 -0
  44. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/dialects-D8eXzoGv.cjs +46 -0
  45. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/dialects-D8eXzoGv.cjs.map +1 -0
  46. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/dialects-DoSzNhcb.mjs +34 -0
  47. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/dialects-DoSzNhcb.mjs.map +1 -0
  48. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.cjs +209 -257
  49. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.cjs.map +1 -1
  50. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.d.cts +45 -3
  51. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.d.cts.map +1 -1
  52. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.d.mts +46 -4
  53. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.d.mts.map +1 -1
  54. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.mjs +201 -252
  55. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/index.mjs.map +1 -1
  56. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{mcp-DM1iHYFo.cjs → mcp-DUcCQSTW.cjs} +458 -35
  57. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/mcp-DUcCQSTW.cjs.map +1 -0
  58. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{mcp-IJurDZVN.mjs → mcp-Dw2OlZ1f.mjs} +389 -32
  59. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs.map +1 -0
  60. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsBrowser.cjs +1 -1
  61. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsBrowser.d.cts +1 -1
  62. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsBrowser.d.mts +1 -1
  63. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsBrowser.mjs +1 -1
  64. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsNode.cjs +1 -1
  65. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsNode.d.cts +1 -1
  66. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsNode.d.mts +1 -1
  67. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs +1 -1
  68. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.cjs +2 -2
  69. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.d.cts +1 -1
  70. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.d.mts +1 -1
  71. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.mjs +2 -2
  72. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{src-BX_fm-dB.cjs → src-CgFsfg3E.cjs} +161 -48
  73. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/src-CgFsfg3E.cjs.map +1 -0
  74. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{src-D86MbS1I.mjs → src-D-y6h4N7.mjs} +161 -48
  75. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs.map +1 -0
  76. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.cjs +30 -3
  77. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.cjs.map +1 -1
  78. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts +9 -1
  79. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts.map +1 -1
  80. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts +9 -1
  81. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts.map +1 -1
  82. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.mjs +30 -3
  83. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/stdio.mjs.map +1 -1
  84. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{types-mS0yxCL0.d.mts → types-DUs7mGBv.d.mts} +1 -1
  85. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/{types-mS0yxCL0.d.mts.map → types-DUs7mGBv.d.mts.map} +1 -1
  86. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/ajv.cjs +1 -1
  87. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/ajv.d.cts +1 -1
  88. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/ajv.d.mts +1 -1
  89. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/ajv.mjs +1 -1
  90. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/cfWorker.cjs +1 -1
  91. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/cfWorker.d.cts +1 -1
  92. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/cfWorker.d.mts +1 -1
  93. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/validators/cfWorker.mjs +1 -1
  94. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/package.json +4 -4
  95. package/assets/mcp/ostacky-controller/package.json +1 -1
  96. package/assets/plugins/ostacky-controller/index.ts +43 -8
  97. package/dist/cli.js +93 -53
  98. package/manifest.json +28 -28
  99. package/package.json +5 -1
  100. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/auth-CUe6YdwF.mjs.map +0 -1
  101. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/core/dist/auth-CfDMXiII.cjs.map +0 -1
  102. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/ajvProvider-Brn-Q2J_.cjs.map +0 -1
  103. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/ajvProvider-CplOkyLC.mjs.map +0 -1
  104. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-BYRW5af5.d.mts.map +0 -1
  105. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-Bd-iTHAF.mjs.map +0 -1
  106. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-D9GAttn8.d.cts.map +0 -1
  107. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/cfWorkerProvider-ojcZaap3.cjs.map +0 -1
  108. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-CEckaSEs.d.mts.map +0 -1
  109. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-DzBzpE4_.d.cts.map +0 -1
  110. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/mcp-DM1iHYFo.cjs.map +0 -1
  111. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/mcp-IJurDZVN.mjs.map +0 -1
  112. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/src-BX_fm-dB.cjs.map +0 -1
  113. package/assets/mcp/ostacky-controller/node_modules/@modelcontextprotocol/server/dist/src-D86MbS1I.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  const require_chunk = require('./chunk-Bnu9O96Y.cjs');
2
- const require_mcp = require('./mcp-DM1iHYFo.cjs');
3
- const require_src = require('./src-BX_fm-dB.cjs');
2
+ const require_mcp = require('./mcp-DUcCQSTW.cjs');
3
+ const require_src = require('./src-CgFsfg3E.cjs');
4
4
  let _modelcontextprotocol_server__shims = require("@modelcontextprotocol/server/_shims");
5
5
  let _modelcontextprotocol_core_internal = require("@modelcontextprotocol/core/internal");
6
6
 
@@ -34,9 +34,11 @@ var PerRequestHTTPServerTransport = class {
34
34
  _deferredResponse;
35
35
  _sse;
36
36
  _abortCleanup;
37
+ _keepAliveMs;
37
38
  constructor(options) {
38
39
  this._classification = options.classification;
39
40
  this._responseMode = options.responseMode ?? "auto";
41
+ this._keepAliveMs = options.keepAliveMs ?? require_mcp.DEFAULT_SSE_KEEP_ALIVE_MS;
40
42
  }
41
43
  async start() {
42
44
  if (this._started) throw new Error("PerRequestHTTPServerTransport is already started");
@@ -150,6 +152,7 @@ var PerRequestHTTPServerTransport = class {
150
152
  this._closed = true;
151
153
  this._abortCleanup?.();
152
154
  this._abortCleanup = void 0;
155
+ if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
153
156
  if (this._sse !== void 0 && !this._sse.closed) {
154
157
  this._sse.closed = true;
155
158
  try {
@@ -182,17 +185,19 @@ var PerRequestHTTPServerTransport = class {
182
185
  encoder: new TextEncoder(),
183
186
  closed: false
184
187
  };
188
+ this._sse.keepAliveTimer = require_mcp.armSseKeepAlive(this._keepAliveMs, () => this.writeCommentFrame("keepalive"));
185
189
  this.settleResponse(new Response(readable, {
186
190
  status: 200,
187
191
  headers: {
188
192
  "Content-Type": "text/event-stream",
189
- "Cache-Control": "no-cache",
193
+ "Cache-Control": "no-cache, no-transform",
190
194
  Connection: "keep-alive",
191
195
  "X-Accel-Buffering": "no"
192
196
  }
193
197
  }));
194
198
  }
195
199
  finalizeStream() {
200
+ if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
196
201
  if (this._sse !== void 0 && !this._sse.closed) {
197
202
  this._sse.closed = true;
198
203
  try {
@@ -233,7 +238,8 @@ var PerRequestHTTPServerTransport = class {
233
238
  async function invoke(server, message, ctx) {
234
239
  const transport = new PerRequestHTTPServerTransport({
235
240
  classification: ctx.classification,
236
- ...ctx.responseMode !== void 0 && { responseMode: ctx.responseMode }
241
+ ...ctx.responseMode !== void 0 && { responseMode: ctx.responseMode },
242
+ ...ctx.keepAliveMs !== void 0 && { keepAliveMs: ctx.keepAliveMs }
237
243
  });
238
244
  await server.connect(transport);
239
245
  return transport.handleMessage(message, {
@@ -242,6 +248,59 @@ async function invoke(server, message, ctx) {
242
248
  });
243
249
  }
244
250
 
251
+ //#endregion
252
+ //#region src/server/requestBody.ts
253
+ /** Default upper bound, in bytes, on a request body read by the HTTP entry points (4 MiB). */
254
+ const DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
255
+ /** Upper bound on the number of messages accepted in one JSON-RPC batch array. */
256
+ const MAX_BATCH_SIZE = 100;
257
+ /** The message answered with 413 for a request body over `maxBytes`. */
258
+ function requestBodyTooLargeMessage(maxBytes) {
259
+ return `Payload Too Large: Request body must not exceed ${maxBytes} bytes`;
260
+ }
261
+ /**
262
+ * Resolves a `maxRequestBodySize` option to the bound to apply: the default when
263
+ * omitted, otherwise the value itself, which must be a positive finite number of
264
+ * bytes (a `RangeError` is thrown at configuration time for anything else).
265
+ */
266
+ function resolveMaxRequestBodySize(value) {
267
+ if (value === void 0) return DEFAULT_MAX_REQUEST_BODY_SIZE;
268
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new RangeError(`maxRequestBodySize must be a positive number of bytes, got ${String(value)}`);
269
+ return value;
270
+ }
271
+ /**
272
+ * Reads a request body as text, up to `maxBytes` (default
273
+ * {@linkcode DEFAULT_MAX_REQUEST_BODY_SIZE}). A declared `Content-Length` over the
274
+ * limit is refused without reading anything; otherwise the read stops as soon as
275
+ * more than the limit has arrived. Stream failures propagate.
276
+ */
277
+ async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE) {
278
+ if (Number(request.headers.get("content-length")) > maxBytes) return { tooLarge: true };
279
+ if (request.body === null) return {
280
+ tooLarge: false,
281
+ text: ""
282
+ };
283
+ const reader = request.body.getReader();
284
+ const decoder = new TextDecoder();
285
+ let received = 0;
286
+ let text = "";
287
+ try {
288
+ for (;;) {
289
+ const { done, value } = await reader.read();
290
+ if (done) break;
291
+ received += value.byteLength;
292
+ if (received > maxBytes) return { tooLarge: true };
293
+ text += decoder.decode(value, { stream: true });
294
+ }
295
+ } finally {
296
+ reader.releaseLock();
297
+ }
298
+ return {
299
+ tooLarge: false,
300
+ text: text + decoder.decode()
301
+ };
302
+ }
303
+
245
304
  //#endregion
246
305
  //#region src/server/streamableHttp.ts
247
306
  /**
@@ -313,6 +372,9 @@ var WebStandardStreamableHTTPServerTransport = class {
313
372
  _enableDnsRebindingProtection;
314
373
  _retryInterval;
315
374
  _supportedProtocolVersions;
375
+ _keepAliveMs;
376
+ _maxRequestBodySize;
377
+ _scopeChallengeResolver;
316
378
  sessionId;
317
379
  onclose;
318
380
  onerror;
@@ -328,6 +390,23 @@ var WebStandardStreamableHTTPServerTransport = class {
328
390
  this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;
329
391
  this._retryInterval = options.retryInterval;
330
392
  this._supportedProtocolVersions = options.supportedProtocolVersions ?? _modelcontextprotocol_core_internal.SUPPORTED_PROTOCOL_VERSIONS;
393
+ this._keepAliveMs = options.keepAliveMs ?? require_mcp.DEFAULT_SSE_KEEP_ALIVE_MS;
394
+ this._maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
395
+ }
396
+ startKeepAlive(controller, encoder) {
397
+ if (this._closed) return void 0;
398
+ const timer = require_mcp.armSseKeepAlive(this._keepAliveMs, () => {
399
+ try {
400
+ controller.enqueue(encoder.encode(": keepalive\n\n"));
401
+ } catch {
402
+ if (timer !== void 0) clearInterval(timer);
403
+ }
404
+ });
405
+ return timer;
406
+ }
407
+ /** Sets the scope challenge resolver for parsed JSON-RPC requests. */
408
+ setScopeChallengeResolver(resolver) {
409
+ this._scopeChallengeResolver = resolver;
331
410
  }
332
411
  /**
333
412
  * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
@@ -365,6 +444,11 @@ var WebStandardStreamableHTTPServerTransport = class {
365
444
  }
366
445
  });
367
446
  }
447
+ async _checkScopeChallenge(messages, authInfo) {
448
+ if (!this._scopeChallengeResolver) return;
449
+ const challenge = await require_mcp.findScopeChallenge(messages.filter((message) => require_src.isJSONRPCRequest(message)), authInfo, this._scopeChallengeResolver);
450
+ return challenge === void 0 ? void 0 : require_mcp.createScopeChallengeResponse(challenge, require_mcp.scopeChallengeResourceMetadataUrl(authInfo));
451
+ }
368
452
  /**
369
453
  * Validates request headers for DNS rebinding protection.
370
454
  * @returns Error response if validation fails, `undefined` if validation passes.
@@ -393,6 +477,7 @@ var WebStandardStreamableHTTPServerTransport = class {
393
477
  * Returns a `Response` object (Web Standard)
394
478
  */
395
479
  async handleRequest(req, options) {
480
+ if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
396
481
  const validationError = this.validateRequestHeaders(req);
397
482
  if (validationError) return validationError;
398
483
  switch (req.method) {
@@ -453,30 +538,35 @@ var WebStandardStreamableHTTPServerTransport = class {
453
538
  }
454
539
  const encoder = new TextEncoder();
455
540
  let streamController;
541
+ let keepAliveTimer;
456
542
  const readable = new ReadableStream({
457
543
  start: (controller) => {
458
544
  streamController = controller;
459
545
  },
460
546
  cancel: () => {
547
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
461
548
  if (this._streamMapping.get(this._standaloneSseStreamId)?.controller === streamController) this._streamMapping.delete(this._standaloneSseStreamId);
462
549
  }
463
550
  });
464
551
  const headers = {
465
552
  "Content-Type": "text/event-stream",
466
553
  "Cache-Control": "no-cache, no-transform",
467
- Connection: "keep-alive"
554
+ Connection: "keep-alive",
555
+ "X-Accel-Buffering": "no"
468
556
  };
469
557
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
470
558
  this._streamMapping.set(this._standaloneSseStreamId, {
471
559
  controller: streamController,
472
560
  encoder,
473
561
  cleanup: () => {
562
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
474
563
  this._streamMapping.delete(this._standaloneSseStreamId);
475
564
  try {
476
565
  streamController.close();
477
566
  } catch {}
478
567
  }
479
568
  });
569
+ keepAliveTimer = this.startKeepAlive(streamController, encoder);
480
570
  return new Response(readable, { headers });
481
571
  }
482
572
  /**
@@ -504,17 +594,22 @@ var WebStandardStreamableHTTPServerTransport = class {
504
594
  const headers = {
505
595
  "Content-Type": "text/event-stream",
506
596
  "Cache-Control": "no-cache, no-transform",
507
- Connection: "keep-alive"
597
+ Connection: "keep-alive",
598
+ "X-Accel-Buffering": "no"
508
599
  };
509
600
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
510
601
  const encoder = new TextEncoder();
511
602
  let streamController;
603
+ let keepAliveTimer;
604
+ let cancelled = false;
512
605
  let replayedStreamId;
513
606
  const readable = new ReadableStream({
514
607
  start: (controller) => {
515
608
  streamController = controller;
516
609
  },
517
610
  cancel: () => {
611
+ cancelled = true;
612
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
518
613
  if (replayedStreamId !== void 0 && this._streamMapping.get(replayedStreamId)?.controller === streamController) this._streamMapping.delete(replayedStreamId);
519
614
  }
520
615
  });
@@ -525,11 +620,19 @@ var WebStandardStreamableHTTPServerTransport = class {
525
620
  streamController.close();
526
621
  } catch {}
527
622
  } });
623
+ if (this._closed || cancelled) {
624
+ try {
625
+ streamController.close();
626
+ } catch {}
627
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
628
+ }
629
+ this._streamMapping.get(replayedStreamId)?.cleanup();
528
630
  this._streamMapping.set(replayedStreamId, {
529
631
  controller: streamController,
530
632
  encoder,
531
633
  replayedEventIds,
532
634
  cleanup: () => {
635
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
533
636
  this._streamMapping.delete(replayedStreamId);
534
637
  try {
535
638
  streamController.close();
@@ -544,6 +647,7 @@ var WebStandardStreamableHTTPServerTransport = class {
544
647
  } catch {}
545
648
  }
546
649
  }
650
+ if (this._streamMapping.get(replayedStreamId)?.controller === streamController) keepAliveTimer = this.startKeepAlive(streamController, encoder);
547
651
  return new Response(readable, { headers });
548
652
  } catch (error) {
549
653
  this.onerror?.(error);
@@ -602,12 +706,22 @@ var WebStandardStreamableHTTPServerTransport = class {
602
706
  const request = req;
603
707
  let rawMessage;
604
708
  if (options?.parsedBody === void 0) try {
605
- rawMessage = await req.json();
709
+ const body = await readRequestBody(req, this._maxRequestBodySize);
710
+ if (body.tooLarge) {
711
+ const message = requestBodyTooLargeMessage(this._maxRequestBodySize);
712
+ this.onerror?.(new Error(message));
713
+ return this.createJsonErrorResponse(413, -32e3, message);
714
+ }
715
+ rawMessage = JSON.parse(body.text);
606
716
  } catch (error) {
607
717
  this.onerror?.(error);
608
718
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
609
719
  }
610
720
  else rawMessage = options.parsedBody;
721
+ if (Array.isArray(rawMessage) && rawMessage.length > MAX_BATCH_SIZE) {
722
+ this.onerror?.(/* @__PURE__ */ new Error(`Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`));
723
+ return this.createJsonErrorResponse(400, -32600, `Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`);
724
+ }
611
725
  let messages;
612
726
  try {
613
727
  messages = Array.isArray(rawMessage) ? rawMessage.map((msg) => _modelcontextprotocol_core_internal.JSONRPCMessageSchema.parse(msg)) : [_modelcontextprotocol_core_internal.JSONRPCMessageSchema.parse(rawMessage)];
@@ -615,6 +729,7 @@ var WebStandardStreamableHTTPServerTransport = class {
615
729
  this.onerror?.(error);
616
730
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
617
731
  }
732
+ if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
618
733
  const isInitializationRequest = messages.some((element) => require_src.isInitializeRequest(element));
619
734
  if (isInitializationRequest) {
620
735
  if (this._initialized && this.sessionId !== void 0) {
@@ -635,6 +750,15 @@ var WebStandardStreamableHTTPServerTransport = class {
635
750
  const protocolError = this.validateProtocolVersion(req);
636
751
  if (protocolError) return protocolError;
637
752
  }
753
+ if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
754
+ let scopeChallengeResponse;
755
+ try {
756
+ scopeChallengeResponse = await this._checkScopeChallenge(messages, options?.authInfo);
757
+ } catch (error) {
758
+ this.onerror?.(error);
759
+ return this.createJsonErrorResponse(500, -32603, "Internal server error");
760
+ }
761
+ if (scopeChallengeResponse) return scopeChallengeResponse;
638
762
  if (!messages.some((element) => require_src.isJSONRPCRequest(element))) {
639
763
  for (const message of messages) this.onmessage?.(message, {
640
764
  authInfo: options?.authInfo,
@@ -660,18 +784,21 @@ var WebStandardStreamableHTTPServerTransport = class {
660
784
  });
661
785
  const encoder = new TextEncoder();
662
786
  let streamController;
787
+ let keepAliveTimer;
663
788
  const readable = new ReadableStream({
664
789
  start: (controller) => {
665
790
  streamController = controller;
666
791
  },
667
792
  cancel: () => {
793
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
668
794
  if (this._streamMapping.get(streamId)?.controller === streamController) this._streamMapping.delete(streamId);
669
795
  }
670
796
  });
671
797
  const headers = {
672
798
  "Content-Type": "text/event-stream",
673
- "Cache-Control": "no-cache",
674
- Connection: "keep-alive"
799
+ "Cache-Control": "no-cache, no-transform",
800
+ Connection: "keep-alive",
801
+ "X-Accel-Buffering": "no"
675
802
  };
676
803
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
677
804
  for (const message of messages) if (require_src.isJSONRPCRequest(message)) {
@@ -679,6 +806,7 @@ var WebStandardStreamableHTTPServerTransport = class {
679
806
  controller: streamController,
680
807
  encoder,
681
808
  cleanup: () => {
809
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
682
810
  this._streamMapping.delete(streamId);
683
811
  try {
684
812
  streamController.close();
@@ -706,6 +834,7 @@ var WebStandardStreamableHTTPServerTransport = class {
706
834
  closeStandaloneSSEStream
707
835
  });
708
836
  }
837
+ if (this._streamMapping.get(streamId)?.controller === streamController) keepAliveTimer = this.startKeepAlive(streamController, encoder);
709
838
  return new Response(readable, {
710
839
  status: 200,
711
840
  headers
@@ -723,9 +852,12 @@ var WebStandardStreamableHTTPServerTransport = class {
723
852
  if (sessionError) return sessionError;
724
853
  const protocolError = this.validateProtocolVersion(req);
725
854
  if (protocolError) return protocolError;
726
- await Promise.resolve(this._onsessionclosed?.(this.sessionId));
727
- await this.close();
728
- return new Response(null, { status: 200 });
855
+ try {
856
+ await Promise.resolve(this._onsessionclosed?.(this.sessionId));
857
+ return new Response(null, { status: 200 });
858
+ } finally {
859
+ await this.close();
860
+ }
729
861
  }
730
862
  /**
731
863
  * Validates session ID for non-initialization requests.
@@ -916,7 +1048,7 @@ function internalServerErrorResponse(id = null) {
916
1048
  * The entry passes its own `onerror` here when expanding the default, so
917
1049
  * legacy-leg failures are never silently swallowed.
918
1050
  */
919
- function legacyStatelessFallback(factory, onerror) {
1051
+ function createLegacyStatelessFallback(factory, onerror, keepAliveMs, maxRequestBodySize) {
920
1052
  return async (request, options) => {
921
1053
  if (request.method.toUpperCase() !== "POST") return jsonRpcErrorResponse(405, -32e3, "Method not allowed.");
922
1054
  try {
@@ -925,7 +1057,11 @@ function legacyStatelessFallback(factory, onerror) {
925
1057
  ...options?.authInfo !== void 0 && { authInfo: options.authInfo },
926
1058
  requestInfo: request
927
1059
  });
928
- const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
1060
+ const transport = new WebStandardStreamableHTTPServerTransport({
1061
+ sessionIdGenerator: void 0,
1062
+ ...keepAliveMs !== void 0 && { keepAliveMs },
1063
+ ...maxRequestBodySize !== void 0 && { maxRequestBodySize }
1064
+ });
929
1065
  await product.connect(transport);
930
1066
  const teardown = () => {
931
1067
  transport.close().catch(() => {});
@@ -981,6 +1117,27 @@ function legacyStatelessFallback(factory, onerror) {
981
1117
  }
982
1118
  };
983
1119
  }
1120
+ function legacyStatelessFallback(factory, onerror, options) {
1121
+ return createLegacyStatelessFallback(factory, onerror, void 0, resolveMaxRequestBodySize(options?.maxRequestBodySize));
1122
+ }
1123
+ /**
1124
+ * Read the SEP-2243 standard request headers off the inbound request.
1125
+ *
1126
+ * Both halves of the standard-header story need them — the body-primary
1127
+ * classifier for its cross-check cells, and
1128
+ * {@linkcode validateStandardRequestHeaders} for the presence half — and a
1129
+ * header read at one site but not the other is precisely how a required header
1130
+ * goes unenforced: that divergence is what let a modern POST omitting
1131
+ * `MCP-Protocol-Version` be served. Read them here once so a header added to
1132
+ * {@linkcode InboundHttpRequest} reaches both sites together.
1133
+ */
1134
+ function standardHeadersOf(request) {
1135
+ return {
1136
+ protocolVersionHeader: request.headers.get("mcp-protocol-version") ?? void 0,
1137
+ mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
1138
+ mcpNameHeader: request.headers.get("mcp-name") ?? void 0
1139
+ };
1140
+ }
984
1141
  /**
985
1142
  * The entry's classification step: read the request body exactly once (unless
986
1143
  * a pre-parsed body is supplied) and classify the request with
@@ -992,7 +1149,7 @@ function legacyStatelessFallback(factory, onerror) {
992
1149
  * the body-preserving clone is then skipped and `forwardRequest` is the
993
1150
  * (consumed) input request.
994
1151
  */
995
- async function classifyEntryRequest(request, providedParsedBody, needsForward = true) {
1152
+ async function classifyEntryRequest(request, providedParsedBody, needsForward = true, maxRequestBodySize = DEFAULT_MAX_REQUEST_BODY_SIZE) {
996
1153
  const httpMethod = request.method.toUpperCase();
997
1154
  let body;
998
1155
  let parsedBody = providedParsedBody;
@@ -1003,7 +1160,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1003
1160
  if (needsForward) forwardRequest = request.clone();
1004
1161
  let bodyText;
1005
1162
  try {
1006
- bodyText = await request.text();
1163
+ const read = await readRequestBody(request, maxRequestBodySize);
1164
+ if (read.tooLarge) return { step: "body-too-large" };
1165
+ bodyText = read.text;
1007
1166
  } catch {
1008
1167
  return { step: "unreadable-body" };
1009
1168
  }
@@ -1023,9 +1182,7 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1023
1182
  step: "classified",
1024
1183
  outcome: require_src.classifyInboundRequest({
1025
1184
  httpMethod,
1026
- protocolVersionHeader: request.headers.get("mcp-protocol-version") ?? void 0,
1027
- mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
1028
- mcpNameHeader: request.headers.get("mcp-name") ?? void 0,
1185
+ ...standardHeadersOf(request),
1029
1186
  ...body !== void 0 && { body }
1030
1187
  }),
1031
1188
  body,
@@ -1093,7 +1250,8 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1093
1250
  * answers it with the unsupported-protocol-version error), a malformed
1094
1251
  * envelope behind a present claim (answered `-32602`), a request whose
1095
1252
  * `MCP-Protocol-Version` header names a modern revision but that lacks the
1096
- * envelope (`-32602`), and header/body mismatches (`-32020`). Consumers
1253
+ * envelope (`-32602`), header/body mismatches (`-32020`), and a POST body
1254
+ * over the size limit (413). Consumers
1097
1255
  * routing on the predicate must send `false` traffic to the modern handler,
1098
1256
  * never to a legacy handler — the modern path owns those error answers.
1099
1257
  * - `server/discover` probes sent by negotiating clients always carry the
@@ -1101,8 +1259,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1101
1259
  * a method named `server/discover` has no claim and classifies legacy,
1102
1260
  * exactly as the entry itself routes it.
1103
1261
  */
1104
- async function isLegacyRequest(request, parsedBody) {
1105
- const classified = await classifyEntryRequest(parsedBody === void 0 && request.method.toUpperCase() === "POST" ? request.clone() : request, parsedBody, false);
1262
+ async function isLegacyRequest(request, parsedBody, options) {
1263
+ const maxRequestBodySize = resolveMaxRequestBodySize(options?.maxRequestBodySize);
1264
+ const classified = await classifyEntryRequest(parsedBody === void 0 && request.method.toUpperCase() === "POST" ? request.clone() : request, parsedBody, false, maxRequestBodySize);
1106
1265
  return classified.step === "no-json-body" || classified.step === "classified" && classified.outcome.kind === "legacy";
1107
1266
  }
1108
1267
  /**
@@ -1151,6 +1310,7 @@ async function isLegacyRequest(request, parsedBody) {
1151
1310
  */
1152
1311
  function createMcpHandler(factory, options = {}) {
1153
1312
  const { legacy, onerror, responseMode } = options;
1313
+ const maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
1154
1314
  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.");
1155
1315
  /** Modern per-request instances with an exchange still in flight (close() tears these down). */
1156
1316
  const inflight = /* @__PURE__ */ new Set();
@@ -1165,11 +1325,11 @@ function createMcpHandler(factory, options = {}) {
1165
1325
  const listenRouter = require_mcp.createListenRouter({
1166
1326
  bus,
1167
1327
  maxSubscriptions: options.maxSubscriptions ?? require_mcp.DEFAULT_MAX_SUBSCRIPTIONS,
1168
- keepAliveMs: options.keepAliveMs ?? require_mcp.DEFAULT_LISTEN_KEEPALIVE_MS,
1328
+ keepAliveMs: options.keepAliveMs ?? require_mcp.DEFAULT_SSE_KEEP_ALIVE_MS,
1169
1329
  onerror: reportError
1170
1330
  });
1171
1331
  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.");
1172
- const legacyHandler = legacy === "reject" ? void 0 : legacyStatelessFallback(factory, reportError);
1332
+ const legacyHandler = legacy === "reject" ? void 0 : createLegacyStatelessFallback(factory, reportError, options.keepAliveMs, maxRequestBodySize);
1173
1333
  async function serveModern(route, request, authInfo) {
1174
1334
  const claimedRevision = route.classification.revision;
1175
1335
  if (claimedRevision === void 0 || !require_src.SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedRevision)) {
@@ -1182,8 +1342,7 @@ function createMcpHandler(factory, options = {}) {
1182
1342
  }
1183
1343
  const stdHeaderRejection = require_src.validateStandardRequestHeaders({
1184
1344
  httpMethod: request.method,
1185
- mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
1186
- mcpNameHeader: request.headers.get("mcp-name") ?? void 0
1345
+ ...standardHeadersOf(request)
1187
1346
  }, route);
1188
1347
  if (stdHeaderRejection !== void 0) {
1189
1348
  reportError(/* @__PURE__ */ new Error(`Rejected inbound request (${stdHeaderRejection.cell}): ${stdHeaderRejection.message}`));
@@ -1230,6 +1389,17 @@ function createMcpHandler(factory, options = {}) {
1230
1389
  }
1231
1390
  }
1232
1391
  }
1392
+ if (route.messageKind === "request" && product instanceof require_mcp.McpServer) try {
1393
+ const challenge = await require_mcp.findScopeChallenge([route.message], authInfo, (context) => product.resolveScopeChallenge(context));
1394
+ if (challenge !== void 0) {
1395
+ product.close().catch(reportError);
1396
+ return require_mcp.createScopeChallengeResponse(challenge, require_mcp.scopeChallengeResourceMetadataUrl(authInfo));
1397
+ }
1398
+ } catch (error) {
1399
+ product.close().catch(reportError);
1400
+ reportError(toError(error));
1401
+ return internalServerErrorResponse(route.message.id);
1402
+ }
1233
1403
  require_src.setNegotiatedProtocolVersion(server, claimedRevision);
1234
1404
  require_mcp.installModernOnlyHandlers(server, require_src.SUPPORTED_MODERN_PROTOCOL_VERSIONS);
1235
1405
  if (meta !== void 0) require_mcp.seedClientIdentityFromEnvelope(server, {
@@ -1247,7 +1417,8 @@ function createMcpHandler(factory, options = {}) {
1247
1417
  classification: route.classification,
1248
1418
  request,
1249
1419
  ...authInfo !== void 0 && { authInfo },
1250
- ...responseMode !== void 0 && { responseMode }
1420
+ ...responseMode !== void 0 && { responseMode },
1421
+ ...options.keepAliveMs !== void 0 && { keepAliveMs: options.keepAliveMs }
1251
1422
  });
1252
1423
  if (route.messageKind === "notification") queueMicrotask(() => void server.close().catch(() => {}));
1253
1424
  return response;
@@ -1275,8 +1446,9 @@ function createMcpHandler(factory, options = {}) {
1275
1446
  reportError(/* @__PURE__ */ new Error("Unsupported Media Type: Content-Type must be application/json"));
1276
1447
  return jsonRpcErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
1277
1448
  }
1278
- const classified = await classifyEntryRequest(request, requestOptions?.parsedBody);
1449
+ const classified = await classifyEntryRequest(request, requestOptions?.parsedBody, true, maxRequestBodySize);
1279
1450
  if (classified.step === "unreadable-body") return jsonRpcErrorResponse(400, -32700, "Parse error: the request body could not be read");
1451
+ if (classified.step === "body-too-large") return jsonRpcErrorResponse(413, -32e3, requestBodyTooLargeMessage(maxRequestBodySize));
1280
1452
  if (classified.step === "no-json-body") {
1281
1453
  if (legacyHandler !== void 0) return legacyHandler(classified.forwardRequest, { ...authInfo !== void 0 && { authInfo } });
1282
1454
  return jsonRpcErrorResponse(400, -32700, "Parse error: the request body is not valid JSON");
@@ -1318,115 +1490,6 @@ function createMcpHandler(factory, options = {}) {
1318
1490
  };
1319
1491
  }
1320
1492
 
1321
- //#endregion
1322
- //#region src/server/middleware/bearerAuth.ts
1323
- function headerQuotedValue(value) {
1324
- return value.replaceAll(/[\\"]/g, String.raw`\$&`).replaceAll(/[^\u0020-\u007E]/g, " ");
1325
- }
1326
- function buildWwwAuthenticateHeader(errorCode, description, requiredScopes, resourceMetadataUrl) {
1327
- let header = `Bearer error="${headerQuotedValue(errorCode)}", error_description="${headerQuotedValue(description)}"`;
1328
- if (requiredScopes.length > 0) header += `, scope="${requiredScopes.join(" ")}"`;
1329
- if (resourceMetadataUrl) header += `, resource_metadata="${resourceMetadataUrl}"`;
1330
- return header;
1331
- }
1332
- /**
1333
- * Validate a raw `Authorization` header value as a Bearer token and return
1334
- * the verified {@link AuthInfo}.
1335
- *
1336
- * The runtime-neutral core of Bearer authentication: it parses the header,
1337
- * runs the verifier, enforces `requiredScopes`, and rejects tokens without an
1338
- * expiration or past it. On any failure it throws an {@link OAuthError} —
1339
- * pass that to {@link bearerAuthChallengeResponse} for the matching HTTP
1340
- * answer, or use {@link requireBearerAuth} to get both steps as one call.
1341
- *
1342
- * Framework adapters build on this: `requireBearerAuth` from
1343
- * `@modelcontextprotocol/express` feeds it `req.headers.authorization`.
1344
- */
1345
- async function verifyBearerToken(authorizationHeader, options) {
1346
- const { verifier, requiredScopes = [] } = options;
1347
- if (!authorizationHeader) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Missing Authorization header");
1348
- const [type, token] = authorizationHeader.split(" ");
1349
- if (type?.toLowerCase() !== "bearer" || !token) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Invalid Authorization header format, expected 'Bearer TOKEN'");
1350
- const authInfo = await verifier.verifyAccessToken(token);
1351
- if (requiredScopes.length > 0) {
1352
- if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new require_src.OAuthError(require_src.OAuthErrorCode.InsufficientScope, "Insufficient scope");
1353
- }
1354
- if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Token has no expiration time");
1355
- else if (authInfo.expiresAt < Date.now() / 1e3) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Token has expired");
1356
- return authInfo;
1357
- }
1358
- /**
1359
- * Build the HTTP answer for a Bearer authentication failure.
1360
- *
1361
- * Maps an {@link OAuthError} to its status — `401` for `invalid_token` and
1362
- * `403` for `insufficient_scope` (both carrying the `WWW-Authenticate: Bearer …`
1363
- * challenge, with `resource_metadata` when configured so clients can discover
1364
- * the Authorization Server), `500` for `server_error`, `400` for anything
1365
- * else. A non-`OAuthError` value answers `500 server_error`. The body is the
1366
- * OAuth error JSON.
1367
- */
1368
- function bearerAuthChallengeResponse(error, options) {
1369
- const { requiredScopes = [], resourceMetadataUrl } = options ?? {};
1370
- if (!(error instanceof require_src.OAuthError)) {
1371
- const serverError = new require_src.OAuthError(require_src.OAuthErrorCode.ServerError, "Internal Server Error");
1372
- return Response.json(serverError.toResponseObject(), { status: 500 });
1373
- }
1374
- switch (error.code) {
1375
- case require_src.OAuthErrorCode.InvalidToken: {
1376
- const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
1377
- return Response.json(error.toResponseObject(), {
1378
- status: 401,
1379
- headers: { "WWW-Authenticate": challenge }
1380
- });
1381
- }
1382
- case require_src.OAuthErrorCode.InsufficientScope: {
1383
- const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
1384
- return Response.json(error.toResponseObject(), {
1385
- status: 403,
1386
- headers: { "WWW-Authenticate": challenge }
1387
- });
1388
- }
1389
- case require_src.OAuthErrorCode.ServerError: return Response.json(error.toResponseObject(), { status: 500 });
1390
- default: return Response.json(error.toResponseObject(), { status: 400 });
1391
- }
1392
- }
1393
- /**
1394
- * Require a valid Bearer token on web-standard requests.
1395
- *
1396
- * The framework-free counterpart of `requireBearerAuth` from
1397
- * `@modelcontextprotocol/express`, for hosts whose HTTP surface is a
1398
- * `fetch(request)` handler — Cloudflare Workers, Deno, Bun, Hono. The
1399
- * returned gate resolves to the verified {@link AuthInfo}, or to the
1400
- * ready-to-return challenge `Response` when the request must be refused.
1401
- *
1402
- * @example
1403
- * ```ts source="./bearerAuth.examples.ts#requireBearerAuth_fetchGate"
1404
- * const gate = requireBearerAuth({ verifier, requiredScopes: ['mcp'] });
1405
- *
1406
- * async function fetchHandler(request: Request): Promise<Response> {
1407
- * const auth: AuthInfo | Response = await gate(request);
1408
- * if (auth instanceof Response) return auth;
1409
- * return handler.fetch(request, { authInfo: auth });
1410
- * }
1411
- * ```
1412
- */
1413
- function requireBearerAuth(options) {
1414
- const { verifier, requiredScopes = [], resourceMetadataUrl } = options;
1415
- const resolved = {
1416
- verifier,
1417
- requiredScopes,
1418
- resourceMetadataUrl
1419
- };
1420
- return async (request) => {
1421
- const [authorizationHeader] = (request.headers.get("authorization") ?? "").split(",");
1422
- try {
1423
- return await verifyBearerToken(authorizationHeader || void 0, resolved);
1424
- } catch (error) {
1425
- return bearerAuthChallengeResponse(error, resolved);
1426
- }
1427
- };
1428
- }
1429
-
1430
1493
  //#endregion
1431
1494
  //#region src/server/middleware/hostHeaderValidation.ts
1432
1495
  /**
@@ -1497,120 +1560,6 @@ function hostHeaderValidationResponse(req, allowedHostnames) {
1497
1560
  });
1498
1561
  }
1499
1562
 
1500
- //#endregion
1501
- //#region src/server/middleware/oauthMetadata.ts
1502
- function checkIssuerUrl(issuer, allowInsecure) {
1503
- if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1" && !allowInsecure) throw new Error("Issuer URL must be HTTPS");
1504
- if (issuer.hash) throw new Error(`Issuer URL must not have a fragment: ${issuer}`);
1505
- if (issuer.search) throw new Error(`Issuer URL must not have a query string: ${issuer}`);
1506
- }
1507
- /**
1508
- * Derive the RFC 9728 Protected Resource Metadata document from
1509
- * {@link AuthMetadataOptions}, validating the Authorization Server issuer URL
1510
- * (HTTPS required outside localhost) in the process.
1511
- *
1512
- * `oauthMetadataResponse` and the Express `mcpAuthMetadataRouter` both build
1513
- * on this; use it directly when serving the document through your own
1514
- * routing — or call it once at startup to fail fast on a misconfigured
1515
- * issuer before any request arrives.
1516
- */
1517
- function buildOAuthProtectedResourceMetadata(options) {
1518
- checkIssuerUrl(new URL(options.oauthMetadata.issuer), options.dangerouslyAllowInsecureIssuerUrl);
1519
- return {
1520
- resource: options.resourceServerUrl.href,
1521
- authorization_servers: [options.oauthMetadata.issuer],
1522
- scopes_supported: options.scopesSupported,
1523
- resource_name: options.resourceName,
1524
- resource_documentation: options.serviceDocumentationUrl?.href
1525
- };
1526
- }
1527
- /**
1528
- * Builds the RFC 9728 Protected Resource Metadata URL for a given MCP server
1529
- * URL by inserting `/.well-known/oauth-protected-resource` ahead of the path.
1530
- *
1531
- * @example
1532
- * ```ts
1533
- * getOAuthProtectedResourceMetadataUrl(new URL('https://api.example.com/mcp'))
1534
- * // → 'https://api.example.com/.well-known/oauth-protected-resource/mcp'
1535
- * ```
1536
- */
1537
- function getOAuthProtectedResourceMetadataUrl(serverUrl) {
1538
- return new URL(protectedResourceMetadataPath(serverUrl), serverUrl).href;
1539
- }
1540
- /** The RFC 9728 path-aware well-known path for a resource URL. */
1541
- function protectedResourceMetadataPath(resourceServerUrl) {
1542
- const rsPath = stripTrailingSlash(resourceServerUrl.pathname);
1543
- return `/.well-known/oauth-protected-resource${rsPath === "/" ? "" : rsPath}`;
1544
- }
1545
- function stripTrailingSlash(path) {
1546
- return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
1547
- }
1548
- const ALLOWED_METHODS = "GET, HEAD, OPTIONS";
1549
- function metadataDocumentResponse(request, metadata) {
1550
- if (request.method === "OPTIONS") {
1551
- const requestedHeaders = request.headers.get("access-control-request-headers");
1552
- return new Response(null, {
1553
- status: 204,
1554
- headers: {
1555
- "Access-Control-Allow-Origin": "*",
1556
- "Access-Control-Allow-Methods": ALLOWED_METHODS,
1557
- ...requestedHeaders === null ? {} : {
1558
- "Access-Control-Allow-Headers": requestedHeaders,
1559
- Vary: "Access-Control-Request-Headers"
1560
- }
1561
- }
1562
- });
1563
- }
1564
- if (request.method !== "GET" && request.method !== "HEAD") {
1565
- const error = new require_src.OAuthError(require_src.OAuthErrorCode.MethodNotAllowed, `The method ${request.method} is not allowed for this endpoint`);
1566
- return Response.json(error.toResponseObject(), {
1567
- status: 405,
1568
- headers: {
1569
- Allow: ALLOWED_METHODS,
1570
- "Access-Control-Allow-Origin": "*"
1571
- }
1572
- });
1573
- }
1574
- const response = Response.json(metadata, { headers: { "Access-Control-Allow-Origin": "*" } });
1575
- return request.method === "HEAD" ? new Response(null, {
1576
- status: response.status,
1577
- headers: response.headers
1578
- }) : response;
1579
- }
1580
- /**
1581
- * Serve the two OAuth discovery documents an MCP server acting as a Resource
1582
- * Server exposes, from a web-standard `fetch(request)` handler:
1583
- *
1584
- * - `/.well-known/oauth-protected-resource[/<path>]` — RFC 9728 Protected
1585
- * Resource Metadata, derived from the supplied options (path-aware: the
1586
- * resource URL's path is reflected in the route).
1587
- * - `/.well-known/oauth-authorization-server` — RFC 8414 Authorization
1588
- * Server Metadata, passed through verbatim.
1589
- *
1590
- * Returns the matched document `Response` (JSON with permissive CORS, `405`
1591
- * with an `Allow` header for non-GET methods, `204` for CORS preflight), or
1592
- * `undefined` when the request path is neither well-known route — fall
1593
- * through to your own routing. The framework-free counterpart of
1594
- * `mcpAuthMetadataRouter` from `@modelcontextprotocol/express`; pair it with
1595
- * `requireBearerAuth` and `getOAuthProtectedResourceMetadataUrl` so
1596
- * unauthenticated clients can discover the AS from the `401` challenge.
1597
- *
1598
- * @example
1599
- * ```ts source="./oauthMetadata.examples.ts#oauthMetadataResponse_fetchHandler"
1600
- * async function fetchHandler(request: Request): Promise<Response> {
1601
- * return oauthMetadataResponse(request, options) ?? serveMcp(request);
1602
- * }
1603
- * ```
1604
- */
1605
- function oauthMetadataResponse(request, options) {
1606
- const requestPath = stripTrailingSlash(new URL(request.url).pathname);
1607
- if (requestPath === protectedResourceMetadataPath(options.resourceServerUrl)) return metadataDocumentResponse(request, buildOAuthProtectedResourceMetadata(options));
1608
- if (requestPath === "/.well-known/oauth-authorization-server") {
1609
- buildOAuthProtectedResourceMetadata(options);
1610
- return metadataDocumentResponse(request, options.oauthMetadata);
1611
- }
1612
- }
1613
-
1614
1563
  //#endregion
1615
1564
  //#region src/server/middleware/originValidation.ts
1616
1565
  /**
@@ -1830,6 +1779,7 @@ Object.defineProperty(exports, 'CLIENT_INFO_META_KEY', {
1830
1779
  return _modelcontextprotocol_core_internal.CLIENT_INFO_META_KEY;
1831
1780
  }
1832
1781
  });
1782
+ exports.DEFAULT_MAX_REQUEST_BODY_SIZE = DEFAULT_MAX_REQUEST_BODY_SIZE;
1833
1783
  Object.defineProperty(exports, 'DEFAULT_NEGOTIATED_PROTOCOL_VERSION', {
1834
1784
  enumerable: true,
1835
1785
  get: function () {
@@ -1952,8 +1902,8 @@ exports.WebStandardStreamableHTTPServerTransport = WebStandardStreamableHTTPServ
1952
1902
  exports.acceptedContent = require_src.acceptedContent;
1953
1903
  exports.assertCompleteRequestPrompt = require_src.assertCompleteRequestPrompt;
1954
1904
  exports.assertCompleteRequestResourceTemplate = require_src.assertCompleteRequestResourceTemplate;
1955
- exports.bearerAuthChallengeResponse = bearerAuthChallengeResponse;
1956
- exports.buildOAuthProtectedResourceMetadata = buildOAuthProtectedResourceMetadata;
1905
+ exports.bearerAuthChallengeResponse = require_mcp.bearerAuthChallengeResponse;
1906
+ exports.buildOAuthProtectedResourceMetadata = require_mcp.buildOAuthProtectedResourceMetadata;
1957
1907
  exports.checkResourceAllowed = require_src.checkResourceAllowed;
1958
1908
  exports.classifyInboundRequest = require_src.classifyInboundRequest;
1959
1909
  exports.completable = require_mcp.completable;
@@ -1963,7 +1913,7 @@ exports.createRequestStateCodec = createRequestStateCodec;
1963
1913
  exports.deserializeMessage = require_src.deserializeMessage;
1964
1914
  exports.fromJsonSchema = fromJsonSchema;
1965
1915
  exports.getDisplayName = require_src.getDisplayName;
1966
- exports.getOAuthProtectedResourceMetadataUrl = getOAuthProtectedResourceMetadataUrl;
1916
+ exports.getOAuthProtectedResourceMetadataUrl = require_mcp.getOAuthProtectedResourceMetadataUrl;
1967
1917
  exports.hostHeaderValidationResponse = hostHeaderValidationResponse;
1968
1918
  exports.inputRequired = require_src.inputRequired;
1969
1919
  exports.inputResponse = require_src.inputResponse;
@@ -1985,15 +1935,17 @@ exports.legacyStatelessFallback = legacyStatelessFallback;
1985
1935
  exports.localhostAllowedHostnames = localhostAllowedHostnames;
1986
1936
  exports.localhostAllowedOrigins = localhostAllowedOrigins;
1987
1937
  exports.mergeCapabilities = require_src.mergeCapabilities;
1988
- exports.oauthMetadataResponse = oauthMetadataResponse;
1938
+ exports.oauthMetadataResponse = require_mcp.oauthMetadataResponse;
1989
1939
  exports.originValidationResponse = originValidationResponse;
1990
1940
  exports.parseJSONRPCMessage = require_src.parseJSONRPCMessage;
1991
1941
  exports.preloadSchemas = require_src.preloadSchemas;
1992
- exports.requireBearerAuth = requireBearerAuth;
1942
+ exports.readRequestBody = readRequestBody;
1943
+ exports.requireBearerAuth = require_mcp.requireBearerAuth;
1944
+ exports.requireScopes = require_mcp.requireScopes;
1993
1945
  exports.resourceUrlFromServerUrl = require_src.resourceUrlFromServerUrl;
1994
1946
  exports.serializeMessage = require_src.serializeMessage;
1995
1947
  exports.specTypeSchemas = require_src.specTypeSchemas;
1996
1948
  exports.validateHostHeader = validateHostHeader;
1997
1949
  exports.validateOriginHeader = validateOriginHeader;
1998
- exports.verifyBearerToken = verifyBearerToken;
1950
+ exports.verifyBearerToken = require_mcp.verifyBearerToken;
1999
1951
  //# sourceMappingURL=index.cjs.map