start_interactive_command
Initiate an interactive command session on Kali Linux MCP Server to handle user inputs like SQL prompts, enabling continued execution without closing the session.
Instructions
(需要交互式比如mysql -u root -p)在Kali Linux环境中启动一个交互式命令,并返回会话ID。交互式命令可以接收用户输入,可以在不close_interactive_command的情况下同时执行execute_command。
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | 要在Kali Linux环境中执行的交互式命令。 |
Implementation Reference
- src/index.ts:212-277 (handler)The primary handler for the 'start_interactive_command' tool. Validates the command input, handles special cases like msfconsole, creates an InteractiveSession using CommandExecutor, stores it in activeSessions map, and returns session details including initial output and input readiness.case "start_interactive_command": { let command = String(request.params.arguments?.command); if (!command) { throw new McpError(ErrorCode.InvalidParams, "命令是必需的"); } // 存储当前命令到全局变量 (global as any).currentInteractiveCommand = command; // 如果是 msfconsole,添加 -q 参数 if (command.trim() === 'msfconsole') { command = 'msfconsole -q'; log.info("检测到 msfconsole,自动添加 -q 参数启动。"); } try { log.info(`准备启动交互式命令: ${command}`); // 显式设置pty选项,特别是对msfconsole这类特殊终端程序 const ptyOptions = { waitForPrompt: true, // 等待提示符后再返回 maxWaitTime: command.includes('msfconsole') ? 3000000 : 30000, // msfconsole等待更长时间(2分钟),其他命令30秒 forcePty: command.includes('msfconsole'), // 为msfconsole强制分配PTY term: "xterm-256color", // 设置终端类型 cols: 100, // 设置列数 rows: 40 // 设置行数 }; // 对于msfconsole特别提示用户可能需要等待较长时间 if (command.includes('msfconsole')) { log.info(`正在启动msfconsole,这可能需要1-2分钟时间,请耐心等待...`); } // 创建交互式会话 const session = await commandExecutor.createInteractiveSession(command, ptyOptions); activeSessions.set(session.sessionId, session); // 显示实时输出信息 log.info(`交互式会话已创建并等待提示符,ID: ${session.sessionId}`); // 添加对msfconsole会话的特别提示 let responseMessage: any = { status: "success", session_id: session.sessionId, initial_output: session.stdout, waiting_for_input: session.isWaitingForInput }; log.info(`输入状态: ${session.isWaitingForInput ? '等待输入' : '不等待输入'}`); return { content: [{ type: "text", text: JSON.stringify(responseMessage) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); log.error(`创建交互式会话失败: ${errorMessage}`); throw new McpError( ErrorCode.InternalError, `无法创建交互式会话: ${errorMessage}` ); } }
- src/index.ts:90-102 (schema)Input schema definition for the 'start_interactive_command' tool, specifying a required 'command' string parameter.{ name: "start_interactive_command", description: "(需要交互式比如mysql -u root -p)在Kali Linux环境中启动一个交互式命令,并返回会话ID。交互式命令可以接收用户输入,可以在不close_interactive_command的情况下同时执行execute_command。", inputSchema: { type: "object", properties: { command: { type: "string", description: "要在Kali Linux环境中执行的交互式命令。" } }, required: ["command"] }
- src/index.ts:73-156 (registration)Registers the 'start_interactive_command' tool by including its definition in the tools list returned by the ListToolsRequestSchema handler.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "execute_command", description: "(无需交互式比如ping 127.0.0.1)在Kali Linux渗透测试环境中执行命令。支持所有Kali Linux内置的安全测试工具和常规Linux命令。", inputSchema: { type: "object", properties: { command: { type: "string", description: "要在Kali Linux环境中执行的命令。可以是任何安全测试、漏洞扫描、密码破解等渗透测试命令。" } }, required: ["command"] } }, { name: "start_interactive_command", description: "(需要交互式比如mysql -u root -p)在Kali Linux环境中启动一个交互式命令,并返回会话ID。交互式命令可以接收用户输入,可以在不close_interactive_command的情况下同时执行execute_command。", inputSchema: { type: "object", properties: { command: { type: "string", description: "要在Kali Linux环境中执行的交互式命令。" } }, required: ["command"] } }, { name: "send_input_to_command", description: "(自行判断是AI输入还是用户手动输入)向正在运行的交互式命令发送用户输入。", inputSchema: { type: "object", properties: { session_id: { type: "string", description: "交互式会话ID。" }, input: { type: "string", description: "发送给命令的输入文本。" }, end_line: { type: "boolean", description: "是否在输入后添加换行符。默认为true。" } }, required: ["session_id", "input"] } }, { name: "get_command_output", description: "获取交互式命令的最新输出。", inputSchema: { type: "object", properties: { session_id: { type: "string", description: "交互式会话ID。" } }, required: ["session_id"] } }, { name: "close_interactive_command", description: "关闭交互式命令会话。", inputSchema: { type: "object", properties: { session_id: { type: "string", description: "交互式会话ID。" } }, required: ["session_id"] } } ] }; });
- src/executor.ts:445-534 (helper)Core helper function in CommandExecutor class that implements the interactive command startup logic: establishes SSH shell with PTY, configures terminal environment, executes the command, sets up event handlers for real-time output processing and input prompt detection, and supports waiting for readiness.async createInteractiveSession( command: string, options: { cwd?: string; env?: Record<string, string>; waitForPrompt?: boolean; // 是否等待提示符后再返回 maxWaitTime?: number; // 最大等待时间(毫秒) forcePty?: boolean; // 是否强制分配PTY term?: string; // 终端类型 cols?: number; // 终端列数 rows?: number; // 终端行数 } = {} ): Promise<InteractiveSession> { if (!this.isConnected || !this.sshClient) { throw new Error('SSH未连接,请先调用connect方法'); } const { cwd = '/', env = {}, waitForPrompt = true, maxWaitTime = 3000000, // 默认最大等待30秒 forcePty = false, // 默认不强制PTY term = 'xterm-256color', // 默认终端类型 cols = 80, // 默认终端列数 rows = 24 // 默认终端行数 } = options; try { log.info(`创建交互式会话: ${command}`); // 创建环境变量设置 let envSettings = Object.entries(env) .map(([key, value]) => `export ${key}="${String(value).replace(/"/g, '\\"')}"`) .join('; '); // 为交互式终端添加必要的环境变量 const defaultEnvSettings = [ `export TERM=${term}`, `export COLUMNS=${cols}`, `export LINES=${rows}`, 'export PS1="\\u@\\h:\\w\\$ "' ].join('; '); envSettings = envSettings ? `${envSettings}; ${defaultEnvSettings}` : defaultEnvSettings; // 特殊命令处理 let processedCommand = command; // 对于msfconsole等命令,添加特殊处理 if (command.includes('msfconsole')) { log.info('检测到msfconsole命令,添加特殊处理'); // 确保使用安静模式启动 if (!processedCommand.includes('-q')) { processedCommand = `${processedCommand} -q`; } log.info(`处理后的msfconsole命令: ${processedCommand}`); } // 最终命令 const finalCommand = `cd "${cwd}" && ${envSettings} && ${processedCommand}`; // 创建会话并配置 const sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`; // 传递PTY相关参数到createSessionObject const session = await this.createSessionObject(sessionId, finalCommand, { forcePty, term, cols, rows }); log.info(`交互式会话创建成功,ID: ${sessionId}`); // 通知实时查看器会话开始 await this.realtimePusher.notifySessionStart(sessionId, command); // 如果需要等待提示符出现 if (waitForPrompt) { return await this.waitForSessionPrompt(session, command, maxWaitTime); } return session; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); log.error(`创建交互式会话失败: ${errorMessage}`); throw error; } }
- src/executor.ts:42-149 (helper)Helper function used by interactive sessions to detect if the command prompt is ready for input, with special handling for msfconsole and various common prompts.function isWaitingForInput(output: string): boolean { // 检查是否有全局重载函数,如果有则使用它 if ((global as any).overrideWaitingCheck) { return (global as any).overrideWaitingCheck(output); } // 检查输出是否为会话对象,如果是并且有msfPromptDetected标记,直接返回true if (output && typeof output === 'object' && (output as any).msfPromptDetected) { return true; } if (!output || output.trim() === '') { return false; } // 首先移除所有ANSI转义序列,确保检查的是纯文本内容 const cleanOutput = stripAnsiCodes(output); // 检查常见的命令行提示符 const lines = cleanOutput.split('\n'); // 获取最后20行非空文本,某些程序可能会有很长的输出 const lastLines = lines.filter(line => line.trim().length > 0).slice(-20); const lastLine = lastLines.length > 0 ? lastLines[lastLines.length - 1] : ''; const cleanLine = lastLine.trim(); // 检查命令是否为msfconsole const isMsfconsole = (global as any).currentInteractiveCommand?.includes('msfc') || false; // 在日志中记录最后几行,帮助调试 // log.debug(`检测输入提示符,最后一行: "${cleanLine}"`); // msfconsole特殊处理 if (isMsfconsole) { // 使用静态变量跟踪用户输入状态 if (!(global as any).msfInputState) { (global as any).msfInputState = { hasReturnedTrue: false, // 是否曾经返回过true hasUserInput: false, // 用户是否输入过命令 outputLength: 0 // 输出长度记录 }; } // 检查是否是第一次(从未返回过true) const isFirstTime = !((global as any).msfInputState.hasReturnedTrue); const isMsf6Prompt = isFirstTime ? /^msf6\s>$/.test(cleanLine.trim()) // 第一次:严格匹配"msf6 >" : /^msf6\s.+>$/.test(cleanLine.trim()); // 之后:要求"msf6"和">"之间有其他内容 // 检测用户是否输入了新命令 // 只有当输出长度增加时才认为是新输入 if (cleanOutput.length > (global as any).msfInputState.outputLength) { // 如果输出增加了,说明有新的用户输入 if ((global as any).msfInputState.hasReturnedTrue) { (global as any).msfInputState.hasUserInput = true; } (global as any).msfInputState.outputLength = cleanOutput.length; } if (isMsf6Prompt) { // 第一次检测到提示符 if (!((global as any).msfInputState.hasReturnedTrue)) { (global as any).msfInputState.hasReturnedTrue = true; (global as any).msfInputState.outputLength = cleanOutput.length; return true; } // 已经返回过true,并且用户已经输入过命令 else if ((global as any).msfInputState.hasUserInput) { (global as any).msfInputState.hasUserInput = false; // 重置用户输入状态 (global as any).msfInputState.outputLength = cleanOutput.length; // 更新输出长度 return true; } } return false; } else { // 非msfconsole命令才使用常见的提示符模式 const promptPatterns = [ /[\$#>]\s*$/, // 常见的shell提示符: $, #, > /password[: ]*$/i, // 密码提示 /continue\? \[(y\/n)\]/i, // 继续提示 /\[\?\]\s*$/, // 问号提示 /输入.*[::]/, // 中文输入提示 /please enter.*:/i, // 英文输入提示 /press.*to continue/i, // 按键继续提示 /Enter\s*.*:/i, // Enter提示 /\(.*\)\s*$/, // 括号内选择提示,如 (Y/n) /\s+y\/n\s*$/i, // y/n选择 /mysql>\s*$/, // mysql提示符 /sqlite>\s*$/, // sqlite提示符 /ftp>\s*$/, // ftp提示符 /postgres=#\s*$/, // postgres提示符 /Press RETURN to continue/, // 按回车继续 /waiting for input/i // 通用等待输入文本 ]; // 检查最后一行是否匹配任何提示符模式 for (const pattern of promptPatterns) { if (pattern.test(cleanLine)) { log.debug(`匹配到提示符模式 ${pattern},判定为等待输入`); return true; } } } // 如果都不匹配,则默认不是在等待输入 return false; }