UNPKG

@houmak/minerva-mcp-server

Version:

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

320 lines (319 loc) 13.4 kB
import { logger } from "../logger.js"; import { IntelligentRouter } from "./intelligent-router.js"; export class RouterIntegrationManager { router; config; powershellExecutor; graphClient; availableScopes = []; constructor(config, powershellExecutor, graphClient) { this.router = new IntelligentRouter(); this.config = config; this.powershellExecutor = powershellExecutor; this.graphClient = graphClient; } /** * Set available scopes for the current session */ setAvailableScopes(scopes) { this.availableScopes = scopes; logger.info(`Router Integration: Available scopes updated: ${scopes.join(", ")}`); } /** * Set user preference for a specific action */ setUserPreference(action, provider) { if (this.config.enableUserPreferences) { this.router.setUserPreference(action, provider); } } /** * Execute an action with intelligent routing and fallback */ async executeAction(action, parameters, context) { const startTime = Date.now(); let retries = 0; let lastError; logger.info(`Router Integration: Executing action '${action}' with intelligent routing`); // Get provider selection const providerSelection = await this.router.selectProvider(action, this.availableScopes, context); if (!providerSelection) { return { success: false, provider: 'none', error: `No suitable provider found for action '${action}'`, executionTime: Date.now() - startTime, retries: 0, fallbackUsed: false }; } logger.info(`Router Integration: Selected provider '${providerSelection.provider}' for action '${action}' (confidence: ${providerSelection.confidence}%)`); // Try primary provider const primaryResult = await this.executeWithProvider(action, parameters, providerSelection.provider); if (primaryResult.success) { const executionTime = Date.now() - startTime; this.updatePerformanceMetrics(providerSelection.provider, executionTime, true); return { success: true, provider: providerSelection.provider, data: primaryResult.data, executionTime, retries: 0, fallbackUsed: false }; } lastError = primaryResult.error; retries++; // Try fallback providers if enabled if (this.config.enableFallback && providerSelection.fallbackProviders.length > 0) { for (const fallbackProvider of providerSelection.fallbackProviders) { if (retries >= this.config.maxRetries) { break; } logger.info(`Router Integration: Trying fallback provider '${fallbackProvider}' for action '${action}'`); // Wait before retry if (retries > 1) { await this.delay(this.config.retryDelay); } const fallbackResult = await this.executeWithProvider(action, parameters, fallbackProvider); if (fallbackResult.success) { const executionTime = Date.now() - startTime; this.updatePerformanceMetrics(fallbackProvider, executionTime, true); return { success: true, provider: fallbackProvider, data: fallbackResult.data, executionTime, retries, fallbackUsed: true }; } lastError = fallbackResult.error; retries++; } } // All providers failed const executionTime = Date.now() - startTime; this.updatePerformanceMetrics(providerSelection.provider, executionTime, false); return { success: false, provider: providerSelection.provider, error: lastError || `All providers failed for action '${action}'`, executionTime, retries, fallbackUsed: false }; } /** * Execute action with specific provider */ async executeWithProvider(action, parameters, provider) { try { switch (provider) { case 'graph': return await this.executeWithGraphAPI(action, parameters); case 'pnp': return await this.executeWithPnP(action, parameters); case 'cli': return await this.executeWithCLI(action, parameters); default: return { success: false, error: `Unknown provider: ${provider}` }; } } catch (error) { return { success: false, error: error.message || 'Unknown error' }; } } /** * Execute action with Microsoft Graph API */ async executeWithGraphAPI(action, parameters) { if (!this.graphClient) { return { success: false, error: 'Graph client not available' }; } try { // Handle different Graph API actions switch (action) { case 'Minerva-Microsoft': // This is handled by the main Minerva-Microsoft tool return { success: false, error: 'Minerva-Microsoft tool should be called directly' }; default: return { success: false, error: `Graph API action '${action}' not implemented` }; } } catch (error) { return { success: false, error: error.message }; } } /** * Execute action with PnP PowerShell */ async executeWithPnP(action, parameters) { if (!this.powershellExecutor) { return { success: false, error: 'PowerShell executor not available' }; } try { // Map action to PowerShell script const scriptMapping = this.getScriptMapping(action); if (!scriptMapping) { return { success: false, error: `No script mapping found for action '${action}'` }; } const result = await this.powershellExecutor.executeScript({ scriptPath: scriptMapping.script, parameters: this.mapParameters(parameters, scriptMapping.parameterMapping) }); if (result.success) { return { success: true, data: result.data }; } else { return { success: false, error: result.error || 'PowerShell execution failed' }; } } catch (error) { return { success: false, error: error.message }; } } /** * Execute action with CLI M365 */ async executeWithCLI(action, parameters) { // CLI M365 integration would be implemented here return { success: false, error: 'CLI M365 integration not implemented yet' }; } /** * Get script mapping for an action */ getScriptMapping(action) { const mappings = { 'getSharePointLists': { script: 'Get-SharePointLists.ps1', parameterMapping: { siteUrl: 'SiteUrl', includeHidden: 'IncludeHidden' } }, 'getSiteInventory': { script: 'Get-SiteInventory.ps1', parameterMapping: { siteUrl: 'SiteUrl', includeSubsites: 'IncludeSubsites', includeLists: 'IncludeLists', includePermissions: 'IncludePermissions' } }, 'getPermissionAudit': { script: 'Get-PermissionAudit.ps1', parameterMapping: { siteUrl: 'SiteUrl', includeListsItems: 'IncludeListsItems', excludeLimitedAccess: 'ExcludeLimitedAccess' } }, 'getSiteSharingSettings': { script: 'Get-SiteSharingSettings.ps1', parameterMapping: { siteUrl: 'SiteUrl' } }, 'getExternalUsers': { script: 'Get-ExternalUsers.ps1', parameterMapping: { siteUrl: 'SiteUrl', includeGroups: 'IncludeGroups' } }, 'exportSiteContent': { script: 'Export-SiteContent.ps1', parameterMapping: { siteUrl: 'SiteUrl', exportFolder: 'ExportFolder', packageName: 'PackageName', createPackage: 'CreatePackage' } }, 'getListFormatting': { script: 'Get-ListFormatting.ps1', parameterMapping: { siteUrl: 'SiteUrl', listTitle: 'ListTitle', includeAllLists: 'IncludeAllLists' } }, 'getFlowRunsSummary': { script: 'Get-FlowRunsSummary.ps1', parameterMapping: { environment: 'Environment', date: 'Date', includeDetails: 'IncludeDetails' } }, 'applySiteTemplate': { script: 'Apply-SiteTemplate.ps1', parameterMapping: { siteUrl: 'SiteUrl', templatePath: 'TemplatePath', extractTemplate: 'ExtractTemplate' } }, 'getAzureResources': { script: 'Get-AzureResources.ps1', parameterMapping: { resourceGroupName: 'ResourceGroupName', subscriptionId: 'SubscriptionId', includeDetails: 'IncludeDetails' } }, 'createSharePointSite': { script: 'New-SharePointSite.ps1', parameterMapping: { siteUrl: 'SiteUrl', title: 'Title', description: 'Description', template: 'Template', owner: 'Owner' } }, 'getTeamsReport': { script: 'Get-TeamsReport.ps1', parameterMapping: { includeDetails: 'IncludeDetails', includeMembers: 'IncludeMembers', includeChannels: 'IncludeChannels', includeApps: 'IncludeApps' } }, 'getAADUsersReport': { script: 'Get-AADUsersReport.ps1', parameterMapping: { includeDetails: 'IncludeDetails', includeGroups: 'IncludeGroups', includeLicenses: 'IncludeLicenses', includeSignIns: 'IncludeSignIns' } }, 'getFlowsReport': { script: 'Get-FlowsReport.ps1', parameterMapping: { environment: 'Environment', includeDetails: 'IncludeDetails', includeConnections: 'IncludeConnections', includeRuns: 'IncludeRuns' } }, 'bulkCreateLists': { script: 'New-BulkLists.ps1', parameterMapping: { siteUrl: 'SiteUrl', csvPath: 'CsvPath', listNames: 'ListNames', template: 'Template', includeContentTypes: 'IncludeContentTypes' } }, 'migrateSharePointList': { script: 'Migrate-SharePointLists.ps1', parameterMapping: { sourceSiteUrl: 'SourceSiteUrl', targetSiteUrl: 'TargetSiteUrl', sourceList: 'SourceList', targetList: 'TargetList', includeData: 'IncludeData', includeSchema: 'IncludeSchema', includePermissions: 'IncludePermissions' } }, 'migrateSharePointDocuments': { script: 'Migrate-SharePointDocuments.ps1', parameterMapping: { sourceSiteUrl: 'SourceSiteUrl', targetSiteUrl: 'TargetSiteUrl', sourceLibrary: 'SourceLibrary', targetLibrary: 'TargetLibrary', includePermissions: 'IncludePermissions', includeMetadata: 'IncludeMetadata' } }, 'testMigrationPrerequisites': { script: 'Test-MigrationPrerequisites.ps1', parameterMapping: { sourceSiteUrl: 'SourceSiteUrl', targetSiteUrl: 'TargetSiteUrl' } } }; return mappings[action] || null; } /** * Map parameters to PowerShell script parameters */ mapParameters(parameters, mapping) { const mappedParams = {}; for (const [key, mappedKey] of Object.entries(mapping)) { if (parameters[key] !== undefined) { mappedParams[mappedKey] = parameters[key]; } } return mappedParams; } /** * Update performance metrics */ updatePerformanceMetrics(provider, executionTime, success) { if (this.config.enablePerformanceTracking) { this.router.updatePerformanceMetrics(provider, executionTime, success); } } /** * Delay function for retries */ delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Get router statistics */ getRouterStats() { return this.router.getRouterStats(); } /** * Get provider recommendations for an action */ getProviderRecommendations(action) { return this.router.getProviderRecommendations(action, this.availableScopes); } /** * Validate action */ validateAction(action) { return this.router.validateAction(action); } /** * Check if action is supported by provider */ isActionSupported(action, provider) { return this.router.isActionSupported(action, provider); } /** * Get required scopes for action */ getRequiredScopes(action) { return this.router.getRequiredScopes(action); } }