inject-and-view-composition.ts•14.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');