genlayer
Execute CLI commands with full access to perform state-changing operations on your project. Configure working directory, environment variables, and timeout.
Instructions
Run the GenLayer CLI with full command access. This can perform state-changing operations.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | Arguments passed to the command. | |
| cwd | No | Working directory for the command. Defaults to the MCP server cwd. | |
| timeoutMs | No | Timeout in milliseconds. Defaults to 120000. | |
| env | No | Extra environment variables merged over the MCP server environment. |
Implementation Reference
- src/index.ts:484-489 (registration)Registration of the 'genlayer' tool via server.tool(), linking it to the runCommand('genlayer', ...) handler.
server.tool( "genlayer", "Run the GenLayer CLI with full command access. This can perform state-changing operations.", commandInputShape, async (input) => textResponse(await runCommand("genlayer", input)) ); - src/index.ts:110-191 (handler)The runCommand function that executes the 'genlayer' CLI command via child_process.spawn, handling args, env, timeout, and collecting stdout/stderr.
async function runCommand( command: string, input: z.infer<typeof commandInputSchema> ): Promise<CommandResult> { const cwd = input.cwd ?? processCwd(); const childEnv = { ...processEnv, ...(input.env ?? {}) }; return await new Promise<CommandResult>((resolve) => { let stdout = ""; let stderr = ""; let settled = false; let timedOut = false; const resolvedCommand = resolveCommand(command, childEnv); const child = spawn(resolvedCommand.command, [...resolvedCommand.argsPrefix, ...input.args], { cwd, env: childEnv, shell: false, windowsHide: true }); const timeout = setTimeout(() => { timedOut = true; child.kill("SIGTERM"); }, input.timeoutMs); child.stdout?.setEncoding("utf8"); child.stderr?.setEncoding("utf8"); child.stdout?.on("data", (chunk: string) => { stdout += chunk; }); child.stderr?.on("data", (chunk: string) => { stderr += chunk; }); child.on("error", (error) => { if (settled) { return; } settled = true; clearTimeout(timeout); resolve({ command, resolvedCommand: resolvedCommand.command, args: input.args, cwd, exitCode: null, signal: null, stdout, stderr, timedOut, error: error.message }); }); child.on("close", (exitCode, signal) => { if (settled) { return; } settled = true; clearTimeout(timeout); resolve({ command, resolvedCommand: resolvedCommand.command, args: input.args, cwd, exitCode, signal, stdout, stderr, timedOut }); }); }); } - src/index.ts:27-42 (schema)Input schema (commandInputShape) defining the args, cwd, timeoutMs, and env parameters accepted by the genlayer tool.
const commandInputShape = { args: z.array(z.string()).default([]).describe("Arguments passed to the command."), cwd: z.string().optional().describe("Working directory for the command. Defaults to the MCP server cwd."), timeoutMs: z .number() .int() .positive() .max(30 * 60 * 1000) .default(120_000) .describe("Timeout in milliseconds. Defaults to 120000."), env: z .record(z.string()) .optional() .describe("Extra environment variables merged over the MCP server environment.") }; - src/index.ts:193-215 (helper)resolveCommand helper that resolves the CLI command path, handling Windows .cmd scripts and npm bin scripts.
function resolveCommand(command: string, env: NodeJS.ProcessEnv): ResolvedCommand { const commandPath = process.platform === "win32" ? findWindowsCommand(command, env) : command; if (process.platform === "win32" && commandPath?.toLowerCase().endsWith(".cmd")) { const npmBin = resolveNpmBinScript(command, commandPath); if (npmBin) { return { command: process.execPath, argsPrefix: [npmBin] }; } return { command: "cmd.exe", argsPrefix: ["/d", "/s", "/c", commandPath] }; } return { command: commandPath ?? command, argsPrefix: [] }; } - src/index.ts:217-240 (helper)findWindowsCommand helper that locates a command on Windows by searching PATH entries with common extensions.
function findWindowsCommand(command: string, env: NodeJS.ProcessEnv): string | undefined { if (command.includes("\\") || command.includes("/")) { return existsSync(command) ? command : undefined; } const pathValue = env.Path ?? env.PATH ?? ""; const pathEntries = pathValue.split(delimiter).filter(Boolean); const extensions = [".exe", ".cmd", ".bat", ".ps1", ""]; for (const extension of extensions) { for (const pathEntry of pathEntries) { const candidate = join(pathEntry, `${command}${extension}`); if (existsSync(candidate)) { if (isBrokenPythonScriptsLauncher(candidate)) { continue; } return candidate; } } } return undefined; }