UNPKG

@simonecoelhosfo/optimizely-mcp-server

Version:

Optimizely MCP Server for AI assistants with integrated CLI tools

388 lines 14.7 kB
/** * Entity Router for Parametric Tool Architecture * @description Central routing system for entity operations across Optimizely platforms. * Enables scaling from entity-specific tools to parametric tools that can handle * any entity type through a unified interface. * * This router is the foundation of the parametric architecture that allows us to: * - Scale from 11 tools to ~20 tools while covering 36+ API endpoints * - Maintain consistent operation patterns across all entity types * - Support both Web Experimentation and Feature Experimentation platforms * - Enable future entity types without creating new tools */ import { OptimizelyAPIHelper } from '../api/OptimizelyAPIHelper.js'; import { CacheManager } from '../cache/CacheManager.js'; import { SQLiteEngine } from '../storage/SQLiteEngine.js'; /** * Supported entity types across both Optimizely platforms */ export type EntityType = 'project' | 'flag' | 'experiment' | 'audience' | 'attribute' | 'list_attribute' | 'event' | 'campaign' | 'environment' | 'feature' | 'feature_variable' | 'ruleset' | 'rule' | 'variation' | 'variable_definition' | 'page' | 'extension' | 'group' | 'segment' | 'webhook' | 'collaborator' | 'report' | 'result' | 'recommendation'; /** * Platform detection for entity operations */ export type Platform = 'feature' | 'web' | 'auto'; /** * Project type information from API */ export interface ProjectTypeInfo { projectId: string; projectType: Platform; projectName?: string; isValid: boolean; lastChecked: number; } /** * Supported CRUD operations */ export type EntityOperation = 'list' | 'get' | 'create' | 'update' | 'delete' | 'archive' | 'enable' | 'disable' | 'history' | 'brainstorm' | 'upload' | 'bulk_update' | 'bulk_archive' | 'get_results'; /** * Entity operation parameters */ export interface EntityOperationParams { operation: EntityOperation; entityType: EntityType; platform?: Platform; projectId?: string; entityId?: string; entityKey?: string; filters?: Record<string, any>; data?: Record<string, any>; options?: Record<string, any>; } /** * Entity metadata for routing decisions */ interface EntityMetadata { platform: Platform; apiEndpoint: string; supportsArchive: boolean; supportsPagination: boolean; paginationType: 'page' | 'cursor'; identifierField: 'id' | 'key' | 'both'; parentEntity?: EntityType; } /** * EntityRouter Class * @description Routes entity operations to appropriate handlers based on entity type * and platform. Provides a unified interface for all entity operations while handling * the complexity of different API patterns and requirements. */ export declare class EntityRouter { private apiHelper; private cacheManager; private storage; private defaultsManager; private schemaBuilder; private mcpTools?; /** * Project type cache to avoid repeated API calls * Maps project ID to project type information */ private projectTypeCache; /** * Cache TTL in milliseconds (30 minutes) */ private readonly CACHE_TTL; /** * Entity metadata registry for routing decisions */ private entityMetadata; constructor(apiHelper: OptimizelyAPIHelper, cacheManager: CacheManager, storage: SQLiteEngine); /** * Get or create OptimizelyMCPTools instance * @returns OptimizelyMCPTools instance */ private getMCPTools; /** * Updates local cache with entity data after successful API operations * @param entityType - Type of entity that was updated * @param apiResult - Result from API operation * @param projectId - Project ID for the entity * @param identifier - Entity identifier (fallback if API result doesn't contain ID) */ private updateCacheAfterOperation; /** * Routes an entity operation to the appropriate handler * @param params - Entity operation parameters * @returns Promise resolving to operation result */ routeEntityOperation(params: EntityOperationParams): Promise<any>; /** * Handles list operations for any entity type with cache-first approach * @returns Object with data array and pagination metadata */ private handleListOperation; /** * Query entities from local cache database with pagination support * @returns Object with data array and pagination metadata */ private queryFromCache; /** * Query entities from API (fallback method) with pagination support * @returns Object with data array and pagination metadata */ private queryFromAPI; /** * Build standardized paginated response from API response * Handles different API response formats (array vs object with metadata) */ private buildPaginatedResponse; /** * Get database table name for entity type */ private getTableName; /** * Get valid database columns for an entity type * Based on actual database schema inspection */ private getValidColumnsForEntity; /** * Build WHERE clause for database queries */ private buildWhereClause; /** * Deserialize entity from SQLite storage format back to API format * Handles boolean conversion (0/1 -> false/true) and JSON parsing */ private deserializeEntityFromStorage; /** * Handles get operations for any entity type */ handleGetOperation(entityType: EntityType, projectId?: string, identifier?: string, options?: Record<string, any>): Promise<any>; /** * Handles create operations for any entity type */ handleCreateOperation(entityType: EntityType, projectId?: string, data?: Record<string, any>, options?: Record<string, any>): Promise<any>; /** * Handles update operations for any entity type */ handleUpdateOperation(entityType: EntityType, projectId?: string, identifier?: string, data?: Record<string, any>, options?: Record<string, any>): Promise<any>; /** * Handles delete operations for any entity type */ private handleDeleteOperation; /** * Handles archive operations for any entity type */ private handleArchiveOperation; /** * Gets metadata for an entity type */ getEntityMetadata(entityType: EntityType): EntityMetadata | undefined; /** * Searches for entities by ID or key only * @param params - Search parameters including entity type, project ID, and search criteria * @returns Array of matching entities */ searchEntities(params: { entityType: EntityType; projectId?: string; searchCriteria: { id?: string; key?: string; name?: string; flag_key?: string; environment_key?: string; }; options?: Record<string, any>; }): Promise<any[]>; /** * Finds a single entity by ID or key only * @param entityType - Type of entity to find * @param identifier - ID or key to search for * @param projectId - Optional project ID for project-scoped entities * @returns The found entity or null if not found */ findEntityByIdOrKey(entityType: EntityType, identifier: string, projectId?: string): Promise<any | null>; /** * Gets and caches project type information * @param projectId - The project ID to check * @returns Project type information with caching */ getProjectType(projectId: string): Promise<ProjectTypeInfo>; /** * Validates that a project exists and is accessible * @param projectId - The project ID to validate */ validateProjectExists(projectId: string): Promise<void>; /** * Checks if cached project type information is still valid */ private isCacheValid; /** * Validates if an entity type is available for the given project type * @param entityType - The entity type to validate * @param projectType - The project type ('feature' or 'web') * @param operation - The operation being performed * @returns Error object if not available, null if available */ private validateEntityAvailability; /** * Gets available entities for a specific project type */ private getAvailableEntitiesForProject; /** * Suggests similar entities for the given project type */ private getSimilarEntitySuggestion; /** * Detects the platform for a given project (legacy method) */ detectPlatform(projectId: string): Promise<Platform>; /** * Lists all supported entity types */ getSupportedEntityTypes(): EntityType[]; /** * Gets entity types for a specific platform */ getEntityTypesForPlatform(platform: Platform): EntityType[]; /** * Handles enable operations for Feature Experimentation entities */ private handleEnableOperation; /** * Handles disable operations for Feature Experimentation entities */ private handleDisableOperation; /** * Handles history operations for Feature Experimentation entities */ private handleHistoryOperation; /** * Handles brainstorm operations (AI-powered suggestions) */ private handleBrainstormOperation; /** * Handles upload operations (bulk operations) */ private handleUploadOperation; /** * Handles bulk update operations for entity types that support them */ private handleBulkUpdateOperation; /** * Handles bulk archive operations for entity types that support them */ private handleBulkArchiveOperation; /** * Handles get results operations for experiments and campaigns * @param entityType - Type of entity (experiment or campaign) * @param projectId - Project ID (optional for some operations) * @param entityId - Entity ID to get results for * @param filters - Optional filters (date range, metrics, etc.) * @param options - Additional options * @returns Results data from the API */ private handleGetResultsOperation; /** * Enhances operation result with project type metadata * @param result - The operation result to enhance * @param projectId - Project ID if available * @param entityType - Entity type for the operation * @param operation - Operation that was performed * @returns Enhanced result with metadata */ enhanceResultWithMetadata(result: any, projectId?: string, entityType?: EntityType, operation?: EntityOperation): Promise<any>; /** * Clears the project type cache * @param projectId - Optional project ID to clear specific entry, or clear all if not provided */ clearProjectTypeCache(projectId?: string): void; /** * Gets cache statistics */ getCacheStats(): { size: number; entries: Array<{ projectId: string; projectType: Platform; lastChecked: Date; isValid: boolean; }>; }; /** * Gets a formatted error for unsupported entity/project combinations * @param entityType - The entity type requested * @param projectId - The project ID * @param projectType - The project type * @returns Formatted error object */ getEntityAvailabilityError(entityType: EntityType, projectId: string, projectType: Platform): any; /** * 🚨 SMART EXPERIMENT ROUTING - Handles experiment confusion intelligently * When agent asks for 'experiment' on Feature Experimentation project, automatically redirect to flag approach * @param projectId - The project ID to check * @param filters - Original filters from the request * @param options - Original options from the request * @returns Enhanced result with flag-based experiment data and explanation */ private handleSmartExperimentRouting; /** * Extracts experiment-like data from flag configurations * @param flags - Array of flags from the API * @param projectId - Project ID for additional context * @returns Array of experiment summaries extracted from flags */ private extractExperimentDataFromFlags; /** * Determines if a ruleset represents an A/B test experiment * @param ruleset - The ruleset to analyze * @returns true if this is an experiment, false if it's just targeted delivery */ private isRulesetAnExperiment; /** * Creates enhanced error messages with prescriptive guidance * @param entityType - The entity type that failed * @param projectId - Project ID if available * @param originalError - The original error * @param suggestions - Additional suggestions for the user * @returns Enhanced MCP error with guidance */ private createEnhancedEntityError; /** * Build operation summary for enhanced metadata * @param operation - The operation performed * @param entityType - The entity type * @param result - The operation result * @param projectInfo - Project information * @returns Summary object for metadata */ private buildOperationSummary; /** * Validates custom attributes in audience conditions and transforms for Web Experimentation * @returns The potentially corrected/transformed conditions string */ private validateCustomAttributesInConditions; /** * Recursively extracts custom attribute references from audience conditions (platform-aware) */ private extractCustomAttributeReferences; /** * CRITICAL: Pre-validate payload for known validation issues before API call * This prevents API-level validation failures by catching issues early and providing * clear hard-stop errors that prevent infinite AI retry loops. */ private validatePayloadBeforeAPI; /** * Proactively syncs environments for a newly created project * @param projectId - Project ID to sync environments for * @description When a project is created, Optimizely automatically creates * "production" and "development" environments. This method fetches them * immediately from the API and stores them in the local database to avoid * waiting for the next sync interval. * @private */ private syncProjectEnvironments; /** * Convert variation_id fields from strings to integers for API compatibility * The Optimizely API expects variation_id as integer, but template data may contain strings */ private convertVariationIdsToIntegers; /** * Helper method to debug variation_id types */ private getVariationIdTypes; } export {}; //# sourceMappingURL=EntityRouter.d.ts.map