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