UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

176 lines 8.58 kB
/** * Get Recommendations Tool - Individual Module * @description Provides intelligent recommendations for optimization improvements * @since 2025-08-04 * @author Tool Modularization Team * * Migration Status: COMPLETED * Original Method: OptimizelyMCPTools.getRecommendations * Complexity: MEDIUM * Dependencies: storage.query, logger, errorMapper, apiClient */ import { MCPErrorUtils } from '../../errors/MCPErrorMapping.js'; /** * Generates recommendations based on project insights * @param insights - Project insights data * @returns Array of recommendations * @private */ function generateInsightRecommendations(insights) { const recommendations = []; const isFeatureExperimentation = insights.project?.is_flags_enabled; // Platform-specific experiment recommendations if (insights.experiments) { if (isFeatureExperimentation) { // Feature Experimentation: Focus on rulesets and flags if (insights.experiments.total_rulesets === 0) { recommendations.push({ type: 'no_rulesets_configured', priority: 'high', message: 'No rulesets configured for your flags. Configure targeting rules or experiments for your flags to start delivering experiences.', affected_count: insights.flags?.total_flags || 0 }); } if (insights.experiments.enabled_rulesets < insights.experiments.total_rulesets * 0.5) { recommendations.push({ type: 'low_ruleset_activation', priority: 'medium', message: 'Less than 50% of your rulesets are enabled. Review disabled rulesets for activation opportunities.', affected_count: insights.experiments.total_rulesets - insights.experiments.enabled_rulesets }); } if (insights.experiments.ab_test_rulesets === 0 && insights.experiments.total_rulesets > 0) { recommendations.push({ type: 'no_experiments_running', priority: 'medium', message: 'No A/B test rulesets found. Consider setting up experiments to measure impact of your feature flags.', affected_count: insights.experiments.rollout_rulesets }); } } else { // Web Experimentation: Focus on traditional experiments if (insights.experiments.paused_count > insights.experiments.running_count) { recommendations.push({ type: 'experiment_activation', priority: 'high', message: 'You have more paused experiments than running ones. Consider reviewing and activating paused experiments.', affected_count: insights.experiments.paused_count }); } if (insights.experiments.running_count === 0 && insights.experiments.total_count > 0) { recommendations.push({ type: 'no_active_experiments', priority: 'high', message: 'No experiments are currently running. Consider starting experiments to gather data.', affected_count: insights.experiments.total_count }); } if (insights.experiments.not_started_count > insights.experiments.total_count * 0.7) { recommendations.push({ type: 'unused_experiments', priority: 'medium', message: 'Many experiments have never been started. Review and launch high-priority experiments.', affected_count: insights.experiments.not_started_count }); } } } // Flag recommendations (Feature Experimentation only) if (insights.flags && isFeatureExperimentation) { const enabledPercentage = insights.flags.total_flags > 0 ? (insights.flags.enabled_flags / insights.flags.total_flags) * 100 : 0; if (enabledPercentage < 50 && insights.flags.total_flags > 0) { recommendations.push({ type: 'low_flag_adoption', priority: 'medium', message: `Only ${enabledPercentage.toFixed(0)}% of flags are enabled across environments. Review disabled flags for potential activation.`, affected_count: insights.flags.total_flags - insights.flags.enabled_flags }); } // Check for environment imbalance if (insights.flags.environment_adoption && insights.flags.environment_adoption.length > 1) { const prodEnv = insights.flags.environment_adoption.find((e) => e.environment_key === 'production'); const devEnv = insights.flags.environment_adoption.find((e) => e.environment_key === 'development'); if (prodEnv && devEnv && prodEnv.enabled_count < devEnv.enabled_count * 0.5) { recommendations.push({ type: 'production_deployment_gap', priority: 'high', message: 'Significantly fewer flags are enabled in production compared to development. Consider promoting tested features.', affected_count: devEnv.enabled_count - prodEnv.enabled_count }); } } } // Audience recommendations (both platforms) if (insights.audiences) { if (insights.audiences.active_audiences < 3) { recommendations.push({ type: 'limited_targeting', priority: 'low', message: 'Consider creating more audience segments for better targeting and personalization.', affected_count: insights.audiences.active_audiences }); } } // Platform-specific recommendations if (!isFeatureExperimentation) { // Web Experimentation specific recommendations.push({ type: 'platform_note', priority: 'info', message: 'This is a Web Experimentation project. Consider upgrading to Feature Experimentation for feature flags and advanced targeting.', affected_count: 0 }); } return recommendations; } /** * Creates the Get Recommendations tool with injected dependencies * @param deps - Injected dependencies (storage, logger, errorMapper, etc.) * @returns Tool definition with handler */ export function createGetRecommendationsTool(deps) { return { name: 'get_recommendations', requiresCache: true, category: 'analytics', description: 'Provides intelligent recommendations for optimization improvements', handler: async (params) => { const { project_id } = params; if (!project_id) { throw MCPErrorUtils.invalidParameters('get_recommendations', ['project_id'], Object.keys(params)); } try { deps.logger.debug({ project_id, focus_area: params.focus_area || 'all', limit: params.limit }, 'OptimizelyMCPTools.getRecommendations: Generating optimization recommendations'); // Use the API helper to generate recommendations const recommendations = await deps.apiClient.getRecommendations(project_id, { focus_area: params.focus_area, include_historical: params.include_historical, timeframe_days: params.timeframe_days, limit: params.limit }); deps.logger.debug({ project_id, recommendationCount: recommendations.recommendations.length, summary: recommendations.summary }, 'OptimizelyMCPTools.getRecommendations: Successfully generated recommendations'); return recommendations; } catch (error) { deps.logger.error({ error: error.message, stack: error.stack }, 'OptimizelyMCPTools.getRecommendations: Failed to generate recommendations'); throw deps.errorMapper.toMCPError(error, 'Failed to generate recommendations'); } } }; } // Export the helper function for potential reuse export { generateInsightRecommendations }; //# sourceMappingURL=GetRecommendations.js.map