Mac Shell MCP Server

by cfdude
Verified
# ADR 003: Command Approval Workflow ## Status Accepted ## Context When executing shell commands, there's a middle ground between completely safe commands and forbidden commands. Some commands can modify the system in potentially harmful ways but are still necessary for legitimate use cases. We need a mechanism to handle these commands safely. Options considered: 1. Reject all potentially dangerous commands 2. Allow all commands with appropriate warnings 3. Implement an approval workflow for commands that require additional verification ## Decision We will implement an approval workflow for commands that are potentially dangerous but still necessary. This workflow will: 1. Queue commands marked as requiring approval 2. Provide tools to list pending commands 3. Allow explicit approval or denial of pending commands 4. Execute approved commands and reject denied commands This approach balances security with usability by allowing potentially dangerous commands to be executed after explicit approval. ## Consequences ### Positive - Provides a middle ground between allowing and forbidding commands - Creates an audit trail of command approvals - Allows for human judgment in borderline cases - Enables safe use of necessary system-modifying commands - Prevents accidental execution of dangerous commands ### Negative - Introduces asynchronous workflow for command execution - Requires additional user interaction for approval - May create confusion if approvals are delayed or forgotten ## Implementation The approval workflow will be implemented using a queue of pending commands: ```typescript interface PendingCommand { id: string; command: string; args: string[]; requestedAt: Date; requestedBy?: string; resolve: (value: CommandResult) => void; reject: (reason: Error) => void; } ``` When a command requiring approval is executed, it will be added to the queue: ```typescript private queueCommandForApproval( command: string, args: string[] = [], requestedBy?: string ): Promise<CommandResult> { return new Promise((resolve, reject) => { const id = randomUUID(); const pendingCommand: PendingCommand = { id, command, args, requestedAt: new Date(), requestedBy, resolve, reject }; this.pendingCommands.set(id, pendingCommand); this.emit('command:pending', pendingCommand); }); } ``` The MCP server will expose tools to list, approve, and deny pending commands: ```typescript // Get pending commands const pendingCommands = await client.callTool('get_pending_commands', {}); // Approve a command await client.callTool('approve_command', { commandId }); // Deny a command await client.callTool('deny_command', { commandId, reason: 'Not allowed' }); ``` This workflow ensures that potentially dangerous commands are only executed after explicit approval, providing an additional layer of security.