Skip to content

fix(mcp): restore Bun version negotiation#2375

Merged
andybevan-scope3 merged 1 commit into
adcontextprotocol:mainfrom
sangilish:agent/fix-mcp-version-negotiation-regression
Jul 23, 2026
Merged

fix(mcp): restore Bun version negotiation#2375
andybevan-scope3 merged 1 commit into
adcontextprotocol:mainfrom
sangilish:agent/fix-mcp-version-negotiation-regression

Conversation

@sangilish

Copy link
Copy Markdown
Contributor

Summary

  • apply the per-file ESM Node shim to protocol transport modules as an explicit allowlist
  • add a clean-room Bun 1.3.8 smoke test that installs the packed artifact and completes modern MCP negotiation plus a tool call
  • preserve the browser-safe @adcp/sdk/enums bundle check

Root cause

The 12.0.1 conditional shim only covered source files that directly referenced __dirname or require. The MCP protocol modules do not contain those references themselves, but Bun needs the createRequire binding when loading their dual ESM/CJS dependency graph. Removing the former blanket banner therefore made the packed ESM artifact fail while loading MCP dependencies before negotiation could complete.

This keeps the conditional build introduced for browser consumers and adds a narrow protocol-directory allowlist instead of restoring the global banner.

Validation

  • npm run build:lib
  • NODE_ENV=test npx --yes node@20 --test-timeout=60000 --test-force-exit --test test/lib/mcp-modern-negotiation.test.js
  • NODE_ENV=test npx --yes node@20 --test-timeout=60000 --test-force-exit --test test/read-path-abort-timeout.test.js
  • npm run verify:package
  • npm run check:package
  • npm run typecheck
  • targeted Prettier check
  • git diff --check
  • repository pre-push validation

Fixes #2369.

@sangilish
sangilish force-pushed the agent/fix-mcp-version-negotiation-regression branch from a5aeced to 87892f0 Compare July 18, 2026 21:47
@sangilish
sangilish marked this pull request as ready for review July 18, 2026 21:52
@sangilish

Copy link
Copy Markdown
Contributor Author

All checks are green and the change remains scoped to the Bun transport-version negotiation regression. No further changes are planned; this is ready for review.

@andybevan-scope3

Copy link
Copy Markdown
Collaborator

getting this reviewed today

@andybevan-scope3

Copy link
Copy Markdown
Collaborator

Approving. This is a well-scoped fix with a genuine regression test.

Problem: The 12.0.1 change (adcp#2364) narrowed the ESM createRequire/__dirname shim to only files whose own source references require( or __dirname, to keep node:url/node:path/node:module out of pure-data modules that browser bundlers can’t resolve. The MCP protocol modules don’t reference those in their own bodies, but their dual ESM/CJS dependencies need the createRequire binding to load under Bun. Node tolerated the missing shim; Bun did not, so the packed ESM artifact broke during MCP negotiation while every Node test stayed green.

Fix: Always apply the shim to files under src/lib/protocols/, layered on top of the existing require/__dirname detection. Restores the shim where Bun needs it without reintroducing the browser-bundle breakage, since the protocols directory is node-only.

What I verified:

The shim condition is correct, and the path check uses nodePath.sep so it’s cross-platform.
No protocol source file declares a top-level require/__dirname, so the injected banner can’t collide.
Browser safety is intact: the only browser-safe entry (@adcp/sdk/enums) doesn’t pull protocol modules, and the smoke test still runs the --platform=browser bundle check.
The new Bun smoke test’s server harness and callMCPTool call exactly match the existing test/lib/mcp-modern-negotiation.test.js, and it exercises the packed artifact through a real modern MCP initialize + tool call under Bun. This is precisely the cross-runtime path the Node-only suite missed.
Changeset present (patch).
One optional note (non-blocking): the allowlist covers the whole protocols/ directory, so pure-logic modules (abort.ts, responseSizeLimit.ts, rawResponseCapture.ts, transportDiagnostics.ts) also pick up node built-ins they don’t use. It’s defensible (node-only today, robust against new MCP modules) but slightly broader than the three modules that actually need it. Worth a one-line comment explaining the directory-wide scope. Ship it.

@andybevan-scope3
andybevan-scope3 merged commit 74c68df into adcontextprotocol:main Jul 23, 2026
32 checks passed
@bokelley

Copy link
Copy Markdown
Contributor

Thanks for the thorough review. Applied your optional note — added a one-liner above the isProtocolTransport check explaining the directory-wide scope (358246c):

// protocols/ is node-only throughout; directory-wide scope also covers future MCP modules automatically.

Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@adcp/sdk 12.0.1 breaks MCP version-negotiation probe (60s timeout) — 12.0.0 unaffected

3 participants