fix(mcp): tolerate synthetic entrypoint paths during import

Treat an unresolvable argv entry path as an imported module instead of throwing during entrypoint detection. Keep canonical direct-entry comparison private.

Validation: real child imports compiled runtime with a nonexistent argv path and no CLI side effects; all six runtime-error tests pass.

Based on #3162.

Co-authored-by: qorvr <330186599+qorvr@users.noreply.github.com>
This commit is contained in:
morlutoandqorvr committed 2026-10-14 13:58:17 +08:00
1 parent ae433f0983
commit ef153774f7
2 files changed
+36 -4

No files matched your search

+14 -4
View File
@@ -109,10 +109,20 @@ export const runEntrypoint = async (
}
};
/** Return false when the runtime's argv path is synthetic or no longer exists. */
const isDirectEntrypoint = (
entryPath: string | undefined,
moduleUrl: string,
): boolean => {
if (entryPath === undefined) return false;
try {
return pathToFileURL(realpathSync(entryPath)).href === moduleUrl;
} catch {
return false;
}
};
const entryPath = process.argv[1];
if (
entryPath !== undefined &&
pathToFileURL(realpathSync(entryPath)).href === import.meta.url
) {
if (isDirectEntrypoint(entryPath, import.meta.url)) {
void runEntrypoint();
}
+22
View File
@@ -1,4 +1,7 @@
import type { ServeStdioOptions } from "@modelcontextprotocol/server/stdio";
import { spawnSync } from "node:child_process";
import { resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import { run, runEntrypoint } from "../../../src/main.js";
@@ -35,6 +38,25 @@ const dependencies = ({
});
describe("MCP runtime errors", () => {
it("imports the compiled runtime when argv[1] is a missing synthetic path", () => {
const runtimeUrl = pathToFileURL(resolve("dist/main.js")).href;
const script = [
'process.argv[1] = "/rea-test-missing-entrypoint/main.js";',
`await import(${JSON.stringify(runtimeUrl)});`,
'console.log("IMPORT_OK");',
].join("\n");
const child = spawnSync(
process.execPath,
["--input-type=module", "--eval", script],
{ cwd: process.cwd(), encoding: "utf8", timeout: 5_000 },
);
expect(child.error).toBeUndefined();
expect(child.status).toBe(0);
expect(child.stdout).toBe("IMPORT_OK\n");
expect(child.stderr).toBe("");
});
it("reports connection loss without the transport cause", async () => {
const output: string[] = [];
const shutdown: Array<() => void> = [];