Skip to main content
Glama
inject-and-view-composition.ts14.1 kB
/** * @document Automated MCP Injection Tool * @version 1.0.0 * @status active * @author Claude Code * @created 2025-06-30 * @description MCP tool for automated composition generation and localStorage injection */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { chromium, Browser, Page } from 'playwright'; import fs from 'fs/promises'; // Import the working intelligent system import { BrazilianEducationalAnalyzer } from '../brazilian-educational-analyzer.js'; import { EducationalContentAnalyzer } from '../educational-content-analyzer.js'; export interface CompositionRequest { prompt: string; subject?: string; gradeLevel?: string; } export interface CompositionResult { success: boolean; compositionId: string; title: string; elementCount: number; viewUrl: string; error?: string; } export class AutomatedCompositionInjector { private browser: Browser | null = null; private page: Page | null = null; private jwtToken: string | null = null; private baseUrl = 'https://composer.euconquisto.com'; private brazilianAnalyzer: BrazilianEducationalAnalyzer; private contentAnalyzer: EducationalContentAnalyzer; constructor() { this.brazilianAnalyzer = new BrazilianEducationalAnalyzer(); this.contentAnalyzer = new EducationalContentAnalyzer(); } async initialize(): Promise<void> { // Load JWT token try { this.jwtToken = await fs.readFile('archive/authentication/correct-jwt-new.txt', 'utf-8'); this.jwtToken = this.jwtToken.trim(); console.log('✅ JWT token loaded for automated injection'); } catch (error) { throw new Error('❌ JWT token required for automated composition injection'); } // Initialize browser this.browser = await chromium.launch({ headless: false, // Keep visible for user interaction slowMo: 300 }); const context = await this.browser.newContext({ viewport: { width: 1920, height: 1080 } }); this.page = await context.newPage(); } async generateComposition(request: CompositionRequest): Promise<any> { console.log('🧠 Generating composition using intelligent systems...'); // Analyze content using Brazilian educational system const analysis = this.brazilianAnalyzer.analyzeContent(request.prompt); // Generate composition structure const compositionId = `composition-${Date.now()}`; const composition = { composition: { id: compositionId, title: this.extractTitle(request.prompt, analysis), description: `Composição educacional sobre ${analysis.subject}`, author: "Sistema Inteligente EuConquisto", created: new Date().toISOString().split('T')[0], version: "1.0.0", metadata: { disciplina: analysis.subject, serie: analysis.gradeLevel, duracao_estimada: `${analysis.duration} minutos`, tags: this.generateTags(request.prompt, analysis) }, elements: this.generateElements(request.prompt, analysis) } }; console.log(`📚 Generated composition: ${composition.composition.title}`); console.log(`🎯 Grade level: ${analysis.gradeLevel}`); console.log(`🧩 Elements: ${composition.composition.elements.length}`); return composition; } private extractTitle(prompt: string, analysis: any): string { // Extract key educational topic for title const words = prompt.toLowerCase().split(' '); const keyTopics = ['fotossíntese', 'matematica', 'historia', 'geografia', 'ciências']; const foundTopic = keyTopics.find(topic => prompt.toLowerCase().includes(topic)); if (foundTopic) { return `${foundTopic.charAt(0).toUpperCase() + foundTopic.slice(1)} - ${analysis.gradeLevel}`; } return `Aula sobre ${analysis.subject} - ${analysis.gradeLevel}`; } private generateTags(prompt: string, analysis: any): string[] { const tags = [analysis.subject.toLowerCase(), analysis.gradeLevel.toLowerCase()]; // Add topic-specific tags const words = prompt.toLowerCase().split(' '); const educationalKeywords = ['processo', 'conceito', 'definição', 'exemplo', 'exercício']; words.forEach(word => { if (word.length > 4 && !tags.includes(word)) { tags.push(word); } }); return tags.slice(0, 5); } private generateElements(prompt: string, analysis: any): any[] { const elements = []; let elementId = 1; // Header element elements.push({ id: `header-${elementId++}`, type: "head-1", content_title: "Apresentação da Aula", padding_top: 0, padding_bottom: 30, background_color: "#4CAF50", primary_color: "#4CAF50", font_family: "Lato", category: `📚 ${analysis.subject.toUpperCase()} - ${analysis.gradeLevel.toUpperCase()}`, show_category: true, show_author_name: true, author_name: "Professor(a)", author_office: `Professor(a) de ${analysis.subject}`, avatar: "https://via.placeholder.com/120x120/4CAF50/FFFFFF?text=Prof", avatar_border_color: "#66BB6A", show_divider: true, progress_tracking: true }); // Main content element elements.push({ id: `content-${elementId++}`, type: "text-1", content_title: "Conteúdo Principal", padding_top: 20, padding_bottom: 20, content: this.generateMainContent(prompt, analysis), text_align: "justify", font_size: 16, line_height: 1.6 }); // Video element for demonstrations elements.push({ id: `video-${elementId++}`, type: "video-1", content_title: "Vídeo Explicativo", padding_top: 20, padding_bottom: 20, video_url: "https://www.youtube.com/embed/dQw4w9WgXcQ", // Placeholder video_title: `Vídeo sobre ${analysis.subject}`, show_controls: true, autoplay: false }); // Interactive flashcards elements.push({ id: `flashcards-${elementId++}`, type: "flashcards-1", content_title: "Cartões de Estudo", padding_top: 20, padding_bottom: 20, cards: this.generateFlashcards(prompt, analysis) }); // Quiz element elements.push({ id: `quiz-${elementId++}`, type: "quiz-1", content_title: "Quiz de Verificação", padding_top: 20, padding_bottom: 30, questions: this.generateQuizQuestions(prompt, analysis) }); return elements; } private generateMainContent(prompt: string, analysis: any): string { return ` ## Introdução Nesta aula, vamos explorar ${analysis.subject} de forma interativa e envolvente. ## Objetivos de Aprendizagem Ao final desta aula, você será capaz de: - Compreender os conceitos fundamentais sobre o tema - Aplicar o conhecimento em situações práticas - Relacionar o conteúdo com o dia a dia ## Desenvolvimento ${prompt} ## Conclusão Este conteúdo foi desenvolvido para estudantes do ${analysis.gradeLevel}, seguindo as diretrizes da BNCC. `.trim(); } private generateFlashcards(prompt: string, analysis: any): any[] { return [ { front: "O que é o tema principal desta aula?", back: `O tema principal é ${analysis.subject}, adequado para ${analysis.gradeLevel}.` }, { front: "Qual a importância deste conteúdo?", back: "Este conteúdo é fundamental para a formação educacional e está alinhado com a BNCC." } ]; } private generateQuizQuestions(prompt: string, analysis: any): any[] { return [ { question: `Qual é o foco principal desta aula de ${analysis.subject}?`, options: [ "Conceitos fundamentais", "Exercícios práticos", "Revisão geral", "Todas as alternativas" ], correct: 3, explanation: "A aula abrange conceitos fundamentais, exercícios práticos e revisão, proporcionando uma experiência completa de aprendizagem." } ]; } async injectAndView(composition: any): Promise<CompositionResult> { if (!this.page || !this.jwtToken) { throw new Error('Browser or JWT token not initialized'); } try { console.log('🔐 Authenticating with Composer...'); // Authenticate with JWT const loginUrl = `${this.baseUrl}/auth/login?token=${this.jwtToken}`; await this.page.goto(loginUrl, { waitUntil: 'networkidle' }); console.log('💉 Injecting composition into localStorage...'); // Inject composition into localStorage const injectionResult = await this.page.evaluate((compositionData) => { try { // Clear existing data localStorage.removeItem('rdp-composer-data'); // Inject new composition localStorage.setItem('rdp-composer-data', JSON.stringify(compositionData)); // Verify injection const stored = localStorage.getItem('rdp-composer-data'); const parsed = JSON.parse(stored); return { success: true, compositionId: parsed.composition.id, title: parsed.composition.title, elementCount: parsed.composition.elements.length }; } catch (error) { return { success: false, error: error.message }; } }, composition); if (!injectionResult.success) { throw new Error(`Injection failed: ${injectionResult.error}`); } console.log('✅ Composition injected successfully'); console.log(`📍 Composition ID: ${injectionResult.compositionId}`); console.log(`📝 Title: ${injectionResult.title}`); // Take screenshot for validation await this.page.screenshot({ path: `logs/screenshots/injection/automated-${Date.now()}.png`, fullPage: true }); // Generate view URL (using the authenticated session URL) const viewUrl = this.page.url(); return { success: true, compositionId: injectionResult.compositionId, title: injectionResult.title, elementCount: injectionResult.elementCount, viewUrl: viewUrl }; } catch (error) { console.error('❌ Injection and view failed:', error); return { success: false, compositionId: '', title: '', elementCount: 0, viewUrl: '', error: error.message }; } } async cleanup(): Promise<void> { if (this.browser) { // Keep browser open for user to interact console.log('🌐 Browser kept open for composition viewing'); // Note: Not closing browser so user can interact with composition } } async processRequest(request: CompositionRequest): Promise<CompositionResult> { await this.initialize(); try { const composition = await this.generateComposition(request); const result = await this.injectAndView(composition); return result; } catch (error) { console.error('❌ Process request failed:', error); return { success: false, compositionId: '', title: '', elementCount: 0, viewUrl: '', error: error.message }; } } } // MCP Server Implementation const server = new Server( { name: 'euconquisto-composer-automated-injection', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'inject-and-view-composition', description: 'Generate educational composition and inject into Composer for interactive viewing', inputSchema: { type: 'object', properties: { prompt: { type: 'string', description: 'Educational content request (e.g., "Create lesson about photosynthesis for 7th grade")' }, subject: { type: 'string', description: 'Subject area (optional, auto-detected if not provided)' }, gradeLevel: { type: 'string', description: 'Target grade level (optional, auto-detected if not provided)' } }, required: ['prompt'] } } ] }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'inject-and-view-composition') { const { prompt, subject, gradeLevel } = request.params.arguments as CompositionRequest; const injector = new AutomatedCompositionInjector(); const result = await injector.processRequest({ prompt, subject, gradeLevel }); if (result.success) { return { content: [ { type: 'text', text: `✅ Interactive composition created successfully! 📚 **Lesson**: ${result.title} 🎯 **Composition ID**: ${result.compositionId} 🧩 **Interactive Elements**: ${result.elementCount} widgets 🌐 **Click here to view**: ${result.viewUrl} The composition has been injected into Composer and is ready for interactive use. The browser window will remain open for your viewing and editing.` } ] }; } else { return { content: [ { type: 'text', text: `❌ Composition creation failed: ${result.error}` } ] }; } } throw new Error(`Unknown tool: ${request.params.name}`); }); // Start the server const transport = new StdioServerTransport(); server.connect(transport); console.log('🚀 Automated Composition Injection MCP Server started'); console.log('📋 Available tool: inject-and-view-composition');

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