UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

519 lines 23.7 kB
import { getLogger } from '../logging/Logger.js'; import { MCPErrorMapper } from '../errors/MCPErrorMapping.js'; import { sampleRegistry } from '../templates/orchestration/samples/SampleRegistry.js'; import { entityTypeRegistry, troubleshootingGuide, orchestrationConcepts } from '../templates/orchestration/samples/SystemTemplateReference.js'; /** * Provider for orchestration sample templates * Educational tool for understanding orchestration structure */ export class OrchestrationSamplesProvider { /** * Get orchestration samples for learning and reference */ async getOrchestrationSamples(params = {}) { try { getLogger().debug({ params }, 'OrchestrationSamplesProvider.getOrchestrationSamples: Called'); const { operation = 'get', sample_type, workflow_type, complexity = 1, platform, include_explanations = true } = params; const timestamp = new Date().toISOString(); // No parameters provided - show discovery catalog if (!operation && !sample_type && !workflow_type && !platform) { return await this.buildDiscoveryResponse(timestamp); } // Handle different operations switch (operation) { case 'list': return await this.buildListResponse(timestamp, { platform, workflow_type, sample_type, complexity }); case 'registry': return await this.buildRegistryResponse(timestamp, params.registry_filter); case 'search': return await this.buildSearchResponse(timestamp, params.search_query || ''); case 'troubleshoot': return await this.buildTroubleshootingResponse(timestamp); case 'concepts': return await this.buildConceptsResponse(timestamp); case 'get': default: // Continue with get operation below break; } // Handle get operation if (operation === 'get') { // Check if getting by ID if (params.sample_id) { const sample = await sampleRegistry.getSampleById(params.sample_id); if (!sample) { return this.buildErrorResponse(timestamp, `No sample found with ID '${params.sample_id}'`, `Try listing samples with operation="list" to see available IDs`); } return this.buildSampleResponse(timestamp, sample, include_explanations); } // No workflow type specified - show error with help if (!workflow_type) { return this.buildErrorResponse(timestamp, 'No workflow_type specified', 'Please specify a workflow_type to retrieve a sample'); } // Try to get the requested sample const sample = await sampleRegistry.getSample(workflow_type, sample_type || 'skeleton', complexity); if (!sample) { // Get available samples to provide specific guidance const catalog = await sampleRegistry.listAvailable(); const availableForType = Object.keys(catalog.by_workflow); return { operation: 'get', timestamp, error: `No sample found for workflow_type '${workflow_type}' with sample_type '${sample_type || 'skeleton'}' and complexity ${complexity}`, // IMMEDIATE NEXT STEPS at the top immediate_solutions: [ { command: `get_orchestration_samples(workflow_type="${availableForType[0]}", sample_type="skeleton")`, description: `Get the simplest ${availableForType[0]} template to start with` }, { command: `get_orchestration_samples(operation="list")`, description: "Browse all available workflow types and their complexity levels" }, { command: `get_orchestration_samples(operation="search", search_query="${workflow_type}")`, description: "Search for templates related to your workflow type" } ], // Available options - detailed information workflow_options: Object.entries(catalog.by_workflow).map(([type, info]) => ({ workflow_type: type, description: info.description, available_complexities: info.complexity_levels, available_types: info.available_types, entity_count: info.entity_count, sample_command: `get_orchestration_samples(workflow_type="${type}")` })), // Simple string array for compatibility available_workflow_types: Object.keys(catalog.by_workflow), quick_fixes: { try_different_complexity: workflow_type in catalog.by_workflow ? `get_orchestration_samples(workflow_type="${workflow_type}", complexity=${catalog.by_workflow[workflow_type].complexity_levels[0]})` : null, try_pattern_instead: workflow_type in catalog.by_workflow ? `get_orchestration_samples(workflow_type="${workflow_type}", sample_type="pattern")` : null } }; } return this.buildSampleResponse(timestamp, sample, include_explanations); } // Should not reach here return this.buildErrorResponse(timestamp, 'Invalid operation', 'Use operation="get" or operation="list"'); } catch (error) { getLogger().error({ error }, 'OrchestrationSamplesProvider.getOrchestrationSamples: Failed'); throw MCPErrorMapper.toMCPError(error, 'Failed to get orchestration samples'); } } /** * Build discovery response when no parameters provided */ async buildDiscoveryResponse(timestamp) { const catalog = await sampleRegistry.listAvailable(); return { operation: 'get', timestamp, discovery_mode: true, message: 'Welcome to Enhanced Orchestration Samples! Now with documentation and search.', quick_start: { // Documentation and learning system_registry: { command: 'get_orchestration_samples(operation="registry")', description: '📚 View ALL available system templates and their requirements' }, search_docs: { command: 'get_orchestration_samples(operation="search", search_query="event")', description: '🔍 Search templates, concepts, and troubleshooting' }, troubleshoot: { command: 'get_orchestration_samples(operation="troubleshoot")', description: '🛠️ Get troubleshooting guide and common errors' }, learn_concepts: { command: 'get_orchestration_samples(operation="concepts")', description: '🎓 Learn variable resolution, dependencies, and patterns' }, // Sample templates list_samples: { command: 'get_orchestration_samples(operation="list")', description: '📋 Browse all workflow samples' }, first_template: { command: 'get_orchestration_samples(workflow_type="ab_test", sample_type="skeleton")', description: '🚀 Start with simple A/B test skeleton' }, full_example: { command: 'get_orchestration_samples(workflow_type="personalization_campaign", sample_type="complete_example")', description: '💎 See production-ready personalization campaign' } }, available_workflows: catalog.by_workflow, learning_path: catalog.learning_path, related_tools: { 'manage_orchestration_templates': 'Create and manage actual orchestration templates', 'orchestrate_template': 'Execute orchestration templates', 'get_entity_templates': 'Get templates for individual entities (not workflows)' } }; } /** * Build list response showing available samples */ async buildListResponse(timestamp, filters) { const catalog = await sampleRegistry.listAvailable(filters); const response = { operation: 'list', timestamp, total_samples: catalog.total_samples, available_samples: catalog.by_workflow, learning_path: catalog.learning_path }; if (filters?.platform) { response.platform_filter = filters.platform; response.message = `Showing samples for ${filters.platform} platform`; } // Add usage examples based on what's available const workflows = Object.keys(catalog.by_workflow); if (workflows.length > 0) { response.quick_start = { try_first: { command: `get_orchestration_samples(workflow_type="${workflows[0]}")`, description: `Get skeleton for ${workflows[0]}` } }; } return response; } /** * Build response for a specific sample */ buildSampleResponse(timestamp, sample, include_explanations) { const response = { operation: 'get', timestamp, sample_type: sample.sample_type, workflow_type: sample.workflow_type, complexity: sample.complexity, template: sample.template, related_tools: { 'manage_orchestration_templates': 'Use this template as a base for creating your own', 'orchestrate_template': 'Execute your customized template', 'get_entity_templates': 'Understand individual entity schemas used in steps' } }; // Add sample-type specific content switch (sample.sample_type) { case 'skeleton': response.structure_guide = sample.explanations || this.getDefaultStructureGuide(); response.next_steps = [ 'Review the structure and understand each section', 'Add parameters for your specific use case', 'Define additional steps as needed', `Try the pattern version: get_orchestration_samples(workflow_type="${sample.workflow_type}", sample_type="pattern")` ]; break; case 'pattern': response.pattern_explanation = { use_case: sample.description, key_patterns: sample.use_cases, customization_points: sample.customization_guide }; response.next_steps = [ 'Adapt the pattern to your specific needs', 'Modify parameters and step configurations', `See complete example: get_orchestration_samples(workflow_type="${sample.workflow_type}", sample_type="complete_example")` ]; break; case 'complete_example': response.implementation_notes = { source: 'Orchestration Bible v2.0', tested: true, platform: sample.platform, entities_created: this.countEntities(sample.template) }; response.best_practices = sample.best_practices || [ 'Always define rollback strategy for production', 'Use meaningful step IDs for debugging', 'Include output mappings for step dependencies', 'Test with small audience first' ]; response.common_mistakes = sample.common_mistakes; break; } // Add explanations if requested if (include_explanations && sample.explanations) { response.structure_guide = sample.explanations; } return response; } /** * Build error response with helpful information */ buildErrorResponse(timestamp, error, suggestion) { const availableWorkflows = [ 'personalization_campaign - Multi-audience personalization with campaign', 'ab_test - Standard A/B testing with variations', 'progressive_rollout - Gradual feature flag deployment', 'feature_flag_with_targeting - Feature flags with audience rules', 'multi_entity_creation - Complex multi-entity workflows', 'campaign_with_experiments - Campaign with multiple experiments' ]; return { operation: 'get', timestamp, error, suggestion, available_workflow_types: availableWorkflows, quick_start: { simple_example: { command: 'get_orchestration_samples(workflow_type="ab_test")', description: 'Start with a simple A/B test example' }, browse_all: { command: 'get_orchestration_samples(operation="list")', description: 'See all available samples' } }, related_tools: { 'get_entity_templates': 'For individual entity templates (not workflows)', 'manage_orchestration_templates': 'For managing existing orchestration templates' } }; } /** * Get default structure guide for skeletons */ getDefaultStructureGuide() { return { 'id': 'Unique identifier for your template', 'name': 'Human-readable template name', 'parameters': 'Input values the template accepts', 'steps': 'Sequential operations to execute', 'step.id': 'Unique identifier for referencing this step', 'step.template': 'Entity operation configuration', 'system_template_id': 'References pre-built entity templates', '${variable}': 'Substitutes values from parameters', '${step.field}': 'References output from previous steps', 'depends_on': 'Ensures proper execution order' }; } /** * Count entities that will be created by a template */ countEntities(template) { if (!template.steps) return 0; return template.steps.filter((step) => step.template?.operation === 'create').length; } /** * Build response for system template registry */ async buildRegistryResponse(timestamp, filter) { let templates = Object.values(entityTypeRegistry); // Apply filters if (filter) { if (filter.entity_type) { templates = templates.filter(t => t.entity_type === filter.entity_type); } if (filter.platform) { templates = templates.filter(t => t.platform === filter.platform || t.platform === 'both'); } // Note: EntityTypeReference doesn't have operation field - it's always 'create' for Direct Templates } // Group by entity type for better organization const grouped = templates.reduce((acc, template) => { if (!acc[template.entity_type]) { acc[template.entity_type] = []; } acc[template.entity_type].push(template); return acc; }, {}); return { operation: 'registry', timestamp, system_templates: grouped, total_templates: templates.length, registry_filter_applied: filter, message: `Found ${templates.length} system templates`, next_steps: [ 'Use these template IDs in your orchestration steps', 'Check required_fields for each template', 'Reference optional_fields for additional configuration', 'See examples for common usage patterns' ], related_tools: { 'get_entity_templates': 'Get the actual template structure for these system templates', 'get_orchestration_samples': 'See how these templates are used in workflows' } }; } /** * Build response for search operation */ async buildSearchResponse(timestamp, query) { if (!query || query.trim().length === 0) { return { operation: 'search', timestamp, search_query: query, error: 'Search query is required', suggestion: 'Provide a search term like "event", "audience", "flag", "troubleshoot", etc.' }; } const results = []; const searchTerm = query.toLowerCase(); // Search entity type registry Object.entries(entityTypeRegistry).forEach(([id, template]) => { const relevance = this.calculateRelevance(searchTerm, [ id, template.entity_type, template.description, template.notes || '' ]); if (relevance > 0) { results.push({ type: 'system_template', name: id, description: template.description, relevance, content: template }); } }); // Search troubleshooting items troubleshootingGuide.common_errors.forEach(error => { const relevance = this.calculateRelevance(searchTerm, [ error.error, error.cause, error.solution ]); if (relevance > 0) { results.push({ type: 'troubleshooting', name: error.error, description: error.cause, relevance, content: error }); } }); // Search concepts Object.entries(orchestrationConcepts).forEach(([concept, data]) => { const relevance = this.calculateRelevance(searchTerm, [ concept, data.description ]); if (relevance > 0) { results.push({ type: 'concept', name: concept, description: data.description, relevance, content: data }); } }); // Search sample templates const catalog = await sampleRegistry.listAvailable(); Object.entries(catalog.by_workflow).forEach(([workflow, info]) => { const relevance = this.calculateRelevance(searchTerm, [ workflow, info.description, ...info.use_cases ]); if (relevance > 0) { results.push({ type: 'workflow_sample', name: workflow, description: info.description, relevance, content: { workflow_type: workflow, available_types: info.available_types, use_cases: info.use_cases } }); } }); // Sort by relevance results.sort((a, b) => b.relevance - a.relevance); return { operation: 'search', timestamp, search_query: query, search_results: results.slice(0, 20), // Top 20 results total_results: results.length, message: `Found ${results.length} results for "${query}"`, next_steps: results.length > 0 ? [ 'Use operation="get" to retrieve specific samples', 'Use operation="registry" to see all system templates', 'Use operation="troubleshoot" for debugging help' ] : [ 'Try broader search terms', 'Use operation="list" to browse all samples', 'Use operation="concepts" to understand orchestration' ] }; } /** * Calculate relevance score for search */ calculateRelevance(searchTerm, fields) { let score = 0; const terms = searchTerm.split(/\s+/); fields.forEach(field => { const fieldLower = field.toLowerCase(); terms.forEach(term => { if (fieldLower.includes(term)) { score += fieldLower === term ? 3 : 1; // Exact match scores higher } }); }); return score; } /** * Build response for troubleshooting */ async buildTroubleshootingResponse(timestamp) { return { operation: 'troubleshoot', timestamp, troubleshooting: troubleshootingGuide, message: 'Orchestration troubleshooting guide', next_steps: [ 'Review common errors and their solutions', 'Use the validation checklist before executing templates', 'Follow debugging tips for complex issues', 'Search for specific error messages using operation="search"' ], related_tools: { 'validate_orchestration_template': 'Validate your template before execution', 'get_orchestration_execution_status': 'Check execution logs for errors' } }; } /** * Build response for concepts */ async buildConceptsResponse(timestamp) { return { operation: 'concepts', timestamp, concepts: orchestrationConcepts, concept_categories: Object.keys(orchestrationConcepts), message: 'Orchestration concepts and patterns', next_steps: [ 'Study variable resolution patterns for dynamic templates', 'Understand dependency management for complex workflows', 'Learn error handling strategies', 'Apply these concepts in your templates' ], related_tools: { 'get_orchestration_samples': 'See these concepts applied in real examples', 'orchestrate_template': 'Execute templates using these concepts' } }; } } // Export singleton instance export const orchestrationSamplesProvider = new OrchestrationSamplesProvider(); //# sourceMappingURL=OrchestrationSamplesProvider.js.map