agents 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +24 -19
  2. package/dist/{agent-tool-types-BNUGGBzQ.d.ts → agent-tool-types-BC-WFlsz.d.ts} +1026 -400
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-BFbzVLFc.d.ts → agent-tools-DeHe9Xov.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/browser/ai.js +1 -1
  7. package/dist/browser/index.js +1 -1
  8. package/dist/chat/index.d.ts +2 -2
  9. package/dist/chat-sdk/index.d.ts +1 -1
  10. package/dist/client-invoker-BNSZxAkv.d.ts +20 -0
  11. package/dist/client-invoker-VNZ7X0nn.js +57 -0
  12. package/dist/client-invoker-VNZ7X0nn.js.map +1 -0
  13. package/dist/{client-CcjiFpTf.js → client-zqKcsyFa.js} +434 -168
  14. package/dist/client-zqKcsyFa.js.map +1 -0
  15. package/dist/client.d.ts +1 -1
  16. package/dist/cloudflare-BduZwmYK.js +204 -0
  17. package/dist/cloudflare-BduZwmYK.js.map +1 -0
  18. package/dist/{connector-CdldGF3h.js → connector-KEJnl6e5.js} +2 -2
  19. package/dist/connector-KEJnl6e5.js.map +1 -0
  20. package/dist/{do-oauth-client-provider-D4ZwyBDu.d.ts → do-oauth-client-provider-VTZj2VtM.d.ts} +23 -11
  21. package/dist/experimental/webmcp.js +1 -1
  22. package/dist/handler-stateless-CIkKPETH.js +318 -0
  23. package/dist/handler-stateless-CIkKPETH.js.map +1 -0
  24. package/dist/handler-stateless-C_bo-Ytq.d.ts +107 -0
  25. package/dist/index.d.ts +14 -12
  26. package/dist/index.js +30 -20
  27. package/dist/index.js.map +1 -1
  28. package/dist/mcp/client.d.ts +22 -18
  29. package/dist/mcp/client.js +1 -1
  30. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  31. package/dist/mcp/do-oauth-client-provider.js +25 -12
  32. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  33. package/dist/mcp/index.d.ts +48 -34
  34. package/dist/mcp/index.js +95 -156
  35. package/dist/mcp/index.js.map +1 -1
  36. package/dist/mcp/server.d.ts +17 -0
  37. package/dist/mcp/server.js +2 -0
  38. package/dist/mcp/x402.d.ts +21 -9
  39. package/dist/mcp/x402.js +8 -7
  40. package/dist/mcp/x402.js.map +1 -1
  41. package/dist/observability/ai/index.d.ts +9 -1
  42. package/dist/observability/ai/index.js +188 -63
  43. package/dist/observability/ai/index.js.map +1 -1
  44. package/dist/react.d.ts +1 -1
  45. package/dist/serializable.d.ts +1 -1
  46. package/dist/sub-routing.d.ts +6 -6
  47. package/dist/workflows.d.ts +1 -1
  48. package/docs/human-in-the-loop.md +63 -82
  49. package/docs/mcp-client.md +31 -7
  50. package/docs/mcp-servers.md +125 -88
  51. package/docs/observability.md +2 -1
  52. package/docs/securing-mcp-servers.md +9 -6
  53. package/package.json +28 -7
  54. package/dist/client-CcjiFpTf.js.map +0 -1
  55. package/dist/cloudflare-BldFV0Pa.js +0 -117
  56. package/dist/cloudflare-BldFV0Pa.js.map +0 -1
  57. package/dist/connector-CdldGF3h.js.map +0 -1
package/dist/mcp/index.js CHANGED
@@ -1,30 +1,24 @@
1
1
  import "../types.js";
2
- import { c as RPC_DO_PREFIX, i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, o as RPCClientTransport, s as RPCServerTransport } from "../client-CcjiFpTf.js";
2
+ import { c as RPC_DO_PREFIX, i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, o as RPCClientTransport, s as RPCServerTransport } from "../client-zqKcsyFa.js";
3
3
  import { Agent, getAgentByName, getCurrentAgent } from "../index.js";
4
- import { AsyncLocalStorage } from "node:async_hooks";
5
- import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
6
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
7
- import { ElicitRequestSchema, InitializeRequestSchema, JSONRPCMessageSchema, isInitializeRequest, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResultResponse } from "@modelcontextprotocol/sdk/types.js";
8
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4
+ import { n as getMcpAuthContext, r as runWithAuthContext, t as createStatelessMcpHandler } from "../handler-stateless-CIkKPETH.js";
5
+ import { SSEClientTransport, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
6
+ import { ElicitRequestSchema, InitializeRequestSchema, JSONRPCMessageSchema, SUPPORTED_PROTOCOL_VERSIONS, isInitializeRequest, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResultResponse } from "@modelcontextprotocol/sdk/types.js";
7
+ import { McpServer, Server } from "@modelcontextprotocol/server";
8
+ import { McpServer as McpServer$1 } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { Server as Server$1 } from "@modelcontextprotocol/sdk/server/index.js";
10
+ import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport$1 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
10
11
  //#region src/mcp/sse-keepalive.ts
11
12
  /**
12
- * Shared SSE keepalive utility for MCP transports.
13
+ * SSE keepalive for the retained McpAgent WebSocket-to-SSE bridge.
13
14
  *
14
- * Cloudflare's edge closes idle SSE responses after ~5 minutes. Writers
15
- * that may sit silent for that long (long-running tool calls, idle
16
- * standalone GET streams) arm a keepalive to keep the response under the
17
- * watchdog.
15
+ * SDK-backed HTTP transports own their keepalive timers. This helper remains
16
+ * only for the custom bridge, where long-running POST tool calls can otherwise
17
+ * sit silent until Cloudflare's edge closes the idle stream.
18
18
  *
19
19
  * See cloudflare/agents#1583.
20
20
  */
21
- /** Interval between SSE keepalive comment frames, in ms.
22
- *
23
- * The WHATWG SSE spec recommends a comment line every "15 seconds or so"
24
- * (html.spec.whatwg.org §9.2.7). 25s gives comfortable headroom below
25
- * both the ~30s post-handler background-work cancellation window on
26
- * Workers and the ~5min Cloudflare edge idle-stream watchdog.
27
- */
21
+ /** Interval between bridge SSE keepalive comment frames, in ms. */
28
22
  const KEEPALIVE_INTERVAL_MS = 25e3;
29
23
  /** SSE comment frame the parser drops before any event dispatch. */
30
24
  const KEEPALIVE_FRAME = ": keepalive\n\n";
@@ -54,6 +48,18 @@ const MCP_HTTP_METHOD_HEADER = "cf-mcp-method";
54
48
  */
55
49
  const MCP_MESSAGE_HEADER = "cf-mcp-message";
56
50
  const MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024;
51
+ function unsupportedProtocolVersionResponse(request) {
52
+ const protocolVersion = request.headers.get("mcp-protocol-version");
53
+ if (protocolVersion === null || SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) return;
54
+ return Response.json({
55
+ error: {
56
+ code: -32e3,
57
+ message: `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`
58
+ },
59
+ id: null,
60
+ jsonrpc: "2.0"
61
+ }, { status: 400 });
62
+ }
57
63
  const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
58
64
  let pathname = basePath;
59
65
  if (basePath === "/") pathname = "/*";
@@ -151,6 +157,10 @@ const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
151
157
  });
152
158
  return new Response(body, { status: 400 });
153
159
  }
160
+ if (!maybeInitializeRequest) {
161
+ const unsupportedVersion = unsupportedProtocolVersionResponse(request);
162
+ if (unsupportedVersion) return unsupportedVersion;
163
+ }
154
164
  if (!maybeInitializeRequest && !sessionId) {
155
165
  const body = JSON.stringify({
156
166
  error: {
@@ -279,6 +289,8 @@ const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
279
289
  id: null,
280
290
  jsonrpc: "2.0"
281
291
  }), { status: 400 });
292
+ const unsupportedVersion = unsupportedProtocolVersionResponse(request);
293
+ if (unsupportedVersion) return unsupportedVersion;
282
294
  const { readable, writable } = new TransformStream();
283
295
  const writer = writable.getWriter();
284
296
  const encoder = new TextEncoder();
@@ -338,6 +350,8 @@ const createStreamingHttpHandler = (basePath, namespace, options = {}) => {
338
350
  status: 200
339
351
  });
340
352
  } else if (request.method === "DELETE") {
353
+ const unsupportedVersion = unsupportedProtocolVersionResponse(request);
354
+ if (unsupportedVersion) return unsupportedVersion;
341
355
  const sessionId = request.headers.get("mcp-session-id");
342
356
  if (!sessionId) return new Response(JSON.stringify({
343
357
  jsonrpc: "2.0",
@@ -980,36 +994,36 @@ DurableObjectEventStore.REPLAY_LIMIT = 1e3;
980
994
  */
981
995
  let didWarnAboutSSEEdgeClientTransport = false;
982
996
  /**
983
- * @deprecated Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. This alias will be removed in the next major version.
997
+ * @deprecated Use SSEClientTransport from @modelcontextprotocol/client instead. This alias will be removed in the next major version.
984
998
  */
985
999
  var SSEEdgeClientTransport = class extends SSEClientTransport {
986
1000
  constructor(url, options) {
987
1001
  super(url, options);
988
1002
  if (!didWarnAboutSSEEdgeClientTransport) {
989
1003
  didWarnAboutSSEEdgeClientTransport = true;
990
- console.warn("SSEEdgeClientTransport is deprecated. Use SSEClientTransport from @modelcontextprotocol/sdk/client/sse.js instead. SSEEdgeClientTransport will be removed in the next major version.");
1004
+ console.warn("SSEEdgeClientTransport is deprecated. Use SSEClientTransport from @modelcontextprotocol/client instead. SSEEdgeClientTransport will be removed in the next major version.");
991
1005
  }
992
1006
  }
993
1007
  };
994
1008
  let didWarnAboutStreamableHTTPEdgeClientTransport = false;
995
1009
  /**
996
- * @deprecated Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. This alias will be removed in the next major version.
1010
+ * @deprecated Use StreamableHTTPClientTransport from @modelcontextprotocol/client instead. This alias will be removed in the next major version.
997
1011
  */
998
1012
  var StreamableHTTPEdgeClientTransport = class extends StreamableHTTPClientTransport {
999
1013
  constructor(url, options) {
1000
1014
  super(url, options);
1001
1015
  if (!didWarnAboutStreamableHTTPEdgeClientTransport) {
1002
1016
  didWarnAboutStreamableHTTPEdgeClientTransport = true;
1003
- console.warn("StreamableHTTPEdgeClientTransport is deprecated. Use StreamableHTTPClientTransport from @modelcontextprotocol/sdk/client/streamableHttp.js instead. StreamableHTTPEdgeClientTransport will be removed in the next major version.");
1017
+ console.warn("StreamableHTTPEdgeClientTransport is deprecated. Use StreamableHTTPClientTransport from @modelcontextprotocol/client instead. StreamableHTTPEdgeClientTransport will be removed in the next major version.");
1004
1018
  }
1005
1019
  }
1006
1020
  };
1007
1021
  //#endregion
1008
1022
  //#region src/mcp/worker-transport.ts
1009
1023
  /**
1010
- * WorkerTransport
1024
+ * WorkerTransport — retained sessionful Legacy transport
1011
1025
  *
1012
- * Thin Cloudflare-Workers wrapper around the official MCP SDK
1026
+ * Thin Cloudflare-Workers wrapper around the official MCP SDK v1
1013
1027
  * `WebStandardStreamableHTTPServerTransport`. The wrapper layers a couple of
1014
1028
  * Workers-specific concerns on top of the SDK transport without forking it:
1015
1029
  *
@@ -1021,15 +1035,12 @@ var StreamableHTTPEdgeClientTransport = class extends StreamableHTTPClientTransp
1021
1035
  * survive DO hibernation / eviction. On the first request after a cold
1022
1036
  * start, the saved initialize params are replayed through the `Server`
1023
1037
  * so client capabilities are re-established.
1024
- * 3. **SSE keepalive** — SSE responses are wrapped in a TransformStream that
1025
- * injects a `: keepalive\n\n` comment frame every 25s so the Cloudflare
1026
- * edge ~5min idle-stream watchdog doesn't kill long-running tool calls.
1027
- * Disabled on the standalone GET stream when an `eventStore` is
1028
- * configured — clients recover idle drops via `Last-Event-ID` instead.
1029
- * POST response streams always keepalive (no resumption path during a
1030
- * mid-flight tool call). See cloudflare/agents#1583.
1038
+ * 3. **SSE keepalive** — delegated to the SDK transport, which writes SSE
1039
+ * comment frames and owns timer cleanup. Configure the cadence with the
1040
+ * inherited `keepAliveMs` option.
1031
1041
  *
1032
- * Everything else (session validation, SSE streaming, protocol-version
1042
+ * Stateless handlers do not import this module. Everything else (session
1043
+ * validation, SSE streaming, protocol-version
1033
1044
  * negotiation, event-store resumability, etc.) is delegated to the SDK
1034
1045
  * transport.
1035
1046
  */
@@ -1042,7 +1053,7 @@ const DEFAULT_CORS_OPTIONS = {
1042
1053
  exposeHeaders: "mcp-session-id",
1043
1054
  maxAge: 86400
1044
1055
  };
1045
- var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1056
+ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport$1 {
1046
1057
  constructor(options = {}) {
1047
1058
  const { corsOptions, storage, onsessioninitialized, ...sdkOptions } = options;
1048
1059
  super({
@@ -1051,7 +1062,6 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1051
1062
  });
1052
1063
  this._stateRestored = false;
1053
1064
  this._bridgeInstalled = false;
1054
- this._keepaliveCleanups = /* @__PURE__ */ new Map();
1055
1065
  this._closedRequestIds = /* @__PURE__ */ new Set();
1056
1066
  this._corsOptions = corsOptions;
1057
1067
  this._storage = storage;
@@ -1067,17 +1077,15 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1067
1077
  /**
1068
1078
  * Top-level request entry point. Handles CORS preflight, restores any
1069
1079
  * persisted state on first invocation, then delegates to the SDK transport
1070
- * and finally appends CORS headers + keepalive to whatever response comes
1071
- * back.
1080
+ * and finally appends CORS headers to whatever response comes back.
1072
1081
  */
1073
1082
  async handleRequest(request, options) {
1074
1083
  if (request.method === "OPTIONS") return new Response(null, { headers: this.getCorsHeaders({ forPreflight: true }) });
1075
1084
  await this.restoreState();
1076
1085
  this.installOnSessionInitializedBridge();
1077
1086
  await this.captureInitializeParams(request, options);
1078
- const requestIdForKeepalive = request.method === "GET" ? "_standalone" : this._pendingRequestId;
1079
1087
  const response = await super.handleRequest(request, options);
1080
- return this.withCorsHeaders(this.withKeepalive(this.normalizeAllowHeader(response), requestIdForKeepalive));
1088
+ return this.withCorsHeaders(this.normalizeAllowHeader(response));
1081
1089
  }
1082
1090
  /**
1083
1091
  * The SDK's 405 responses advertise `Allow: GET, POST, DELETE` because
@@ -1097,19 +1105,10 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1097
1105
  });
1098
1106
  }
1099
1107
  closeSSEStream(requestId) {
1100
- this._keepaliveCleanups.get(requestId)?.();
1101
- this._keepaliveCleanups.delete(requestId);
1102
1108
  this._closedRequestIds.add(requestId);
1103
1109
  super.closeSSEStream(requestId);
1104
1110
  }
1105
- closeStandaloneSSEStream() {
1106
- this._keepaliveCleanups.get("_standalone")?.();
1107
- this._keepaliveCleanups.delete("_standalone");
1108
- super.closeStandaloneSSEStream();
1109
- }
1110
1111
  async close() {
1111
- for (const cleanup of Array.from(this._keepaliveCleanups.values())) cleanup();
1112
- this._keepaliveCleanups.clear();
1113
1112
  this._closedRequestIds.clear();
1114
1113
  await super.close();
1115
1114
  }
@@ -1139,77 +1138,6 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1139
1138
  if (requestId !== void 0 && this._closedRequestIds.has(requestId)) return;
1140
1139
  await super.send(message, options);
1141
1140
  }
1142
- /**
1143
- * If the response is an SSE stream, tee the body through a TransformStream
1144
- * that injects a `: keepalive\n\n` comment frame every 25s. The interval
1145
- * is cleared when the wrapped stream closes — which happens both when the
1146
- * SDK ends the underlying stream naturally and when `closeSSEStream` is
1147
- * called.
1148
- *
1149
- * Keepalive policy:
1150
- * - POST response streams (`key` is a request id): always keepalive.
1151
- * In-progress tool calls have no recovery path — if the stream drops
1152
- * mid-execution the result is lost — so we keep it under the
1153
- * Cloudflare edge ~5min idle watchdog.
1154
- * - Standalone GET stream (`key === "_standalone"`): keepalive only
1155
- * when no `eventStore` is configured. When resumability is enabled,
1156
- * clients reconnect with `Last-Event-ID` after an idle drop, so we
1157
- * skip the keepalive and let the DO hibernate.
1158
- *
1159
- * Uses the shared `sse-keepalive` constants so both this wrapper and
1160
- * `McpAgent.serve()` write identical frames at the same cadence.
1161
- * See cloudflare/agents#1583.
1162
- */
1163
- withKeepalive(response, key) {
1164
- if (!(response.headers.get("Content-Type") ?? "").includes("text/event-stream") || !response.body) return response;
1165
- if (key === "_standalone" && this.eventStoreConfigured()) return response;
1166
- const encoder = new TextEncoder();
1167
- let intervalId;
1168
- let controllerRef;
1169
- const clear = () => {
1170
- if (intervalId !== void 0) {
1171
- clearInterval(intervalId);
1172
- intervalId = void 0;
1173
- }
1174
- if (key !== void 0) this._keepaliveCleanups.delete(key);
1175
- };
1176
- const transform = new TransformStream({
1177
- start: (controller) => {
1178
- controllerRef = controller;
1179
- intervalId = setInterval(() => {
1180
- try {
1181
- controllerRef?.enqueue(encoder.encode(KEEPALIVE_FRAME));
1182
- } catch {
1183
- clear();
1184
- }
1185
- }, KEEPALIVE_INTERVAL_MS);
1186
- if (key !== void 0) this._keepaliveCleanups.set(key, clear);
1187
- },
1188
- transform(chunk, controller) {
1189
- controller.enqueue(chunk);
1190
- },
1191
- flush() {
1192
- clear();
1193
- },
1194
- cancel() {
1195
- clear();
1196
- }
1197
- });
1198
- const piped = response.body.pipeThrough(transform);
1199
- return new Response(piped, {
1200
- status: response.status,
1201
- statusText: response.statusText,
1202
- headers: response.headers
1203
- });
1204
- }
1205
- /**
1206
- * Does the SDK transport have an `eventStore`? Reaches into the SDK's
1207
- * private field because the option isn't surfaced on the public API —
1208
- * we only need a yes/no for keepalive policy.
1209
- */
1210
- eventStoreConfigured() {
1211
- return this._eventStore !== void 0;
1212
- }
1213
1141
  getCorsHeaders({ forPreflight } = {}) {
1214
1142
  const merged = {
1215
1143
  ...DEFAULT_CORS_OPTIONS,
@@ -1245,19 +1173,15 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1245
1173
  this._bridgeInstalled = true;
1246
1174
  }
1247
1175
  async captureInitializeParams(request, handleOptions) {
1248
- this._pendingRequestId = void 0;
1249
1176
  if (request.method !== "POST") return;
1250
1177
  try {
1251
1178
  const parsed = handleOptions?.parsedBody ?? await request.clone().json();
1252
- const messages = Array.isArray(parsed) ? parsed : [parsed];
1253
- const init = messages.find((m) => typeof m === "object" && m !== null && isInitializeRequest(m));
1179
+ const init = (Array.isArray(parsed) ? parsed : [parsed]).find((m) => typeof m === "object" && m !== null && isInitializeRequest(m));
1254
1180
  if (init && isInitializeRequest(init)) this._capturedInitializeParams = {
1255
1181
  capabilities: init.params.capabilities,
1256
1182
  clientInfo: init.params.clientInfo,
1257
1183
  protocolVersion: init.params.protocolVersion
1258
1184
  };
1259
- const firstRequest = messages.find((m) => typeof m === "object" && m !== null && "id" in m && "method" in m);
1260
- if (firstRequest) this._pendingRequestId = firstRequest.id;
1261
1185
  } catch {}
1262
1186
  }
1263
1187
  async restoreState() {
@@ -1294,67 +1218,81 @@ var WorkerTransport = class extends WebStandardStreamableHTTPServerTransport {
1294
1218
  }
1295
1219
  };
1296
1220
  //#endregion
1297
- //#region src/mcp/auth-context.ts
1298
- const authContextStorage = new AsyncLocalStorage();
1299
- function getMcpAuthContext() {
1300
- return authContextStorage.getStore();
1301
- }
1302
- function runWithAuthContext(context, fn) {
1303
- return authContextStorage.run(context, fn);
1304
- }
1305
- //#endregion
1306
- //#region src/mcp/handler.ts
1307
- function createMcpHandler(server, options = {}) {
1221
+ //#region src/mcp/handler-legacy.ts
1222
+ /**
1223
+ * Create a sessionful Legacy MCP handler backed by SDK v1.
1224
+ *
1225
+ * New Stateless servers should use `createMcpHandler` from
1226
+ * `agents/mcp/server` instead.
1227
+ */
1228
+ function createLegacyMcpHandler(server, options = {}) {
1308
1229
  const route = options.route ?? "/mcp";
1309
1230
  const { route: _route, authContext, transport: providedTransport, ...transportOptions } = options;
1310
1231
  return async (request, _env, ctx) => {
1311
1232
  const url = new URL(request.url);
1312
1233
  if (route && url.pathname !== route) return new Response("Not Found", { status: 404 });
1313
1234
  const transport = providedTransport ?? new WorkerTransport(transportOptions);
1314
- const buildAuthContext = () => {
1315
- if (authContext) return authContext;
1316
- if (ctx.props && Object.keys(ctx.props).length > 0) return { props: ctx.props };
1317
- };
1318
- const handleRequest = async () => {
1319
- return await transport.handleRequest(request);
1320
- };
1321
- const resolvedAuthContext = buildAuthContext();
1235
+ const resolvedAuthContext = authContext ?? (ctx.props && Object.keys(ctx.props).length > 0 ? { props: ctx.props } : void 0);
1322
1236
  if (!transport.started) {
1323
- if (server instanceof McpServer ? server.isConnected() : server.transport !== void 0) throw new Error("Server is already connected to a transport. Create a new McpServer instance per request for stateless handlers.");
1237
+ if (server instanceof McpServer$1 ? server.isConnected() : server.transport !== void 0) throw new Error("Server is already connected to a transport. Create a new McpServer instance per request for stateless handlers.");
1324
1238
  await server.connect(transport);
1325
1239
  }
1240
+ const handleRequest = () => transport.handleRequest(request);
1326
1241
  try {
1327
- if (resolvedAuthContext) return await runWithAuthContext(resolvedAuthContext, handleRequest);
1328
- else return await handleRequest();
1242
+ return resolvedAuthContext ? await runWithAuthContext(resolvedAuthContext, handleRequest) : await handleRequest();
1329
1243
  } catch (error) {
1330
1244
  console.error("MCP handler error:", error);
1331
- return new Response(JSON.stringify({
1245
+ return Response.json({
1332
1246
  jsonrpc: "2.0",
1333
1247
  error: {
1334
1248
  code: -32603,
1335
1249
  message: error instanceof Error ? error.message : "Internal server error"
1336
1250
  },
1337
1251
  id: null
1338
- }), {
1339
- status: 500,
1340
- headers: { "Content-Type": "application/json" }
1341
- });
1252
+ }, { status: 500 });
1342
1253
  }
1343
1254
  };
1344
1255
  }
1256
+ //#endregion
1257
+ //#region src/mcp/handler-warning.ts
1258
+ let didWarnAboutLegacyCreateMcpHandlerOverload = false;
1259
+ function warnLegacyCreateMcpHandlerOverload() {
1260
+ if (didWarnAboutLegacyCreateMcpHandlerOverload) return;
1261
+ didWarnAboutLegacyCreateMcpHandlerOverload = true;
1262
+ console.warn("[agents/mcp] Passing an MCP SDK v1 server to createMcpHandler is deprecated and will be removed in the next major version. Pass an @modelcontextprotocol/server factory to createMcpHandler. To temporarily retain sessionful SDK v1 behavior while migrating, use createLegacyMcpHandler.");
1263
+ }
1264
+ //#endregion
1265
+ //#region src/mcp/handler-compat.ts
1266
+ function createMcpHandler(serverOrFactory, options = {}) {
1267
+ if (typeof serverOrFactory === "function") return createStatelessMcpHandler(serverOrFactory, options);
1268
+ if (serverOrFactory instanceof McpServer$1 || serverOrFactory instanceof Server$1) {
1269
+ warnLegacyCreateMcpHandlerOverload();
1270
+ return createLegacyMcpHandler(serverOrFactory, options);
1271
+ }
1272
+ throw new TypeError("createMcpHandler received an unsupported server. Pass a factory returning McpServer or Server from \"@modelcontextprotocol/server\", or use createLegacyMcpHandler with an MCP SDK v1 server.");
1273
+ }
1345
1274
  let didWarnAboutExperimentalCreateMcpHandler = false;
1346
1275
  /**
1347
- * @deprecated This has been renamed to createMcpHandler, and experimental_createMcpHandler will be removed in the next major version
1276
+ * @deprecated Pass an SDK v2 factory to createMcpHandler.
1277
+ * experimental_createMcpHandler will be removed in the next major version.
1278
+ * Use createLegacyMcpHandler only to temporarily retain sessionful SDK v1
1279
+ * behavior while migrating.
1348
1280
  */
1349
1281
  function experimental_createMcpHandler(server, options = {}) {
1350
1282
  if (!didWarnAboutExperimentalCreateMcpHandler) {
1351
1283
  didWarnAboutExperimentalCreateMcpHandler = true;
1352
- console.warn("experimental_createMcpHandler is deprecated, use createMcpHandler instead. experimental_createMcpHandler will be removed in the next major version.");
1284
+ console.warn("experimental_createMcpHandler is deprecated and will be removed in the next major version. Pass an @modelcontextprotocol/server factory to createMcpHandler. To temporarily retain sessionful SDK v1 behavior while migrating, use createLegacyMcpHandler.");
1353
1285
  }
1354
- return createMcpHandler(server, options);
1286
+ return createLegacyMcpHandler(server, options);
1355
1287
  }
1356
1288
  //#endregion
1357
- //#region src/mcp/index.ts
1289
+ //#region src/mcp/legacy-agent.ts
1290
+ /**
1291
+ * @deprecated McpAgent is feature-frozen. Migrate to an SDK v2 factory with
1292
+ * createMcpHandler from agents/mcp/server. When sessionful features prevent an
1293
+ * immediate migration, run the stateless route beside the existing McpAgent
1294
+ * route until clients transition and sessions drain.
1295
+ */
1358
1296
  var McpAgent = class McpAgent extends Agent {
1359
1297
  constructor(..._args) {
1360
1298
  super(..._args);
@@ -1502,6 +1440,7 @@ var McpAgent = class McpAgent extends Agent {
1502
1440
  else this.props = await this.ctx.storage.get("props");
1503
1441
  await this.init();
1504
1442
  const server = await this.server;
1443
+ if (server instanceof McpServer || server instanceof Server) throw new TypeError("McpAgent uses MCP SDK v1 and cannot serve McpServer from \"@modelcontextprotocol/server\". For MCP SDK v2, use createMcpHandler. Existing McpAgent applications should continue importing McpServer from \"@modelcontextprotocol/sdk/server/mcp.js\".");
1505
1444
  this._transport = this.initTransport();
1506
1445
  if (!this._transport) throw new Error("Failed to initialize transport");
1507
1446
  await server.connect(this._transport);
@@ -1698,6 +1637,6 @@ var McpAgent = class McpAgent extends Agent {
1698
1637
  };
1699
1638
  McpAgent.STREAM_REQS_KEY_PREFIX = "__mcp_stream_reqs__:";
1700
1639
  //#endregion
1701
- export { DurableObjectEventStore, ElicitRequestSchema, MCP_SERVER_ID_MAX_LENGTH, McpAgent, RPCClientTransport, RPCServerTransport, RPC_DO_PREFIX, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport, WorkerTransport, createMcpHandler, experimental_createMcpHandler, getMcpAuthContext, normalizeServerId };
1640
+ export { DurableObjectEventStore, ElicitRequestSchema, MCP_SERVER_ID_MAX_LENGTH, McpAgent, RPCClientTransport, RPCServerTransport, RPC_DO_PREFIX, SSEEdgeClientTransport, StreamableHTTPEdgeClientTransport, WorkerTransport, createLegacyMcpHandler, createMcpHandler, experimental_createMcpHandler, getMcpAuthContext, normalizeServerId };
1702
1641
 
1703
1642
  //# sourceMappingURL=index.js.map