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