@frontmcp/sdk 1.0.0-beta.4 → 1.0.0-beta.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"decide-request-intent.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/decide-request-intent.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAI/C,eAAO,MAAM,YAAY,iOAQvB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;iBAiBzB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,KAAK,GACL,iBAAiB,GACjB,eAAe,GACf,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,MAAM,MAAM,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAEnD,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzD,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,MAAO,SAAQ,mBAAmB;IACjD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAkWD,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAsDtE"}
1
+ {"version":3,"file":"decide-request-intent.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/decide-request-intent.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAI/C,eAAO,MAAM,YAAY,iOAQvB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;iBAiBzB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,KAAK,GACL,iBAAiB,GACjB,eAAe,GACf,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,MAAM,MAAM,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAEnD,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzD,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,MAAO,SAAQ,mBAAmB;IACjD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAuWD,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAsDtE"}
package/esm/index.mjs CHANGED
@@ -28342,6 +28342,11 @@ var init_sse_transport = __esm({
28342
28342
  // libs/sdk/src/transport/mcp-handlers/initialize-request.handler.ts
28343
28343
  import { InitializeRequestSchema } from "@frontmcp/protocol";
28344
28344
  import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from "@frontmcp/protocol";
28345
+ function persistInitPayload(sessionId, initPayload, ctx) {
28346
+ updateSessionPayload(sessionId, initPayload);
28347
+ const transport = ctx.authInfo?.transport;
28348
+ transport?.setInitSessionPayload(initPayload);
28349
+ }
28345
28350
  function guardClientVersion(clientVersion) {
28346
28351
  const parsed = new Date(clientVersion);
28347
28352
  if (isNaN(parsed.getTime())) {
@@ -28402,28 +28407,30 @@ function initializeRequestHandler({
28402
28407
  if (finalPlatform) {
28403
28408
  ctx.authInfo.sessionIdPayload.platformType = finalPlatform;
28404
28409
  }
28405
- const initPayload = {
28406
- clientName,
28407
- clientVersion,
28408
- supportsElicitation: clientSupportsElicitation,
28409
- ...finalPlatform && { platformType: finalPlatform }
28410
- };
28411
- updateSessionPayload(sessionId, initPayload);
28412
- const transport = ctx.authInfo?.transport;
28413
- transport?.setInitSessionPayload(initPayload);
28410
+ persistInitPayload(
28411
+ sessionId,
28412
+ {
28413
+ clientName,
28414
+ clientVersion,
28415
+ supportsElicitation: clientSupportsElicitation,
28416
+ ...finalPlatform && { platformType: finalPlatform }
28417
+ },
28418
+ ctx
28419
+ );
28414
28420
  }
28415
28421
  } else if (ctx.authInfo?.sessionIdPayload) {
28416
28422
  ctx.authInfo.sessionIdPayload.supportsElicitation = clientSupportsElicitation;
28417
28423
  if (detectedPlatform) {
28418
28424
  ctx.authInfo.sessionIdPayload.platformType = detectedPlatform;
28419
28425
  }
28420
- const initPayload = {
28421
- supportsElicitation: clientSupportsElicitation,
28422
- ...detectedPlatform && { platformType: detectedPlatform }
28423
- };
28424
- updateSessionPayload(sessionId, initPayload);
28425
- const transport = ctx.authInfo?.transport;
28426
- transport?.setInitSessionPayload(initPayload);
28426
+ persistInitPayload(
28427
+ sessionId,
28428
+ {
28429
+ supportsElicitation: clientSupportsElicitation,
28430
+ ...detectedPlatform && { platformType: detectedPlatform }
28431
+ },
28432
+ ctx
28433
+ );
28427
28434
  }
28428
28435
  }
28429
28436
  const requestedVersion = request.params.protocolVersion;
@@ -31021,9 +31028,16 @@ var init_streamable_http_transport = __esm({
31021
31028
  * so we need to create fresh instances for each request.
31022
31029
  */
31023
31030
  _constructorOptions;
31031
+ /**
31032
+ * When true, the transport recreates the internal transport for each request.
31033
+ * Decoupled from sessionIdGenerator so stateless transports can still
31034
+ * provide a session ID (e.g., '__stateless__') in the response header.
31035
+ */
31036
+ _isStateless;
31024
31037
  constructor(options = {}) {
31025
31038
  super(options);
31026
31039
  this._constructorOptions = options;
31040
+ this._isStateless = options.isStateless ?? false;
31027
31041
  }
31028
31042
  /**
31029
31043
  * Returns whether the transport has been initialized.
@@ -31087,7 +31101,7 @@ var init_streamable_http_transport = __esm({
31087
31101
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31088
31102
  async handleRequest(req, res, body) {
31089
31103
  const oldWebTransport = this._webStandardTransport;
31090
- if (oldWebTransport && !oldWebTransport.sessionIdGenerator && oldWebTransport._hasHandledRequest) {
31104
+ if (oldWebTransport && this._isStateless && oldWebTransport._hasHandledRequest) {
31091
31105
  const fresh = new WebStandardStreamableHTTPServerTransport(this._constructorOptions);
31092
31106
  fresh.onmessage = oldWebTransport.onmessage;
31093
31107
  fresh.onclose = oldWebTransport.onclose;
@@ -31119,14 +31133,16 @@ var init_transport_streamable_http_adapter = __esm({
31119
31133
  init_streamable_http_transport();
31120
31134
  init_errors();
31121
31135
  resolveSessionIdGenerator = (transportType, sessionId) => {
31122
- return transportType === "stateless-http" ? void 0 : () => sessionId;
31136
+ return transportType === "stateless-http" ? () => "__stateless__" : () => sessionId;
31123
31137
  };
31124
31138
  TransportStreamableHttpAdapter = class extends LocalTransportAdapter {
31125
31139
  createTransport(sessionId, response) {
31126
31140
  const sessionIdGenerator = resolveSessionIdGenerator(this.key.type, sessionId);
31127
31141
  const eventStore = this.scope.eventStore;
31142
+ const isStateless = this.key.type === "stateless-http";
31128
31143
  return new RecreateableStreamableHTTPServerTransport({
31129
31144
  sessionIdGenerator,
31145
+ isStateless,
31130
31146
  onsessionclosed: () => {
31131
31147
  },
31132
31148
  onsessioninitialized: (sessionId2) => {
@@ -45124,9 +45140,12 @@ var init_decide_request_intent_utils = __esm({
45124
45140
  outcome: { intent: "sse", reason: "GET /sse with Mcp-Session-Id." }
45125
45141
  },
45126
45142
  // D) Initialize (POST → SSE)
45127
- // D1) Stateless initialize (no session, stateless enabled) - must come before streamable rules
45143
+ // D1) Stateless initialize (no session, stateless enabled, streamable NOT enabled)
45144
+ // When streamable is also enabled, prefer streamable-http (which creates a session).
45145
+ // Per MCP spec, first initialize naturally has no session — stateless should only
45146
+ // match when it's the sole enabled protocol.
45128
45147
  {
45129
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45148
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45130
45149
  match: CH_POST_INIT_SSE | B_STATELESS_EN,
45131
45150
  outcome: { intent: "stateless-http", reason: "Stateless initialize (no session)." }
45132
45151
  },
@@ -45145,9 +45164,9 @@ var init_decide_request_intent_utils = __esm({
45145
45164
  outcome: { intent: "streamable-http", reason: "Initialize with SSE." }
45146
45165
  },
45147
45166
  // E) Initialize (POST → JSON)
45148
- // E1) Stateless initialize JSON (no session, stateless enabled) - must come before stateful rules
45167
+ // E1) Stateless initialize JSON (no session, stateless enabled, streamable NOT enabled)
45149
45168
  {
45150
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45169
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45151
45170
  match: CH_POST_INIT_JSON | B_STATELESS_EN,
45152
45171
  outcome: { intent: "stateless-http", reason: "Stateless initialize JSON (no session)." }
45153
45172
  },
@@ -45176,7 +45195,7 @@ var init_decide_request_intent_utils = __esm({
45176
45195
  }
45177
45196
  },
45178
45197
  {
45179
- care: CH_MASK | B_STREAMABLE_EN,
45198
+ care: CH_MASK | B_STREAMABLE_EN | B_STATELESS_EN,
45180
45199
  match: CH_POST_SSE,
45181
45200
  outcome: {
45182
45201
  intent: "unknown",
@@ -45184,8 +45203,9 @@ var init_decide_request_intent_utils = __esm({
45184
45203
  recommendation: { httpStatus: 405, message: "Streamable HTTP disabled" }
45185
45204
  }
45186
45205
  },
45206
+ // Stateless short-lived SSE only when streamable is NOT enabled
45187
45207
  {
45188
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45208
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45189
45209
  match: CH_POST_SSE | B_STATELESS_EN,
45190
45210
  outcome: { intent: "stateless-http", reason: "Stateless short-lived SSE." }
45191
45211
  },
@@ -45205,7 +45225,7 @@ var init_decide_request_intent_utils = __esm({
45205
45225
  }
45206
45226
  },
45207
45227
  {
45208
- care: CH_MASK | B_STATEFUL_EN | B_STREAMABLE_EN,
45228
+ care: CH_MASK | B_STATEFUL_EN | B_STREAMABLE_EN | B_STATELESS_EN,
45209
45229
  match: CH_POST_JSON,
45210
45230
  outcome: {
45211
45231
  intent: "unknown",
@@ -45213,8 +45233,9 @@ var init_decide_request_intent_utils = __esm({
45213
45233
  recommendation: { httpStatus: 405, message: "JSON mode disabled" }
45214
45234
  }
45215
45235
  },
45236
+ // Stateless JSON only when streamable is NOT enabled
45216
45237
  {
45217
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45238
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45218
45239
  match: CH_POST_JSON | B_STATELESS_EN,
45219
45240
  outcome: { intent: "stateless-http", reason: "Stateless JSON request." }
45220
45241
  },
package/index.js CHANGED
@@ -28278,6 +28278,11 @@ var init_sse_transport = __esm({
28278
28278
  });
28279
28279
 
28280
28280
  // libs/sdk/src/transport/mcp-handlers/initialize-request.handler.ts
28281
+ function persistInitPayload(sessionId, initPayload, ctx) {
28282
+ updateSessionPayload(sessionId, initPayload);
28283
+ const transport = ctx.authInfo?.transport;
28284
+ transport?.setInitSessionPayload(initPayload);
28285
+ }
28281
28286
  function guardClientVersion(clientVersion) {
28282
28287
  const parsed = new Date(clientVersion);
28283
28288
  if (isNaN(parsed.getTime())) {
@@ -28338,28 +28343,30 @@ function initializeRequestHandler({
28338
28343
  if (finalPlatform) {
28339
28344
  ctx.authInfo.sessionIdPayload.platformType = finalPlatform;
28340
28345
  }
28341
- const initPayload = {
28342
- clientName,
28343
- clientVersion,
28344
- supportsElicitation: clientSupportsElicitation,
28345
- ...finalPlatform && { platformType: finalPlatform }
28346
- };
28347
- updateSessionPayload(sessionId, initPayload);
28348
- const transport = ctx.authInfo?.transport;
28349
- transport?.setInitSessionPayload(initPayload);
28346
+ persistInitPayload(
28347
+ sessionId,
28348
+ {
28349
+ clientName,
28350
+ clientVersion,
28351
+ supportsElicitation: clientSupportsElicitation,
28352
+ ...finalPlatform && { platformType: finalPlatform }
28353
+ },
28354
+ ctx
28355
+ );
28350
28356
  }
28351
28357
  } else if (ctx.authInfo?.sessionIdPayload) {
28352
28358
  ctx.authInfo.sessionIdPayload.supportsElicitation = clientSupportsElicitation;
28353
28359
  if (detectedPlatform) {
28354
28360
  ctx.authInfo.sessionIdPayload.platformType = detectedPlatform;
28355
28361
  }
28356
- const initPayload = {
28357
- supportsElicitation: clientSupportsElicitation,
28358
- ...detectedPlatform && { platformType: detectedPlatform }
28359
- };
28360
- updateSessionPayload(sessionId, initPayload);
28361
- const transport = ctx.authInfo?.transport;
28362
- transport?.setInitSessionPayload(initPayload);
28362
+ persistInitPayload(
28363
+ sessionId,
28364
+ {
28365
+ supportsElicitation: clientSupportsElicitation,
28366
+ ...detectedPlatform && { platformType: detectedPlatform }
28367
+ },
28368
+ ctx
28369
+ );
28363
28370
  }
28364
28371
  }
28365
28372
  const requestedVersion = request.params.protocolVersion;
@@ -30964,9 +30971,16 @@ var init_streamable_http_transport = __esm({
30964
30971
  * so we need to create fresh instances for each request.
30965
30972
  */
30966
30973
  _constructorOptions;
30974
+ /**
30975
+ * When true, the transport recreates the internal transport for each request.
30976
+ * Decoupled from sessionIdGenerator so stateless transports can still
30977
+ * provide a session ID (e.g., '__stateless__') in the response header.
30978
+ */
30979
+ _isStateless;
30967
30980
  constructor(options = {}) {
30968
30981
  super(options);
30969
30982
  this._constructorOptions = options;
30983
+ this._isStateless = options.isStateless ?? false;
30970
30984
  }
30971
30985
  /**
30972
30986
  * Returns whether the transport has been initialized.
@@ -31030,7 +31044,7 @@ var init_streamable_http_transport = __esm({
31030
31044
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31031
31045
  async handleRequest(req, res, body) {
31032
31046
  const oldWebTransport = this._webStandardTransport;
31033
- if (oldWebTransport && !oldWebTransport.sessionIdGenerator && oldWebTransport._hasHandledRequest) {
31047
+ if (oldWebTransport && this._isStateless && oldWebTransport._hasHandledRequest) {
31034
31048
  const fresh = new import_protocol37.WebStandardStreamableHTTPServerTransport(this._constructorOptions);
31035
31049
  fresh.onmessage = oldWebTransport.onmessage;
31036
31050
  fresh.onclose = oldWebTransport.onclose;
@@ -31062,14 +31076,16 @@ var init_transport_streamable_http_adapter = __esm({
31062
31076
  init_streamable_http_transport();
31063
31077
  init_errors();
31064
31078
  resolveSessionIdGenerator = (transportType, sessionId) => {
31065
- return transportType === "stateless-http" ? void 0 : () => sessionId;
31079
+ return transportType === "stateless-http" ? () => "__stateless__" : () => sessionId;
31066
31080
  };
31067
31081
  TransportStreamableHttpAdapter = class extends LocalTransportAdapter {
31068
31082
  createTransport(sessionId, response) {
31069
31083
  const sessionIdGenerator = resolveSessionIdGenerator(this.key.type, sessionId);
31070
31084
  const eventStore = this.scope.eventStore;
31085
+ const isStateless = this.key.type === "stateless-http";
31071
31086
  return new RecreateableStreamableHTTPServerTransport({
31072
31087
  sessionIdGenerator,
31088
+ isStateless,
31073
31089
  onsessionclosed: () => {
31074
31090
  },
31075
31091
  onsessioninitialized: (sessionId2) => {
@@ -45080,9 +45096,12 @@ var init_decide_request_intent_utils = __esm({
45080
45096
  outcome: { intent: "sse", reason: "GET /sse with Mcp-Session-Id." }
45081
45097
  },
45082
45098
  // D) Initialize (POST → SSE)
45083
- // D1) Stateless initialize (no session, stateless enabled) - must come before streamable rules
45099
+ // D1) Stateless initialize (no session, stateless enabled, streamable NOT enabled)
45100
+ // When streamable is also enabled, prefer streamable-http (which creates a session).
45101
+ // Per MCP spec, first initialize naturally has no session — stateless should only
45102
+ // match when it's the sole enabled protocol.
45084
45103
  {
45085
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45104
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45086
45105
  match: CH_POST_INIT_SSE | B_STATELESS_EN,
45087
45106
  outcome: { intent: "stateless-http", reason: "Stateless initialize (no session)." }
45088
45107
  },
@@ -45101,9 +45120,9 @@ var init_decide_request_intent_utils = __esm({
45101
45120
  outcome: { intent: "streamable-http", reason: "Initialize with SSE." }
45102
45121
  },
45103
45122
  // E) Initialize (POST → JSON)
45104
- // E1) Stateless initialize JSON (no session, stateless enabled) - must come before stateful rules
45123
+ // E1) Stateless initialize JSON (no session, stateless enabled, streamable NOT enabled)
45105
45124
  {
45106
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45125
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45107
45126
  match: CH_POST_INIT_JSON | B_STATELESS_EN,
45108
45127
  outcome: { intent: "stateless-http", reason: "Stateless initialize JSON (no session)." }
45109
45128
  },
@@ -45132,7 +45151,7 @@ var init_decide_request_intent_utils = __esm({
45132
45151
  }
45133
45152
  },
45134
45153
  {
45135
- care: CH_MASK | B_STREAMABLE_EN,
45154
+ care: CH_MASK | B_STREAMABLE_EN | B_STATELESS_EN,
45136
45155
  match: CH_POST_SSE,
45137
45156
  outcome: {
45138
45157
  intent: "unknown",
@@ -45140,8 +45159,9 @@ var init_decide_request_intent_utils = __esm({
45140
45159
  recommendation: { httpStatus: 405, message: "Streamable HTTP disabled" }
45141
45160
  }
45142
45161
  },
45162
+ // Stateless short-lived SSE only when streamable is NOT enabled
45143
45163
  {
45144
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45164
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45145
45165
  match: CH_POST_SSE | B_STATELESS_EN,
45146
45166
  outcome: { intent: "stateless-http", reason: "Stateless short-lived SSE." }
45147
45167
  },
@@ -45161,7 +45181,7 @@ var init_decide_request_intent_utils = __esm({
45161
45181
  }
45162
45182
  },
45163
45183
  {
45164
- care: CH_MASK | B_STATEFUL_EN | B_STREAMABLE_EN,
45184
+ care: CH_MASK | B_STATEFUL_EN | B_STREAMABLE_EN | B_STATELESS_EN,
45165
45185
  match: CH_POST_JSON,
45166
45186
  outcome: {
45167
45187
  intent: "unknown",
@@ -45169,8 +45189,9 @@ var init_decide_request_intent_utils = __esm({
45169
45189
  recommendation: { httpStatus: 405, message: "JSON mode disabled" }
45170
45190
  }
45171
45191
  },
45192
+ // Stateless JSON only when streamable is NOT enabled
45172
45193
  {
45173
- care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN,
45194
+ care: CH_MASK | B_HAS_SESSION | B_STATELESS_EN | B_STREAMABLE_EN,
45174
45195
  match: CH_POST_JSON | B_STATELESS_EN,
45175
45196
  outcome: { intent: "stateless-http", reason: "Stateless JSON request." }
45176
45197
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/sdk",
3
- "version": "1.0.0-beta.4",
3
+ "version": "1.0.0-beta.6",
4
4
  "description": "FrontMCP SDK",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -73,7 +73,7 @@
73
73
  "raw-body": "^3.0.0",
74
74
  "content-type": "^1.0.5",
75
75
  "@vercel/kv": "^3.0.0",
76
- "@frontmcp/storage-sqlite": "1.0.0-beta.4",
76
+ "@frontmcp/storage-sqlite": "1.0.0-beta.6",
77
77
  "@enclave-vm/core": "^2.11.1",
78
78
  "openai": "^4.0.0 || ^5.0.0 || ^6.0.0",
79
79
  "@anthropic-ai/sdk": "^0.30.0 || ^0.78.0"
@@ -97,12 +97,12 @@
97
97
  },
98
98
  "dependencies": {
99
99
  "@types/cors": "^2.8.17",
100
- "@frontmcp/utils": "1.0.0-beta.4",
101
- "@frontmcp/guard": "1.0.0-beta.4",
102
- "@frontmcp/di": "1.0.0-beta.4",
103
- "@frontmcp/uipack": "1.0.0-beta.4",
104
- "@frontmcp/auth": "1.0.0-beta.4",
105
- "@frontmcp/protocol": "1.0.0-beta.4",
100
+ "@frontmcp/utils": "1.0.0-beta.6",
101
+ "@frontmcp/guard": "1.0.0-beta.6",
102
+ "@frontmcp/di": "1.0.0-beta.6",
103
+ "@frontmcp/uipack": "1.0.0-beta.6",
104
+ "@frontmcp/auth": "1.0.0-beta.6",
105
+ "@frontmcp/protocol": "1.0.0-beta.6",
106
106
  "ioredis": "^5.8.0",
107
107
  "vectoriadb": "^2.1.3",
108
108
  "js-yaml": "^4.1.1",
@@ -36,6 +36,12 @@ export interface StreamableHTTPServerTransportOptions {
36
36
  * Callback when a session is closed.
37
37
  */
38
38
  onsessionclosed?: (sessionId?: string) => void | Promise<void>;
39
+ /**
40
+ * When true, the transport operates in stateless mode and recreates
41
+ * the internal WebStandardStreamableHTTPServerTransport for each request.
42
+ * This is needed because MCP SDK 1.26.0 enforces single-use for stateless transports.
43
+ */
44
+ isStateless?: boolean;
39
45
  }
40
46
  /**
41
47
  * StreamableHTTPServerTransport with session recreation support.
@@ -60,6 +66,12 @@ export declare class RecreateableStreamableHTTPServerTransport extends Streamabl
60
66
  * so we need to create fresh instances for each request.
61
67
  */
62
68
  private readonly _constructorOptions;
69
+ /**
70
+ * When true, the transport recreates the internal transport for each request.
71
+ * Decoupled from sessionIdGenerator so stateless transports can still
72
+ * provide a session ID (e.g., '__stateless__') in the response header.
73
+ */
74
+ private readonly _isStateless;
63
75
  constructor(options?: StreamableHTTPServerTransportOptions);
64
76
  /**
65
77
  * Returns whether the transport has been initialized.
@@ -1 +1 @@
1
- {"version":3,"file":"streamable-http-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/adapters/streamable-http-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,6BAA6B,EAA4C,MAAM,oBAAoB,CAAC;AAG7G,MAAM,WAAW,oCAAoC;IACnD;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAElC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;OAKG;IAEH,UAAU,CAAC,EAAE,GAAG,CAAC;IAEjB;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED;;;;;;;;;;GAUG;AACH,qBAAa,yCAA0C,SAAQ,6BAA6B;IAC1F;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAC,CAAS;IAEnC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAuC;gBAE/D,OAAO,GAAE,oCAAyC;IAK9D;;OAEG;IACH,IAAI,aAAa,IAAI,OAAO,CAK3B;IAED;;;OAGG;IACH,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED;;;;;;;;;;;;;OAaG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqB/C;;;;;OAKG;IAEH,OAAO,CAAC,eAAe;IAevB;;;;OAIG;IAEY,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA8B5E"}
1
+ {"version":3,"file":"streamable-http-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/adapters/streamable-http-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,6BAA6B,EAA4C,MAAM,oBAAoB,CAAC;AAG7G,MAAM,WAAW,oCAAoC;IACnD;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAElC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;OAKG;IAEH,UAAU,CAAC,EAAE,GAAG,CAAC;IAEjB;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,yCAA0C,SAAQ,6BAA6B;IAC1F;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAC,CAAS;IAEnC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAuC;IAE3E;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;gBAE3B,OAAO,GAAE,oCAAyC;IAM9D;;OAEG;IACH,IAAI,aAAa,IAAI,OAAO,CAK3B;IAED;;;OAGG;IACH,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED;;;;;;;;;;;;;OAaG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqB/C;;;;;OAKG;IAEH,OAAO,CAAC,eAAe;IAevB;;;;OAIG;IAEY,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CAiC5E"}
@@ -7,10 +7,12 @@ import { ServerResponse } from '../../common';
7
7
  import { RecreateableStreamableHTTPServerTransport } from './streamable-http-transport';
8
8
  import { ElicitResult, ElicitOptions } from '../../elicitation';
9
9
  /**
10
- * Stateless HTTP requests must be able to send multiple initialize calls without
11
- * tripping the MCP transport's "already initialized" guard. The upstream SDK
12
- * treats any transport with a session ID generator as stateful, so we disable
13
- * session generation entirely for stateless transports.
10
+ * Resolves the session ID generator for the transport.
11
+ *
12
+ * For stateless-http, returns a generator that always yields '__stateless__'
13
+ * so the MCP SDK sets the Mcp-Session-Id response header (required by the
14
+ * MCP spec for streamable HTTP). The per-request recreation logic uses the
15
+ * dedicated `isStateless` flag instead of checking sessionIdGenerator.
14
16
  */
15
17
  export declare const resolveSessionIdGenerator: (transportType: TransportType, sessionId: string) => (() => string) | undefined;
16
18
  export declare class TransportStreamableHttpAdapter extends LocalTransportAdapter<RecreateableStreamableHTTPServerTransport> {
@@ -1 +1 @@
1
- {"version":3,"file":"transport.streamable-http.adapter.d.ts","sourceRoot":"","sources":["../../../src/transport/adapters/transport.streamable-http.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAG9B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,yCAAyC,EAAE,MAAM,6BAA6B,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGhE;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACpC,eAAe,aAAa,EAC5B,WAAW,MAAM,KAChB,CAAC,MAAM,MAAM,CAAC,GAAG,SAEnB,CAAC;AAEF,qBAAa,8BAA+B,SAAQ,qBAAqB,CAAC,yCAAyC,CAAC;IACzG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,yCAAyC;IA6B1G,UAAU,CAAC,GAAG,EAAE,0BAA0B,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA4D/E,aAAa,CAAC,GAAG,EAAE,0BAA0B,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxF;;;;;;;;;;;;;;;;;OAiBG;IACG,iBAAiB,CAAC,CAAC,SAAS,OAAO,EACvC,gBAAgB,EAAE,SAAS,EAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,CAAC,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAiHlE;;;;;;;OAOG;IACM,iBAAiB,IAAI,IAAI;CAOnC"}
1
+ {"version":3,"file":"transport.streamable-http.adapter.d.ts","sourceRoot":"","sources":["../../../src/transport/adapters/transport.streamable-http.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAG9B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,yCAAyC,EAAE,MAAM,6BAA6B,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGhE;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,GACpC,eAAe,aAAa,EAC5B,WAAW,MAAM,KAChB,CAAC,MAAM,MAAM,CAAC,GAAG,SAEnB,CAAC;AAEF,qBAAa,8BAA+B,SAAQ,qBAAqB,CAAC,yCAAyC,CAAC;IACzG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,yCAAyC;IAgC1G,UAAU,CAAC,GAAG,EAAE,0BAA0B,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA4D/E,aAAa,CAAC,GAAG,EAAE,0BAA0B,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxF;;;;;;;;;;;;;;;;;OAiBG;IACG,iBAAiB,CAAC,CAAC,SAAS,OAAO,EACvC,gBAAgB,EAAE,SAAS,EAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,CAAC,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAiHlE;;;;;;;OAOG;IACM,iBAAiB,IAAI,IAAI;CAOnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"initialize-request.handler.d.ts","sourceRoot":"","sources":["../../../src/transport/mcp-handlers/initialize-request.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5G,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAmBrE,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,EAC/C,aAAa,EACb,KAAK,GACN,EAAE,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAyJrE"}
1
+ {"version":3,"file":"initialize-request.handler.d.ts","sourceRoot":"","sources":["../../../src/transport/mcp-handlers/initialize-request.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5G,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAwCrE,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,EAC/C,aAAa,EACb,KAAK,GACN,EAAE,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAgJrE"}