Skip to main content
Glama
inject-and-view-composition-v2.0.0.ts8.81 kB
#!/usr/bin/env node /** * Enhanced MCP Tool v2.0.0 with Browser Automation Workflow * @version 2.0.0 * @created 2025-07-02 * @description Production-ready MCP tool using browser automation to bypass API restrictions * @supersedes inject-and-view-composition-v1.1.0.js */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { RealBrowserManager } from '../browser-intelligent-mcp-server.js'; import { ComposerUIAutomation } from '../browser-automation/composer-ui-automation.js'; import { IntelligentWidgetGenerator } from '../browser-intelligent-mcp-server.js'; import { readFileSync } from 'fs'; import { join } from 'path'; class BrowserAutomationComposerServer { private server: Server; private browserManager: RealBrowserManager; private uiAutomation: ComposerUIAutomation; private widgetGenerator: IntelligentWidgetGenerator; private jwtToken: string | null = null; constructor() { this.server = new Server( { name: 'euconquisto-composer-browser-automation', version: '2.0.0', }, { capabilities: { tools: {}, }, } ); this.browserManager = new RealBrowserManager(); this.uiAutomation = new ComposerUIAutomation(); this.widgetGenerator = new IntelligentWidgetGenerator(); this.setupToolHandlers(); this.loadJwtToken(); } private loadJwtToken() { try { const tokenPath = join(process.cwd(), 'archive/authentication/correct-jwt-new.txt'); this.jwtToken = readFileSync(tokenPath, 'utf-8').trim(); console.log('✅ JWT token loaded successfully'); } catch (error) { console.error('⚠️ Failed to load JWT token:', error); } } private setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'inject_and_view_composition', description: `Create and save educational compositions using browser automation. This tool: 1. Generates educational composition JSON from your prompt 2. Uses browser automation to create and save the composition 3. Returns a shareable URL for the saved composition The workflow bypasses API restrictions by using browser automation with localStorage injection.`, inputSchema: { type: 'object', properties: { prompt: { type: 'string', description: 'Educational content prompt (e.g., "Create a lesson about photosynthesis for 7th grade")' }, subject: { type: 'string', description: 'Subject area (e.g., "Ciências", "Matemática", "História")', default: 'Ciências' }, gradeLevel: { type: 'string', description: 'Grade level (e.g., "7º ano", "fundamental-2", "médio")', default: '7º ano' }, title: { type: 'string', description: 'Optional custom title for the composition' } }, required: ['prompt'] } } ] })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'inject_and_view_composition') { return this.handleInjectAndView(request.params.arguments); } throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); }); } private async handleInjectAndView(args: any) { const { prompt, subject = 'Ciências', gradeLevel = '7º ano', title } = args; try { console.log('🎯 Processing composition request...'); console.log(` - Prompt: ${prompt}`); console.log(` - Subject: ${subject}`); console.log(` - Grade: ${gradeLevel}`); // Step 1: Generate composition using existing intelligent generator const generatedComposition = this.widgetGenerator.generateComposition(prompt, title); // Transform to localStorage format const compositionData = { composition: { id: `composition-${Date.now()}`, title: generatedComposition.metadata.title, description: generatedComposition.metadata.description, author: "Sistema Inteligente EuConquisto", created: new Date().toISOString().split('T')[0], version: "2.0.0", metadata: { disciplina: subject, serie: gradeLevel, duracao_estimada: "45 minutos", tags: generatedComposition.metadata.tags, generatedBy: "browser-automation-v2.0.0" }, elements: this.transformWidgetsToElements(generatedComposition.structure) } }; // Step 2: Execute browser automation workflow const result = await this.browserManager.withStableSession(async (session) => { return await this.uiAutomation.executeCompleteWorkflow( session.page, compositionData ); }); if (result.success && result.url) { return { content: [ { type: 'text', text: `✅ Composition created successfully! 📎 **URL**: ${result.url} 📚 **Title**: ${compositionData.composition.title} 🎓 **Subject**: ${subject} - ${gradeLevel} 🧩 **Elements**: ${compositionData.composition.elements.length} The composition has been saved and is ready to use. You can share the URL above to access it.` } ] }; } else { throw new Error(result.error || 'Unknown error occurred'); } } catch (error) { console.error('❌ Error in browser automation workflow:', error); return { content: [ { type: 'text', text: `❌ Failed to create composition: ${error.message} Please ensure: 1. The JWT redirect server is running on localhost:8080 2. You have a valid JWT token in archive/authentication/correct-jwt-new.txt 3. The EuConquisto Composer platform is accessible Error details: ${error.stack}` } ], isError: true }; } } /** * Transform widget structure to localStorage element format */ private transformWidgetsToElements(widgets: any[]): any[] { return widgets.map((widget, index) => { const baseElement = { id: widget.id || `element-${index + 1}`, type: widget.type, content_title: widget.content_title || null, padding_top: widget.padding_top || 0, padding_bottom: widget.padding_bottom || 30 }; // Add type-specific properties switch (widget.type) { case 'head-1': return { ...baseElement, ...widget, background_color: widget.primary_color || '#4CAF50' }; case 'text-1': return { ...baseElement, content: widget.text || '', text_align: 'justify', font_size: 16, line_height: 1.6, background_color: widget.background_color || '#FFFFFF' }; case 'video-1': return { ...baseElement, video_url: widget.video || '', video_title: widget.content_title || 'Vídeo Educativo', show_controls: true, autoplay: false, background_color: widget.background_color || '#FFFFFF' }; case 'quiz-1': return { ...baseElement, questions: widget.questions || [], primary_color: widget.primary_color || '#2d7b45', background_color: widget.background_color || '#FFFFFF' }; case 'flashcards-1': return { ...baseElement, items: widget.items || [], card_height: widget.card_height || 240, card_width: widget.card_width || 240, border_color: widget.border_color || '#00643e', background_color: widget.background_color || '#FFFFFF' }; default: return { ...baseElement, ...widget }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.log('🚀 Browser Automation Composer MCP Server v2.0.0 running'); } } // Run the server const server = new BrowserAutomationComposerServer(); server.run().catch(console.error);

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/rkm097git/euconquisto-composer-mcp-poc'

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