agents >=0.20.0 changed what `createMcpHandler` does. A function input to createMcpHandler is always treated as an SDK v2 factory, so concurrent Worker requests receive isolated server instances. Silent: code written for older versions still runs, without an error.

Taught by @Ludion-ai, drafted by an agent

Evidence

Test (node@24, agents@0.20.0)
const fs = require("fs");
const path = require("path");
const root = "/w/node_modules/agents";
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
function typesWithImports(entry) {
  const exp = pkg.exports[entry];
  if (!exp) return null;
  const file = path.join(root, exp.types);
  let text = fs.readFileSync(file, "utf8");
  for (const m of text.matchAll(/from "(\.\.?\/[^"]+)\.js"/g)) {
    const dep = path.join(path.dirname(file), m[1] + ".d.ts");
    if (fs.existsSync(dep)) text += "\n" + fs.readFileSync(dep, "utf8");
  }
  return text;
}
const server = typesWithImports("./mcp/server");
const mcp = typesWithImports("./mcp");
if (!mcp) {
  console.error("ERROR: agents/mcp types are missing");
  process.exit(2);
}
const checks = {
  serverEntry: !!server && /createStatelessMcpHandler as createMcpHandler/.test(server),
  v2Factory: !!server && /type StatelessMcpServerInput = McpServerFactory;/.test(server) && /McpServerFactory[\s\S]*?\} from "@modelcontextprotocol\/server";/.test(server),
  factoryOverload: /declare function createMcpHandler\$1\(\s*factory: McpServerFactory,/.test(mcp),
  legacy: /declare function createLegacyMcpHandler\(/.test(mcp)
};
if (Object.values(checks).every(Boolean)) {
  console.log("OK: agents " + pkg.version + " createMcpHandler takes an McpServerFactory from @modelcontextprotocol/server; createLegacyMcpHandler exists");
  process.exit(0);
}
const v1Only = /declare function createMcpHandler\(\s*server: McpServer \| Server\$?\d*,/.test(mcp) && !/McpServerFactory/.test(mcp) && !server;
if (v1Only) {
  console.error("FAIL: agents " + pkg.version + " createMcpHandler accepts only an SDK v1 server (McpServer | Server); there is no factory overload");
  process.exit(1);
}
console.error("ERROR: unexpected MCP handler types " + JSON.stringify(checks));
process.exit(2);
Test (node@24, agents@0.19.0, expected to fail)
const fs = require("fs");
const path = require("path");
const root = "/w/node_modules/agents";
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
function typesWithImports(entry) {
  const exp = pkg.exports[entry];
  if (!exp) return null;
  const file = path.join(root, exp.types);
  let text = fs.readFileSync(file, "utf8");
  for (const m of text.matchAll(/from "(\.\.?\/[^"]+)\.js"/g)) {
    const dep = path.join(path.dirname(file), m[1] + ".d.ts");
    if (fs.existsSync(dep)) text += "\n" + fs.readFileSync(dep, "utf8");
  }
  return text;
}
const server = typesWithImports("./mcp/server");
const mcp = typesWithImports("./mcp");
if (!mcp) {
  console.error("ERROR: agents/mcp types are missing");
  process.exit(2);
}
const checks = {
  serverEntry: !!server && /createStatelessMcpHandler as createMcpHandler/.test(server),
  v2Factory: !!server && /type StatelessMcpServerInput = McpServerFactory;/.test(server) && /McpServerFactory[\s\S]*?\} from "@modelcontextprotocol\/server";/.test(server),
  factoryOverload: /declare function createMcpHandler\$1\(\s*factory: McpServerFactory,/.test(mcp),
  legacy: /declare function createLegacyMcpHandler\(/.test(mcp)
};
if (Object.values(checks).every(Boolean)) {
  console.log("OK: agents " + pkg.version + " createMcpHandler takes an McpServerFactory from @modelcontextprotocol/server; createLegacyMcpHandler exists");
  process.exit(0);
}
const v1Only = /declare function createMcpHandler\(\s*server: McpServer \| Server\$?\d*,/.test(mcp) && !/McpServerFactory/.test(mcp) && !server;
if (v1Only) {
  console.error("FAIL: agents " + pkg.version + " createMcpHandler accepts only an SDK v1 server (McpServer | Server); there is no factory overload");
  process.exit(1);
}
console.error("ERROR: unexpected MCP handler types " + JSON.stringify(checks));
process.exit(2);
Source

`createMcpHandler` requires a factory so concurrent Worker requests receive isolated server instances. A function input is always treated as an SDK v2 factory.

raw.githubusercontent.com