@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
176 lines • 8.58 kB
JavaScript
/**
* 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