File size: 1,872 Bytes
35f99ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/** Spawns bundled LSP server processes with sanitized environment and platform handling. */
import { sanitizeHostExecEnv } from "../infra/host-env-security.js";
import {
  materializeWindowsSpawnProgram,
  resolveWindowsSpawnProgram,
} from "../plugin-sdk/windows-spawn.js";
import { createOwnedStdioProcess, type OwnedStdioProcess } from "../process/owned-stdio.js";
import type { StdioMcpServerLaunchConfig } from "./mcp-stdio.js";

type LspSpawnDependencies = {
  spawn: typeof createOwnedStdioProcess;
  sanitizeHostExecEnv: typeof sanitizeHostExecEnv;
  resolveWindowsSpawnProgram: typeof resolveWindowsSpawnProgram;
  materializeWindowsSpawnProgram: typeof materializeWindowsSpawnProgram;
};

const defaultLspSpawnDependencies: LspSpawnDependencies = {
  spawn: createOwnedStdioProcess,
  sanitizeHostExecEnv,
  resolveWindowsSpawnProgram,
  materializeWindowsSpawnProgram,
};

export async function spawnLspServerProcess(
  config: StdioMcpServerLaunchConfig,
  options: { abortSignal?: AbortSignal; dependencies?: LspSpawnDependencies } = {},
): Promise<OwnedStdioProcess> {
  const dependencies = options.dependencies ?? defaultLspSpawnDependencies;
  const mergedEnv = dependencies.sanitizeHostExecEnv({
    baseEnv: process.env,
    overrides: config.env ?? null,
  });
  const program = dependencies.resolveWindowsSpawnProgram({
    command: config.command,
    env: mergedEnv,
    allowShellFallback: true,
  });
  const invocation = dependencies.materializeWindowsSpawnProgram(program, config.args ?? []);
  return await dependencies.spawn({
    argv: [invocation.command, ...invocation.argv],
    env: mergedEnv,
    exactEnv: true,
    cwd: config.cwd,
    abortSignal: options.abortSignal,
    // Stable LSP config permits unresolved Windows wrappers to use Node's shell parsing.
    ...(invocation.shell === true ? { windowsShell: true } : {}),
  });
}