Skip to main content
Glama
simon-ami

Windows CLI MCP Server

execute_command

Execute commands in Windows shells (PowerShell, CMD, or Git Bash) with specified working directories for system management and automation tasks.

Instructions

Execute a command in the specified shell (powershell, cmd, or gitbash)

Example usage (PowerShell):

{
  "shell": "powershell",
  "command": "Get-Process | Select-Object -First 5",
  "workingDir": "C:\Users\username"
}

Example usage (CMD):

{
  "shell": "cmd",
  "command": "dir /b",
  "workingDir": "C:\Projects"
}

Example usage (Git Bash):

{
  "shell": "gitbash",
  "command": "ls -la",
  "workingDir": "/c/Users/username"
}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
shellYesShell to use for command execution
commandYesCommand to execute
workingDirNoWorking directory for command execution (optional)

Implementation Reference

  • src/index.ts:272-323 (registration)
    Registration of the 'execute_command' tool in the ListTools response, including name, detailed description with examples, and input schema definition.
            {
              name: "execute_command",
              description: `Execute a command in the specified shell (powershell, cmd, or gitbash)
    
    Example usage (PowerShell):
    \`\`\`json
    {
      "shell": "powershell",
      "command": "Get-Process | Select-Object -First 5",
      "workingDir": "C:\\Users\\username"
    }
    \`\`\`
    
    Example usage (CMD):
    \`\`\`json
    {
      "shell": "cmd",
      "command": "dir /b",
      "workingDir": "C:\\Projects"
    }
    \`\`\`
    
    Example usage (Git Bash):
    \`\`\`json
    {
      "shell": "gitbash",
      "command": "ls -la",
      "workingDir": "/c/Users/username"
    }
    \`\`\``,
              inputSchema: {
                type: "object",
                properties: {
                  shell: {
                    type: "string",
                    enum: Object.keys(this.config.shells).filter(shell => 
                      this.config.shells[shell as keyof typeof this.config.shells].enabled
                    ),
                    description: "Shell to use for command execution"
                  },
                  command: {
                    type: "string",
                    description: "Command to execute"
                  },
                  workingDir: {
                    type: "string",
                    description: "Working directory for command execution (optional)"
                  }
                },
                required: ["shell", "command"]
              }
            },
  • Runtime input validation schema using Zod that matches the tool's inputSchema.
    const args = z.object({
      shell: z.enum(Object.keys(this.config.shells).filter(shell => 
        this.config.shells[shell as keyof typeof this.config.shells].enabled
      ) as [string, ...string[]]),
      command: z.string(),
      workingDir: z.string().optional()
    }).parse(request.params.arguments);
  • Core handler logic for 'execute_command': validates inputs, spawns the configured shell process, streams and captures stdout/stderr, handles process close/error/timeout, logs to command history if enabled, constructs and returns the tool response with output, error status, and metadata including exit code.
    case "execute_command": {
      const args = z.object({
        shell: z.enum(Object.keys(this.config.shells).filter(shell => 
          this.config.shells[shell as keyof typeof this.config.shells].enabled
        ) as [string, ...string[]]),
        command: z.string(),
        workingDir: z.string().optional()
      }).parse(request.params.arguments);
    
      // Validate command
      this.validateCommand(args.shell as keyof ServerConfig['shells'], args.command);
    
      // Validate working directory if provided
      let workingDir = args.workingDir ? 
        path.resolve(args.workingDir) : 
        process.cwd();
    
      const shellKey = args.shell as keyof typeof this.config.shells;
      const shellConfig = this.config.shells[shellKey];
      
      if (this.config.security.restrictWorkingDirectory) {
        const isAllowedPath = Array.from(this.allowedPaths).some(
          allowedPath => workingDir.startsWith(allowedPath)
        );
    
        if (!isAllowedPath) {
          throw new McpError(
            ErrorCode.InvalidRequest,
            `Working directory (${workingDir}) outside allowed paths. Consult the server admin for configuration changes (config.json - restrictWorkingDirectory, allowedPaths).`
          );
        }
      }
    
      // Execute command
      return new Promise((resolve, reject) => {
        let shellProcess: ReturnType<typeof spawn>;
        
        try {
          shellProcess = spawn(
            shellConfig.command,
            [...shellConfig.args, args.command],
            { cwd: workingDir, stdio: ['pipe', 'pipe', 'pipe'] }
          );
        } catch (err) {
          throw new McpError(
            ErrorCode.InternalError,
            `Failed to start shell process: ${err instanceof Error ? err.message : String(err)}. Consult the server admin for configuration changes (config.json - shells).`
          );
        }
    
        if (!shellProcess.stdout || !shellProcess.stderr) {
          throw new McpError(
            ErrorCode.InternalError,
            'Failed to initialize shell process streams'
          );
        }
    
        let output = '';
        let error = '';
    
        shellProcess.stdout.on('data', (data) => {
          output += data.toString();
        });
    
        shellProcess.stderr.on('data', (data) => {
          error += data.toString();
        });
    
        shellProcess.on('close', (code) => {
          // Prepare detailed result message
          let resultMessage = '';
          
          if (code === 0) {
            resultMessage = output || 'Command completed successfully (no output)';
          } else {
            resultMessage = `Command failed with exit code ${code}\n`;
            if (error) {
              resultMessage += `Error output:\n${error}\n`;
            }
            if (output) {
              resultMessage += `Standard output:\n${output}`;
            }
            if (!error && !output) {
              resultMessage += 'No error message or output was provided';
            }
          }
    
          // Store in history if enabled
          if (this.config.security.logCommands) {
            this.commandHistory.push({
              command: args.command,
              output: resultMessage,
              timestamp: new Date().toISOString(),
              exitCode: code ?? -1
            });
    
            // Trim history if needed
            if (this.commandHistory.length > this.config.security.maxHistorySize) {
              this.commandHistory = this.commandHistory.slice(-this.config.security.maxHistorySize);
            }
          }
    
          resolve({
            content: [{
              type: "text",
              text: resultMessage
            }],
            isError: code !== 0,
            metadata: {
              exitCode: code ?? -1,
              shell: args.shell,
              workingDirectory: workingDir
            }
          });
        });
    
        // Handle process errors (e.g., shell crashes)
        shellProcess.on('error', (err) => {
          const errorMessage = `Shell process error: ${err.message}`;
          if (this.config.security.logCommands) {
            this.commandHistory.push({
              command: args.command,
              output: errorMessage,
              timestamp: new Date().toISOString(),
              exitCode: -1
            });
          }
          reject(new McpError(
            ErrorCode.InternalError,
            errorMessage
          ));
        });
    
        // Set configurable timeout to prevent hanging
        const timeout = setTimeout(() => {
          shellProcess.kill();
          const timeoutMessage = `Command execution timed out after ${this.config.security.commandTimeout} seconds. Consult the server admin for configuration changes (config.json - commandTimeout).`;
          if (this.config.security.logCommands) {
            this.commandHistory.push({
              command: args.command,
              output: timeoutMessage,
              timestamp: new Date().toISOString(),
              exitCode: -1
            });
          }
          reject(new McpError(
            ErrorCode.InternalError,
            timeoutMessage
          ));
        }, this.config.security.commandTimeout * 1000);
    
        shellProcess.on('close', () => clearTimeout(timeout));
      });
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/simon-ami/win-cli-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server