/** * MCP PowerPoint Backend Service * Integrates with MCP PowerPoint server for presentation generation */ import { eventBus } from '../../mcp/EventBus.js'; import { logger } from '../../utils/logger.js'; interface MCPClient { callTool(toolName: string, params: Record): Promise; } interface SlideData { title: string; content: string[]; notes?: string; imageUrl?: string; } interface PresentationConfig { name: string; title: string; theme?: string; author?: string; } /** * MCPPowerPointBackend - Handles PowerPoint generation via MCP */ export class MCPPowerPointBackend { private mcpClient: MCPClient | null = null; private isInitialized = false; private presentations: Map = new Map(); constructor() { this.setupEventListeners(); } private setupEventListeners(): void { eventBus.on('docgen:powerpoint:create', async (data) => { try { await this.createPresentation({ name: data.presentationId, title: data.title, theme: data.theme, author: data.userId }); eventBus.emit('docgen:powerpoint:created', { presentationId: data.presentationId, status: 'created' }); } catch (error) { logger.error('PowerPoint creation failed:', error); eventBus.emit('docgen:powerpoint:error', { presentationId: data.presentationId, error: String(error) }); } }); } /** * Initialize MCP client connection */ async initialize(client?: MCPClient): Promise { if (client) { this.mcpClient = client; } else { // Create mock client for development this.mcpClient = this.createMockClient(); } this.isInitialized = true; logger.info('MCPPowerPointBackend initialized'); } private createMockClient(): MCPClient { return { callTool: async (toolName: string, params: Record) => { logger.debug(`Mock MCP call: ${toolName}`, params); // Simulate tool responses switch (toolName) { case 'create-presentation': return { success: true, name: params.name }; case 'add-slide-title': case 'add-slide-content': case 'add-slide-bullet': case 'add-slide-image': return { success: true, slideIndex: Math.floor(Math.random() * 10) }; case 'generate-and-save-image': return { success: true, image_path: `/images/${params.file_name || 'generated'}.png` }; case 'save-presentation': return { success: true, file_path: `/presentations/${params.presentation_name}.pptx` }; default: return { success: false, error: 'Unknown tool' }; } } }; } /** * Create a new presentation */ async createPresentation(config: PresentationConfig): Promise { if (!this.isInitialized || !this.mcpClient) { throw new Error('MCPPowerPointBackend not initialized'); } const result = await this.mcpClient.callTool('create-presentation', { name: config.name, title: config.title, theme: config.theme || 'corporate' }) as { success: boolean; name: string }; if (result.success) { this.presentations.set(config.name, { name: config.name, slides: [] }); return config.name; } throw new Error('Failed to create presentation'); } /** * Add a slide to a presentation */ async addSlide( presentationName: string, slideType: 'title' | 'content' | 'bullet' | 'image' | 'two-column', data: SlideData ): Promise { if (!this.mcpClient) { throw new Error('MCPPowerPointBackend not initialized'); } const toolName = `add-slide-${slideType}`; await this.mcpClient.callTool(toolName, { presentation_name: presentationName, title: data.title, content: data.content, notes: data.notes, image_url: data.imageUrl }); // Track slide locally const presentation = this.presentations.get(presentationName); if (presentation) { presentation.slides.push(data); } } /** * Generate an image using AI */ async generateImage(prompt: string, fileName: string): Promise { if (!this.mcpClient) { throw new Error('MCPPowerPointBackend not initialized'); } const result = await this.mcpClient.callTool('generate-and-save-image', { prompt, file_name: fileName }) as { success: boolean; image_path: string }; return result.image_path; } /** * Save the presentation */ async savePresentation(presentationName: string): Promise { if (!this.mcpClient) { throw new Error('MCPPowerPointBackend not initialized'); } const result = await this.mcpClient.callTool('save-presentation', { presentation_name: presentationName }) as { success: boolean; file_path: string }; return result.file_path; } /** * Get presentation info */ getPresentation(name: string): { name: string; slides: SlideData[] } | undefined { return this.presentations.get(name); } /** * List all presentations */ listPresentations(): string[] { return Array.from(this.presentations.keys()); } } // Singleton instance let instance: MCPPowerPointBackend | null = null; export function getMCPPowerPointBackend(): MCPPowerPointBackend { if (!instance) { instance = new MCPPowerPointBackend(); } return instance; } export default MCPPowerPointBackend;