shell_ls
List directory contents to view files and folders. Use command arguments to customize output for specific directory exploration needs.
Instructions
List directory contents
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | Command arguments |
Implementation Reference
- src/config/allowlist.ts:15-20 (registration)Configuration defining the 'shell.ls' tool: maps to 'ls' command, provides description, allowed arguments, and execution timeout.'shell.ls': { command: 'ls', description: 'List directory contents', allowedArgs: ['-l', '-a', '-h', '-R', '--help', '*'], timeout: 5000 },
- src/mcp/server.ts:113-137 (registration)Dynamically registers 'shell.ls' from allowedCommands as MCP tool 'ls' with description and input schema during ListTools processing.Object.entries(allowedCommands).forEach(([name, config]) => { const toolName = name.replace('shell.', ''); this.logger.debug('Processing command', { originalName: name, toolName, isProcessed: processedNames.has(toolName) }); if (!processedNames.has(toolName)) { processedNames.add(toolName); tools.push({ name: toolName, description: config.description, inputSchema: { type: "object", properties: { args: { type: "array", items: { type: "string" }, description: "Command arguments" } } } }); }
- src/mcp/server.ts:127-135 (schema)Defines the input schema for the 'ls' tool: object with 'args' array of strings.type: "object", properties: { args: { type: "array", items: { type: "string" }, description: "Command arguments" } } }
- src/mcp/server.ts:178-233 (handler)MCP CallTool handler: maps tool name 'ls' to 'shell.ls' config, validates, executes via executor, collects and returns stdout.const command = String(request.params.name); const fullCommand = command.startsWith('shell.') ? command : `shell.${command}`; if (!(fullCommand in allowedCommands)) { throw new ToolError('COMMAND_NOT_FOUND', 'Command not found', { command }); } const config = allowedCommands[fullCommand]; const args = Array.isArray(request.params.arguments?.args) ? request.params.arguments.args.map(String) : []; const context: CommandContext = { requestId: ext.id || 'unknown', command, args, timeout: config.timeout, workDir: config.workDir, env: config.env }; this.logger.info('Starting command execution', context); try { this.validator.validateCommand(command, args); this.logger.debug('Command validation passed', { ...context, config }); const stream = await this.executor.execute(command, args, { timeout: config.timeout, cwd: config.workDir, env: config.env }); ext.onCancel?.(() => { this.logger.info('Received cancel request', context); this.executor.interrupt(); }); const output = await this.collectOutput(stream); this.logger.info('Command execution completed', { ...context, outputLength: output.length }); return { content: [{ type: "text", text: output }] };
- src/core/executor.ts:32-121 (handler)Executes the shell command ('ls') by spawning child_process.spawn(baseCommand='ls', args), returns stdout stream.command: string, args: string[] = [], options: ExecuteOptions = {} ): Promise<{ stdout: Readable }> { const commandKey = `${command} ${args.join(' ')}`; try { // Check security await this.securityChecker.validateCommand(command, args, options); // Check cache const cached = this.cache.get(commandKey); if (cached) { this.logger.debug('Using cached command result', { command, args }); return this.createStreamFromCache(cached); } // Remove 'shell.' prefix for execution const baseCommand = command.replace('shell.', ''); // Execute command this.logger.debug('Starting command execution', { command, args, options }); const childProcess = spawn(baseCommand, args, { stdio: ['ignore', 'pipe', 'pipe'], timeout: options.timeout, cwd: options.cwd, env: { ...process.env, ...options.env }, signal: options.signal }); this.currentProcess = childProcess; // Error handling childProcess.on('error', (error: Error) => { this.logger.error('Command execution error', { command, args, error: error.message }); throw new ToolError( 'PROCESS_ERROR', 'Command execution error', { command, args, error: error.message } ); }); // Timeout handling if (options.timeout) { setTimeout(() => { if (childProcess.exitCode === null) { this.logger.warn('Command execution timeout', { command, args, timeout: options.timeout }); childProcess.kill(); throw new ToolError( 'TIMEOUT', 'Command execution timeout', { command, args, timeout: options.timeout } ); } }, options.timeout); } if (!childProcess.stdout) { throw new ToolError( 'STREAM_ERROR', 'Unable to get command output stream', { command, args } ); } // Monitor process status childProcess.on('exit', (code, signal) => { this.logger.debug('Command execution completed', { command, args, exitCode: code, signal }); }); return { stdout: childProcess.stdout };