UNPKG

@houmak/minerva-mcp-server

Version:

Minerva Model Context Protocol (MCP) Server for Microsoft 365 and Azure integrations

164 lines (163 loc) 5.57 kB
// powershell-executor.ts // Module pour exécuter des scripts PowerShell/PnP depuis Node.js import { execa } from 'execa'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export class PowerShellExecutor { defaultTimeout = 30000; // 30 secondes scriptsBasePath; constructor(customScriptsPath) { // Chemin vers les scripts PowerShell (soit dans le conteneur, soit en local) this.scriptsBasePath = customScriptsPath || process.env.POWERSHELL_SCRIPTS_PATH || path.resolve(__dirname, '../../../powershell'); console.log(`PowerShell scripts base path: ${this.scriptsBasePath}`); } /** * Exécute un script PowerShell avec les paramètres donnés */ async executeScript(options) { const startTime = Date.now(); const timeout = options.timeout || this.defaultTimeout; try { const scriptFullPath = path.resolve(this.scriptsBasePath, options.scriptPath); // Construire la commande PowerShell const args = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptFullPath]; // Ajouter les paramètres if (options.parameters) { for (const [key, value] of Object.entries(options.parameters)) { args.push(`-${key}`); if (typeof value === 'boolean') { args.push(`$${value}`); } else { args.push(`"${value}"`); } } } console.log(`Executing PowerShell: pwsh ${args.join(' ')}`); const result = await execa('pwsh', args, { timeout, cwd: options.workingDirectory || process.cwd(), encoding: 'utf8', env: { ...process.env, POWERSHELL_SCRIPTS_PATH: this.scriptsBasePath } }); const executionTime = Date.now() - startTime; // Essayer de parser la sortie comme JSON let data = null; try { data = JSON.parse(result.stdout); } catch { // Si ce n'est pas du JSON, garder la sortie brute data = result.stdout; } return { success: true, data, stdout: result.stdout, stderr: result.stderr, executionTime }; } catch (error) { const executionTime = Date.now() - startTime; let errorMessage = error.message; let stdout = ''; let stderr = ''; if (error.stdout) stdout = error.stdout; if (error.stderr) stderr = error.stderr; // Si l'erreur contient des informations de sortie, essayer de les parser if (error.stdout) { try { const data = JSON.parse(error.stdout); if (data.error) { errorMessage = data.error; } } catch { // Ignorer les erreurs de parsing } } return { success: false, error: errorMessage, stdout, stderr, executionTime }; } } /** * Teste la disponibilité de PowerShell */ async testPowerShellAvailability() { try { const result = await execa('pwsh', ['--version'], { timeout: 5000 }); return { available: true, version: result.stdout.trim(), scriptsPath: this.scriptsBasePath }; } catch (error) { return { available: false, error: error.message, scriptsPath: this.scriptsBasePath }; } } /** * Liste les scripts disponibles */ async listAvailableScripts() { try { const fs = await import('fs'); const files = await fs.promises.readdir(this.scriptsBasePath); return files.filter(file => file.endsWith('.ps1')); } catch (error) { console.error('Error listing PowerShell scripts:', error); return []; } } /** * Vérifie si un script existe */ async scriptExists(scriptPath) { try { const fs = await import('fs'); const fullPath = path.resolve(this.scriptsBasePath, scriptPath); await fs.promises.access(fullPath); return true; } catch { return false; } } } // Factory function to create PowerShell executor with appropriate path export function createPowerShellExecutor(context = 'shared') { let scriptsPath; switch (context) { case 'mcp': scriptsPath = path.resolve(__dirname, '../../../powershell'); break; case 'web': scriptsPath = path.resolve(__dirname, '../../../powershell'); break; case 'shared': default: scriptsPath = path.resolve(__dirname, '../../../powershell'); break; } return new PowerShellExecutor(scriptsPath); }