@akms/mcp-wsl 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/_defs/defaults.ts","../src/_defs/env-vars.ts","../src/_defs/wsl-rules.ts","../src/_libs/logger.ts","../src/_libs/text.ts","../src/_libs/fs-path.ts","../src/modules/config/host-profile.ts","../src/modules/guard/wsl-guard.ts","../src/modules/wsl/wsl-command.ts","../src/modules/wsl/wsl-host.ts","../src/modules/wsl/session-manager.ts","../src/modules/wsl/file-operations.ts","../src/modules/wsl/wsl-status.ts","../src/modules/tools/format.ts","../src/modules/tools/tool-context.ts","../src/modules/tools/exec-tools.ts","../src/modules/tools/file-tools.ts","../src/modules/tools/host-tools.ts","../src/modules/tools/session-tools.ts","../src/modules/tools/index.ts","../src/server.ts"],"names":["os","path","inspectCommand","extractSubstitutions","splitCommandSegments","analyzeSegment","inspectRemotePath","inspectLocalPath","canonicalizeCommand","GuardRejectionError","inspectWorkingDirectory","spawn","setInterval","clearInterval","fs","describeError","z","McpServer"],"mappings":"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","file":"index.cjs","sourcesContent":["/** Env var overriding the stderr log level (\"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\"). */\nexport const LOG_LEVEL_ENV = \"WSL_MCP_LOG_LEVEL\";\n\nexport const DEFAULT_EXEC_TIMEOUT_MS = 60_000;\n\n/** stdout / stderr cutoff — roughly 25k tokens of context at worst. */\nexport const DEFAULT_MAX_OUTPUT_CHARACTERS = 100_000;\n\nexport const DEFAULT_MAX_READ_FILE_BYTES = 200_000;\n\n/** Raw bytes buffered per stream before the process is killed — a runaway `cat /dev/zero` must not take the server with it. */\nexport const OUTPUT_HARD_CAP_MULTIPLIER = 4;\n\n/** Sessions untouched for this long are forgotten by the sweeper. */\nexport const SESSION_IDLE_TIMEOUT_MS = 15 * 60 * 1000;\n\nexport const SESSION_SWEEP_INTERVAL_MS = 60_000;\n\n/** Ceiling on simultaneously running `wsl.exe` processes, so a runaway tool batch can't fork-bomb the host. */\nexport const MAX_CONCURRENT_PROCESSES = 32;\n\n/** Emitted after the user command so a session can track `cd` between execs. */\nexport const CWD_MARKER = \"__AKMS_WSL_CWD__\";\n\n/** `wsl_list_dir` stops here — a directory with 500k entries would otherwise return megabytes. */\nexport const MAX_DIRECTORY_ENTRIES = 1_000;\n\n/** Resolved through PATH: `C:\\Windows\\System32\\wsl.exe`, or the Store build under WindowsApps. */\nexport const WSL_EXECUTABLE = \"wsl.exe\";\n\n/**\n * Exit status `wsl.exe` returns when *it* failed (unknown distro, service down) rather than\n * the Linux command. Node reports the uint32 form on Windows; `-1` is kept for safety.\n */\nexport const WSL_FAILURE_EXIT_CODES = [4294967295, -1];\n\nexport const SERVER_NAME = \"akms-mcp-wsl\";\n\nexport const SERVER_VERSION = \"0.0.1\";\n","/**\n * Environment variables that define the distro, one MCP server entry per distro + user.\n *\n * The `SSH_*` surface of `@akms/mcp-ssh` with the connection and authentication\n * variables removed — there is no connection, `wsl.exe` is the transport.\n */\nexport const SINGLE_HOST_ENV = {\n /** Presence of this variable is what registers a distro at all. Name as `wsl -l -q` prints it. */\n DISTRO: \"WSL_DISTRO\",\n /** Linux user to run as (`wsl -u`); the distro's default user when unset. */\n USER: \"WSL_USER\",\n /** Alias shown to the model; defaults to the distro name. */\n NAME: \"WSL_NAME\",\n DESCRIPTION: \"WSL_DESCRIPTION\",\n /** Directory new sessions start in. */\n CWD: \"WSL_CWD\",\n READONLY: \"WSL_READONLY\",\n ALLOW_SUDO: \"WSL_ALLOW_SUDO\",\n /** Interop `.exe` execution and writes under `/mnt/<drive>/`. Default false. */\n ALLOW_WINDOWS: \"WSL_ALLOW_WINDOWS\",\n /** Comma-separated binary names. */\n ALLOW_COMMANDS: \"WSL_ALLOW_COMMANDS\",\n /** Comma-separated regex sources. */\n DENY_PATTERNS: \"WSL_DENY_PATTERNS\",\n /** Comma-separated absolute path prefixes. */\n ALLOWED_PATHS: \"WSL_ALLOWED_PATHS\",\n EXEC_TIMEOUT_MS: \"WSL_EXEC_TIMEOUT_MS\",\n MAX_OUTPUT_CHARACTERS: \"WSL_MAX_OUTPUT\",\n MAX_READ_FILE_BYTES: \"WSL_MAX_READ_BYTES\",\n} as const;\n\n/** Accepted spellings for a true boolean env value. */\nexport const TRUTHY_ENV_VALUES = [\"true\", \"1\", \"yes\", \"on\"];\n\n/** Accepted spellings for a false boolean env value. */\nexport const FALSY_ENV_VALUES = [\"false\", \"0\", \"no\", \"off\"];\n","/** One deny rule: a regex tested against a segment's normalized text plus the message shown on a hit. */\r\nexport interface CommandRule {\r\n pattern: RegExp;\r\n reason: string;\r\n}\r\n\r\n/**\r\n * Catastrophe rules specific to a WSL host, on top of `@akms/mcp-ssh`'s (which already\r\n * refuse `shutdown` / `reboot`). The criterion is the same: an operation that kills the\r\n * machine this server is working through, or cuts the channel it works through. Tested\r\n * against `analyzeSegment(...).normalizedText`, which starts at the binary.\r\n */\r\nexport const WSL_CATASTROPHE_RULES: CommandRule[] = [\r\n {\r\n pattern: /^wsl(?:\\.exe)?\\b.*\\s-(?:-shutdown|-terminate|-unregister|t)(?:\\s|$)/i,\r\n reason: \"stops or removes the distro this server runs in (wsl --shutdown / --terminate / --unregister)\",\r\n },\r\n {\r\n pattern: /^wslconfig(?:\\.exe)?\\b.*\\s\\/(?:t|u)\\b/i,\r\n reason: \"terminates or unregisters the distro this server runs in (wslconfig /t, /u)\",\r\n },\r\n {\r\n pattern: /^(?:poweroff|halt)\\b/,\r\n reason: \"powers off the distro this server runs in\",\r\n },\r\n {\r\n pattern: /^systemctl\\b.*\\b(?:poweroff|halt|reboot|kexec|suspend|hibernate)\\b/,\r\n reason: \"powers off or restarts the distro this server runs in\",\r\n },\r\n {\r\n pattern: /^(?:telinit|init)\\s+[06]\\b/,\r\n reason: \"halts or reboots the distro this server runs in\",\r\n },\r\n];\r\n\r\n/**\r\n * Binaries that leave the distro for Windows through interop. Matched against the\r\n * segment's resolved binary basename, so `/mnt/c/Windows/System32/cmd.exe` and `cmd.exe`\r\n * read the same. The extension rule catches every other Windows executable.\r\n */\r\nexport const WINDOWS_INTEROP_BINARY_PATTERN = new RegExp(\r\n \"^(?:\"\r\n + \"(?:powershell|pwsh|cmd|explorer|wsl|wslconfig|wslview|reg|regedit|schtasks|sc|net|netsh|taskkill|tasklist|mshta|rundll32|wscript|cscript|msiexec|start|winget|choco|scoop)(?:\\\\.exe|\\\\.cmd|\\\\.bat)?\"\r\n + \"|.*\\\\.(?:exe|cmd|bat|ps1|msi|com)\"\r\n + \")$\",\r\n \"i\"\r\n);\r\n\r\n/** Every `/mnt/<drive>/…` reference in a segment, quotes or not — the threat model is a mistaken agent, not an adversary. */\r\nexport const MOUNT_PATH_PATTERN = /\\/mnt\\/([a-z])(\\/[^\\s'\"|;&<>]*)?/gi;\r\n","import { LOG_LEVEL_ENV } from \"@/_defs\";\n\nexport type LogLevel = \"silent\" | \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface Logger {\n /** Returns a logger that appends `meta` to every record it writes. */\n child(meta: Record<string, unknown>): Logger;\n debug(message: string, meta?: Record<string, unknown>): void;\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(error: unknown, message: string, meta?: Record<string, unknown>): void;\n}\n\nconst LEVEL_WEIGHTS: Record<LogLevel, number> = {\n silent: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n};\n\n/** Meta keys whose values never reach the log output. */\nconst SECRET_META_KEYS = [\"password\", \"passphrase\", \"secret\", \"token\"];\n\nfunction resolveThreshold(): LogLevel {\n const configured = process.env[LOG_LEVEL_ENV];\n if (configured == null) {\n return \"info\";\n }\n\n // Own-property check: a plain `LEVEL_WEIGHTS[x] == null` test walks the prototype, so\n // WSL_MCP_LOG_LEVEL=constructor would pass validation and disable all filtering.\n const normalized = configured.toLowerCase() as LogLevel;\n if (Object.hasOwn(LEVEL_WEIGHTS, normalized) == false) {\n return \"info\";\n }\n\n return normalized;\n}\n\nfunction maskSecrets(meta: Record<string, unknown>): Record<string, unknown> {\n const masked: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(meta)) {\n if (SECRET_META_KEYS.includes(key.toLowerCase()) == true) {\n masked[key] = \"***\";\n continue;\n }\n masked[key] = value;\n }\n\n return masked;\n}\n\nfunction describeError(error: unknown): string {\n if (error instanceof Error) {\n if (error.stack != null) {\n return error.stack;\n }\n return error.message;\n }\n\n return String(error);\n}\n\n/**\n * Writes one line to stderr — stdout is the MCP protocol channel and must stay clean.\n * The threshold is read per call so `--check` can silence the logger after imports ran.\n */\nfunction write(level: LogLevel, message: string, meta: Record<string, unknown>): void {\n const threshold = resolveThreshold();\n if (threshold === \"silent\") {\n return;\n }\n\n if (LEVEL_WEIGHTS[level] < LEVEL_WEIGHTS[threshold]) {\n return;\n }\n\n const record = {\n time: new Date().toISOString(),\n level: level,\n message: message,\n ...maskSecrets(meta),\n };\n process.stderr.write(`${JSON.stringify(record)}\\n`);\n}\n\nfunction createLogger(baseMeta: Record<string, unknown>): Logger {\n return {\n child(meta: Record<string, unknown>): Logger {\n return createLogger({ ...baseMeta, ...meta });\n },\n debug(message: string, meta?: Record<string, unknown>): void {\n write(\"debug\", message, { ...baseMeta, ...meta });\n },\n info(message: string, meta?: Record<string, unknown>): void {\n write(\"info\", message, { ...baseMeta, ...meta });\n },\n warn(message: string, meta?: Record<string, unknown>): void {\n write(\"warn\", message, { ...baseMeta, ...meta });\n },\n error(error: unknown, message: string, meta?: Record<string, unknown>): void {\n write(\"error\", message, { ...baseMeta, ...meta, error: describeError(error) });\n },\n };\n}\n\nexport const $logger: Logger = createLogger({});\n","/** Output cut to `maxCharacters`, with a note appended when anything was dropped. */\nexport interface TruncatedText {\n text: string;\n truncated: boolean;\n}\n\n/**\n * Cuts `text` to `maxCharacters`, appending a note saying how much was dropped.\n *\n * @returns The possibly-cut text and whether anything was removed.\n */\nexport function truncateOutput(text: string, maxCharacters: number): TruncatedText {\n if (text.length <= maxCharacters) {\n return { text: text, truncated: false };\n }\n\n // Never cut between the halves of a surrogate pair: the orphaned half renders as a\n // replacement character, so an emoji at the boundary would come back corrupted.\n let cutAt = maxCharacters;\n const lastKeptCode = text.charCodeAt(cutAt - 1);\n if (lastKeptCode >= 0xd800 && lastKeptCode <= 0xdbff) {\n cutAt -= 1;\n }\n\n const droppedCharacters = text.length - cutAt;\n const kept = text.slice(0, cutAt);\n return {\n text: `${kept}\\n... [truncated ${droppedCharacters} characters of ${text.length}]`,\n truncated: true,\n };\n}\n\n/**\n * Wraps a value in single quotes for POSIX shells, escaping embedded quotes as `'\\''`.\n * Used for interpolating paths into generated scripts — never for user commands, which\n * are passed through verbatim so bash parses them as written.\n */\nexport function quoteShellArgument(value: string): string {\n const escaped = value.replace(/'/g, `'\\\\''`);\n return `'${escaped}'`;\n}\n\n/** Renders a byte count as `B` / `KB` / `MB` for display in tool output. */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1024 * 1024) {\n const kilobytes = bytes / 1024;\n return `${kilobytes.toFixed(1)} KB`;\n }\n\n const megabytes = bytes / (1024 * 1024);\n return `${megabytes.toFixed(1)} MB`;\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\n\n/** Expands a leading `~` to the local home directory and returns an absolute path. */\nexport function expandHomePath(inputPath: string): string {\n let expanded = inputPath;\n if (inputPath === \"~\") {\n expanded = os.homedir();\n }\n else if (inputPath.startsWith(\"~/\") == true || inputPath.startsWith(\"~\\\\\") == true) {\n expanded = path.join(os.homedir(), inputPath.slice(2));\n }\n\n return path.resolve(expanded);\n}\n\n/** True for POSIX absolute paths — the only form the path guard can reason about. */\nexport function isAbsoluteDistroPath(distroPath: string): boolean {\n return distroPath.startsWith(\"/\");\n}\n\n/**\n * `/mnt/c/Users/x` → `C:/Users/x`, or null when the path is not under a drive mount.\n *\n * Lexical, like the default `automount` layout — a custom `/etc/wsl.conf` mount root is\n * not read. That is fine for a guard whose job is to recognise the operator's own\n * credential and configuration paths, which live under the default mount.\n */\nexport function mountPathToWindows(distroPath: string): string | null {\n const match = /^\\/mnt\\/([a-z])(?:\\/(.*))?$/i.exec(distroPath.trim());\n if (match == null) {\n return null;\n }\n\n const drive = match[1].toUpperCase();\n const rest = match[2] ?? \"\";\n return `${drive}:/${rest}`;\n}\n","import {\n DEFAULT_EXEC_TIMEOUT_MS,\n DEFAULT_MAX_OUTPUT_CHARACTERS,\n DEFAULT_MAX_READ_FILE_BYTES,\n FALSY_ENV_VALUES,\n SINGLE_HOST_ENV,\n TRUTHY_ENV_VALUES,\n} from \"@/_defs\";\nimport { $logger } from \"@/_libs\";\nimport type { WslHostProfile, WslHostSummary, WslPolicy } from \"@/_types\";\n\n/** Trimmed value, or undefined when the variable is unset or blank. */\nfunction readEnv(name: string): string | undefined {\n const value = process.env[name];\n if (value == null) {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (trimmed === \"\") {\n return undefined;\n }\n\n return trimmed;\n}\n\n/**\n * @throws {Error} If the value is set but is neither a truthy nor a falsy spelling —\n * `WSL_READONLY=ture` must fail loudly, not resolve to \"not read-only\".\n */\nfunction readBooleanEnv(name: string): boolean | undefined {\n const value = readEnv(name);\n if (value == null) {\n return undefined;\n }\n\n const normalized = value.toLowerCase();\n if (TRUTHY_ENV_VALUES.includes(normalized) == true) {\n return true;\n }\n\n if (FALSY_ENV_VALUES.includes(normalized) == false) {\n throw new Error(`${name} must be one of ${[...TRUTHY_ENV_VALUES, ...FALSY_ENV_VALUES].join(\", \")} (got \"${value}\")`);\n }\n\n return false;\n}\n\n/**\n * @throws {Error} If the value is set but is not a positive integer.\n */\nfunction readIntegerEnv(name: string): number | undefined {\n const value = readEnv(name);\n if (value == null) {\n return undefined;\n }\n\n const parsed = Number(value);\n if (Number.isInteger(parsed) == false || parsed <= 0) {\n throw new Error(`${name} must be a positive integer (got \"${value}\")`);\n }\n\n return parsed;\n}\n\n/** Comma-separated list, blanks dropped. */\nfunction readListEnv(name: string): string[] | undefined {\n const value = readEnv(name);\n if (value == null) {\n return undefined;\n }\n\n const items = value.split(\",\").map((item) => item.trim()).filter((item) => item !== \"\");\n if (items.length === 0) {\n return undefined;\n }\n\n return items;\n}\n\n/**\n * Compiles `WSL_DENY_PATTERNS` at startup, so a typo'd regex aborts the server instead\n * of silently not being in force at the moment it matters.\n *\n * @throws {Error} If a pattern is not a valid regular expression.\n */\nfunction compileDenyPatterns(sources: string[]): RegExp[] {\n return sources.map((source) => {\n try {\n return new RegExp(source, \"i\");\n }\n catch (ex) {\n let detail = String(ex);\n if (ex instanceof Error) {\n detail = ex.message;\n }\n\n throw new Error(`${SINGLE_HOST_ENV.DENY_PATTERNS} has an invalid entry /${source}/: ${detail}`);\n }\n });\n}\n\n/**\n * Builds the profile from the `WSL_*` variables, or null when `WSL_DISTRO` is unset.\n *\n * The distro is required by name rather than falling back to `wsl --set-default`'s pick:\n * that default is a machine-wide setting anyone can change, and a server silently\n * following it would one day run every command in a different distro than the entry\n * says. A malformed value aborts startup rather than being ignored, because silently\n * dropping `WSL_READONLY` would leave a distro the operator believed was read-only\n * fully writable.\n *\n * Flow:\n * 1) Guard: no `WSL_DISTRO` means nothing is registered — the server still starts and says so\n * 2) Resolve the policy over the built-in permissive stance; each variable is opt-in restriction\n * 3) Assemble the profile\n *\n * @throws {Error} If a typed value is malformed.\n */\nexport function loadHostProfile(): WslHostProfile | null {\n // (1) Guard — a missing distro is not an error: the server reports \"not configured\"\n // through the tools, which is a far clearer signal to the model than a dead server.\n const distro = readEnv(SINGLE_HOST_ENV.DISTRO);\n if (distro == null) {\n const _startupLogger = $logger.child({ context: \"loadHostProfile\" });\n _startupLogger.warn(\"no distro is registered; set the distro variable and restart\", {\n env_vars: [SINGLE_HOST_ENV.DISTRO],\n });\n return null;\n }\n\n const name = readEnv(SINGLE_HOST_ENV.NAME) ?? distro;\n const _logger = $logger.child({ context: \"loadHostProfile\", profile: name });\n\n // (2) Policy — the built-in stance is permissive: an unconfigured distro allows\n // everything except the catastrophe rules, because a guard nobody can work through\n // gets turned off wholesale rather than tuned. The one exception is Windows access,\n // which is opt-in — see `WslHostProfile.allowWindows`.\n const allowCommands = readListEnv(SINGLE_HOST_ENV.ALLOW_COMMANDS) ?? [];\n\n // `wsl_connect` probes with `pwd` to settle the session's starting directory; without\n // this an allow-list profile could never open a session at all.\n if (allowCommands.length > 0 && allowCommands.includes(\"pwd\") == false) {\n allowCommands.push(\"pwd\");\n }\n\n const policy: WslPolicy = {\n readonly: readBooleanEnv(SINGLE_HOST_ENV.READONLY) ?? false,\n allowSudo: readBooleanEnv(SINGLE_HOST_ENV.ALLOW_SUDO) ?? true,\n execTimeoutMs: readIntegerEnv(SINGLE_HOST_ENV.EXEC_TIMEOUT_MS) ?? DEFAULT_EXEC_TIMEOUT_MS,\n // Nothing connects; carried only because the shared policy type declares it.\n connectTimeoutMs: 0,\n maxOutputCharacters: readIntegerEnv(SINGLE_HOST_ENV.MAX_OUTPUT_CHARACTERS) ?? DEFAULT_MAX_OUTPUT_CHARACTERS,\n maxReadFileBytes: readIntegerEnv(SINGLE_HOST_ENV.MAX_READ_FILE_BYTES) ?? DEFAULT_MAX_READ_FILE_BYTES,\n allowCommands: allowCommands,\n denyPatterns: compileDenyPatterns(readListEnv(SINGLE_HOST_ENV.DENY_PATTERNS) ?? []),\n allowedPaths: readListEnv(SINGLE_HOST_ENV.ALLOWED_PATHS) ?? [],\n };\n\n // (3) Profile\n const profile: WslHostProfile = {\n name: name,\n distro: distro,\n username: readEnv(SINGLE_HOST_ENV.USER),\n description: readEnv(SINGLE_HOST_ENV.DESCRIPTION),\n defaultCwd: readEnv(SINGLE_HOST_ENV.CWD),\n allowWindows: readBooleanEnv(SINGLE_HOST_ENV.ALLOW_WINDOWS) ?? false,\n policy: policy,\n };\n\n _logger.info(\"host profile loaded\", {\n distro: distro,\n username: profile.username ?? \"(distro default)\",\n readonly: policy.readonly,\n allow_windows: profile.allowWindows,\n });\n\n return profile;\n}\n\n/** The profile as described back to the model. Nothing secret lives in a WSL profile, but the shape mirrors mcp-ssh. */\nexport function toHostSummary(profile: WslHostProfile): WslHostSummary {\n return {\n name: profile.name,\n distro: profile.distro,\n username: profile.username ?? \"(distro default)\",\n description: profile.description,\n readonly: profile.policy.readonly,\n allowSudo: profile.policy.allowSudo,\n allowWindows: profile.allowWindows,\n allowedPaths: profile.policy.allowedPaths,\n allowCommands: profile.policy.allowCommands,\n };\n}\n","import {\r\n analyzeSegment,\r\n extractSubstitutions,\r\n inspectCommand,\r\n inspectLocalPath,\r\n inspectRemotePath,\r\n splitCommandSegments,\r\n} from \"@akms/mcp-ssh\";\r\nimport type { RemotePathAccess, SegmentAnalysis } from \"@akms/mcp-ssh\";\r\n\r\nimport { MOUNT_PATH_PATTERN, WINDOWS_INTEROP_BINARY_PATTERN, WSL_CATASTROPHE_RULES } from \"@/_defs\";\r\nimport { mountPathToWindows } from \"@/_libs\";\r\nimport type { GuardVerdict, WslHostProfile, WslPolicy } from \"@/_types\";\r\n\r\n/** Nested `$(…)` levels the WSL-specific pass descends into; matches the base guard's own limit. */\r\nconst MAX_INSPECTION_DEPTH = 5;\r\n\r\n/**\r\n * Screens a command for a WSL host: the `@akms/mcp-ssh` guard first (catastrophe rules,\r\n * read-only, sudo, allow-list, deny patterns), then what only matters here.\r\n *\r\n * The WSL additions exist because one assumption of the base guard does not hold: that\r\n * the remote account is the real boundary. In WSL the \"remote\" is the machine running\r\n * this server. Through interop (`powershell.exe`) or a write under `/mnt/c/Users/…`, a\r\n * mistaken agent can reach `~/.claude.json` — the file that defines this very guard — so\r\n * both routes are closed unless `WSL_ALLOW_WINDOWS` opens them, and the operator's\r\n * credential and configuration paths stay closed either way.\r\n *\r\n * Flow:\r\n * 1) Base guard on the whole command\r\n * 2) Per segment (and per `$(…)` substitution, recursively): WSL catastrophe rules\r\n * 3) Per segment: interop binary\r\n * 4) Per segment: `/mnt/<drive>/` references — write shape, then protected Windows paths\r\n */\r\nexport function inspectWslCommand(canonicalCommand: string, profile: WslHostProfile, depth = 0): GuardVerdict {\r\n // (1) Base guard\r\n if (depth === 0) {\r\n const baseVerdict = inspectCommand(canonicalCommand, profile.policy);\r\n if (baseVerdict.allowed == false) {\r\n return baseVerdict;\r\n }\r\n }\r\n\r\n if (depth > MAX_INSPECTION_DEPTH) {\r\n return {\r\n allowed: false,\r\n reason: `command nests substitutions deeper than ${MAX_INSPECTION_DEPTH} levels`,\r\n offendingText: canonicalCommand,\r\n };\r\n }\r\n\r\n for (const substitution of extractSubstitutions(canonicalCommand)) {\r\n const nestedVerdict = inspectWslCommand(substitution, profile, depth + 1);\r\n if (nestedVerdict.allowed == false) {\r\n return nestedVerdict;\r\n }\r\n }\r\n\r\n for (const segment of splitCommandSegments(canonicalCommand)) {\r\n const analysis = analyzeSegment(segment);\r\n\r\n // (2) Catastrophe — never configurable, same stance as the base rules.\r\n for (const rule of WSL_CATASTROPHE_RULES) {\r\n if (rule.pattern.test(analysis.normalizedText) == true) {\r\n return { allowed: false, reason: rule.reason, offendingText: segment.trim() };\r\n }\r\n }\r\n\r\n // (3) Interop\r\n if (profile.allowWindows == false && WINDOWS_INTEROP_BINARY_PATTERN.test(analysis.binary) == true) {\r\n return {\r\n allowed: false,\r\n reason: `'${analysis.binary}' is a Windows executable: interop leaves the distro for the machine running this server (set WSL_ALLOW_WINDOWS=true to permit it)`,\r\n offendingText: segment.trim(),\r\n };\r\n }\r\n\r\n // (4) Drive mounts\r\n const mountPaths = collectMountPaths(segment, analysis);\r\n if (mountPaths.length === 0) {\r\n continue;\r\n }\r\n\r\n const writeShaped = isWriteShaped(segment, profile.policy);\r\n if (profile.allowWindows == false && writeShaped == true) {\r\n const mountTarget = findMountWriteTarget(segment, analysis);\r\n if (mountTarget != null) {\r\n return {\r\n allowed: false,\r\n reason: `writing to ${mountTarget} lands on the Windows filesystem of the machine running this server (set WSL_ALLOW_WINDOWS=true to permit writes under /mnt/<drive>/; reads and copies out of it are already allowed)`,\r\n offendingText: segment.trim(),\r\n };\r\n }\r\n }\r\n\r\n let access: RemotePathAccess = \"read\";\r\n if (writeShaped == true) {\r\n access = \"write\";\r\n }\r\n\r\n for (const mountPath of mountPaths) {\r\n const protectedVerdict = inspectMountPath(mountPath, access);\r\n if (protectedVerdict.allowed == false) {\r\n return protectedVerdict;\r\n }\r\n }\r\n }\r\n\r\n return { allowed: true };\r\n}\r\n\r\n/**\r\n * Decides whether a file tool may touch a path in the distro: the base path guard\r\n * (`allowedPaths`, read-only), then the Windows rules for anything under `/mnt/<drive>/`.\r\n */\r\nexport function inspectWslPath(distroPath: string, profile: WslHostProfile, access: RemotePathAccess): GuardVerdict {\r\n const baseVerdict = inspectRemotePath(distroPath, profile.policy, access);\r\n if (baseVerdict.allowed == false) {\r\n return baseVerdict;\r\n }\r\n\r\n if (mountPathToWindows(distroPath) == null) {\r\n return { allowed: true };\r\n }\r\n\r\n if (access === \"write\" && profile.allowWindows == false) {\r\n return {\r\n allowed: false,\r\n reason: \"writes under /mnt/<drive>/ land on the Windows filesystem of the machine running this server (set WSL_ALLOW_WINDOWS=true to permit them)\",\r\n offendingText: distroPath.trim(),\r\n };\r\n }\r\n\r\n return inspectMountPath(distroPath.trim(), access);\r\n}\r\n\r\n/**\r\n * Applies `@akms/mcp-ssh`'s local-path protection to a `/mnt/<drive>/` path by translating\r\n * it to the Windows path it is — the same credential and MCP-configuration rules, the\r\n * same symlink resolution, so the two servers refuse the same files.\r\n */\r\nfunction inspectMountPath(distroPath: string, access: RemotePathAccess): GuardVerdict {\r\n const windowsPath = mountPathToWindows(distroPath);\r\n if (windowsPath == null) {\r\n return { allowed: true };\r\n }\r\n\r\n const verdict = inspectLocalPath(windowsPath, access);\r\n if (verdict.allowed == true) {\r\n return verdict;\r\n }\r\n\r\n return {\r\n allowed: false,\r\n reason: `${verdict.reason} (reached through ${distroPath})`,\r\n offendingText: distroPath,\r\n };\r\n}\r\n\r\n/** Binaries whose write lands on their *last* operand only; earlier operands are sources. */\r\nconst DESTINATION_LAST_BINARIES = new Set([\"cp\", \"rsync\", \"install\", \"scp\"]);\r\n\r\n/** Binaries that write where an option says, not where an operand is. */\r\nconst DESTINATION_BY_OPTION: Record<string, RegExp> = {\r\n tar: /^(?:-C|--directory)$/,\r\n unzip: /^-d$/,\r\n curl: /^(?:-o|--output)$/,\r\n wget: /^(?:-O|--output-document)$/,\r\n};\r\n\r\n/** `tar` creates or appends an archive — then the `f` operand is the write target. */\r\nconst TAR_CREATE_FLAG_PATTERN = /^(?:-[a-zA-Z]*[cru][a-zA-Z]*|--create|--append|--update|--concatenate|--delete)$/;\r\n\r\n/**\r\n * The `/mnt/<drive>/` path a write-shaped segment would write *to*, or null when it only\r\n * reads from the mount.\r\n *\r\n * \"Mentions /mnt and is a write\" was the first rule and it refused the commonest legitimate\r\n * case — `cp /mnt/c/app/dist.tgz /home/app/`, deploying a file built on Windows. So the\r\n * target is worked out per binary shape: copy-likes write their last operand, archivers\r\n * and downloaders write where an option points, and everything else write-shaped (`rm`,\r\n * `sed -i`, `mv`, `tee`, `chmod`…) writes every operand. Output redirection is a write\r\n * target for any binary.\r\n */\r\nfunction findMountWriteTarget(segment: string, analysis: SegmentAnalysis): string | null {\r\n for (const redirectionTarget of collectRedirectionTargets(segment)) {\r\n if (isMountPath(redirectionTarget) == true) {\r\n return redirectionTarget;\r\n }\r\n }\r\n\r\n const binary = analysis.binary.toLowerCase();\r\n let candidates: string[] = analysis.operands;\r\n\r\n if (DESTINATION_LAST_BINARIES.has(binary) == true) {\r\n // `cp -t DIR src…` puts the destination first.\r\n candidates = [...analysis.operands.slice(-1), ...valuesAfterOption(analysis.tokens, TARGET_DIRECTORY_OPTION)];\r\n }\r\n else if (binary === \"tar\") {\r\n const creating = analysis.flags.some((flag) => TAR_CREATE_FLAG_PATTERN.test(flag) == true);\r\n if (creating == false) {\r\n candidates = valuesAfterOption(analysis.tokens, DESTINATION_BY_OPTION.tar);\r\n }\r\n }\r\n else if (DESTINATION_BY_OPTION[binary] != null) {\r\n candidates = valuesAfterOption(analysis.tokens, DESTINATION_BY_OPTION[binary]);\r\n }\r\n\r\n // `--output=/mnt/c/y`, `--target-directory=/mnt/c/out`, `--directory=/mnt/c/out`: the\r\n // value rides inside the flag, whatever the binary.\r\n candidates = [...candidates, ...valuesInFlags(analysis.flags)];\r\n\r\n for (const candidate of candidates) {\r\n if (isMountPath(candidate) == true) {\r\n return candidate;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** `cp` / `install` / `mv` destination given ahead of the sources. */\r\nconst TARGET_DIRECTORY_OPTION = /^(?:-t|--target-directory)$/;\r\n\r\n/** The `X` of `--flag=X` for every flag carrying a value — `--output=/mnt/c/x`, `--target-directory=/mnt/c/out`. */\r\nfunction valuesInFlags(flags: string[]): string[] {\r\n const values: string[] = [];\r\n for (const flag of flags) {\r\n const separator = flag.indexOf(\"=\");\r\n if (separator > 0) {\r\n values.push(flag.slice(separator + 1));\r\n }\r\n }\r\n\r\n return values;\r\n}\r\n\r\n/** Tokens that follow an option matching `optionPattern`, e.g. the `X` of `-C X`. */\r\nfunction valuesAfterOption(tokens: string[], optionPattern: RegExp): string[] {\r\n const values: string[] = [];\r\n for (let index = 0; index < tokens.length - 1; index++) {\r\n if (optionPattern.test(tokens[index]) == true) {\r\n values.push(tokens[index + 1]);\r\n }\r\n }\r\n\r\n return values;\r\n}\r\n\r\n/**\r\n * Targets of `>`, `>>`, `&>`, `2>` in one segment, quotes stripped. No character is\r\n * required before the `>` — `echo x>/mnt/c/f` is as much a redirection as `echo x > f`.\r\n * `2>&1` is skipped because the target class excludes `&`.\r\n */\r\nfunction collectRedirectionTargets(segment: string): string[] {\r\n const targets: string[] = [];\r\n for (const match of segment.matchAll(/>{1,2}\\s*(['\"]?)([^\\s'\"|;&<>]+)/g)) {\r\n targets.push(match[2]);\r\n }\r\n\r\n return targets;\r\n}\r\n\r\n/** Strips surrounding quotes and a `key=` prefix (`dd of=/mnt/c/x`, `'/mnt/c/a b'`). */\r\nfunction bareCandidate(candidate: string): string {\r\n return candidate.replace(/^['\"]|['\"]$/g, \"\").replace(/^[A-Za-z_][\\w-]*=/, \"\");\r\n}\r\n\r\n/** True for `/mnt/<drive>` or below. */\r\nfunction isMountPath(candidate: string): boolean {\r\n return /^\\/mnt\\/[a-z](?:\\/|$)/i.test(bareCandidate(candidate));\r\n}\r\n\r\n/**\r\n * Every `/mnt/<drive>/…` reference in one segment.\r\n *\r\n * The analysed tokens come first because they keep a quoted path whole — the raw regex\r\n * stops at the first space, so `'/mnt/c/Users/Jun Cha/.ssh/id_rsa'` would have been seen\r\n * as `/mnt/c/Users/Jun` and the credential rule never reached. The raw scan stays as the\r\n * net for whatever the tokenizer did not classify.\r\n */\r\nfunction collectMountPaths(segment: string, analysis: SegmentAnalysis): string[] {\r\n const found = new Set<string>();\r\n\r\n const candidates = [\r\n ...analysis.operands,\r\n ...valuesInFlags(analysis.flags),\r\n ...collectRedirectionTargets(segment),\r\n ];\r\n for (const candidate of candidates) {\r\n if (isMountPath(candidate) == true) {\r\n found.add(bareCandidate(candidate));\r\n }\r\n }\r\n\r\n for (const match of segment.matchAll(MOUNT_PATH_PATTERN)) {\r\n found.add(match[0]);\r\n }\r\n\r\n return Array.from(found);\r\n}\r\n\r\n/**\r\n * True when the base guard's read-only rules would refuse the segment — the same\r\n * definition of \"a write\" that `WSL_READONLY` uses, so the two never disagree.\r\n */\r\nfunction isWriteShaped(segment: string, policy: WslPolicy): boolean {\r\n const readonlyPolicy: WslPolicy = { ...policy, readonly: true };\r\n const verdict = inspectCommand(segment, readonlyPolicy);\r\n return verdict.allowed == false;\r\n}\r\n","import { CWD_MARKER } from \"@/_defs\";\nimport { quoteShellArgument } from \"@/_libs\";\nimport type { WslHostProfile } from \"@/_types\";\n\n/**\n * The `wsl.exe` argument vector for running `script` in the profile's distro as its user.\n *\n * `--exec`, never `--`. With `--`, wsl.exe hands the arguments to the distro's *default\n * shell* for a second parse: backslashes vanish (`printf '\\n'` breaks, `find … \\;`\n * breaks) and `$HOME` / `$PATH` are expanded before bash ever sees the script — that is,\n * before the text the guard screened is the text that runs. `--exec` is a straight\n * execve, so the argument arrives byte for byte; `bash -lc` then gives the login\n * environment (PATH from `.profile`, nvm) that `--exec` alone would skip.\n */\nexport function buildWslArguments(profile: WslHostProfile, script: string): string[] {\n const wslArguments: string[] = [\"-d\", profile.distro];\n\n if (profile.username != null) {\n wslArguments.push(\"-u\", profile.username);\n }\n\n wslArguments.push(\"--exec\", \"bash\", \"-lc\", script);\n return wslArguments;\n}\n\n/**\n * Wraps the user command so bash reports where it ended up.\n *\n * The `cd` is done inside the script rather than with `wsl --cd`: a missing directory\n * makes `--cd` fall back to `/` with exit 0 and a warning on stderr, so the command\n * would run in the wrong place and look successful.\n *\n * `$?` is captured before the marker is printed and replayed via `exit`, so the exit\n * status the caller sees is the command's, not `printf`'s.\n *\n * `cwd` appears exactly once, inside `quoteShellArgument`. It must never be interpolated\n * anywhere else — echoing it into a double-quoted diagnostic would let\n * `cwd: '/x\"; rm -rf /; #'` run arbitrary commands with every guard bypassed. The\n * failure message is therefore a fixed string.\n */\nexport function buildDistroScript(command: string, cwd: string | undefined, trackCwd: boolean): string {\n const lines: string[] = [];\n\n if (cwd != null && cwd !== \"\") {\n const quotedCwd = quoteShellArgument(cwd);\n lines.push(`cd ${quotedCwd} 2>/dev/null || { echo 'akms-mcp-wsl: cannot enter the requested working directory' >&2; exit 1; }`);\n }\n\n lines.push(command);\n\n if (trackCwd == true) {\n lines.push(\"__akms_exit=$?\");\n lines.push(`printf '\\\\n${CWD_MARKER}%s' \"$PWD\"`);\n lines.push(\"exit $__akms_exit\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Splits the trailing `$PWD` marker off stdout. */\nexport function extractCwdMarker(stdout: string): { output: string; cwd?: string } {\n const markerIndex = stdout.lastIndexOf(CWD_MARKER);\n if (markerIndex < 0) {\n return { output: stdout };\n }\n\n // First line only: `$PWD` is a single line, so anything past a newline is not the\n // directory and must not end up in the `cd` prefix of the next command.\n const markerPayload = stdout.slice(markerIndex + CWD_MARKER.length);\n const cwd = (markerPayload.split(\"\\n\")[0] ?? \"\").trim();\n\n let output = stdout.slice(0, markerIndex);\n if (output.endsWith(\"\\n\") == true) {\n output = output.slice(0, -1);\n }\n\n if (cwd === \"\") {\n return { output: output };\n }\n\n return { output: output, cwd: cwd };\n}\n","import { spawn } from \"node:child_process\";\r\nimport type { Readable, Writable } from \"node:stream\";\r\n\r\nimport { MAX_CONCURRENT_PROCESSES, OUTPUT_HARD_CAP_MULTIPLIER, WSL_EXECUTABLE, WSL_FAILURE_EXIT_CODES } from \"@/_defs\";\r\nimport { $logger, truncateOutput } from \"@/_libs\";\r\nimport type { WslExecResult, WslHostProfile } from \"@/_types\";\r\nimport { GuardRejectionError, canonicalizeCommand, inspectWorkingDirectory, inspectWslCommand } from \"@/modules/guard\";\r\n\r\nimport { buildDistroScript, buildWslArguments, extractCwdMarker } from \"./wsl-command\";\r\n\r\nexport interface WslExecOptions {\r\n command: string;\r\n /** Directory to `cd` into first; the login shell's default is used when absent. */\r\n cwd?: string;\r\n timeoutMs: number;\r\n maxOutputCharacters: number;\r\n /** Appends a `$PWD` marker so a session can follow `cd` between commands. */\r\n trackCwd: boolean;\r\n}\r\n\r\n/** A fixed script run without the command guard — the file operations, whose only variable part is a quoted path. */\r\nexport interface WslProcessOptions {\r\n script: string;\r\n /** Fed to the process and then closed; absent means stdin is closed from the start. */\r\n stdin?: Buffer | Readable;\r\n /** When set, stdout streams here instead of being buffered, and `stdout` comes back empty. */\r\n stdoutSink?: Writable;\r\n timeoutMs: number;\r\n /** Bytes buffered per stream before the process is killed. */\r\n maxCapturedBytes: number;\r\n}\r\n\r\nexport interface WslProcessOutput {\r\n stdout: Buffer;\r\n stderr: Buffer;\r\n /** Bytes that went to `stdoutSink`, when one was given. */\r\n sinkBytes: number;\r\n exitCode: number | null;\r\n signal?: string;\r\n timedOut: boolean;\r\n capExceeded: boolean;\r\n durationMs: number;\r\n}\r\n\r\nlet activeProcessCount = 0;\r\n\r\n/**\r\n * One distro + user, plus the operations run in it. Every call is its own `wsl.exe`\r\n * process; nothing is held between calls.\r\n *\r\n * This class is the chokepoint: it holds the profile, so it applies the command guard\r\n * itself rather than trusting each caller to remember — the same reasoning as\r\n * `SshConnection` in `@akms/mcp-ssh`.\r\n */\r\nexport class WslHost {\r\n constructor(public readonly profile: WslHostProfile) {\r\n }\r\n\r\n /**\r\n * Screens a command against this profile's policy, then runs it.\r\n *\r\n * The canonical form is what gets screened *and* what gets sent — validating one\r\n * string while executing another is a bypass by construction.\r\n *\r\n * @throws {GuardRejectionError} If the policy refuses the command or the cwd.\r\n * @throws {Error} If `wsl.exe` itself fails (unknown distro, service down) or cannot be spawned.\r\n */\r\n async exec(options: WslExecOptions): Promise<WslExecResult> {\r\n const canonicalCommand = canonicalizeCommand(options.command);\r\n\r\n const verdict = inspectWslCommand(canonicalCommand, this.profile);\r\n if (verdict.allowed == false) {\r\n throw new GuardRejectionError(verdict);\r\n }\r\n\r\n if (options.cwd != null) {\r\n const cwdVerdict = inspectWorkingDirectory(options.cwd);\r\n if (cwdVerdict.allowed == false) {\r\n throw new GuardRejectionError(cwdVerdict);\r\n }\r\n }\r\n\r\n const _logger = $logger.child({ context: \"WslHost.exec\", profile: this.profile.name, cwd: options.cwd });\r\n\r\n const script = buildDistroScript(canonicalCommand, options.cwd, options.trackCwd);\r\n const raw = await this.runProcess({\r\n script: script,\r\n timeoutMs: options.timeoutMs,\r\n maxCapturedBytes: options.maxOutputCharacters * OUTPUT_HARD_CAP_MULTIPLIER,\r\n });\r\n\r\n // Only parse the marker when this call asked for it — otherwise output that merely\r\n // contains the marker text would be silently cut at that point.\r\n let output = raw.stdout.toString(\"utf8\");\r\n let cwd: string | undefined = undefined;\r\n if (options.trackCwd == true) {\r\n const parsed = extractCwdMarker(output);\r\n output = parsed.output;\r\n cwd = parsed.cwd;\r\n }\r\n\r\n const truncatedStdout = truncateOutput(output, options.maxOutputCharacters);\r\n const truncatedStderr = truncateOutput(raw.stderr.toString(\"utf8\"), options.maxOutputCharacters);\r\n\r\n const result: WslExecResult = {\r\n stdout: truncatedStdout.text,\r\n stderr: truncatedStderr.text,\r\n exitCode: raw.exitCode,\r\n timedOut: raw.timedOut,\r\n truncated: truncatedStdout.truncated == true || truncatedStderr.truncated == true || raw.capExceeded == true,\r\n durationMs: raw.durationMs,\r\n };\r\n\r\n if (raw.signal != null) {\r\n result.signal = raw.signal;\r\n }\r\n\r\n if (cwd != null) {\r\n result.cwd = cwd;\r\n }\r\n\r\n _logger.debug(\"command finished\", {\r\n exit_code: result.exitCode,\r\n duration_ms: result.durationMs,\r\n timed_out: result.timedOut,\r\n truncated: result.truncated,\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Spawns `wsl.exe` for one script and collects what it produced.\r\n *\r\n * Not guarded — callers own that: `exec` screens the command, the file operations\r\n * screen the path and build the script themselves. stdin is closed (or fed and then\r\n * closed) so anything that waits for input fails at once instead of hanging until the\r\n * timeout.\r\n *\r\n * @throws {Error} If the process ceiling is reached, `wsl.exe` cannot be started, or\r\n * `wsl.exe` reports a failure of its own rather than the command's exit\r\n * status — that message (unknown distro, service down) is the whole diagnosis.\r\n */\r\n async runProcess(options: WslProcessOptions): Promise<WslProcessOutput> {\r\n if (activeProcessCount >= MAX_CONCURRENT_PROCESSES) {\r\n throw new Error(`too many concurrent wsl.exe processes (${MAX_CONCURRENT_PROCESSES}); wait for running calls to finish`);\r\n }\r\n\r\n const _logger = $logger.child({ context: \"WslHost.runProcess\", profile: this.profile.name });\r\n const wslArguments = buildWslArguments(this.profile, options.script);\r\n const startedAt = Date.now();\r\n\r\n activeProcessCount += 1;\r\n try {\r\n const raw = await new Promise<WslProcessOutput>((resolve, reject) => {\r\n let stdinMode: \"ignore\" | \"pipe\" = \"ignore\";\r\n if (options.stdin != null) {\r\n stdinMode = \"pipe\";\r\n }\r\n\r\n const child = spawn(WSL_EXECUTABLE, wslArguments, {\r\n // WSL_UTF8: wsl.exe's *own* messages (unknown distro, service errors) are\r\n // UTF-16 by default even on a pipe; the Linux side is UTF-8 regardless.\r\n env: { ...process.env, WSL_UTF8: \"1\" },\r\n stdio: [stdinMode, \"pipe\", \"pipe\"],\r\n windowsHide: true,\r\n });\r\n\r\n // Typed nullable for the 'ignore' / 'inherit' cases; both are pipes here.\r\n const stdoutStream = child.stdout;\r\n const stderrStream = child.stderr;\r\n if (stdoutStream == null || stderrStream == null) {\r\n reject(new Error(\"wsl.exe was spawned without stdio pipes\"));\r\n return;\r\n }\r\n\r\n const stdoutChunks: Buffer[] = [];\r\n const stderrChunks: Buffer[] = [];\r\n let stdoutBytes = 0;\r\n let stderrBytes = 0;\r\n let sinkBytes = 0;\r\n let timedOut = false;\r\n let capExceeded = false;\r\n let settled = false;\r\n // A local read error mid-upload: the distro-side `cat` would see a clean\r\n // EOF and exit 0, reporting a truncated upload as success.\r\n let stdinFailure: Error | null = null;\r\n\r\n const timeoutTimer = setTimeout(() => {\r\n timedOut = true;\r\n _logger.warn(\"command timed out, killing wsl.exe\", { timeout_ms: options.timeoutMs });\r\n child.kill();\r\n }, options.timeoutMs);\r\n timeoutTimer.unref();\r\n\r\n const finish = (exitCode: number | null, signal: NodeJS.Signals | null): void => {\r\n if (settled == true) {\r\n return;\r\n }\r\n settled = true;\r\n clearTimeout(timeoutTimer);\r\n\r\n const output: WslProcessOutput = {\r\n stdout: Buffer.concat(stdoutChunks),\r\n stderr: Buffer.concat(stderrChunks),\r\n sinkBytes: sinkBytes,\r\n exitCode: exitCode,\r\n timedOut: timedOut,\r\n capExceeded: capExceeded,\r\n durationMs: Date.now() - startedAt,\r\n };\r\n if (signal != null) {\r\n output.signal = signal;\r\n }\r\n\r\n resolve(output);\r\n };\r\n\r\n const fail = (error: Error): void => {\r\n if (settled == true) {\r\n return;\r\n }\r\n settled = true;\r\n clearTimeout(timeoutTimer);\r\n reject(error);\r\n };\r\n\r\n // Latch: packets keep arriving after the cap trips and kill() is asynchronous.\r\n const exceedCap = (stream: string): void => {\r\n if (capExceeded == true) {\r\n return;\r\n }\r\n capExceeded = true;\r\n _logger.warn(`${stream} exceeded the hard cap, killing wsl.exe`, { hard_cap: options.maxCapturedBytes });\r\n child.kill();\r\n };\r\n\r\n if (options.stdoutSink != null) {\r\n const sink = options.stdoutSink;\r\n stdoutStream.on(\"data\", (chunk: Buffer) => {\r\n sinkBytes += chunk.length;\r\n });\r\n stdoutStream.pipe(sink, { end: false });\r\n sink.on(\"error\", fail);\r\n }\r\n else {\r\n stdoutStream.on(\"data\", (chunk: Buffer) => {\r\n if (capExceeded == true) {\r\n return;\r\n }\r\n stdoutChunks.push(chunk);\r\n stdoutBytes += chunk.length;\r\n if (stdoutBytes > options.maxCapturedBytes) {\r\n exceedCap(\"stdout\");\r\n }\r\n });\r\n }\r\n\r\n stderrStream.on(\"data\", (chunk: Buffer) => {\r\n if (capExceeded == true) {\r\n return;\r\n }\r\n stderrChunks.push(chunk);\r\n stderrBytes += chunk.length;\r\n if (stderrBytes > options.maxCapturedBytes) {\r\n exceedCap(\"stderr\");\r\n }\r\n });\r\n\r\n child.on(\"error\", fail);\r\n // 'close' rather than 'exit': the stdio streams are drained by then.\r\n child.on(\"close\", (exitCode, signal) => {\r\n if (stdinFailure != null) {\r\n fail(new Error(`local input failed while feeding the distro: ${stdinFailure.message}`));\r\n return;\r\n }\r\n finish(exitCode, signal);\r\n });\r\n\r\n if (options.stdin != null && child.stdin != null) {\r\n // A process that exits before reading everything (a guard-free `head`,\r\n // a failing `cat`) makes the pipe error with EPIPE; that is not a failure\r\n // of the operation, whose exit code and stderr say what happened.\r\n child.stdin.on(\"error\", () => {\r\n // intentionally ignored\r\n });\r\n\r\n if (Buffer.isBuffer(options.stdin) == true) {\r\n child.stdin.end(options.stdin);\r\n }\r\n else {\r\n const source = options.stdin as Readable;\r\n source.on(\"error\", (error: Error) => {\r\n stdinFailure = error;\r\n child.kill();\r\n });\r\n source.pipe(child.stdin);\r\n }\r\n }\r\n });\r\n\r\n // wsl.exe's own failure comes back as an exit status the command could never\r\n // produce, with the reason on stdout (Windows-localised). Surface it as an error\r\n // rather than an \"exit code 4294967295\" that the model would misread.\r\n if (raw.exitCode != null && WSL_FAILURE_EXIT_CODES.includes(raw.exitCode) == true) {\r\n let detail = `${raw.stdout.toString(\"utf8\")}\\n${raw.stderr.toString(\"utf8\")}`.trim();\r\n if (detail === \"\" && options.stdoutSink != null) {\r\n // The reason went down the sink with the rest of stdout.\r\n detail = \"wsl.exe reported a failure of its own (unknown distro, WSL service down) — run akms-mcp-wsl --check\";\r\n }\r\n throw new Error(`wsl.exe failed for distro '${this.profile.distro}': ${detail}`);\r\n }\r\n\r\n return raw;\r\n }\r\n finally {\r\n activeProcessCount -= 1;\r\n }\r\n }\r\n}\r\n","import { setInterval, clearInterval } from \"node:timers\";\n\nimport { SESSION_IDLE_TIMEOUT_MS, SESSION_SWEEP_INTERVAL_MS } from \"@/_defs\";\nimport { $logger } from \"@/_libs\";\nimport type { WslExecResult, WslHostProfile, WslSessionInfo } from \"@/_types\";\nimport { inspectWorkingDirectory } from \"@/modules/guard\";\n\nimport { WslHost } from \"./wsl-host\";\n\n/** Ceiling on open sessions — a runaway loop must not grow the map without bound. */\nconst MAX_OPEN_SESSIONS = 32;\n\n/**\n * Shell state carried across commands — the working directory. Nothing else persists:\n * each command is its own `wsl.exe` process, so the session is the memory, not a channel.\n */\nexport class WslSession {\n /** Empty until the first command reports `$PWD`; then the real distro path. */\n cwd: string;\n lastUsedAt: Date;\n execCount = 0;\n\n readonly openedAt = new Date();\n\n /** Tail of the serialized operation chain; see `runExclusive`. */\n private operationChain: Promise<unknown> = Promise.resolve();\n private activeOperationCount = 0;\n\n constructor(\n public readonly sessionId: string,\n public readonly host: WslHost\n ) {\n this.cwd = host.profile.defaultCwd ?? \"\";\n this.lastUsedAt = new Date();\n }\n\n get profile(): WslHostProfile {\n return this.host.profile;\n }\n\n /** True while an operation is running, so the idle sweeper leaves it alone. */\n get isBusy(): boolean {\n return this.activeOperationCount > 0;\n }\n\n touch(): void {\n this.lastUsedAt = new Date();\n }\n\n /**\n * Runs `operation` with exclusive use of this session.\n *\n * Serialized because `cwd` is read-modify-write across a process run: two concurrent\n * calls both read the old directory, and the one that finishes second writes it back —\n * silently undoing the other's `cd`.\n */\n async runExclusive<T>(operation: (host: WslHost) => Promise<T>): Promise<T> {\n const previous = this.operationChain;\n\n let releaseChain: () => void = () => {\n // Replaced below; assigned here so the type is not nullable.\n };\n this.operationChain = new Promise<void>((resolve) => {\n releaseChain = resolve;\n });\n\n await previous.catch(() => {\n // A failed predecessor must not poison the queue for later callers.\n });\n\n this.activeOperationCount += 1;\n this.touch();\n\n try {\n return await operation(this.host);\n }\n finally {\n this.activeOperationCount -= 1;\n this.touch();\n releaseChain();\n }\n }\n\n /**\n * Runs a command in this session's working directory and adopts wherever it ended up,\n * so a `cd` in one call is still in effect on the next.\n *\n * Passing `cwd` runs this command elsewhere *and* moves the session there — same\n * result as prefixing `cd <cwd> &&`, which is what a shell user would expect.\n */\n async exec(command: string, options?: { cwd?: string; timeoutMs?: number }): Promise<WslExecResult> {\n const policy = this.profile.policy;\n const targetCwd = options?.cwd ?? this.cwd;\n\n return await this.runExclusive(async (host) => {\n const result = await host.exec({\n command: command,\n cwd: targetCwd,\n timeoutMs: options?.timeoutMs ?? policy.execTimeoutMs,\n maxOutputCharacters: policy.maxOutputCharacters,\n trackCwd: true,\n });\n\n if (result.cwd != null && result.cwd !== \"\") {\n // The reported `$PWD` becomes the `cd` argument of the next command, so it\n // goes through the same metacharacter check as a caller-supplied cwd.\n const verdict = inspectWorkingDirectory(result.cwd);\n if (verdict.allowed == true) {\n this.cwd = result.cwd;\n }\n else {\n const _logger = $logger.child({ context: \"WslSession.exec\", session_id: this.sessionId });\n _logger.warn(\"reported working directory contains unsafe characters, keeping the previous cwd\", {\n reported_cwd: result.cwd,\n });\n }\n }\n\n this.execCount += 1;\n return result;\n });\n }\n\n toInfo(): WslSessionInfo {\n let displayCwd = this.cwd;\n if (displayCwd === \"\") {\n displayCwd = \"(login default)\";\n }\n\n return {\n sessionId: this.sessionId,\n profileName: this.profile.name,\n distro: this.profile.distro,\n username: this.profile.username ?? \"(distro default)\",\n cwd: displayCwd,\n openedAt: this.openedAt.toISOString(),\n lastUsedAt: this.lastUsedAt.toISOString(),\n execCount: this.execCount,\n };\n }\n}\n\n/** Owns every open session: creation, lookup, idle expiry and shutdown. */\nexport class WslSessionManager {\n private readonly sessions = new Map<string, WslSession>();\n private sequence = 0;\n private sweepTimer: NodeJS.Timeout | null = null;\n\n /**\n * Registers a session. Nothing is opened — the caller probes with `pwd` to prove\n * the distro answers and to settle the starting directory.\n *\n * @throws {Error} If the session ceiling is reached.\n */\n open(host: WslHost): WslSession {\n if (this.sessions.size >= MAX_OPEN_SESSIONS) {\n throw new Error(`too many open wsl sessions (${MAX_OPEN_SESSIONS}), close some with wsl_disconnect first`);\n }\n\n this.sequence += 1;\n const sessionId = `${host.profile.name}#${this.sequence}`;\n\n const session = new WslSession(sessionId, host);\n this.sessions.set(sessionId, session);\n\n const _logger = $logger.child({ context: \"WslSessionManager.open\", session_id: sessionId, profile: host.profile.name });\n _logger.info(\"wsl session opened\", { open_sessions: this.sessions.size });\n\n return session;\n }\n\n /**\n * Looks up a session, failing with the list of live ids so the caller can self-correct.\n *\n * @throws {Error} If no session matches `sessionId`.\n */\n require(sessionId: string): WslSession {\n const session = this.sessions.get(sessionId);\n if (session == null) {\n const openIds = Array.from(this.sessions.keys());\n\n let openSummary = \"none\";\n if (openIds.length > 0) {\n openSummary = openIds.join(\", \");\n }\n\n throw new Error(`unknown wsl session '${sessionId}' (open sessions: ${openSummary})`);\n }\n\n return session;\n }\n\n close(sessionId: string): boolean {\n const deleted = this.sessions.delete(sessionId);\n if (deleted == false) {\n return false;\n }\n\n const _logger = $logger.child({ context: \"WslSessionManager.close\", session_id: sessionId });\n _logger.info(\"wsl session closed\", { open_sessions: this.sessions.size });\n\n return true;\n }\n\n closeAll(): void {\n for (const sessionId of Array.from(this.sessions.keys())) {\n this.close(sessionId);\n }\n }\n\n list(): WslSessionInfo[] {\n return Array.from(this.sessions.values()).map((session) => session.toInfo());\n }\n\n /** Starts the idle sweeper; the timer is unref'd so it never holds the process open. */\n startIdleSweeper(): void {\n if (this.sweepTimer != null) {\n return;\n }\n\n this.sweepTimer = setInterval(() => {\n const expiredAt = Date.now() - SESSION_IDLE_TIMEOUT_MS;\n for (const session of Array.from(this.sessions.values())) {\n if (session.isBusy == true) {\n continue;\n }\n\n if (session.lastUsedAt.getTime() > expiredAt) {\n continue;\n }\n\n const _logger = $logger.child({\n context: \"WslSessionManager.sweep\",\n session_id: session.sessionId,\n idle_ms: Date.now() - session.lastUsedAt.getTime(),\n });\n _logger.info(\"forgetting idle wsl session\");\n this.close(session.sessionId);\n }\n }, SESSION_SWEEP_INTERVAL_MS);\n\n this.sweepTimer.unref();\n }\n\n stopIdleSweeper(): void {\n if (this.sweepTimer == null) {\n return;\n }\n\n clearInterval(this.sweepTimer);\n this.sweepTimer = null;\n }\n}\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\n\r\nimport { MAX_DIRECTORY_ENTRIES } from \"@/_defs\";\r\nimport { quoteShellArgument } from \"@/_libs\";\r\nimport type { WslDirectoryEntry } from \"@/_types\";\r\nimport { GuardRejectionError, inspectWslPath } from \"@/modules/guard\";\r\nimport type { RemotePathAccess } from \"@/modules/guard\";\r\n\r\nimport type { WslHost, WslProcessOutput } from \"./wsl-host\";\r\n\r\n/** Bytes a fixed script may print before it is cut off — listings and stat output, never file content. */\r\nconst METADATA_CAPTURE_BYTES = 4 * 1024 * 1024;\r\n\r\nexport interface DirectoryListing {\r\n entries: WslDirectoryEntry[];\r\n /** Entries the distro reported, before the cap was applied. */\r\n totalCount: number;\r\n truncated: boolean;\r\n}\r\n\r\nexport interface FileContent {\r\n content: string;\r\n /** Size `stat` reported; 0 for virtual files that do not declare one. */\r\n sizeBytes: number;\r\n /** Bytes actually read. */\r\n readBytes: number;\r\n truncated: boolean;\r\n}\r\n\r\n/**\r\n * The file operations run **fixed scripts** (`find`, `stat`, `head`, `cat`) with the\r\n * path single-quoted through `quoteShellArgument` — so they bypass the command guard,\r\n * exactly as SFTP bypasses it in `@akms/mcp-ssh`, and are governed by the path guard\r\n * (`allowedPaths`, read-only, the Windows-mount rules) instead. Two consequences worth\r\n * knowing: `WSL_ALLOW_COMMANDS` does not have to list `find` or `cat`, and a read-only\r\n * profile still refuses writes here because `inspectWslPath` checks `policy.readonly`.\r\n *\r\n * Content travels over the process's stdin / stdout, which are byte-clean pipes — the\r\n * `\\\\wsl$\\` share was rejected because it opens files as the distro's default user,\r\n * not as the registered one.\r\n */\r\nfunction requirePermittedPath(host: WslHost, distroPath: string, access: RemotePathAccess): void {\r\n const verdict = inspectWslPath(distroPath, host.profile, access);\r\n if (verdict.allowed == false) {\r\n throw new GuardRejectionError(verdict);\r\n }\r\n}\r\n\r\n/** Runs a fixed script and throws with its stderr when it failed — the file operations never return partial results. */\r\nasync function runFixedScript(host: WslHost, script: string, stdin?: Buffer | fs.ReadStream): Promise<Buffer> {\r\n const output = await host.runProcess({\r\n script: script,\r\n stdin: stdin,\r\n timeoutMs: host.profile.policy.execTimeoutMs,\r\n maxCapturedBytes: METADATA_CAPTURE_BYTES,\r\n });\r\n\r\n if (output.timedOut == true) {\r\n throw new Error(`timed out after ${host.profile.policy.execTimeoutMs}ms`);\r\n }\r\n\r\n if (output.exitCode !== 0) {\r\n const detail = output.stderr.toString(\"utf8\").trim();\r\n throw new Error(detail === \"\" ? `exit code ${output.exitCode}` : detail);\r\n }\r\n\r\n return output.stdout;\r\n}\r\n\r\nconst ENTRY_TYPES: Record<string, WslDirectoryEntry[\"type\"]> = {\r\n f: \"file\",\r\n d: \"directory\",\r\n l: \"symlink\",\r\n};\r\n\r\n/**\r\n * Lists a directory, directories first then files, each group alphabetical, capped at\r\n * `MAX_DIRECTORY_ENTRIES`. One `find -printf` call; `%y` is the type letter, `%m` the\r\n * octal mode, `%s` bytes, `%T+` the mtime.\r\n */\r\nexport async function listDirectory(host: WslHost, distroPath: string): Promise<DirectoryListing> {\r\n requirePermittedPath(host, distroPath, \"read\");\r\n\r\n const quotedPath = quoteShellArgument(distroPath);\r\n const findPrefix = `find ${quotedPath} -mindepth 1 -maxdepth 1`;\r\n const script = [\r\n `test -d ${quotedPath} || { echo 'not a directory' >&2; exit 2; }`,\r\n // First line: the true entry count. The listing itself is bounded with `head`, so\r\n // a directory of a million files costs the distro a `find`, not this server 4 MB.\r\n `${findPrefix} -printf x | wc -c`,\r\n // One line per entry: type \\t mode \\t size \\t mtime \\t name. `-printf` never quotes,\r\n // and a name cannot contain a newline in any directory a tool should be listing.\r\n `${findPrefix} -printf '%y\\\\t%m\\\\t%s\\\\t%TY-%Tm-%TdT%TH:%TM:%.2TS\\\\t%f\\\\n' | head -n ${MAX_DIRECTORY_ENTRIES + 1}`,\r\n ].join(\"\\n\");\r\n\r\n const stdout = await runFixedScript(host, script);\r\n const [countLine, ...lines] = stdout.toString(\"utf8\").split(\"\\n\").filter((line) => line !== \"\");\r\n const reportedCount = Number(countLine) || 0;\r\n\r\n const entries: WslDirectoryEntry[] = [];\r\n for (const line of lines) {\r\n const [typeLetter, mode, size, modifiedAt, ...nameParts] = line.split(\"\\t\");\r\n const name = nameParts.join(\"\\t\");\r\n if (name == null || name === \"\") {\r\n continue;\r\n }\r\n\r\n entries.push({\r\n name: name,\r\n type: ENTRY_TYPES[typeLetter] ?? \"other\",\r\n sizeBytes: Number(size) || 0,\r\n mode: `0${mode}`,\r\n modifiedAt: modifiedAt,\r\n });\r\n }\r\n\r\n entries.sort((left, right) => {\r\n if (left.type === \"directory\" && right.type !== \"directory\") {\r\n return -1;\r\n }\r\n if (left.type !== \"directory\" && right.type === \"directory\") {\r\n return 1;\r\n }\r\n return left.name.localeCompare(right.name);\r\n });\r\n\r\n const totalCount = Math.max(reportedCount, entries.length);\r\n const truncated = totalCount > MAX_DIRECTORY_ENTRIES;\r\n\r\n return {\r\n entries: entries.slice(0, MAX_DIRECTORY_ENTRIES),\r\n totalCount: totalCount,\r\n truncated: truncated,\r\n };\r\n}\r\n\r\n/**\r\n * Reads the leading `maxBytes` of a file. Two processes — `stat` for the declared size,\r\n * then `head -c` — because mixing a size line into the content stream would need\r\n * escaping that a fixed script should not have.\r\n */\r\nexport async function readFile(host: WslHost, distroPath: string, maxBytes: number): Promise<FileContent> {\r\n requirePermittedPath(host, distroPath, \"read\");\r\n\r\n const quotedPath = quoteShellArgument(distroPath);\r\n const statScript = [\r\n `test -e ${quotedPath} || { echo 'no such file' >&2; exit 2; }`,\r\n `test -d ${quotedPath} && { echo 'is a directory' >&2; exit 2; }`,\r\n `stat -c %s ${quotedPath}`,\r\n ].join(\"\\n\");\r\n const sizeBytes = Number((await runFixedScript(host, statScript)).toString(\"utf8\").trim()) || 0;\r\n\r\n // One byte past the limit tells truncation apart from \"exactly the limit\" without a\r\n // second stat of a file that may have grown in between.\r\n const probeBytes = maxBytes + 1;\r\n const output = await host.runProcess({\r\n script: `head -c ${probeBytes} ${quotedPath}`,\r\n timeoutMs: host.profile.policy.execTimeoutMs,\r\n maxCapturedBytes: probeBytes,\r\n });\r\n\r\n if (output.exitCode !== 0 && output.capExceeded == false) {\r\n throw new Error(output.stderr.toString(\"utf8\").trim() || `exit code ${output.exitCode}`);\r\n }\r\n\r\n const truncated = output.stdout.length > maxBytes;\r\n const kept = output.stdout.subarray(0, maxBytes);\r\n\r\n return {\r\n content: kept.toString(\"utf8\"),\r\n sizeBytes: sizeBytes,\r\n readBytes: kept.length,\r\n truncated: truncated,\r\n };\r\n}\r\n\r\n/**\r\n * Writes or appends UTF-8 text. Content goes through stdin, so nothing in it is ever\r\n * shell-parsed; only the path is interpolated, quoted.\r\n *\r\n * @returns Bytes written.\r\n */\r\nexport async function writeFile(host: WslHost, args: { distroPath: string; content: string; append: boolean }): Promise<number> {\r\n const { distroPath, content, append } = args;\r\n\r\n requirePermittedPath(host, distroPath, \"write\");\r\n\r\n const payload = Buffer.from(content, \"utf8\");\r\n const quotedPath = quoteShellArgument(distroPath);\r\n\r\n let redirection = \">\";\r\n if (append == true) {\r\n redirection = \">>\";\r\n }\r\n\r\n await runFixedScript(host, `cat ${redirection} ${quotedPath}`, payload);\r\n return payload.length;\r\n}\r\n\r\n/**\r\n * Local → distro. The local file is streamed into the process's stdin, so size is bounded\r\n * by the distro's disk, not this server's memory.\r\n *\r\n * @returns Bytes sent, from the local file's size.\r\n */\r\nexport async function uploadFile(host: WslHost, localPath: string, distroPath: string): Promise<number> {\r\n requirePermittedPath(host, distroPath, \"write\");\r\n\r\n const localStats = fs.statSync(localPath);\r\n if (localStats.isFile() == false) {\r\n throw new Error(`local path is not a regular file: ${localPath}`);\r\n }\r\n\r\n const stream = fs.createReadStream(localPath);\r\n try {\r\n await runFixedScript(host, `cat > ${quoteShellArgument(distroPath)}`, stream);\r\n }\r\n finally {\r\n stream.destroy();\r\n }\r\n\r\n return localStats.size;\r\n}\r\n\r\n/**\r\n * Distro → local. stdout streams straight into the destination file, so a large download\r\n * never sits in memory. The destination's parent must already exist — the tool creates\r\n * no directories on the operator's machine.\r\n *\r\n * @returns Bytes received.\r\n */\r\nexport async function downloadFile(host: WslHost, distroPath: string, localPath: string): Promise<number> {\r\n requirePermittedPath(host, distroPath, \"read\");\r\n\r\n const parent = path.dirname(localPath);\r\n if (fs.existsSync(parent) == false) {\r\n throw new Error(`local directory does not exist: ${parent}`);\r\n }\r\n\r\n const quotedPath = quoteShellArgument(distroPath);\r\n const script = [\r\n `test -f ${quotedPath} || { echo 'not a regular file' >&2; exit 2; }`,\r\n `cat ${quotedPath}`,\r\n ].join(\"\\n\");\r\n\r\n const sink = fs.createWriteStream(localPath);\r\n let output: WslProcessOutput;\r\n try {\r\n output = await host.runProcess({\r\n script: script,\r\n stdoutSink: sink,\r\n timeoutMs: host.profile.policy.execTimeoutMs,\r\n maxCapturedBytes: METADATA_CAPTURE_BYTES,\r\n });\r\n\r\n if (output.timedOut == true) {\r\n throw new Error(`timed out after ${host.profile.policy.execTimeoutMs}ms; the partial file was removed`);\r\n }\r\n\r\n if (output.exitCode !== 0) {\r\n throw new Error(output.stderr.toString(\"utf8\").trim() || `exit code ${output.exitCode}`);\r\n }\r\n }\r\n catch (ex) {\r\n // Whatever failed — the distro, wsl.exe itself, the timeout — a half-written or\r\n // empty destination must not be left looking like a download.\r\n await new Promise<void>((resolve) => {\r\n sink.end(resolve);\r\n });\r\n fs.rmSync(localPath, { force: true });\r\n throw ex;\r\n }\r\n\r\n await new Promise<void>((resolve) => {\r\n sink.end(resolve);\r\n });\r\n\r\n return output.sinkBytes;\r\n}\r\n","import { spawn } from \"node:child_process\";\r\n\r\nimport { WSL_EXECUTABLE } from \"@/_defs\";\r\nimport { $logger } from \"@/_libs\";\r\nimport type { WslDistroStatus } from \"@/_types\";\r\n\r\nimport type { WslHost } from \"./wsl-host\";\r\n\r\nconst LISTING_TIMEOUT_MS = 10_000;\r\n\r\n/** Bytes to keep from a probe — a few lines at most. */\r\nconst PROBE_CAPTURE_BYTES = 64 * 1024;\r\n\r\n/** One row of `wsl -l -v`: optional default marker, name, state, version. */\r\nconst LISTING_ROW_PATTERN = /^\\s*\\*?\\s*(.+?)\\s+(Running|Stopped|Installing)\\s+(\\d)\\s*$/;\r\n\r\n/**\r\n * What `wsl.exe -l -v` says about the distro. Does not start it — that is what makes\r\n * this safe to call from `wsl_list_hosts` and `--check` without side effects.\r\n *\r\n * @throws {Error} If `wsl.exe` cannot be started at all.\r\n */\r\nexport async function queryDistroListing(distro: string): Promise<WslDistroStatus> {\r\n const _logger = $logger.child({ context: \"queryDistroListing\", distro: distro });\r\n\r\n const listing = await new Promise<string>((resolve, reject) => {\r\n const child = spawn(WSL_EXECUTABLE, [\"-l\", \"-v\"], {\r\n env: { ...process.env, WSL_UTF8: \"1\" },\r\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\r\n windowsHide: true,\r\n });\r\n\r\n const chunks: Buffer[] = [];\r\n const timer = setTimeout(() => {\r\n child.kill();\r\n }, LISTING_TIMEOUT_MS);\r\n timer.unref();\r\n\r\n child.stdout.on(\"data\", (chunk: Buffer) => {\r\n chunks.push(chunk);\r\n });\r\n child.on(\"error\", (error) => {\r\n clearTimeout(timer);\r\n reject(error);\r\n });\r\n child.on(\"close\", () => {\r\n clearTimeout(timer);\r\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\r\n });\r\n });\r\n\r\n for (const line of listing.split(/\\r?\\n/)) {\r\n const match = LISTING_ROW_PATTERN.exec(line);\r\n if (match == null) {\r\n continue;\r\n }\r\n\r\n if (match[1].toLowerCase() !== distro.toLowerCase()) {\r\n continue;\r\n }\r\n\r\n return {\r\n installed: true,\r\n state: match[2] as WslDistroStatus[\"state\"],\r\n wslVersion: Number(match[3]),\r\n };\r\n }\r\n\r\n _logger.warn(\"distro not present in wsl -l -v\");\r\n return { installed: false, state: \"unknown\" };\r\n}\r\n\r\n/**\r\n * Facts only visible from inside: networking mode, whether systemd is PID 1, the kernel.\r\n * Starts the distro when it is stopped, so callers check the listing first and skip this\r\n * for a stopped distro unless starting it is the intent.\r\n *\r\n * Runs as a fixed script through `runProcess`, bypassing the command guard — the script\r\n * has no variable part and an allow-list profile must still be able to describe itself.\r\n */\r\nexport async function probeDistroFacts(host: WslHost): Promise<Pick<WslDistroStatus, \"networkingMode\" | \"systemd\" | \"kernel\">> {\r\n const script = [\r\n \"printf 'mode=%s\\\\n' \\\"$(wslinfo --networking-mode 2>/dev/null || echo unknown)\\\"\",\r\n \"printf 'init=%s\\\\n' \\\"$(ps -p 1 -o comm= 2>/dev/null || echo unknown)\\\"\",\r\n \"printf 'kernel=%s\\\\n' \\\"$(uname -r 2>/dev/null || echo unknown)\\\"\",\r\n ].join(\"\\n\");\r\n\r\n const output = await host.runProcess({\r\n script: script,\r\n timeoutMs: LISTING_TIMEOUT_MS,\r\n maxCapturedBytes: PROBE_CAPTURE_BYTES,\r\n });\r\n\r\n const facts: Pick<WslDistroStatus, \"networkingMode\" | \"systemd\" | \"kernel\"> = {};\r\n for (const line of output.stdout.toString(\"utf8\").split(\"\\n\")) {\r\n const [key, ...rest] = line.split(\"=\");\r\n const value = rest.join(\"=\").trim();\r\n if (key === \"mode\") {\r\n facts.networkingMode = value;\r\n }\r\n else if (key === \"init\") {\r\n facts.systemd = value === \"systemd\";\r\n }\r\n else if (key === \"kernel\") {\r\n facts.kernel = value;\r\n }\r\n }\r\n\r\n return facts;\r\n}\r\n","import { SINGLE_HOST_ENV } from \"@/_defs\";\nimport { formatBytes } from \"@/_libs\";\nimport type { GuardVerdict, WslDirectoryEntry, WslDistroStatus, WslExecResult, WslHostProfile, WslSessionInfo } from \"@/_types\";\nimport { toHostSummary } from \"@/modules/config\";\nimport type { DirectoryListing } from \"@/modules/wsl\";\n\nconst ENTRY_TYPE_MARKERS: Record<WslDirectoryEntry[\"type\"], string> = {\n file: \"-\",\n directory: \"d\",\n symlink: \"l\",\n other: \"?\",\n};\n\n/**\n * Renders the configured distro for `wsl_list_hosts`, or setup instructions when none is\n * registered. `status` is what `wsl -l -v` (and, when running, a probe inside) reported.\n */\nexport function formatHostProfile(profile: WslHostProfile | null, status: WslDistroStatus | null): string {\n if (profile == null) {\n return [\n \"No WSL distro is registered.\",\n \"\",\n \"Put the distro in this server's MCP entry — one server entry per distro and user:\",\n \"\",\n ` \"env\": {`,\n ` \"${SINGLE_HOST_ENV.DISTRO}\": \"ubuntu\",`,\n ` \"${SINGLE_HOST_ENV.USER}\": \"root\"`,\n \" }\",\n \"\",\n `${SINGLE_HOST_ENV.DISTRO} is the whole minimum (the name as 'wsl -l -q' prints it); ${SINGLE_HOST_ENV.USER} defaults to the distro's default user.`,\n \"Restart this server after changing it — environment variables are fixed for the life of the process.\",\n ].join(\"\\n\");\n }\n\n const summary = toHostSummary(profile);\n\n let accessLabel = \"writable\";\n if (summary.readonly == true) {\n accessLabel = \"READ-ONLY\";\n }\n\n let sudoLabel = \"sudo=disabled\";\n if (summary.allowSudo == true) {\n sudoLabel = \"sudo=enabled\";\n }\n\n let windowsLabel = \"windows=locked (no interop .exe, no writes under /mnt/<drive>/)\";\n if (summary.allowWindows == true) {\n windowsLabel = \"windows=open (interop .exe and /mnt/<drive>/ writes allowed; operator credential and MCP config paths still refused)\";\n }\n\n const lines: string[] = [];\n lines.push(`${summary.name} → ${summary.username}@${summary.distro} (WSL, this machine) ${accessLabel} ${sudoLabel}`);\n lines.push(` ${windowsLabel}`);\n\n if (summary.description != null) {\n lines.push(` ${summary.description}`);\n }\n\n if (status != null) {\n lines.push(` ${formatDistroStatus(status)}`);\n }\n\n if (summary.allowedPaths.length > 0) {\n // Scope stated explicitly: allowedPaths binds the file tools only, and reading it\n // as a filesystem-wide restriction would be a dangerous misunderstanding —\n // wsl_exec can still `cat` anything the user can read.\n lines.push(` file tools limited to: ${summary.allowedPaths.join(\", \")} (does not restrict wsl_exec)`);\n }\n\n if (summary.allowCommands.length > 0) {\n lines.push(` commands limited to: ${summary.allowCommands.join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** One line: installed / state / WSL version, plus the inside facts when they were probed. */\nexport function formatDistroStatus(status: WslDistroStatus): string {\n if (status.installed == false) {\n return \"distro: NOT FOUND in 'wsl -l -v' — check the name (wsl -l -q) and the WSL_DISTRO variable\";\n }\n\n const parts: string[] = [`distro: ${status.state}`];\n if (status.wslVersion != null) {\n parts.push(`WSL ${status.wslVersion}`);\n }\n if (status.networkingMode != null) {\n parts.push(`networking ${status.networkingMode}`);\n }\n if (status.systemd != null) {\n if (status.systemd == true) {\n parts.push(\"systemd\");\n }\n else {\n parts.push(\"no systemd\");\n }\n }\n if (status.kernel != null) {\n parts.push(`kernel ${status.kernel}`);\n }\n if (status.state === \"Stopped\") {\n parts.push(\"(the first command will start it)\");\n }\n\n return parts.join(\" · \");\n}\n\n/**\n * Renders a command result: a status line (exit code, duration, cwd), any timeout or\n * truncation notice, then the stdout and stderr sections.\n *\n * @param timeoutMs The limit that applied, quoted in the timeout notice.\n */\nexport function formatExecResult(result: WslExecResult, timeoutMs: number): string {\n const headerParts: string[] = [];\n\n if (result.exitCode != null) {\n headerParts.push(`exit code: ${result.exitCode}`);\n }\n else {\n headerParts.push(\"exit code: none (killed)\");\n }\n\n if (result.signal != null) {\n headerParts.push(`signal: ${result.signal}`);\n }\n\n headerParts.push(`${result.durationMs}ms`);\n\n if (result.cwd != null) {\n headerParts.push(`cwd: ${result.cwd}`);\n }\n\n const lines: string[] = [headerParts.join(\" · \")];\n\n if (result.timedOut == true) {\n lines.push(`TIMED OUT after ${timeoutMs}ms — wsl.exe was killed, but the process inside the distro may still be running.`);\n }\n\n if (result.truncated == true) {\n lines.push(\"Output was truncated; narrow the command (grep / head / tail) or raise WSL_MAX_OUTPUT for this profile.\");\n }\n\n lines.push(\"\");\n lines.push(\"--- stdout ---\");\n if (result.stdout === \"\") {\n lines.push(\"(empty)\");\n }\n else {\n lines.push(result.stdout);\n }\n\n if (result.stderr !== \"\") {\n lines.push(\"\");\n lines.push(\"--- stderr ---\");\n lines.push(result.stderr);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Rejection message: what was blocked, why, and what would make it legal. */\nexport function formatGuardRejection(action: string, verdict: GuardVerdict): string {\n const lines: string[] = [`Blocked by the host profile's guard policy: ${verdict.reason}`];\n\n if (verdict.offendingText != null && verdict.offendingText !== action) {\n lines.push(`Offending part: ${verdict.offendingText}`);\n }\n\n lines.push(`Requested: ${action}`);\n lines.push(\"Nothing was run in the distro. Adjust the request, or relax the profile's policy in the MCP entry.\");\n\n return lines.join(\"\\n\");\n}\n\n/** Renders open sessions with distro, working directory, command count and idle time. */\nexport function formatSessionList(sessions: WslSessionInfo[]): string {\n if (sessions.length === 0) {\n return \"No open WSL sessions. Open one with wsl_connect, or omit 'session' to run a one-off command.\";\n }\n\n const lines: string[] = [`${sessions.length} open WSL session(s):`];\n const now = Date.now();\n\n for (const session of sessions) {\n const idleSeconds = Math.round((now - new Date(session.lastUsedAt).getTime()) / 1000);\n lines.push(\"\");\n lines.push(`${session.sessionId} → ${session.username}@${session.distro} profile: ${session.profileName}`);\n lines.push(` cwd: ${session.cwd} · ${session.execCount} command(s) · idle ${idleSeconds}s · opened ${session.openedAt}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Renders a directory listing as one row per entry (type, mode, size, mtime, name),\n * noting the true total when the listing was capped.\n */\nexport function formatDirectoryListing(distroPath: string, listing: DirectoryListing): string {\n if (listing.totalCount === 0) {\n return `${distroPath} is empty.`;\n }\n\n let header = `${distroPath} — ${listing.totalCount} entrie(s):`;\n if (listing.truncated == true) {\n header = `${distroPath} — ${listing.totalCount} entrie(s), showing the first ${listing.entries.length}:`;\n }\n\n const lines: string[] = [header, \"\"];\n\n for (const entry of listing.entries) {\n const marker = ENTRY_TYPE_MARKERS[entry.type];\n const size = formatBytes(entry.sizeBytes).padStart(9);\n\n let name = entry.name;\n if (entry.type === \"directory\") {\n name = `${entry.name}/`;\n }\n\n lines.push(`${marker} ${entry.mode} ${size} ${entry.modifiedAt} ${name}`);\n }\n\n if (listing.truncated == true) {\n lines.push(\"\");\n lines.push(\"Listing was capped; narrow the path or filter with wsl_exec if you need the rest.\");\n }\n\n return lines.join(\"\\n\");\n}\n","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { SINGLE_HOST_ENV } from \"@/_defs\";\nimport { $logger } from \"@/_libs\";\nimport { GuardRejectionError } from \"@/modules/guard\";\nimport { WslHost, WslSession, WslSessionManager } from \"@/modules/wsl\";\n\nimport { formatGuardRejection } from \"./format\";\n\n/** Everything the tool handlers share: the configured distro and the live sessions. */\nexport interface ToolContext {\n /** The distro from the `WSL_*` variables, or null when none is registered. */\n host: WslHost | null;\n sessions: WslSessionManager;\n}\n\nexport function textResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text: text }] };\n}\n\n/** Marked `isError` so the model sees the call failed rather than reading it as output. */\nexport function errorResult(message: string): CallToolResult {\n return { content: [{ type: \"text\", text: message }], isError: true };\n}\n\nexport function describeError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\n/**\n * Renders a failure for the model, separating the two cases it must treat differently:\n * a guard rejection is a policy decision not worth retrying, anything else is an\n * operational failure that might succeed on a second attempt.\n */\nexport function toToolError(error: unknown, toolName: string, action: string): CallToolResult {\n const _logger = $logger.child({ context: toolName });\n\n if (error instanceof GuardRejectionError) {\n _logger.warn(\"rejected by the guard\", { reason: error.verdict.reason, action: action });\n\n const rendered = formatGuardRejection(action, error.verdict);\n return errorResult(rendered);\n }\n\n _logger.error(error, `${toolName} failed`);\n return errorResult(`${toolName} failed: ${describeError(error)}`);\n}\n\n/**\n * Resolves the optional `session` argument to the host, without running anything.\n *\n * There is no distro argument — this server fronts exactly the distro in its own env\n * block, which is what keeps the model from being able to name one.\n *\n * @throws {Error} If no distro is registered, or the session id is not open.\n */\nexport function resolveHost(\n context: ToolContext,\n args: { session?: string }\n): { host: WslHost; session: WslSession | null } {\n const hasSession = args.session != null && args.session.trim() !== \"\";\n if (hasSession == true) {\n const session = context.sessions.require((args.session as string).trim());\n return { host: session.host, session: session };\n }\n\n if (context.host == null) {\n throw new Error(`no distro is registered — set ${SINGLE_HOST_ENV.DISTRO} (and optionally ${SINGLE_HOST_ENV.USER}) in this server's env block, then restart it`);\n }\n\n return { host: context.host, session: null };\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport { $logger } from \"@/_libs\";\nimport type { WslExecResult } from \"@/_types\";\n\nimport { formatExecResult } from \"./format\";\nimport { resolveHost, textResult, toToolError } from \"./tool-context\";\nimport type { ToolContext } from \"./tool-context\";\n\nexport function registerExecTools(server: McpServer, context: ToolContext): void {\n server.registerTool(\n \"wsl_exec\",\n {\n title: \"Run a command in WSL\",\n description: [\n \"Run a shell command in the configured WSL distro (as the configured user, in a login bash) and return stdout, stderr and the exit code.\",\n \"Pass 'session' to reuse a session, which remembers its working directory; omit it for a one-off call.\",\n \"A non-zero exit code is reported as normal output, not as a tool error — read the exit code and stderr to judge the outcome.\",\n \"Almost everything is permitted: package installs, service restarts, sudo, interpreters. Refused outright: catastrophic operations (wiping the filesystem root, formatting a disk, powering off or shutting down the distro), and — unless the profile opens them — Windows interop executables and writes under /mnt/<drive>/.\",\n \"stdin is closed. A job that must outlive the call needs all three descriptors detached: nohup cmd > log 2>&1 < /dev/null &\",\n ].join(\" \"),\n inputSchema: {\n command: z.string().min(1).describe(\"Shell command, exactly as it would be typed in a terminal. Chaining with ';', '&&', '||' and pipes is allowed; each part is screened separately.\"),\n session: z.string().optional().describe(\"Session id from wsl_connect. Keeps the working directory across calls.\"),\n cwd: z.string().optional().describe(\"Absolute directory to run in, with no shell metacharacters. With a session, the session also moves there.\"),\n timeoutMs: z.number().int().positive().optional().describe(\"Lowers the command timeout for this call; it cannot exceed the profile's own limit. wsl.exe is killed when it elapses; the process inside the distro may survive.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n async ({ command, session, cwd, timeoutMs }) => {\n let _logger = $logger.child({ context: \"wsl_exec\" });\n\n try {\n const { host, session: openSession } = resolveHost(context, { session: session });\n const profile = host.profile;\n _logger = _logger.child({ profile: profile.name, session_id: openSession?.sessionId });\n\n // Clamped, not defaulted: a per-call override that could exceed the profile\n // ceiling would make the ceiling advisory.\n const requestedTimeoutMs = timeoutMs ?? profile.policy.execTimeoutMs;\n const effectiveTimeoutMs = Math.min(requestedTimeoutMs, profile.policy.execTimeoutMs);\n\n // An empty string is \"not specified\", not \"the root of nowhere\" — passing it\n // through would silently reset a session's tracked directory.\n let requestedCwd: string | undefined = undefined;\n if (cwd != null && cwd.trim() !== \"\") {\n requestedCwd = cwd.trim();\n }\n\n _logger.debug(\"running command\", { command: command, timeout_ms: effectiveTimeoutMs });\n\n let result: WslExecResult;\n if (openSession != null) {\n result = await openSession.exec(command, { cwd: requestedCwd, timeoutMs: effectiveTimeoutMs });\n }\n else {\n result = await host.exec({\n command: command,\n cwd: requestedCwd ?? profile.defaultCwd,\n timeoutMs: effectiveTimeoutMs,\n maxOutputCharacters: profile.policy.maxOutputCharacters,\n trackCwd: false,\n });\n }\n\n _logger.info(\"command finished\", {\n exit_code: result.exitCode,\n duration_ms: result.durationMs,\n timed_out: result.timedOut,\n });\n return textResult(formatExecResult(result, effectiveTimeoutMs));\n }\n catch (ex) {\n return toToolError(ex, \"wsl_exec\", command);\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport { $logger, expandHomePath, formatBytes } from \"@/_libs\";\nimport { GuardRejectionError, inspectLocalPath } from \"@/modules/guard\";\nimport { downloadFile, listDirectory, readFile, uploadFile, writeFile } from \"@/modules/wsl\";\n\nimport { formatDirectoryListing } from \"./format\";\nimport { resolveHost, textResult, toToolError } from \"./tool-context\";\nimport type { ToolContext } from \"./tool-context\";\n\nconst SESSION_DESCRIPTION = \"Session id from wsl_connect. Optional — the file tools do not depend on a session's working directory, paths are absolute.\";\n\n/**\n * Screens a path on the Windows side of this machine.\n *\n * The distro side is guarded inside the file operations, where the policy lives. The\n * Windows side has no policy — it is the operator's own filesystem — so it is checked\n * here, at the only layer that knows the path came from a tool argument. Same rules as\n * `@akms/mcp-ssh`: credentials and the files that define the guards.\n *\n * @throws {GuardRejectionError} If the path is protected.\n */\nfunction requirePermittedLocalPath(localPath: string, access: \"read\" | \"write\"): void {\n const verdict = inspectLocalPath(localPath, access);\n if (verdict.allowed == false) {\n throw new GuardRejectionError(verdict);\n }\n}\n\nexport function registerFileTools(server: McpServer, context: ToolContext): void {\n server.registerTool(\n \"wsl_list_dir\",\n {\n title: \"List a directory in WSL\",\n description: [\n \"List a directory in the distro, with type, permissions, size and mtime.\",\n \"Cheaper and more structured than running 'ls -la' through wsl_exec, and it works on a read-only profile.\",\n ].join(\" \"),\n inputSchema: {\n path: z.string().min(1).describe(\"Absolute directory path in the distro. When WSL_ALLOWED_PATHS is set, only paths inside it are accepted.\"),\n session: z.string().optional().describe(SESSION_DESCRIPTION),\n },\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n },\n async ({ path: distroPath, session }) => {\n const _logger = $logger.child({ context: \"wsl_list_dir\", distro_path: distroPath });\n\n try {\n const { host } = resolveHost(context, { session: session });\n const listing = await listDirectory(host, distroPath);\n\n _logger.info(\"directory listed\", { entry_count: listing.totalCount, truncated: listing.truncated });\n return textResult(formatDirectoryListing(distroPath, listing));\n }\n catch (ex) {\n return toToolError(ex, \"wsl_list_dir\", `list ${distroPath}`);\n }\n }\n );\n\n server.registerTool(\n \"wsl_read_file\",\n {\n title: \"Read a file in WSL\",\n description: [\n \"Read a text file in the distro and return its contents.\",\n \"Oversized files come back truncated to their leading bytes rather than failing, so pointing this at a large log is safe.\",\n \"Files that report size 0 but hold content (/proc, /sys) are read in full up to the ceiling.\",\n ].join(\" \"),\n inputSchema: {\n path: z.string().min(1).describe(\"Absolute file path in the distro.\"),\n session: z.string().optional().describe(SESSION_DESCRIPTION),\n maxBytes: z.number().int().positive().optional().describe(\"Lowers the read ceiling for this call; it cannot exceed WSL_MAX_READ_BYTES.\"),\n },\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n },\n async ({ path: distroPath, session, maxBytes }) => {\n const _logger = $logger.child({ context: \"wsl_read_file\", distro_path: distroPath });\n\n try {\n const { host } = resolveHost(context, { session: session });\n\n // Clamped, not defaulted: an override above the profile ceiling would let one\n // call buffer hundreds of megabytes and take the server down.\n const requestedLimit = maxBytes ?? host.profile.policy.maxReadFileBytes;\n const readLimit = Math.min(requestedLimit, host.profile.policy.maxReadFileBytes);\n\n const file = await readFile(host, distroPath, readLimit);\n\n let header = `${distroPath} — ${formatBytes(file.readBytes)} read`;\n if (file.sizeBytes > 0) {\n header = `${distroPath} — ${formatBytes(file.sizeBytes)}`;\n }\n\n if (file.truncated == true) {\n header += `, truncated to the first ${formatBytes(file.readBytes)}`;\n }\n\n _logger.info(\"file read\", { size_bytes: file.sizeBytes, read_bytes: file.readBytes, truncated: file.truncated });\n return textResult(`${header}\\n\\n${file.content}`);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_read_file\", `read ${distroPath}`);\n }\n }\n );\n\n server.registerTool(\n \"wsl_write_file\",\n {\n title: \"Write a file in WSL\",\n description: [\n \"Write or append UTF-8 text to a file in the distro. The content never passes through a shell, so quoting is not a concern.\",\n \"Prefer this over heredocs in wsl_exec. Parent directories must exist. Refused on a read-only profile, and under /mnt/<drive>/ unless the profile allows Windows writes.\",\n ].join(\" \"),\n inputSchema: {\n path: z.string().min(1).describe(\"Absolute file path in the distro.\"),\n content: z.string().describe(\"Text to write.\"),\n append: z.boolean().optional().describe(\"Append instead of overwrite. Default false.\"),\n session: z.string().optional().describe(SESSION_DESCRIPTION),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n async ({ path: distroPath, content, append, session }) => {\n const _logger = $logger.child({ context: \"wsl_write_file\", distro_path: distroPath });\n\n try {\n const { host } = resolveHost(context, { session: session });\n const written = await writeFile(host, { distroPath: distroPath, content: content, append: append ?? false });\n\n let verb = \"Wrote\";\n if (append == true) {\n verb = \"Appended\";\n }\n\n _logger.info(\"file written\", { bytes: written, append: append ?? false });\n return textResult(`${verb} ${formatBytes(written)} to ${distroPath}`);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_write_file\", `write ${distroPath}`);\n }\n }\n );\n\n server.registerTool(\n \"wsl_upload\",\n {\n title: \"Upload a file into WSL\",\n description: [\n \"Copy a file from this machine into the distro. The local path is resolved on the Windows side (a POSIX-looking path becomes <current drive>\\\\…), and the reply prints it — check it.\",\n \"Credential files and MCP configuration on the local side are refused.\",\n ].join(\" \"),\n inputSchema: {\n localPath: z.string().min(1).describe(\"Path on this machine, '~' expanded.\"),\n remotePath: z.string().min(1).describe(\"Absolute destination path in the distro (the file, not its directory).\"),\n session: z.string().optional().describe(SESSION_DESCRIPTION),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n async ({ localPath, remotePath, session }) => {\n const resolvedLocalPath = expandHomePath(localPath);\n const _logger = $logger.child({ context: \"wsl_upload\", local_path: resolvedLocalPath, distro_path: remotePath });\n\n try {\n requirePermittedLocalPath(resolvedLocalPath, \"read\");\n\n const { host } = resolveHost(context, { session: session });\n const sent = await uploadFile(host, resolvedLocalPath, remotePath);\n\n _logger.info(\"file uploaded\", { bytes: sent });\n return textResult(`Uploaded ${formatBytes(sent)}: ${resolvedLocalPath} → ${remotePath}`);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_upload\", `upload ${resolvedLocalPath} to ${remotePath}`);\n }\n }\n );\n\n server.registerTool(\n \"wsl_download\",\n {\n title: \"Download a file from WSL\",\n description: [\n \"Copy a file from the distro to this machine. The local path is resolved on the Windows side and printed in the reply — check it.\",\n \"The destination directory must already exist; credential locations and MCP configuration on the local side are refused.\",\n ].join(\" \"),\n inputSchema: {\n remotePath: z.string().min(1).describe(\"Absolute source path in the distro.\"),\n localPath: z.string().min(1).describe(\"Destination path on this machine, '~' expanded.\"),\n session: z.string().optional().describe(SESSION_DESCRIPTION),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n async ({ remotePath, localPath, session }) => {\n const resolvedLocalPath = expandHomePath(localPath);\n const _logger = $logger.child({ context: \"wsl_download\", local_path: resolvedLocalPath, distro_path: remotePath });\n\n try {\n requirePermittedLocalPath(resolvedLocalPath, \"write\");\n\n const { host } = resolveHost(context, { session: session });\n const received = await downloadFile(host, remotePath, resolvedLocalPath);\n\n _logger.info(\"file downloaded\", { bytes: received });\n return textResult(`Downloaded ${formatBytes(received)}: ${remotePath} → ${resolvedLocalPath}`);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_download\", `download ${remotePath} to ${resolvedLocalPath}`);\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport { $logger } from \"@/_libs\";\nimport type { WslDistroStatus } from \"@/_types\";\nimport { probeDistroFacts, queryDistroListing } from \"@/modules/wsl\";\n\nimport { formatHostProfile } from \"./format\";\nimport { textResult, toToolError } from \"./tool-context\";\nimport type { ToolContext } from \"./tool-context\";\n\nexport function registerHostTools(server: McpServer, context: ToolContext): void {\n server.registerTool(\n \"wsl_list_hosts\",\n {\n title: \"Show the WSL distro\",\n description: [\n \"Show the WSL distro and user this server runs commands in, with its guard policy and current state (running or stopped, WSL version, networking mode, whether systemd is PID 1).\",\n \"Call this first: it is the only reachable distro, and its policy decides what the other tools will accept.\",\n \"The networking mode matters when reasoning about ports — in mirrored mode a port Windows holds cannot be bound inside the distro, and a listing inside the distro shows only its own namespace.\",\n ].join(\" \"),\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async () => {\n const _logger = $logger.child({ context: \"wsl_list_hosts\" });\n\n try {\n const host = context.host;\n let status: WslDistroStatus | null = null;\n\n if (host != null) {\n status = await queryDistroListing(host.profile.distro);\n\n // The inside facts need the distro running; probing a stopped one would\n // start it as a side effect of a \"show me\" call.\n if (status.installed == true && status.state === \"Running\") {\n const facts = await probeDistroFacts(host);\n status = { ...status, ...facts };\n }\n }\n\n const listing = formatHostProfile(host?.profile ?? null, status);\n _logger.debug(\"host profile returned\", { profile: host?.profile.name, state: status?.state });\n return textResult(listing);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_list_hosts\", \"show the distro\");\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport { $logger } from \"@/_libs\";\n\nimport { formatSessionList } from \"./format\";\nimport { errorResult, resolveHost, textResult, toToolError } from \"./tool-context\";\nimport type { ToolContext } from \"./tool-context\";\n\nexport function registerSessionTools(server: McpServer, context: ToolContext): void {\n server.registerTool(\n \"wsl_connect\",\n {\n title: \"Open a WSL session\",\n description: [\n \"Open a session in the configured distro and return its session id.\",\n \"A session remembers the working directory, so a 'cd' in one wsl_exec still applies to the next. Each command is still its own process — nothing else (environment variables, background jobs) persists between calls.\",\n \"Close it with wsl_disconnect when done; idle sessions are forgotten automatically.\",\n ].join(\" \"),\n inputSchema: {\n cwd: z.string().optional().describe(\"Absolute directory to start in, with no shell metacharacters. Defaults to WSL_CWD, else the login shell's directory.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n async ({ cwd }) => {\n let _logger = $logger.child({ context: \"wsl_connect\" });\n\n // Tracked outside the try so a probe that *throws* still tears the session\n // down — leaking it would burn one of the 32 slots until the sweeper ran.\n let openedSessionId: string | null = null;\n\n try {\n const { host } = resolveHost(context, {});\n const session = context.sessions.open(host);\n openedSessionId = session.sessionId;\n _logger = _logger.child({ session_id: session.sessionId });\n\n if (cwd != null && cwd.trim() !== \"\") {\n session.cwd = cwd.trim();\n }\n\n // One `pwd` settles the real starting directory (proves `cwd` exists, starts\n // the distro if it was stopped), so the session reports a concrete path.\n const probe = await session.exec(\"pwd\");\n\n const probeSucceeded = probe.exitCode === 0 && probe.timedOut == false;\n if (probeSucceeded == false) {\n context.sessions.close(session.sessionId);\n openedSessionId = null;\n _logger.warn(\"session probe failed, closing the session\", {\n exit_code: probe.exitCode,\n timed_out: probe.timedOut,\n stderr: probe.stderr,\n });\n return errorResult(`wsl_connect failed: could not confirm the starting directory.\\n${probe.stderr.trim()}`);\n }\n\n const profile = host.profile;\n const lines: string[] = [\n `Opened session ${session.sessionId} → ${profile.username ?? \"(distro default)\"}@${profile.distro}`,\n `cwd: ${session.cwd}`,\n ];\n\n if (profile.policy.readonly == true) {\n lines.push(\"This distro is READ-ONLY: writes, redirections and uploads will be rejected.\");\n }\n\n lines.push(`Run commands with wsl_exec({ session: \"${session.sessionId}\", command: \"...\" }).`);\n\n _logger.info(\"session opened via tool\", { cwd: session.cwd });\n return textResult(lines.join(\"\\n\"));\n }\n catch (ex) {\n if (openedSessionId != null) {\n context.sessions.close(openedSessionId);\n }\n return toToolError(ex, \"wsl_connect\", \"open a session\");\n }\n }\n );\n\n server.registerTool(\n \"wsl_disconnect\",\n {\n title: \"Close a WSL session\",\n description: \"Close a session opened with wsl_connect. Nothing in the distro is affected — only this server's memory of the working directory.\",\n inputSchema: {\n session: z.string().min(1).describe(\"Session id from wsl_connect.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ session }) => {\n const _logger = $logger.child({ context: \"wsl_disconnect\", session_id: session });\n\n try {\n const closed = context.sessions.close(session.trim());\n if (closed == false) {\n return errorResult(`no open session '${session}'`);\n }\n\n _logger.info(\"session closed via tool\");\n return textResult(`Closed session ${session}.`);\n }\n catch (ex) {\n return toToolError(ex, \"wsl_disconnect\", `close session ${session}`);\n }\n }\n );\n\n server.registerTool(\n \"wsl_list_sessions\",\n {\n title: \"List open WSL sessions\",\n description: \"List the sessions this server holds, with their working directory, command count and idle time.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async () => {\n try {\n return textResult(formatSessionList(context.sessions.list()));\n }\n catch (ex) {\n return toToolError(ex, \"wsl_list_sessions\", \"list sessions\");\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport { registerExecTools } from \"./exec-tools\";\nimport { registerFileTools } from \"./file-tools\";\nimport { registerHostTools } from \"./host-tools\";\nimport { registerSessionTools } from \"./session-tools\";\nimport type { ToolContext } from \"./tool-context\";\n\nexport { registerHostTools } from \"./host-tools\";\nexport { registerSessionTools } from \"./session-tools\";\nexport { registerExecTools } from \"./exec-tools\";\nexport { registerFileTools } from \"./file-tools\";\n\nexport { textResult, errorResult, describeError, toToolError, resolveHost } from \"./tool-context\";\nexport type { ToolContext } from \"./tool-context\";\n\nexport {\n formatHostProfile,\n formatDistroStatus,\n formatExecResult,\n formatGuardRejection,\n formatSessionList,\n formatDirectoryListing,\n} from \"./format\";\n\n/** Registers every tool this server exposes, in the order the model should discover them. */\nexport function registerAllTools(server: McpServer, context: ToolContext): void {\n registerHostTools(server, context);\n registerSessionTools(server, context);\n registerExecTools(server, context);\n registerFileTools(server, context);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport { SERVER_NAME, SERVER_VERSION } from \"@/_defs\";\nimport { $logger } from \"@/_libs\";\nimport type { WslHostProfile } from \"@/_types\";\nimport { loadHostProfile } from \"@/modules/config\";\nimport { WslHost, WslSessionManager } from \"@/modules/wsl\";\nimport { registerAllTools } from \"@/modules/tools\";\nimport type { ToolContext } from \"@/modules/tools\";\n\nexport interface WslMcpServerInstance {\n server: McpServer;\n sessions: WslSessionManager;\n /** The distro read from the `WSL_*` variables at startup, or null when none is set. */\n readonly profile: WslHostProfile | null;\n /** Stops the sweeper and forgets every open session. Call before the process exits. */\n shutdown(): void;\n}\n\n/** Handed to the client on connect, so the model knows the workflow before its first call. */\nconst SERVER_INSTRUCTIONS = [\n \"This server runs shell commands and transfers files in one WSL distro on this machine, through wsl.exe — no SSH, no network.\",\n \"The distro and the Linux user are fixed in this server's own environment — there is no distro or user argument, and no other machine is reachable through it.\",\n \"\",\n \"wsl_list_hosts shows which distro and user this is, whether the distro is running, its networking mode, and what it permits. Call it before assuming anything about access or ports.\",\n \"\",\n \"Workflow:\",\n \"1. One command: wsl_exec with just 'command'.\",\n \"2. Several commands in a row: wsl_connect once, then wsl_exec with 'session' (the working directory persists across calls), then wsl_disconnect. Only the directory persists — each command is its own process.\",\n \"3. Files: wsl_list_dir, wsl_read_file, wsl_write_file, wsl_upload, wsl_download — prefer these over shell equivalents; no quoting to get wrong.\",\n \"\",\n \"What is permitted: ordinary administration, without asking — package installs, service restarts, sudo, interpreters, config edits, deployments.\",\n \"Refused always: operations that destroy the distro or cut this channel — wiping the filesystem root or a system directory, deleting a file the distro cannot boot without, formatting a disk, writing raw bytes to a block device, powering off, wsl --shutdown / --terminate / --unregister, flushing the firewall, removing every cron job.\",\n \"Refused unless the profile opens them (WSL_ALLOW_WINDOWS): running Windows executables through interop (powershell.exe, cmd.exe, any .exe) and writing under /mnt/<drive>/. Reading under /mnt/<drive>/ is allowed. The operator's credential files and MCP configuration under /mnt/ are refused regardless — those define this very guard.\",\n \"The profile may add its own limits (read-only, an allow-list, deny patterns, path restrictions). wsl_list_hosts shows which apply.\",\n \"\",\n \"Commands run in a login bash with no terminal and with stdin closed, so anything that waits for input fails immediately instead of hanging: use non-interactive flags (apt-get -y, sudo -n), 'top -bn1' rather than 'top', and wsl_write_file rather than an editor.\",\n \"A job that may outlive its timeout must be detached with all three descriptors redirected — nohup cmd > log 2>&1 < /dev/null & — otherwise wsl.exe waits on the open pipe until the timeout. Poll it through its log.\",\n \"\",\n \"A guard rejection is a policy decision, not a transient failure — do not retry the same command; report it and ask before working around it.\",\n \"A non-zero exit code is returned as normal output; read it and stderr to judge what happened.\",\n \"You still carry the judgement the guards do not: this is a real host, and an irreversible action deserves a check with the operator first.\",\n].join(\"\\n\");\n\n/**\n * Builds the MCP server: reads the distro from the environment, wires the session\n * manager, registers tools.\n *\n * Transport is deliberately left to the caller — `cli.ts` attaches stdio, tests can attach\n * an in-memory pair.\n *\n * @throws {Error} If the `WSL_*` variables are malformed (a bad policy value must not\n * silently degrade into \"no guard\").\n */\nexport function createWslMcpServer(): WslMcpServerInstance {\n const _logger = $logger.child({ context: \"createWslMcpServer\" });\n\n const profile = loadHostProfile();\n\n let host: WslHost | null = null;\n if (profile != null) {\n host = new WslHost(profile);\n }\n\n const sessions = new WslSessionManager();\n sessions.startIdleSweeper();\n\n const server = new McpServer(\n {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n {\n instructions: SERVER_INSTRUCTIONS,\n }\n );\n\n const context: ToolContext = {\n host: host,\n sessions: sessions,\n };\n\n registerAllTools(server, context);\n\n _logger.info(\"mcp server built\", { profile: profile?.name ?? null });\n\n return {\n server: server,\n sessions: sessions,\n profile: profile,\n shutdown(): void {\n sessions.stopIdleSweeper();\n sessions.closeAll();\n },\n };\n}\n"]}