Skip to content

@modelcontextprotocol/sdk fails in CommonJS projects due to incompatible ESM-only dependency (pkce-challenge) #217

Open
@MauroPerna

Description

@MauroPerna

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch @modelcontextprotocol/[email protected] for the project I'm working on.

When importing @langchain/mcp-adapters in a CommonJS project (such as NestJS), the following error occurs at runtime:

Error [ERR_REQUIRE_ESM]: require() of ES Module pkce-challenge is not supported in CommonJS modules. Use dynamic import() instead.

The issue originates from @modelcontextprotocol/sdk, which uses a CommonJS-style require() to import pkce-challenge, an ESM-only package.


Steps to Reproduce

  1. Use @langchain/mcp-adapters in a CommonJS-based NestJS backend
  2. Run the project
  3. Crash occurs when MCP client initializes

Suggested fix

Use dynamic import() instead of require() in auth.js to support ESM-only dependencies within CommonJS projects.

Here’s the minimal diff that solved the issue:

diff --git a/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js b/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js
index 636d770..933474a 100644
--- a/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js
+++ b/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js
@@ -10,7 +10,16 @@ exports.startAuthorization = startAuthorization;
 exports.exchangeAuthorization = exchangeAuthorization;
 exports.refreshAuthorization = refreshAuthorization;
 exports.registerClient = registerClient;
-const pkce_challenge_1 = __importDefault(require("pkce-challenge"));
+let pkce_challenge_1 = { default: null };
+
+async function loadPkceChallenge() {
+  if (!pkce_challenge_1.default) {
+    const mod = await import("pkce-challenge");
+    pkce_challenge_1.default = mod.default;
+  }
+}

 const types_js_1 = require("../types.js");
 const auth_js_1 = require("../shared/auth.js");
@@ -137,7 +146,8 @@ async function startAuthorization(serverUrl, { metadata, clientInformation, redi
         authorizationUrl = new URL("/authorize", serverUrl);
     }
     // Generate PKCE challenge
-    const challenge = await (0, pkce_challenge_1.default)();
+    await loadPkceChallenge();
+    const challenge = await pkce_challenge_1.default();
     const codeVerifier = challenge.code_verifier;
     const codeChallenge = challenge.code_challenge;
     authorizationUrl.searchParams.set("response_type", responseType);

This issue body was partially generated by patch-package.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions