Skip to main content
Glama
workflow-orchestrator.ts6.6 kB
// Workflow Orchestrator - Controls which tools Claude Desktop can access based on session state export interface WorkflowSession { id: string; stage: WorkflowStage; context: Record<string, any>; createdAt: Date; lastActivity: Date; } export enum WorkflowStage { CHARACTER_ANALYSIS = 'character_analysis', PUPPET_GENERATION = 'puppet_generation', VOICE_CREATION = 'voice_creation', PRODUCTION_REVIEW = 'production_review', COMPLETE = 'complete' } export interface ToolDefinition { name: string; description: string; inputSchema: any; allowedStages?: WorkflowStage[]; isCore?: boolean; // Core puppet production tools } class WorkflowOrchestrator { private sessions = new Map<string, WorkflowSession>(); // Get session ID from connection (simplified - could use connection metadata) private getSessionId(connectionId?: string): string { return connectionId || 'default-session'; } // Get or create workflow session getSession(connectionId?: string): WorkflowSession { const sessionId = this.getSessionId(connectionId); if (!this.sessions.has(sessionId)) { this.sessions.set(sessionId, { id: sessionId, stage: WorkflowStage.CHARACTER_ANALYSIS, context: {}, createdAt: new Date(), lastActivity: new Date() }); } const session = this.sessions.get(sessionId)!; session.lastActivity = new Date(); return session; } // Filter tools based on current workflow stage filterToolsForSession(allTools: ToolDefinition[], connectionId?: string): ToolDefinition[] { const session = this.getSession(connectionId); // Always include core puppet production tools const coreTools = allTools.filter(tool => tool.isCore); // Add stage-specific tools const stageTools = allTools.filter(tool => !tool.isCore && (!tool.allowedStages || tool.allowedStages.includes(session.stage)) ); return [...coreTools, ...stageTools]; } // Validate if a tool call is allowed in current stage isToolAllowed(toolName: string, allTools: ToolDefinition[], connectionId?: string): { allowed: boolean; message?: string; redirect?: string; } { const session = this.getSession(connectionId); const tool = allTools.find(t => t.name === toolName); if (!tool) { return { allowed: false, message: "Unknown tool. Please use the puppet production tools to create your character.", redirect: "Use 'analyze_character_image' to start creating a puppet character from a photo." }; } // Core puppet tools are always allowed if (tool.isCore) { return { allowed: true }; } // Check stage-specific tools if (tool.allowedStages && !tool.allowedStages.includes(session.stage)) { return { allowed: false, message: `This tool is not available in the current workflow stage (${session.stage}). Please continue with puppet production.`, redirect: this.getStageGuidance(session.stage) }; } return { allowed: true }; } // Get guidance for current stage private getStageGuidance(stage: WorkflowStage): string { switch (stage) { case WorkflowStage.CHARACTER_ANALYSIS: return "Upload a photo and use 'analyze_character_image' to start character analysis."; case WorkflowStage.PUPPET_GENERATION: return "Use 'generate_puppet_image' to create your puppet character."; case WorkflowStage.VOICE_CREATION: return "Use 'create_voice_profile' to add voice to your character."; case WorkflowStage.PRODUCTION_REVIEW: return "Review and finalize your puppet character production."; default: return "Continue with the puppet production workflow."; } } // Update session stage updateStage(stage: WorkflowStage, connectionId?: string): void { const session = this.getSession(connectionId); session.stage = stage; session.lastActivity = new Date(); } // Add context to session addContext(key: string, value: any, connectionId?: string): void { const session = this.getSession(connectionId); session.context[key] = value; session.lastActivity = new Date(); } // Clean up old sessions (older than 1 hour) cleanup(): void { const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); for (const [sessionId, session] of this.sessions) { if (session.lastActivity < oneHourAgo) { this.sessions.delete(sessionId); } } } } // Singleton instance export const workflowOrchestrator = new WorkflowOrchestrator(); // Tool definitions with workflow stages export const getPuppetProductionTools = (): ToolDefinition[] => [ { name: 'analyze_character_image', description: 'Analyze uploaded photo to extract character features for puppet creation', inputSchema: { type: 'object', properties: { image_url: { type: 'string' }, analysis_type: { type: 'string', enum: ['full', 'face_only', 'style_only'] } }, required: ['image_url'] }, isCore: true, allowedStages: [WorkflowStage.CHARACTER_ANALYSIS] }, { name: 'generate_puppet_image', description: 'Generate puppet character image with hand controls based on character analysis', inputSchema: { type: 'object', properties: { character_features: { type: 'object' }, puppet_style: { type: 'string', enum: ['hand_puppet', 'marionette_hand', 'finger_puppet'] }, background: { type: 'string' } }, required: ['character_features'] }, isCore: true, allowedStages: [WorkflowStage.PUPPET_GENERATION] }, { name: 'create_voice_profile', description: 'Create ElevenLabs voice profile for the puppet character', inputSchema: { type: 'object', properties: { character_name: { type: 'string' }, voice_style: { type: 'string' }, sample_text: { type: 'string' } }, required: ['character_name'] }, isCore: true, allowedStages: [WorkflowStage.VOICE_CREATION] }, { name: 'finalize_character', description: 'Complete puppet character production and generate final assets', inputSchema: { type: 'object', properties: { character_data: { type: 'object' }, export_format: { type: 'string', enum: ['json', 'zip', 'pdf'] } }, required: ['character_data'] }, isCore: true, allowedStages: [WorkflowStage.PRODUCTION_REVIEW, WorkflowStage.COMPLETE] } ];

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bermingham85/mcp-puppet-pipeline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server