Files
bigwo/dev-assistant-mcp/src/tools/execCommand.ts

68 lines
2.0 KiB
TypeScript
Raw Normal View History

2026-03-12 12:47:56 +08:00
import { exec, spawn } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
export const execCommandTool = {
name: "exec_command",
description:
"在本地电脑上执行 Shell 命令。用于运行编译、测试、构建、安装依赖等任何命令。返回 stdout、stderr 和退出码。",
inputSchema: {
type: "object" as const,
properties: {
command: {
type: "string",
description: "要执行的命令(如 npm install, tsc --noEmit, python script.py",
},
cwd: {
type: "string",
description: "工作目录(绝对路径)",
},
timeout: {
type: "number",
description: "超时时间(毫秒),默认 60000",
},
},
required: ["command"],
},
};
export async function executeExecCommand(args: {
command: string;
cwd?: string;
timeout?: number;
}): Promise<string> {
const { command, cwd, timeout = 60000 } = args;
const workDir = cwd || process.cwd();
try {
const { stdout, stderr } = await execAsync(command, {
cwd: workDir,
timeout,
maxBuffer: 1024 * 1024 * 10, // 10MB
shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash",
});
const output: string[] = [
`$ ${command}`,
`📂 ${workDir}`,
`✅ 退出码: 0`,
];
if (stdout.trim()) output.push(`\n--- stdout ---\n${stdout.trim()}`);
if (stderr.trim()) output.push(`\n--- stderr ---\n${stderr.trim()}`);
return output.join("\n");
} catch (error: any) {
const output: string[] = [
`$ ${command}`,
`📂 ${workDir}`,
`❌ 退出码: ${error.code ?? "unknown"}`,
];
if (error.stdout?.trim()) output.push(`\n--- stdout ---\n${error.stdout.trim()}`);
if (error.stderr?.trim()) output.push(`\n--- stderr ---\n${error.stderr.trim()}`);
if (error.killed) output.push(`\n⏰ 命令超时(${timeout}ms被终止`);
return output.join("\n");
}
}