Skip to main content
Glama
development-guide.md25.5 kB
# EuConquisto Composer MCP - Development Guide **Document**: Developer Guide for System Enhancement **Version**: 1.0 **Date**: July 5, 2025 **Status**: Production Ready **Author**: Claude Code Migration Team ## Table of Contents 1. [Development Environment Setup](#development-environment-setup) 2. [Architecture Overview](#architecture-overview) 3. [Code Organization](#code-organization) 4. [Development Workflow](#development-workflow) 5. [Adding New Features](#adding-new-features) 6. [Testing Guidelines](#testing-guidelines) 7. [Performance Optimization](#performance-optimization) 8. [Deployment Process](#deployment-process) 9. [Code Standards](#code-standards) 10. [Best Practices](#best-practices) ## Development Environment Setup ### Prerequisites **System Requirements**: - Node.js 18+ (LTS recommended) - npm 9+ or yarn 3+ - Git 2.30+ - 8GB+ RAM (16GB recommended) - 10GB+ free disk space **Development Tools**: - VS Code or similar IDE - Docker (optional, for containerized development) - Playwright browser dependencies - TypeScript 5.0+ ### Initial Setup ```bash # Clone repository git clone https://github.com/your-org/euconquisto-composer-mcp.git cd euconquisto-composer-mcp # Install dependencies npm install # Install Playwright browsers npx playwright install # Set up environment variables cp .env.example .env # Edit .env with your configuration # Build project npm run build # Run tests npm test # Start development server npm run dev ``` ### Environment Configuration **`.env` Configuration**: ```bash # API Configuration API_BASE_URL=https://composer.digitalpages.com.br/api/v4 COMPOSER_URL=https://composer.digitalpages.com.br # Authentication JWT_TOKEN_PATH=./correct-jwt-new.txt AUTH_REDIRECT_PORT=3000 # Performance Settings NODE_OPTIONS=--max-old-space-size=4096 MEMORY_WARNING_THRESHOLD=512 MEMORY_CRITICAL_THRESHOLD=1024 # Browser Configuration BROWSER_HEADLESS=true BROWSER_TIMEOUT=30000 BROWSER_POOL_MIN=2 BROWSER_POOL_MAX=5 # Development Settings LOG_LEVEL=debug ENABLE_PERFORMANCE_MONITORING=true ENABLE_MEMORY_MONITORING=true ``` ### VS Code Configuration **`.vscode/settings.json`**: ```json { "typescript.preferences.importModuleSpecifier": "relative", "editor.codeActionsOnSave": { "source.fixAll.eslint": true, "source.organizeImports": true }, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "files.exclude": { "**/node_modules": true, "**/dist": true, "**/.git": true } } ``` ## Architecture Overview ### System Architecture The system follows a **4-phase content-first architecture**: ``` Phase 1: Infrastructure → Phase 2: Content Generation → Phase 3: Widget Mapping → Phase 4: Integration ``` ### Core Principles 1. **Universal Topic Handling**: No pre-mapping required for new subjects 2. **Modular Design**: Each component can be developed and tested independently 3. **Performance First**: Optimization built into every component 4. **Educational Standards**: BNCC compliance and pedagogical best practices 5. **Error Resilience**: Graceful degradation and comprehensive error handling ## Code Organization ### Directory Structure ``` euconquisto-composer-mcp/ ├── src/ # Source code │ ├── infrastructure/ # Phase 1: Core infrastructure │ │ ├── authentication/ # JWT and auth management │ │ ├── browser/ # Browser automation │ │ └── api/ # Composer API integration │ ├── content-generation/ # Phase 2: Content creation │ │ ├── base-adapter.ts # Universal content generator │ │ ├── subject-adapters/ # Subject-specific enhancers │ │ └── assessment/ # Assessment generation │ ├── services/ # Phase 3: Widget mapping │ │ ├── content-widget-mapper.ts │ │ ├── image-selection-service.ts │ │ └── educational-flow-optimizer.ts │ ├── integration/ # Phase 4: System coordination │ │ ├── main-integration-orchestrator.ts │ │ └── performance/ # Performance optimization │ └── types/ # TypeScript type definitions ├── tests/ # Test suites │ ├── unit/ # Unit tests │ ├── integration/ # Integration tests │ ├── comprehensive/ # End-to-end tests │ └── performance/ # Performance tests ├── docs/ # Documentation │ ├── technical/ # Technical documentation │ ├── user/ # User guides │ └── planning/ # Project planning ├── tools/ # Development tools │ ├── servers/ # Development servers │ └── scripts/ # Build and deployment scripts └── config/ # Configuration files ``` ### Module Dependencies ```typescript // Dependency flow (arrows show dependencies) Infrastructure ← Content Generation ← Widget Mapping ← Integration ↑ ↑ ↑ ↑ Browser BaseAdapter ImageService Orchestrator Authentication SubjectAdapters FlowOptimizer Performance API AssessmentEngine WidgetMapper Testing ``` ## Development Workflow ### Git Workflow **Branch Strategy**: ```bash main # Production-ready code ├── develop # Integration branch ├── feature/* # Feature development ├── bugfix/* # Bug fixes └── hotfix/* # Production hotfixes ``` **Feature Development Process**: ```bash # Create feature branch git checkout develop git pull origin develop git checkout -b feature/new-subject-adapter # Development cycle git add . git commit -m "feat: add support for biology subject adapter" git push origin feature/new-subject-adapter # Create pull request gh pr create --title "Add Biology Subject Adapter" --body "..." # After review and approval git checkout develop git pull origin develop git branch -d feature/new-subject-adapter ``` ### Commit Message Standards Follow [Conventional Commits](https://www.conventionalcommits.org/): ```bash # Format <type>[optional scope]: <description> # Examples feat(content): add biology subject adapter fix(auth): handle expired JWT tokens gracefully docs(api): update endpoint documentation perf(memory): optimize garbage collection test(integration): add comprehensive subject testing ``` ### Code Review Process **Pull Request Requirements**: - [ ] All tests passing - [ ] Code coverage >90% - [ ] Documentation updated - [ ] Performance impact assessed - [ ] Security review completed **Review Checklist**: - [ ] Follows coding standards - [ ] Proper error handling - [ ] Performance optimizations - [ ] Educational standards compliance - [ ] TypeScript types correct ## Adding New Features ### Adding a New Subject Adapter **1. Create Subject Adapter**: ```typescript // src/content-generation/subject-adapters/biology-adapter.ts export class BiologyAdapter implements SubjectAdapter { async enhance(content: BaseContent, context: EnhancementContext): Promise<EnhancedContent> { return { ...content, biology_features: { scientific_nomenclature: this.addScientificNames(content.text), biological_processes: this.identifyProcesses(content.text), diagrams: this.suggestDiagrams(content.topic), lab_procedures: this.generateLabProcedures(content.topic) } }; } private addScientificNames(text: string): ScientificName[] { // Implementation for adding scientific nomenclature } private identifyProcesses(text: string): BiologicalProcess[] { // Implementation for identifying biological processes } } ``` **2. Register in Factory**: ```typescript // src/content-generation/subject-adapters/subject-adapter-factory.ts export class SubjectAdapterFactory { private static adapters = new Map([ ['física', () => new PhysicsAdapter()], ['química', () => new ChemistryAdapter()], ['história', () => new HistoryAdapter()], ['biologia', () => new BiologyAdapter()], // Add new adapter ]); } ``` **3. Add Tests**: ```typescript // tests/unit/subject-adapters/biology-adapter.test.ts describe('BiologyAdapter', () => { let adapter: BiologyAdapter; beforeEach(() => { adapter = new BiologyAdapter(); }); test('should enhance content with scientific nomenclature', async () => { const content = { text: 'Células são unidades básicas da vida' }; const enhanced = await adapter.enhance(content, { grade_level: 'médio' }); expect(enhanced.biology_features.scientific_nomenclature).toBeDefined(); expect(enhanced.biology_features.scientific_nomenclature.length).toBeGreaterThan(0); }); }); ``` ### Adding a New Widget Type **1. Define Widget Type**: ```typescript // src/types/widget-types.ts export interface InteractiveSimulationWidget extends BaseWidget { type: 'interactive-simulation'; simulation_type: 'physics' | 'chemistry' | 'biology'; parameters: SimulationParameters; controls: ControlConfiguration[]; } ``` **2. Create Widget Mapper**: ```typescript // src/services/widget-mappers/simulation-mapper.ts export class SimulationMapper implements WidgetMapper { canHandle(content: any, context: MappingContext): boolean { return content.type === 'simulation' || context.subject_features?.includes('interactive_simulation'); } async map(content: any, context: MappingContext): Promise<InteractiveSimulationWidget> { return { id: `simulation-${Date.now()}`, type: 'interactive-simulation', simulation_type: this.determineSimulationType(context.subject), parameters: this.extractParameters(content), controls: this.generateControls(content) }; } } ``` **3. Register in Widget Factory**: ```typescript // src/services/widget-factory.ts export class WidgetFactory { private static mappers: WidgetMapper[] = [ new TextMapper(), new ImageMapper(), new QuizMapper(), new SimulationMapper(), // Add new mapper ]; } ``` ### Adding Performance Optimizations **1. Create Optimization Strategy**: ```typescript // src/performance/optimizations/content-optimization.ts export class ContentOptimization implements OptimizationStrategy { async optimize(operation: ContentGenerationOperation): Promise<OptimizationResult> { const startTime = Date.now(); // Apply caching const cacheKey = this.generateCacheKey(operation.request); if (this.cache.has(cacheKey)) { return { result: this.cache.get(cacheKey), fromCache: true }; } // Apply parallel processing if applicable const result = await this.executeOptimizedGeneration(operation); // Cache result this.cache.set(cacheKey, result); return { result, executionTime: Date.now() - startTime, optimizationsApplied: ['caching', 'parallel-processing'] }; } } ``` **2. Integrate with Performance Manager**: ```typescript // src/performance/performance-manager.ts export class PerformanceManager { private optimizations: OptimizationStrategy[] = [ new ContentOptimization(), new MemoryOptimization(), new BrowserOptimization() ]; async optimize(operation: any): Promise<any> { for (const optimization of this.optimizations) { if (optimization.canOptimize(operation)) { return await optimization.optimize(operation); } } return operation.execute(); } } ``` ## Testing Guidelines ### Testing Strategy **Testing Pyramid**: ``` E2E Tests (Comprehensive) ________________ / \ / Integration \ / Tests \ /_____________________\ / \ / Unit Tests \ /_________________________\ ``` ### Unit Testing **Test Structure**: ```typescript // tests/unit/content-generation/base-adapter.test.ts describe('BaseAdapter', () => { let adapter: BaseAdapter; let mockContext: ContentContext; beforeEach(() => { adapter = new BaseAdapter(); mockContext = { topic: 'Test Topic', subject: 'física', grade_level: 'médio' }; }); describe('generateContent', () => { test('should generate content for physics topic', async () => { const result = await adapter.generateContent(mockContext); expect(result).toBeDefined(); expect(result.introduction).toContain('Test Topic'); expect(result.main_content).toBeTruthy(); expect(result.examples).toHaveLength(3); }); test('should handle empty topic gracefully', async () => { mockContext.topic = ''; await expect(adapter.generateContent(mockContext)).rejects.toThrow('Topic cannot be empty'); }); }); describe('performance', () => { test('should complete generation within performance limits', async () => { const startTime = Date.now(); await adapter.generateContent(mockContext); const duration = Date.now() - startTime; expect(duration).toBeLessThan(5000); // 5 seconds max }); }); }); ``` ### Integration Testing **Test Structure**: ```typescript // tests/integration/end-to-end-workflow.test.ts describe('End-to-End Workflow', () => { let orchestrator: MainIntegrationOrchestrator; beforeEach(() => { orchestrator = new MainIntegrationOrchestrator(testConfig); }); test('should generate complete composition for physics topic', async () => { const request = { topic: 'Movimento de Projéteis', subject: 'física', grade_level: 'médio', author: 'Test Teacher' }; const result = await orchestrator.orchestrateEducationalComposition(request); expect(result.success).toBe(true); expect(result.composition_data).toBeDefined(); expect(result.composition_data.composition.elements.length).toBeGreaterThan(3); expect(result.execution_time).toBeLessThan(30000); }); }); ``` ### Performance Testing **Test Structure**: ```typescript // tests/performance/load-testing.test.ts describe('Load Testing', () => { test('should handle concurrent requests efficiently', async () => { const concurrentRequests = 10; const requests = Array(concurrentRequests).fill(null).map(() => orchestrator.orchestrateEducationalComposition(standardRequest) ); const startTime = Date.now(); const results = await Promise.all(requests); const totalTime = Date.now() - startTime; expect(results.every(r => r.success)).toBe(true); expect(totalTime).toBeLessThan(10000); // 10 seconds for 10 requests expect(totalTime / concurrentRequests).toBeLessThan(2000); // 2s average per request }); }); ``` ### Test Commands ```bash # Run all tests npm test # Run specific test suite npm test -- tests/unit/ npm test -- tests/integration/ npm test -- tests/performance/ # Run tests with coverage npm run test:coverage # Run tests in watch mode npm run test:watch # Run performance tests npm run test:performance ``` ## Performance Optimization ### Profiling and Monitoring **Performance Profiling**: ```typescript // src/utils/profiler.ts export class Profiler { private static marks = new Map<string, number>(); static start(operation: string): void { this.marks.set(operation, Date.now()); } static end(operation: string): number { const startTime = this.marks.get(operation); if (!startTime) { throw new Error(`No start mark for operation: ${operation}`); } const duration = Date.now() - startTime; console.log(`[PERF] ${operation}: ${duration}ms`); this.marks.delete(operation); return duration; } static async measure<T>(operation: string, fn: () => Promise<T>): Promise<T> { this.start(operation); try { const result = await fn(); this.end(operation); return result; } catch (error) { this.marks.delete(operation); throw error; } } } ``` **Usage Example**: ```typescript // Profile content generation const content = await Profiler.measure('content-generation', async () => { return await baseAdapter.generateContent(context); }); // Profile with manual timing Profiler.start('widget-mapping'); const widgets = await widgetMapper.mapContent(content); Profiler.end('widget-mapping'); ``` ### Memory Optimization **Memory Monitoring**: ```typescript // src/utils/memory-monitor.ts export class MemoryMonitor { static logMemoryUsage(label: string = ''): void { const usage = process.memoryUsage(); console.log(`[MEMORY] ${label}:`, { heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`, heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`, external: `${Math.round(usage.external / 1024 / 1024)}MB` }); } static async trackMemory<T>(operation: string, fn: () => Promise<T>): Promise<T> { this.logMemoryUsage(`Before ${operation}`); const result = await fn(); this.logMemoryUsage(`After ${operation}`); return result; } } ``` ### Caching Strategies **Content Caching**: ```typescript // src/cache/content-cache.ts export class ContentCache { private cache = new Map<string, CachedContent>(); private readonly maxSize = 1000; generateKey(topic: string, subject: string, gradeLevel: string): string { return `${topic}:${subject}:${gradeLevel}`.toLowerCase(); } get(key: string): CachedContent | null { const cached = this.cache.get(key); if (cached && !this.isExpired(cached)) { cached.lastAccessed = Date.now(); return cached; } this.cache.delete(key); return null; } set(key: string, content: any): void { if (this.cache.size >= this.maxSize) { this.evictOldest(); } this.cache.set(key, { content, createdAt: Date.now(), lastAccessed: Date.now() }); } private evictOldest(): void { let oldestKey = ''; let oldestTime = Date.now(); for (const [key, cached] of this.cache.entries()) { if (cached.lastAccessed < oldestTime) { oldestTime = cached.lastAccessed; oldestKey = key; } } if (oldestKey) { this.cache.delete(oldestKey); } } } ``` ## Deployment Process ### Build Process ```bash # Clean build npm run clean npm run build # Type checking npm run type-check # Linting npm run lint # Testing npm run test:all # Bundle analysis npm run analyze ``` ### Production Deployment **Docker Deployment**: ```dockerfile # Dockerfile FROM node:18-alpine WORKDIR /app # Install dependencies COPY package*.json ./ RUN npm ci --only=production # Install Playwright browsers RUN npx playwright install-deps RUN npx playwright install # Copy application COPY dist/ ./dist/ COPY config/ ./config/ # Set environment ENV NODE_ENV=production ENV NODE_OPTIONS=--max-old-space-size=4096 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=60s \ CMD curl -f http://localhost:3000/health || exit 1 EXPOSE 3000 CMD ["node", "dist/index.js"] ``` **Kubernetes Deployment**: ```yaml # k8s/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: composer-mcp spec: replicas: 3 selector: matchLabels: app: composer-mcp template: metadata: labels: app: composer-mcp spec: containers: - name: composer-mcp image: composer-mcp:latest ports: - containerPort: 3000 env: - name: NODE_OPTIONS value: "--max-old-space-size=4096" resources: requests: memory: "2Gi" cpu: "500m" limits: memory: "4Gi" cpu: "2000m" livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 60 periodSeconds: 30 ``` ### Environment Management **Environment-Specific Configuration**: ```typescript // config/environments.ts export const environments = { development: { api: { baseUrl: 'http://localhost:3000/api/v4', timeout: 30000 }, performance: { enableCaching: true, cacheSize: 500, memoryThreshold: 256 }, logging: { level: 'debug', enablePerformanceLogs: true } }, production: { api: { baseUrl: 'https://composer.digitalpages.com.br/api/v4', timeout: 15000 }, performance: { enableCaching: true, cacheSize: 2000, memoryThreshold: 512 }, logging: { level: 'info', enablePerformanceLogs: false } } }; ``` ## Code Standards ### TypeScript Standards **Type Definitions**: ```typescript // Always use explicit types for public APIs export interface EducationalRequest { topic: string; subject: string; grade_level: 'fundamental' | 'médio' | 'superior'; author: string; learning_objectives?: string[]; } // Use generic types appropriately export interface ApiResponse<T> { success: boolean; data?: T; error?: string; } // Use utility types when appropriate export type PartialEducationalRequest = Partial<EducationalRequest>; export type RequiredEducationalRequest = Required<EducationalRequest>; ``` **Error Handling**: ```typescript // Custom error classes export class ContentGenerationError extends Error { constructor( message: string, public readonly cause?: Error, public readonly context?: any ) { super(message); this.name = 'ContentGenerationError'; } } // Error handling pattern async function generateContent(request: EducationalRequest): Promise<Content> { try { return await contentGenerator.generate(request); } catch (error) { if (error instanceof ValidationError) { throw new ContentGenerationError( 'Invalid request parameters', error, { request } ); } throw error; } } ``` ### ESLint Configuration **`.eslintrc.js`**: ```javascript module.exports = { parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint', 'import'], extends: [ 'eslint:recommended', '@typescript-eslint/recommended', 'prettier' ], rules: { '@typescript-eslint/explicit-function-return-type': 'error', '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/no-unused-vars': 'error', 'import/order': ['error', { 'groups': ['builtin', 'external', 'internal'] }], 'prefer-const': 'error', 'no-var': 'error' } }; ``` ## Best Practices ### Performance Best Practices 1. **Always Profile Before Optimizing**: ```typescript // Use profiler to identify bottlenecks const result = await Profiler.measure('content-generation', async () => { return await generateContent(request); }); ``` 2. **Implement Caching Strategically**: ```typescript // Cache expensive operations const cacheKey = generateCacheKey(request); if (cache.has(cacheKey)) { return cache.get(cacheKey); } ``` 3. **Use Lazy Loading**: ```typescript // Lazy load subject adapters class SubjectAdapterFactory { private static adapters = new Map([ ['física', () => import('./physics-adapter').then(m => new m.PhysicsAdapter())], ]); } ``` ### Memory Management Best Practices 1. **Clean Up Resources**: ```typescript class ResourceManager { private resources: Resource[] = []; async cleanup(): Promise<void> { await Promise.all(this.resources.map(r => r.dispose())); this.resources = []; } } ``` 2. **Use WeakRef for Caching**: ```typescript class WeakCache { private cache = new Map<string, WeakRef<CachedItem>>(); get(key: string): CachedItem | null { const ref = this.cache.get(key); const item = ref?.deref(); if (!item) { this.cache.delete(key); return null; } return item; } } ``` ### Educational Content Best Practices 1. **Follow BNCC Standards**: ```typescript // Validate content against educational standards const validator = new BNCCValidator(); const compliance = await validator.validate(content, { subject: 'física', gradeLevel: 'médio' }); ``` 2. **Ensure Accessibility**: ```typescript // Generate alt text for images const imageElement = { type: 'image-1', src: imageUrl, alt: generateAltText(imageContent, context), caption: generateCaption(imageContent) }; ``` 3. **Support Multiple Learning Styles**: ```typescript // Include diverse content types const lesson = { visual: generateVisualContent(topic), auditory: generateNarrativeContent(topic), kinesthetic: generateInteractiveElements(topic) }; ``` --- **Development Guide Status**: ✅ **COMPREHENSIVE** **Setup Instructions**: ✅ **COMPLETE** development environment setup **Code Examples**: ✅ **PRACTICAL** real-world implementation patterns **Best Practices**: ✅ **INDUSTRY-STANDARD** development guidelines **Testing Coverage**: ✅ **THOROUGH** testing strategies and examples **🎯 Key Strength: Complete development guide enabling efficient onboarding and consistent development practices for maintaining and extending the universal educational content generation system**

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