UNPKG

@houmak/minerva-mcp-server

Version:

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

225 lines (224 loc) 8.38 kB
import { logger } from '../logger.js'; export class ConnectorFramework { connectors = new Map(); configs = new Map(); executionHistory = []; /** * Enregistrer un connecteur */ async registerConnector(connector) { logger.info('Registering connector', { name: connector.name, version: connector.version }); try { // Valider le connecteur const validation = await this.validateConnector(connector); if (!validation.isValid) { throw new Error(`Connector validation failed: ${validation.errors.join(', ')}`); } this.connectors.set(connector.name, connector); logger.info('Connector registered successfully', { name: connector.name }); } catch (error) { logger.error('Failed to register connector', { name: connector.name, error: error instanceof Error ? error.message : String(error) }); throw error; } } /** * Exécuter un connecteur */ async executeConnector(name, params) { logger.info('Executing connector', { name, params }); const startTime = Date.now(); try { const connector = this.connectors.get(name); if (!connector) { throw new Error(`Connector '${name}' not found`); } // Valider les paramètres if (!connector.validate(params)) { throw new Error(`Invalid parameters for connector '${name}'`); } // Exécuter le connecteur const data = await connector.execute(params); const result = { success: true, data, executionTime: Date.now() - startTime, timestamp: new Date() }; this.executionHistory.push(result); logger.info('Connector executed successfully', { name, executionTime: result.executionTime }); return result; } catch (error) { const result = { success: false, error: error instanceof Error ? error.message : String(error), executionTime: Date.now() - startTime, timestamp: new Date() }; this.executionHistory.push(result); logger.error('Connector execution failed', { name, error: error instanceof Error ? error.message : String(error) }); return result; } } /** * Lister tous les connecteurs */ async listConnectors() { logger.info('Listing connectors'); const connectors = []; for (const [name, connector] of this.connectors) { connectors.push({ name, version: connector.version, description: connector.description, enabled: true, capabilities: connector.getCapabilities(), lastUsed: this.getLastUsage(name) }); } logger.info('Connectors listed successfully', { count: connectors.length }); return connectors; } /** * Valider un connecteur */ async validateConnector(connector) { logger.info('Validating connector', { name: connector.name }); const errors = []; const warnings = []; // Vérifications de base if (!connector.name || connector.name.trim() === '') { errors.push('Connector name is required'); } if (!connector.version || connector.version.trim() === '') { errors.push('Connector version is required'); } if (typeof connector.execute !== 'function') { errors.push('Connector must have an execute method'); } if (typeof connector.validate !== 'function') { errors.push('Connector must have a validate method'); } if (typeof connector.getCapabilities !== 'function') { errors.push('Connector must have a getCapabilities method'); } // Vérifier si le nom est unique if (this.connectors.has(connector.name)) { warnings.push(`Connector with name '${connector.name}' already exists and will be replaced`); } const result = { isValid: errors.length === 0, errors, warnings }; logger.info('Connector validation completed', { name: connector.name, isValid: result.isValid }); return result; } /** * Configurer un connecteur */ async configureConnector(config) { logger.info('Configuring connector', { name: config.name, type: config.type }); try { this.configs.set(config.name, config); logger.info('Connector configured successfully', { name: config.name }); } catch (error) { logger.error('Failed to configure connector', { name: config.name, error: error instanceof Error ? error.message : String(error) }); throw error; } } /** * Obtenir la configuration d'un connecteur */ async getConnectorConfig(name) { return this.configs.get(name) || null; } /** * Activer/désactiver un connecteur */ async setConnectorEnabled(name, enabled) { logger.info('Setting connector enabled state', { name, enabled }); const config = this.configs.get(name); if (config) { config.enabled = enabled; this.configs.set(name, config); logger.info('Connector enabled state updated', { name, enabled }); } else { throw new Error(`Connector configuration not found: ${name}`); } } /** * Obtenir l'historique d'exécution */ async getExecutionHistory(limit = 50) { return this.executionHistory.slice(-limit); } /** * Obtenir les statistiques d'utilisation */ async getUsageStats() { const stats = { totalConnectors: this.connectors.size, totalExecutions: this.executionHistory.length, successfulExecutions: this.executionHistory.filter(r => r.success).length, failedExecutions: this.executionHistory.filter(r => !r.success).length, averageExecutionTime: this.calculateAverageExecutionTime(), mostUsedConnectors: this.getMostUsedConnectors() }; return stats; } /** * Nettoyer l'historique d'exécution */ async clearExecutionHistory() { logger.info('Clearing execution history'); this.executionHistory = []; logger.info('Execution history cleared'); } /** * Obtenir les connecteurs par capacité */ async getConnectorsByCapability(capability) { const connectors = await this.listConnectors(); return connectors.filter(c => c.capabilities.includes(capability)); } /** * Vérifier la disponibilité d'un connecteur */ async isConnectorAvailable(name) { const connector = this.connectors.get(name); const config = this.configs.get(name); return connector !== undefined && config?.enabled === true; } /** * Méthodes privées utilitaires */ getLastUsage(connectorName) { const executions = this.executionHistory.filter(r => r.data?.connectorName === connectorName || r.data?.name === connectorName); if (executions.length > 0) { return executions[executions.length - 1].timestamp; } return undefined; } calculateAverageExecutionTime() { if (this.executionHistory.length === 0) { return 0; } const totalTime = this.executionHistory.reduce((sum, result) => sum + result.executionTime, 0); return totalTime / this.executionHistory.length; } getMostUsedConnectors() { const usageCount = {}; this.executionHistory.forEach(result => { const connectorName = result.data?.connectorName || result.data?.name || 'unknown'; usageCount[connectorName] = (usageCount[connectorName] || 0) + 1; }); return Object.entries(usageCount) .map(([name, count]) => ({ name, count })) .sort((a, b) => b.count - a.count) .slice(0, 5); } }