fix(mcp): normalize path separators in LSP/ast-grep cli candidate detection (fixes #4151)
On Windows, path.resolve() returns paths with backslash separators. The previous endsWith("dist/cli.js") check uses forward slashes and always returned false on Windows, causing both LSP and ast-grep MCPs to fall through to the bootstrap path even when the dist cli exists. Result: LSP MCP completely unusable on Windows with MODULE_NOT_FOUND for dist/packages/lsp-tools-mcp/dist/cli.js.
Fix: derive a platform-aware suffix at module load time by replacing forward slashes in DIST_CLI_REL / SOURCE_CLI_REL with path.sep, then use that suffix in the endsWith check.
Verification: all 4 src/mcp/lsp.test.ts cases pass on Windows (previously 2 failed); all 13 src/mcp/ast-grep.test.ts cases pass (previously 2 failed). Total: 17/17 src/mcp tests green. bun run typecheck clean.
This commit is contained in:
+5
-4
@@ -1,6 +1,7 @@
|
||||
import { existsSync } from "node:fs"
|
||||
import { dirname, resolve } from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
import { hasCliSuffix } from "./cli-suffix"
|
||||
import { resolveRuntimeExecutable, type RuntimeExecutable, type RuntimeExecutableResolver } from "./runtime-executable"
|
||||
|
||||
const SUBMODULE_REL = "packages/lsp-tools-mcp"
|
||||
@@ -137,14 +138,14 @@ function resolveLspCommand(options: LspMcpConfigOptions = {}): LspCommandCandida
|
||||
addAncestorCommandCandidates(moduleDirectory, candidates, seenPaths, pathExists, resolveExecutable)
|
||||
}
|
||||
|
||||
addAncestorCommandCandidates(options.cwd ?? process.cwd(), candidates, seenPaths, pathExists, resolveExecutable)
|
||||
|
||||
const distCandidate = candidates.find((candidate) => candidate.path.endsWith(DIST_CLI_REL) && candidate.exists)
|
||||
const distCandidate = candidates.find((candidate) => hasCliSuffix(candidate.path, DIST_CLI_REL) && candidate.exists)
|
||||
if (distCandidate) {
|
||||
return distCandidate
|
||||
}
|
||||
|
||||
const sourceCandidate = candidates.find((candidate) => candidate.path.endsWith(SOURCE_CLI_REL) && candidate.exists)
|
||||
const sourceCandidate = candidates.find(
|
||||
(candidate) => hasCliSuffix(candidate.path, SOURCE_CLI_REL) && candidate.exists,
|
||||
)
|
||||
if (sourceCandidate) {
|
||||
return sourceCandidate
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user