Fix MCP TypeScript SDK Next.js AppRouter Response Breakage: Hono Overwrites global.Response (v1.25.0–v1.25.2) Causing TypeError in Claude Desktop, Cursor, and Custom MCP Servers
Starting with @modelcontextprotocol/sdk v1.25.0 (December 2025), the introduction of @hono/node-server as a dependency causes global.Response to be silently overwritten when StreamableHTTPServerTransport is instantiated. Hono's default `overrideGlobalObjects: true` behavior replaces the native Response constructor with Hono's internal _Response class. This breaks any framework that extends or checks instanceof against the original Response — most notably Next.js AppRouter routes which use NextResponse (which extends Response). After the first MCP endpoint call, all Next.js API routes return `TypeError: Expected an instance of Response to be returned`. The bug also affects any web framework with custom Response subclasses, Express-based servers with response middleware, and Cloudflare Workers using MCP SDK alongside framework routes. ## Agent Decision Tree ``` 1. Is your app using @modelcontextprotocol/sdk AND a web framework (Next.js, Express, etc.)? ├─ NO → This issue does not apply. └─ YES → Continue to step 2. 2. Check SDK version: npm list @modelcontextprotocol/sdk ├─ Version < 1.25.0 → This issue does not apply (hono was introduced in v1.25.0). ├─ Version 1.25.0–1.25.2 → CONFIRMED: You are affected. Upgrade to v1.25.3+. └─ Version ≥ 1.25.3 → You should NOT be affected by THIS bug. Check for other causes. 3. Verify hono is in the dependency tree: npm ls @hono/node-server 2>&1 ├─ Found (exit 0) → hono is present. Check if overrideGlobalObjects is the issue. └─ Not found (exit 1) → hono is absent. This bug does not apply. 4. Confirm the bug: Run diagnostic script to check Response identity before/after transport init. └─ Response !== OriginalResponse after init → CONFIRMED. Apply fix. ``` MCP SDK maintainer mattzcarey (@cloudflare) confirmed the fix in v1.25.3 (January 20, 2026) by passing `overrideGlobalObjects: false` to getRequestListener() calls in NodeStreamableHTTPServerTransport. The fix commit (fafa0d14a4fb) landed sa...
Symptoms
- TypeError: Expected an instance of Response to be returned in Next.js AppRouter API routes after MCP SDK initialization
- NextResponse.json() responses fail instanceof Response check after StreamableHTTPServerTransport instantiation
- global.Response identity changes from native function Response() to Hono's class _Response after MCP SDK starts
- App works correctly before first MCP endpoint call, breaks immediately after
- Only one framework (app or MCP) works at a time on the same localhost port
- Response === OriginalResponse evaluates to false after MCP SDK initialization
Error signatures
TypeError: Expected an instance of Response to be returned
response instanceof Response: false
Response === OriginalResponse: false
NextResponse.prototype instanceof Response: false
Possible causes
- @modelcontextprotocol/sdk v1.25.0 (December 15, 2025) introduced @hono/node-server as a dependency for the new StreamableHTTPServerTransport, replacing the previous web-standard transport implementation
- @hono/node-server defaults to `overrideGlobalObjects: true` in its `getRequestListener()` function (documented behavior in hono's README). When StreamableHTTPServerTransport is instantiated, it calls `getRequestListener()` which silently replaces `globalThis.Response` with Hono's internal `_Response` class
- The global override happens during StreamableHTTPServerTransport instantiation — any code path that creates an MCP server transport triggers the bug regardless of whether the transport is actually used or if MCP endpoints are ever called
- Next.js AppRouter's `NextResponse` extends the original `globalThis.Response` at server startup time. When Hono overwrites `Response` AFTER startup, the prototype chain breaks: `NextResponse` instances inherit from the ORIGINAL Response (captured at startup), but runtime `instanceof` checks compare against the NEW Hono Response (set after SDK init). Since these are different constructors, all `instanceof Response` checks fail
- This is a 'global mutable state' conflict pattern: two libraries (Next.js and Hono) both depend on Response identity, but Hono's override breaks Next.js's assumption that Response is stable across the process lifetime
Solutions
Downgrade to @modelcontextprotocol/sdk v1.24.3 (Pre-Hono Baseline)
Versions prior to v1.25.0 do not include @hono/node-server and are not affected by this bug. Downgrading to the latest v1.24.x release (v1.24.3, published December 4, 2025) removes the hono dependency entirely, restoring the original Response behavior.
- Step 1: Uninstall current version — `npm uninstall @modelcontextprotocol/sdk`
- Step 2: Install last pre-hono version — `npm install @modelcontextprotocol/sdk@1.24.3`
- Step 3: Verify hono is NOT in the dependency tree — `npm ls @hono/node-server 2>&1; echo exit=$?` → expect exit code 1 (not found)
- Step 4: Test your app and MCP endpoints
Commands
npm uninstall @modelcontextprotocol/sdk
npm install @modelcontextprotocol/sdk@1.24.3
npm ls @hono/node-server 2>&1; echo exit=$?
Config examples
{
"dependencies": {
"@modelcontextprotocol/sdk": "1.24.3"
}
}Risks
- v1.24.x lacks StreamableHTTPServerTransport features introduced in v1.25.x including streaming improvements and transport enhancements
- May miss security patches or bug fixes released after December 2025
- Downgrade is a last resort — upgrading to v1.25.3+ is strongly preferred as it keeps all v1.25.x features while fixing the bug
Verification
- Step 1: Run `npm list @modelcontextprotocol/sdk 2>&1; echo exit=$?` → expect stdout contains '1.24.3', exit code 0
- Step 2: Run `npm ls @hono/node-server 2>&1; echo exit=$?` → expect exit code 1 (hono not found in tree). If exit code is 0, hono was pulled in by another dependency — investigate.
- Step 3: Start your server and test both Next.js AppRouter routes and MCP endpoints → expect: no TypeError, both systems operational simultaneously
Use webStandardStreamableHTTPServerTransport as Alternative (v1.25.x Workaround)
If you cannot immediately upgrade, use the `webStandardStreamableHTTPServerTransport` instead of `StreamableHTTPServerTransport`. This alternative transport does not depend on @hono/node-server and does not trigger the global Response override. This workaround was suggested by MCP SDK maintainer mattzcarey in the GitHub issue thread.
- Step 1: Replace import — change `StreamableHTTPServerTransport` to `webStandardStreamableHTTPServerTransport`
- Step 2: Update server initialization to use the webStandard variant (API is compatible)
- Step 3: Test both MCP endpoints and app routes simultaneously
- Step 4: Verify no TypeError occurs on Next.js AppRouter routes
Commands
grep -rn 'StreamableHTTPServerTransport' --include='*.ts' --include='*.js' . 2>/dev/null
grep -rn 'webStandardStreamableHTTPServerTransport' --include='*.ts' --include='*.js' . 2>/dev/null
Config examples
// Before (broken — imports hono-dependent transport):
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
// After (workaround — uses web-standard transport without hono):
import { webStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
// Use webStandardStreamableHTTPServerTransport for your server setupRisks
- webStandardStreamableHTTPServerTransport may have slightly different API surface in edge cases — verify your session handling and streaming code is compatible
- This is a temporary workaround; upgrading to v1.25.3+ is the permanent solution
Verification
- Step 1: After switching transports, run `grep -rn 'StreamableHTTPServerTransport[^W]' --include='*.ts' --include='*.js' . 2>/dev/null; echo exit=$?` → expect exit code 1 (no matches for old transport name, only webStandard variant should remain)
- Step 2: Start your server with the new transport and make a request to a Next.js AppRouter route → expect: response passes `instanceof Response` check, no TypeError in server output
- Step 3: Make a request to your MCP endpoint → expect: normal MCP protocol response, connection established
Upgrade @modelcontextprotocol/sdk to v1.25.3+ (Official Fix)
The MCP SDK v1.25.3 includes the official fix: `overrideGlobalObjects: false` is now passed to all `getRequestListener()` calls in NodeStreamableHTTPServerTransport, preventing Hono from overwriting `global.Response`. Upgrade your dependency and the bug is resolved without any code changes. The fix was committed by MCP SDK maintainer mattzcarey in commit fafa0d14a4fb on January 20, 2026.
- Step 1: Check current version — `npm list @modelcontextprotocol/sdk 2>&1`
- Step 2: If version is 1.25.0, 1.25.1, or 1.25.2, upgrade — `npm install @modelcontextprotocol/sdk@^1.25.3`
- Step 3: Verify the installed version — `npm list @modelcontextprotocol/sdk 2>&1; echo exit=$?` → expect stdout contains '@modelcontextprotocol/sdk@1.25.3' or higher, exit code 0
- Step 4: Restart your development server and test both app routes and MCP endpoints simultaneously
- Step 5: Verify Response identity is preserved — add diagnostic check after transport instantiation
Commands
npm list @modelcontextprotocol/sdk 2>&1; echo exit=$?
npm install @modelcontextprotocol/sdk@^1.25.3
npm view @modelcontextprotocol/sdk version 2>&1; echo exit=$?
npm ls @hono/node-server 2>&1; echo exit=$?
Config examples
{
"dependencies": {
"@modelcontextprotocol/sdk": "^1.25.3"
}
}Risks
- None — v1.25.3 is a patch release that only adds `overrideGlobalObjects: false` without breaking API changes. Forward-compatible with all v1.25.x APIs.
Verification
- Step 1: Run `npm list @modelcontextprotocol/sdk 2>&1; echo exit=$?` → expect stdout contains '@modelcontextprotocol/sdk@1.25.3' (or higher), exit code 0. If exit code is non-zero or version is < 1.25.3, the upgrade did not apply — abort and retry.
- Step 2: Run `npm ls @hono/node-server 2>&1; echo exit=$?` → expect exit code 0 (hono is present) AND version ^1.19.9 or higher. If hono is absent, the SDK install is incomplete.
- Step 3: Create a quick diagnostic script that captures `const OriginalResponse = globalThis.Response` before instantiating StreamableHTTPServerTransport, then checks `Response === OriginalResponse` after → expect: true. If false, the fix did not apply — the SDK may be cached or incorrectly resolved.
- Step 4: Start your Next.js dev server with MCP endpoint and make a request to an AppRouter API route → expect: normal JSON response, HTTP 200, no 'TypeError: Expected an instance of Response' in server logs
Agent JSON
Canonical machine-readable representation of this issue:
{
"issue_id": "e93102bb-ef82-4e0d-938e-1a6ef3822f07",
"slug": "fix-mcp-typescript-sdk-next-js-approuter-response-breakage-hono-overwrites-global-response-v1-25-0-v1-25-2-causing-typee-9dt142",
"verification_status": "unverified",
"canonical_json": "https://codekb.dev/v1/issues/fix-mcp-typescript-sdk-next-js-approuter-response-breakage-hono-overwrites-global-response-v1-25-0-v1-25-2-causing-typee-9dt142"
}