ostacky 0.9.3 → 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 +5 -4
  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 +185 -29
  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 +53 -11
  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,5 +1,5 @@
1
- import { a as seedClientIdentityFromEnvelope, c as DEFAULT_MAX_SUBSCRIPTIONS, d as InMemoryServerEventBus, f as createServerNotifier, i as installModernOnlyHandlers, m as isCompletable, n as ResourceTemplate, o as serverIdentityOf, p as completable, r as Server, s as DEFAULT_LISTEN_KEEPALIVE_MS, t as McpServer, u as createListenRouter } from "./mcp-IJurDZVN.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-D86MbS1I.mjs";
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
@@ -32,9 +32,11 @@ var PerRequestHTTPServerTransport = class {
32
32
  _deferredResponse;
33
33
  _sse;
34
34
  _abortCleanup;
35
+ _keepAliveMs;
35
36
  constructor(options) {
36
37
  this._classification = options.classification;
37
38
  this._responseMode = options.responseMode ?? "auto";
39
+ this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;
38
40
  }
39
41
  async start() {
40
42
  if (this._started) throw new Error("PerRequestHTTPServerTransport is already started");
@@ -148,6 +150,7 @@ var PerRequestHTTPServerTransport = class {
148
150
  this._closed = true;
149
151
  this._abortCleanup?.();
150
152
  this._abortCleanup = void 0;
153
+ if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
151
154
  if (this._sse !== void 0 && !this._sse.closed) {
152
155
  this._sse.closed = true;
153
156
  try {
@@ -180,17 +183,19 @@ var PerRequestHTTPServerTransport = class {
180
183
  encoder: new TextEncoder(),
181
184
  closed: false
182
185
  };
186
+ this._sse.keepAliveTimer = armSseKeepAlive(this._keepAliveMs, () => this.writeCommentFrame("keepalive"));
183
187
  this.settleResponse(new Response(readable, {
184
188
  status: 200,
185
189
  headers: {
186
190
  "Content-Type": "text/event-stream",
187
- "Cache-Control": "no-cache",
191
+ "Cache-Control": "no-cache, no-transform",
188
192
  Connection: "keep-alive",
189
193
  "X-Accel-Buffering": "no"
190
194
  }
191
195
  }));
192
196
  }
193
197
  finalizeStream() {
198
+ if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
194
199
  if (this._sse !== void 0 && !this._sse.closed) {
195
200
  this._sse.closed = true;
196
201
  try {
@@ -231,7 +236,8 @@ var PerRequestHTTPServerTransport = class {
231
236
  async function invoke(server, message, ctx) {
232
237
  const transport = new PerRequestHTTPServerTransport({
233
238
  classification: ctx.classification,
234
- ...ctx.responseMode !== void 0 && { responseMode: ctx.responseMode }
239
+ ...ctx.responseMode !== void 0 && { responseMode: ctx.responseMode },
240
+ ...ctx.keepAliveMs !== void 0 && { keepAliveMs: ctx.keepAliveMs }
235
241
  });
236
242
  await server.connect(transport);
237
243
  return transport.handleMessage(message, {
@@ -240,6 +246,59 @@ async function invoke(server, message, ctx) {
240
246
  });
241
247
  }
242
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
+
243
302
  //#endregion
244
303
  //#region src/server/streamableHttp.ts
245
304
  /**
@@ -311,6 +370,9 @@ var WebStandardStreamableHTTPServerTransport = class {
311
370
  _enableDnsRebindingProtection;
312
371
  _retryInterval;
313
372
  _supportedProtocolVersions;
373
+ _keepAliveMs;
374
+ _maxRequestBodySize;
375
+ _scopeChallengeResolver;
314
376
  sessionId;
315
377
  onclose;
316
378
  onerror;
@@ -326,6 +388,23 @@ var WebStandardStreamableHTTPServerTransport = class {
326
388
  this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;
327
389
  this._retryInterval = options.retryInterval;
328
390
  this._supportedProtocolVersions = options.supportedProtocolVersions ?? SUPPORTED_PROTOCOL_VERSIONS;
391
+ this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;
392
+ this._maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
393
+ }
394
+ startKeepAlive(controller, encoder) {
395
+ if (this._closed) return void 0;
396
+ const timer = armSseKeepAlive(this._keepAliveMs, () => {
397
+ try {
398
+ controller.enqueue(encoder.encode(": keepalive\n\n"));
399
+ } catch {
400
+ if (timer !== void 0) clearInterval(timer);
401
+ }
402
+ });
403
+ return timer;
404
+ }
405
+ /** Sets the scope challenge resolver for parsed JSON-RPC requests. */
406
+ setScopeChallengeResolver(resolver) {
407
+ this._scopeChallengeResolver = resolver;
329
408
  }
330
409
  /**
331
410
  * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
@@ -363,6 +442,11 @@ var WebStandardStreamableHTTPServerTransport = class {
363
442
  }
364
443
  });
365
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
+ }
366
450
  /**
367
451
  * Validates request headers for DNS rebinding protection.
368
452
  * @returns Error response if validation fails, `undefined` if validation passes.
@@ -391,6 +475,7 @@ var WebStandardStreamableHTTPServerTransport = class {
391
475
  * Returns a `Response` object (Web Standard)
392
476
  */
393
477
  async handleRequest(req, options) {
478
+ if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
394
479
  const validationError = this.validateRequestHeaders(req);
395
480
  if (validationError) return validationError;
396
481
  switch (req.method) {
@@ -451,30 +536,35 @@ var WebStandardStreamableHTTPServerTransport = class {
451
536
  }
452
537
  const encoder = new TextEncoder();
453
538
  let streamController;
539
+ let keepAliveTimer;
454
540
  const readable = new ReadableStream({
455
541
  start: (controller) => {
456
542
  streamController = controller;
457
543
  },
458
544
  cancel: () => {
545
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
459
546
  if (this._streamMapping.get(this._standaloneSseStreamId)?.controller === streamController) this._streamMapping.delete(this._standaloneSseStreamId);
460
547
  }
461
548
  });
462
549
  const headers = {
463
550
  "Content-Type": "text/event-stream",
464
551
  "Cache-Control": "no-cache, no-transform",
465
- Connection: "keep-alive"
552
+ Connection: "keep-alive",
553
+ "X-Accel-Buffering": "no"
466
554
  };
467
555
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
468
556
  this._streamMapping.set(this._standaloneSseStreamId, {
469
557
  controller: streamController,
470
558
  encoder,
471
559
  cleanup: () => {
560
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
472
561
  this._streamMapping.delete(this._standaloneSseStreamId);
473
562
  try {
474
563
  streamController.close();
475
564
  } catch {}
476
565
  }
477
566
  });
567
+ keepAliveTimer = this.startKeepAlive(streamController, encoder);
478
568
  return new Response(readable, { headers });
479
569
  }
480
570
  /**
@@ -502,17 +592,22 @@ var WebStandardStreamableHTTPServerTransport = class {
502
592
  const headers = {
503
593
  "Content-Type": "text/event-stream",
504
594
  "Cache-Control": "no-cache, no-transform",
505
- Connection: "keep-alive"
595
+ Connection: "keep-alive",
596
+ "X-Accel-Buffering": "no"
506
597
  };
507
598
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
508
599
  const encoder = new TextEncoder();
509
600
  let streamController;
601
+ let keepAliveTimer;
602
+ let cancelled = false;
510
603
  let replayedStreamId;
511
604
  const readable = new ReadableStream({
512
605
  start: (controller) => {
513
606
  streamController = controller;
514
607
  },
515
608
  cancel: () => {
609
+ cancelled = true;
610
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
516
611
  if (replayedStreamId !== void 0 && this._streamMapping.get(replayedStreamId)?.controller === streamController) this._streamMapping.delete(replayedStreamId);
517
612
  }
518
613
  });
@@ -523,11 +618,19 @@ var WebStandardStreamableHTTPServerTransport = class {
523
618
  streamController.close();
524
619
  } catch {}
525
620
  } });
621
+ if (this._closed || cancelled) {
622
+ try {
623
+ streamController.close();
624
+ } catch {}
625
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
626
+ }
627
+ this._streamMapping.get(replayedStreamId)?.cleanup();
526
628
  this._streamMapping.set(replayedStreamId, {
527
629
  controller: streamController,
528
630
  encoder,
529
631
  replayedEventIds,
530
632
  cleanup: () => {
633
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
531
634
  this._streamMapping.delete(replayedStreamId);
532
635
  try {
533
636
  streamController.close();
@@ -542,6 +645,7 @@ var WebStandardStreamableHTTPServerTransport = class {
542
645
  } catch {}
543
646
  }
544
647
  }
648
+ if (this._streamMapping.get(replayedStreamId)?.controller === streamController) keepAliveTimer = this.startKeepAlive(streamController, encoder);
545
649
  return new Response(readable, { headers });
546
650
  } catch (error) {
547
651
  this.onerror?.(error);
@@ -600,12 +704,22 @@ var WebStandardStreamableHTTPServerTransport = class {
600
704
  const request = req;
601
705
  let rawMessage;
602
706
  if (options?.parsedBody === void 0) try {
603
- rawMessage = await req.json();
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);
604
714
  } catch (error) {
605
715
  this.onerror?.(error);
606
716
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
607
717
  }
608
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
+ }
609
723
  let messages;
610
724
  try {
611
725
  messages = Array.isArray(rawMessage) ? rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(rawMessage)];
@@ -613,6 +727,7 @@ var WebStandardStreamableHTTPServerTransport = class {
613
727
  this.onerror?.(error);
614
728
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
615
729
  }
730
+ if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
616
731
  const isInitializationRequest = messages.some((element) => isInitializeRequest(element));
617
732
  if (isInitializationRequest) {
618
733
  if (this._initialized && this.sessionId !== void 0) {
@@ -633,6 +748,15 @@ var WebStandardStreamableHTTPServerTransport = class {
633
748
  const protocolError = this.validateProtocolVersion(req);
634
749
  if (protocolError) return protocolError;
635
750
  }
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;
636
760
  if (!messages.some((element) => isJSONRPCRequest(element))) {
637
761
  for (const message of messages) this.onmessage?.(message, {
638
762
  authInfo: options?.authInfo,
@@ -658,18 +782,21 @@ var WebStandardStreamableHTTPServerTransport = class {
658
782
  });
659
783
  const encoder = new TextEncoder();
660
784
  let streamController;
785
+ let keepAliveTimer;
661
786
  const readable = new ReadableStream({
662
787
  start: (controller) => {
663
788
  streamController = controller;
664
789
  },
665
790
  cancel: () => {
791
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
666
792
  if (this._streamMapping.get(streamId)?.controller === streamController) this._streamMapping.delete(streamId);
667
793
  }
668
794
  });
669
795
  const headers = {
670
796
  "Content-Type": "text/event-stream",
671
- "Cache-Control": "no-cache",
672
- Connection: "keep-alive"
797
+ "Cache-Control": "no-cache, no-transform",
798
+ Connection: "keep-alive",
799
+ "X-Accel-Buffering": "no"
673
800
  };
674
801
  if (this.sessionId !== void 0) headers["mcp-session-id"] = this.sessionId;
675
802
  for (const message of messages) if (isJSONRPCRequest(message)) {
@@ -677,6 +804,7 @@ var WebStandardStreamableHTTPServerTransport = class {
677
804
  controller: streamController,
678
805
  encoder,
679
806
  cleanup: () => {
807
+ if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
680
808
  this._streamMapping.delete(streamId);
681
809
  try {
682
810
  streamController.close();
@@ -704,6 +832,7 @@ var WebStandardStreamableHTTPServerTransport = class {
704
832
  closeStandaloneSSEStream
705
833
  });
706
834
  }
835
+ if (this._streamMapping.get(streamId)?.controller === streamController) keepAliveTimer = this.startKeepAlive(streamController, encoder);
707
836
  return new Response(readable, {
708
837
  status: 200,
709
838
  headers
@@ -721,9 +850,12 @@ var WebStandardStreamableHTTPServerTransport = class {
721
850
  if (sessionError) return sessionError;
722
851
  const protocolError = this.validateProtocolVersion(req);
723
852
  if (protocolError) return protocolError;
724
- await Promise.resolve(this._onsessionclosed?.(this.sessionId));
725
- await this.close();
726
- return new Response(null, { status: 200 });
853
+ try {
854
+ await Promise.resolve(this._onsessionclosed?.(this.sessionId));
855
+ return new Response(null, { status: 200 });
856
+ } finally {
857
+ await this.close();
858
+ }
727
859
  }
728
860
  /**
729
861
  * Validates session ID for non-initialization requests.
@@ -914,7 +1046,7 @@ function internalServerErrorResponse(id = null) {
914
1046
  * The entry passes its own `onerror` here when expanding the default, so
915
1047
  * legacy-leg failures are never silently swallowed.
916
1048
  */
917
- function legacyStatelessFallback(factory, onerror) {
1049
+ function createLegacyStatelessFallback(factory, onerror, keepAliveMs, maxRequestBodySize) {
918
1050
  return async (request, options) => {
919
1051
  if (request.method.toUpperCase() !== "POST") return jsonRpcErrorResponse(405, -32e3, "Method not allowed.");
920
1052
  try {
@@ -923,7 +1055,11 @@ function legacyStatelessFallback(factory, onerror) {
923
1055
  ...options?.authInfo !== void 0 && { authInfo: options.authInfo },
924
1056
  requestInfo: request
925
1057
  });
926
- const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
1058
+ const transport = new WebStandardStreamableHTTPServerTransport({
1059
+ sessionIdGenerator: void 0,
1060
+ ...keepAliveMs !== void 0 && { keepAliveMs },
1061
+ ...maxRequestBodySize !== void 0 && { maxRequestBodySize }
1062
+ });
927
1063
  await product.connect(transport);
928
1064
  const teardown = () => {
929
1065
  transport.close().catch(() => {});
@@ -979,6 +1115,27 @@ function legacyStatelessFallback(factory, onerror) {
979
1115
  }
980
1116
  };
981
1117
  }
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
+ };
1138
+ }
982
1139
  /**
983
1140
  * The entry's classification step: read the request body exactly once (unless
984
1141
  * a pre-parsed body is supplied) and classify the request with
@@ -990,7 +1147,7 @@ function legacyStatelessFallback(factory, onerror) {
990
1147
  * the body-preserving clone is then skipped and `forwardRequest` is the
991
1148
  * (consumed) input request.
992
1149
  */
993
- async function classifyEntryRequest(request, providedParsedBody, needsForward = true) {
1150
+ async function classifyEntryRequest(request, providedParsedBody, needsForward = true, maxRequestBodySize = DEFAULT_MAX_REQUEST_BODY_SIZE) {
994
1151
  const httpMethod = request.method.toUpperCase();
995
1152
  let body;
996
1153
  let parsedBody = providedParsedBody;
@@ -1001,7 +1158,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1001
1158
  if (needsForward) forwardRequest = request.clone();
1002
1159
  let bodyText;
1003
1160
  try {
1004
- bodyText = await request.text();
1161
+ const read = await readRequestBody(request, maxRequestBodySize);
1162
+ if (read.tooLarge) return { step: "body-too-large" };
1163
+ bodyText = read.text;
1005
1164
  } catch {
1006
1165
  return { step: "unreadable-body" };
1007
1166
  }
@@ -1021,9 +1180,7 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1021
1180
  step: "classified",
1022
1181
  outcome: classifyInboundRequest({
1023
1182
  httpMethod,
1024
- protocolVersionHeader: request.headers.get("mcp-protocol-version") ?? void 0,
1025
- mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
1026
- mcpNameHeader: request.headers.get("mcp-name") ?? void 0,
1183
+ ...standardHeadersOf(request),
1027
1184
  ...body !== void 0 && { body }
1028
1185
  }),
1029
1186
  body,
@@ -1091,7 +1248,8 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1091
1248
  * answers it with the unsupported-protocol-version error), a malformed
1092
1249
  * envelope behind a present claim (answered `-32602`), a request whose
1093
1250
  * `MCP-Protocol-Version` header names a modern revision but that lacks the
1094
- * envelope (`-32602`), and header/body mismatches (`-32020`). Consumers
1251
+ * envelope (`-32602`), header/body mismatches (`-32020`), and a POST body
1252
+ * over the size limit (413). Consumers
1095
1253
  * routing on the predicate must send `false` traffic to the modern handler,
1096
1254
  * never to a legacy handler — the modern path owns those error answers.
1097
1255
  * - `server/discover` probes sent by negotiating clients always carry the
@@ -1099,8 +1257,9 @@ async function classifyEntryRequest(request, providedParsedBody, needsForward =
1099
1257
  * a method named `server/discover` has no claim and classifies legacy,
1100
1258
  * exactly as the entry itself routes it.
1101
1259
  */
1102
- async function isLegacyRequest(request, parsedBody) {
1103
- const classified = await classifyEntryRequest(parsedBody === void 0 && request.method.toUpperCase() === "POST" ? request.clone() : request, parsedBody, false);
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);
1104
1263
  return classified.step === "no-json-body" || classified.step === "classified" && classified.outcome.kind === "legacy";
1105
1264
  }
1106
1265
  /**
@@ -1149,6 +1308,7 @@ async function isLegacyRequest(request, parsedBody) {
1149
1308
  */
1150
1309
  function createMcpHandler(factory, options = {}) {
1151
1310
  const { legacy, onerror, responseMode } = options;
1311
+ const maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
1152
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.");
1153
1313
  /** Modern per-request instances with an exchange still in flight (close() tears these down). */
1154
1314
  const inflight = /* @__PURE__ */ new Set();
@@ -1163,11 +1323,11 @@ function createMcpHandler(factory, options = {}) {
1163
1323
  const listenRouter = createListenRouter({
1164
1324
  bus,
1165
1325
  maxSubscriptions: options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS,
1166
- keepAliveMs: options.keepAliveMs ?? DEFAULT_LISTEN_KEEPALIVE_MS,
1326
+ keepAliveMs: options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS,
1167
1327
  onerror: reportError
1168
1328
  });
1169
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.");
1170
- const legacyHandler = legacy === "reject" ? void 0 : legacyStatelessFallback(factory, reportError);
1330
+ const legacyHandler = legacy === "reject" ? void 0 : createLegacyStatelessFallback(factory, reportError, options.keepAliveMs, maxRequestBodySize);
1171
1331
  async function serveModern(route, request, authInfo) {
1172
1332
  const claimedRevision = route.classification.revision;
1173
1333
  if (claimedRevision === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedRevision)) {
@@ -1180,8 +1340,7 @@ function createMcpHandler(factory, options = {}) {
1180
1340
  }
1181
1341
  const stdHeaderRejection = validateStandardRequestHeaders({
1182
1342
  httpMethod: request.method,
1183
- mcpMethodHeader: request.headers.get("mcp-method") ?? void 0,
1184
- mcpNameHeader: request.headers.get("mcp-name") ?? void 0
1343
+ ...standardHeadersOf(request)
1185
1344
  }, route);
1186
1345
  if (stdHeaderRejection !== void 0) {
1187
1346
  reportError(/* @__PURE__ */ new Error(`Rejected inbound request (${stdHeaderRejection.cell}): ${stdHeaderRejection.message}`));
@@ -1228,6 +1387,17 @@ function createMcpHandler(factory, options = {}) {
1228
1387
  }
1229
1388
  }
1230
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
+ }
1231
1401
  setNegotiatedProtocolVersion(server, claimedRevision);
1232
1402
  installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
1233
1403
  if (meta !== void 0) seedClientIdentityFromEnvelope(server, {
@@ -1245,7 +1415,8 @@ function createMcpHandler(factory, options = {}) {
1245
1415
  classification: route.classification,
1246
1416
  request,
1247
1417
  ...authInfo !== void 0 && { authInfo },
1248
- ...responseMode !== void 0 && { responseMode }
1418
+ ...responseMode !== void 0 && { responseMode },
1419
+ ...options.keepAliveMs !== void 0 && { keepAliveMs: options.keepAliveMs }
1249
1420
  });
1250
1421
  if (route.messageKind === "notification") queueMicrotask(() => void server.close().catch(() => {}));
1251
1422
  return response;
@@ -1273,8 +1444,9 @@ function createMcpHandler(factory, options = {}) {
1273
1444
  reportError(/* @__PURE__ */ new Error("Unsupported Media Type: Content-Type must be application/json"));
1274
1445
  return jsonRpcErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
1275
1446
  }
1276
- const classified = await classifyEntryRequest(request, requestOptions?.parsedBody);
1447
+ const classified = await classifyEntryRequest(request, requestOptions?.parsedBody, true, maxRequestBodySize);
1277
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));
1278
1450
  if (classified.step === "no-json-body") {
1279
1451
  if (legacyHandler !== void 0) return legacyHandler(classified.forwardRequest, { ...authInfo !== void 0 && { authInfo } });
1280
1452
  return jsonRpcErrorResponse(400, -32700, "Parse error: the request body is not valid JSON");
@@ -1316,115 +1488,6 @@ function createMcpHandler(factory, options = {}) {
1316
1488
  };
1317
1489
  }
1318
1490
 
1319
- //#endregion
1320
- //#region src/server/middleware/bearerAuth.ts
1321
- function headerQuotedValue(value) {
1322
- return value.replaceAll(/[\\"]/g, String.raw`\$&`).replaceAll(/[^\u0020-\u007E]/g, " ");
1323
- }
1324
- function buildWwwAuthenticateHeader(errorCode, description, requiredScopes, resourceMetadataUrl) {
1325
- let header = `Bearer error="${headerQuotedValue(errorCode)}", error_description="${headerQuotedValue(description)}"`;
1326
- if (requiredScopes.length > 0) header += `, scope="${requiredScopes.join(" ")}"`;
1327
- if (resourceMetadataUrl) header += `, resource_metadata="${resourceMetadataUrl}"`;
1328
- return header;
1329
- }
1330
- /**
1331
- * Validate a raw `Authorization` header value as a Bearer token and return
1332
- * the verified {@link AuthInfo}.
1333
- *
1334
- * The runtime-neutral core of Bearer authentication: it parses the header,
1335
- * runs the verifier, enforces `requiredScopes`, and rejects tokens without an
1336
- * expiration or past it. On any failure it throws an {@link OAuthError} —
1337
- * pass that to {@link bearerAuthChallengeResponse} for the matching HTTP
1338
- * answer, or use {@link requireBearerAuth} to get both steps as one call.
1339
- *
1340
- * Framework adapters build on this: `requireBearerAuth` from
1341
- * `@modelcontextprotocol/express` feeds it `req.headers.authorization`.
1342
- */
1343
- async function verifyBearerToken(authorizationHeader, options) {
1344
- const { verifier, requiredScopes = [] } = options;
1345
- if (!authorizationHeader) throw new OAuthError(OAuthErrorCode.InvalidToken, "Missing Authorization header");
1346
- const [type, token] = authorizationHeader.split(" ");
1347
- if (type?.toLowerCase() !== "bearer" || !token) throw new OAuthError(OAuthErrorCode.InvalidToken, "Invalid Authorization header format, expected 'Bearer TOKEN'");
1348
- const authInfo = await verifier.verifyAccessToken(token);
1349
- if (requiredScopes.length > 0) {
1350
- if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new OAuthError(OAuthErrorCode.InsufficientScope, "Insufficient scope");
1351
- }
1352
- if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has no expiration time");
1353
- else if (authInfo.expiresAt < Date.now() / 1e3) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has expired");
1354
- return authInfo;
1355
- }
1356
- /**
1357
- * Build the HTTP answer for a Bearer authentication failure.
1358
- *
1359
- * Maps an {@link OAuthError} to its status — `401` for `invalid_token` and
1360
- * `403` for `insufficient_scope` (both carrying the `WWW-Authenticate: Bearer …`
1361
- * challenge, with `resource_metadata` when configured so clients can discover
1362
- * the Authorization Server), `500` for `server_error`, `400` for anything
1363
- * else. A non-`OAuthError` value answers `500 server_error`. The body is the
1364
- * OAuth error JSON.
1365
- */
1366
- function bearerAuthChallengeResponse(error, options) {
1367
- const { requiredScopes = [], resourceMetadataUrl } = options ?? {};
1368
- if (!(error instanceof OAuthError)) {
1369
- const serverError = new OAuthError(OAuthErrorCode.ServerError, "Internal Server Error");
1370
- return Response.json(serverError.toResponseObject(), { status: 500 });
1371
- }
1372
- switch (error.code) {
1373
- case OAuthErrorCode.InvalidToken: {
1374
- const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
1375
- return Response.json(error.toResponseObject(), {
1376
- status: 401,
1377
- headers: { "WWW-Authenticate": challenge }
1378
- });
1379
- }
1380
- case OAuthErrorCode.InsufficientScope: {
1381
- const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl);
1382
- return Response.json(error.toResponseObject(), {
1383
- status: 403,
1384
- headers: { "WWW-Authenticate": challenge }
1385
- });
1386
- }
1387
- case OAuthErrorCode.ServerError: return Response.json(error.toResponseObject(), { status: 500 });
1388
- default: return Response.json(error.toResponseObject(), { status: 400 });
1389
- }
1390
- }
1391
- /**
1392
- * Require a valid Bearer token on web-standard requests.
1393
- *
1394
- * The framework-free counterpart of `requireBearerAuth` from
1395
- * `@modelcontextprotocol/express`, for hosts whose HTTP surface is a
1396
- * `fetch(request)` handler — Cloudflare Workers, Deno, Bun, Hono. The
1397
- * returned gate resolves to the verified {@link AuthInfo}, or to the
1398
- * ready-to-return challenge `Response` when the request must be refused.
1399
- *
1400
- * @example
1401
- * ```ts source="./bearerAuth.examples.ts#requireBearerAuth_fetchGate"
1402
- * const gate = requireBearerAuth({ verifier, requiredScopes: ['mcp'] });
1403
- *
1404
- * async function fetchHandler(request: Request): Promise<Response> {
1405
- * const auth: AuthInfo | Response = await gate(request);
1406
- * if (auth instanceof Response) return auth;
1407
- * return handler.fetch(request, { authInfo: auth });
1408
- * }
1409
- * ```
1410
- */
1411
- function requireBearerAuth(options) {
1412
- const { verifier, requiredScopes = [], resourceMetadataUrl } = options;
1413
- const resolved = {
1414
- verifier,
1415
- requiredScopes,
1416
- resourceMetadataUrl
1417
- };
1418
- return async (request) => {
1419
- const [authorizationHeader] = (request.headers.get("authorization") ?? "").split(",");
1420
- try {
1421
- return await verifyBearerToken(authorizationHeader || void 0, resolved);
1422
- } catch (error) {
1423
- return bearerAuthChallengeResponse(error, resolved);
1424
- }
1425
- };
1426
- }
1427
-
1428
1491
  //#endregion
1429
1492
  //#region src/server/middleware/hostHeaderValidation.ts
1430
1493
  /**
@@ -1495,120 +1558,6 @@ function hostHeaderValidationResponse(req, allowedHostnames) {
1495
1558
  });
1496
1559
  }
1497
1560
 
1498
- //#endregion
1499
- //#region src/server/middleware/oauthMetadata.ts
1500
- function checkIssuerUrl(issuer, allowInsecure) {
1501
- if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1" && !allowInsecure) throw new Error("Issuer URL must be HTTPS");
1502
- if (issuer.hash) throw new Error(`Issuer URL must not have a fragment: ${issuer}`);
1503
- if (issuer.search) throw new Error(`Issuer URL must not have a query string: ${issuer}`);
1504
- }
1505
- /**
1506
- * Derive the RFC 9728 Protected Resource Metadata document from
1507
- * {@link AuthMetadataOptions}, validating the Authorization Server issuer URL
1508
- * (HTTPS required outside localhost) in the process.
1509
- *
1510
- * `oauthMetadataResponse` and the Express `mcpAuthMetadataRouter` both build
1511
- * on this; use it directly when serving the document through your own
1512
- * routing — or call it once at startup to fail fast on a misconfigured
1513
- * issuer before any request arrives.
1514
- */
1515
- function buildOAuthProtectedResourceMetadata(options) {
1516
- checkIssuerUrl(new URL(options.oauthMetadata.issuer), options.dangerouslyAllowInsecureIssuerUrl);
1517
- return {
1518
- resource: options.resourceServerUrl.href,
1519
- authorization_servers: [options.oauthMetadata.issuer],
1520
- scopes_supported: options.scopesSupported,
1521
- resource_name: options.resourceName,
1522
- resource_documentation: options.serviceDocumentationUrl?.href
1523
- };
1524
- }
1525
- /**
1526
- * Builds the RFC 9728 Protected Resource Metadata URL for a given MCP server
1527
- * URL by inserting `/.well-known/oauth-protected-resource` ahead of the path.
1528
- *
1529
- * @example
1530
- * ```ts
1531
- * getOAuthProtectedResourceMetadataUrl(new URL('https://api.example.com/mcp'))
1532
- * // → 'https://api.example.com/.well-known/oauth-protected-resource/mcp'
1533
- * ```
1534
- */
1535
- function getOAuthProtectedResourceMetadataUrl(serverUrl) {
1536
- return new URL(protectedResourceMetadataPath(serverUrl), serverUrl).href;
1537
- }
1538
- /** The RFC 9728 path-aware well-known path for a resource URL. */
1539
- function protectedResourceMetadataPath(resourceServerUrl) {
1540
- const rsPath = stripTrailingSlash(resourceServerUrl.pathname);
1541
- return `/.well-known/oauth-protected-resource${rsPath === "/" ? "" : rsPath}`;
1542
- }
1543
- function stripTrailingSlash(path) {
1544
- return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
1545
- }
1546
- const ALLOWED_METHODS = "GET, HEAD, OPTIONS";
1547
- function metadataDocumentResponse(request, metadata) {
1548
- if (request.method === "OPTIONS") {
1549
- const requestedHeaders = request.headers.get("access-control-request-headers");
1550
- return new Response(null, {
1551
- status: 204,
1552
- headers: {
1553
- "Access-Control-Allow-Origin": "*",
1554
- "Access-Control-Allow-Methods": ALLOWED_METHODS,
1555
- ...requestedHeaders === null ? {} : {
1556
- "Access-Control-Allow-Headers": requestedHeaders,
1557
- Vary: "Access-Control-Request-Headers"
1558
- }
1559
- }
1560
- });
1561
- }
1562
- if (request.method !== "GET" && request.method !== "HEAD") {
1563
- const error = new OAuthError(OAuthErrorCode.MethodNotAllowed, `The method ${request.method} is not allowed for this endpoint`);
1564
- return Response.json(error.toResponseObject(), {
1565
- status: 405,
1566
- headers: {
1567
- Allow: ALLOWED_METHODS,
1568
- "Access-Control-Allow-Origin": "*"
1569
- }
1570
- });
1571
- }
1572
- const response = Response.json(metadata, { headers: { "Access-Control-Allow-Origin": "*" } });
1573
- return request.method === "HEAD" ? new Response(null, {
1574
- status: response.status,
1575
- headers: response.headers
1576
- }) : response;
1577
- }
1578
- /**
1579
- * Serve the two OAuth discovery documents an MCP server acting as a Resource
1580
- * Server exposes, from a web-standard `fetch(request)` handler:
1581
- *
1582
- * - `/.well-known/oauth-protected-resource[/<path>]` — RFC 9728 Protected
1583
- * Resource Metadata, derived from the supplied options (path-aware: the
1584
- * resource URL's path is reflected in the route).
1585
- * - `/.well-known/oauth-authorization-server` — RFC 8414 Authorization
1586
- * Server Metadata, passed through verbatim.
1587
- *
1588
- * Returns the matched document `Response` (JSON with permissive CORS, `405`
1589
- * with an `Allow` header for non-GET methods, `204` for CORS preflight), or
1590
- * `undefined` when the request path is neither well-known route — fall
1591
- * through to your own routing. The framework-free counterpart of
1592
- * `mcpAuthMetadataRouter` from `@modelcontextprotocol/express`; pair it with
1593
- * `requireBearerAuth` and `getOAuthProtectedResourceMetadataUrl` so
1594
- * unauthenticated clients can discover the AS from the `401` challenge.
1595
- *
1596
- * @example
1597
- * ```ts source="./oauthMetadata.examples.ts#oauthMetadataResponse_fetchHandler"
1598
- * async function fetchHandler(request: Request): Promise<Response> {
1599
- * return oauthMetadataResponse(request, options) ?? serveMcp(request);
1600
- * }
1601
- * ```
1602
- */
1603
- function oauthMetadataResponse(request, options) {
1604
- const requestPath = stripTrailingSlash(new URL(request.url).pathname);
1605
- if (requestPath === protectedResourceMetadataPath(options.resourceServerUrl)) return metadataDocumentResponse(request, buildOAuthProtectedResourceMetadata(options));
1606
- if (requestPath === "/.well-known/oauth-authorization-server") {
1607
- buildOAuthProtectedResourceMetadata(options);
1608
- return metadataDocumentResponse(request, options.oauthMetadata);
1609
- }
1610
- }
1611
-
1612
1561
  //#endregion
1613
1562
  //#region src/server/middleware/originValidation.ts
1614
1563
  /**
@@ -1810,5 +1759,5 @@ function fromJsonSchema(schema, validator) {
1810
1759
  }
1811
1760
 
1812
1761
  //#endregion
1813
- 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 };
1814
1763
  //# sourceMappingURL=index.mjs.map