Merge pull request #3685 from Tibsfox/fix/mcp-server-subpath-imports
fix(mcp): use createRequire to resolve SDK wildcard subpath imports
This commit is contained in:
commit
0163b5b5bf
2 changed files with 54 additions and 2 deletions
|
|
@ -19,6 +19,10 @@ export interface McpToolDef {
|
|||
// MCP SDK subpath imports use wildcard exports (./*) that NodeNext resolves
|
||||
// at runtime but TypeScript cannot statically type-check. We construct the
|
||||
// specifiers dynamically so tsc treats them as `any`.
|
||||
// Use createRequire to resolve wildcard subpaths — CJS resolver auto-appends
|
||||
// .js, which the ESM wildcard export map does not (#3603).
|
||||
import { createRequire } from 'node:module'
|
||||
const _require = createRequire(import.meta.url)
|
||||
const MCP_PKG = '@modelcontextprotocol/sdk'
|
||||
|
||||
/**
|
||||
|
|
@ -42,8 +46,8 @@ export async function startMcpServer(options: {
|
|||
const { tools, version = '0.0.0' } = options
|
||||
|
||||
const serverMod = await import(`${MCP_PKG}/server`)
|
||||
const stdioMod = await import(`${MCP_PKG}/server/stdio`)
|
||||
const typesMod = await import(`${MCP_PKG}/types`)
|
||||
const stdioMod = await import(_require.resolve(`${MCP_PKG}/server/stdio`))
|
||||
const typesMod = await import(_require.resolve(`${MCP_PKG}/types`))
|
||||
|
||||
const Server = serverMod.Server
|
||||
const StdioServerTransport = stdioMod.StdioServerTransport
|
||||
|
|
|
|||
48
src/tests/mcp-createRequire.test.ts
Normal file
48
src/tests/mcp-createRequire.test.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Regression test for #3603 — MCP server subpath imports via createRequire
|
||||
*
|
||||
* The ESM wildcard export map in @modelcontextprotocol/sdk does not resolve
|
||||
* subpath imports correctly. The fix uses createRequire from node:module to
|
||||
* resolve wildcard subpaths via the CJS resolver which auto-appends .js.
|
||||
*
|
||||
* Structural verification test — reads source to confirm createRequire import
|
||||
* and _require.resolve usage exist.
|
||||
*/
|
||||
|
||||
import { describe, test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const source = readFileSync(join(__dirname, '..', 'mcp-server.ts'), 'utf-8');
|
||||
|
||||
describe('MCP server createRequire subpath resolution (#3603)', () => {
|
||||
test('createRequire is imported from node:module', () => {
|
||||
assert.match(source, /import\s*\{\s*createRequire\s*\}\s*from\s*['"]node:module['"]/,
|
||||
'createRequire should be imported from node:module');
|
||||
});
|
||||
|
||||
test('_require is created from import.meta.url', () => {
|
||||
assert.match(source, /createRequire\(import\.meta\.url\)/,
|
||||
'_require should be created using createRequire(import.meta.url)');
|
||||
});
|
||||
|
||||
test('_require.resolve is used for subpath imports', () => {
|
||||
assert.match(source, /_require\.resolve\(/,
|
||||
'_require.resolve should be used for subpath resolution');
|
||||
});
|
||||
|
||||
test('server/stdio subpath uses _require.resolve', () => {
|
||||
assert.match(source, /_require\.resolve\(`\$\{MCP_PKG\}\/server\/stdio`\)/,
|
||||
'server/stdio import should use _require.resolve');
|
||||
});
|
||||
|
||||
test('types subpath uses _require.resolve', () => {
|
||||
assert.match(source, /_require\.resolve\(`\$\{MCP_PKG\}\/types`\)/,
|
||||
'types import should use _require.resolve');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue