@houmak/minerva-mcp-server
Version:
Minerva Model Context Protocol (MCP) Server for Microsoft 365 and Azure integrations
164 lines (163 loc) • 5.57 kB
JavaScript
// 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);
}