compare_competition
Analyze competitor pricing and services using real market data to identify opportunities and optimize business strategies.
Instructions
Compara precios y servicios con la competencia basado en datos reales
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| analysis_type | No | all |
Implementation Reference
- server.js:143-181 (registration)Registration of the 'compare_competition' tool including schema, inline handler, logging, error handling, data loading, and delegation to analyzer.// --- Herramienta: compare_competition --- // ✅ IMPLEMENTA GUÍA DE TRABAJO FUNDAMENTAL: Sin hardcodeo, datos reales server.registerTool( 'compare_competition', { title: 'Comparar competencia', description: 'Compara precios y servicios con la competencia basado en datos reales', inputSchema: z.object({ analysis_type: z.string().default('all'), }), }, async ({ analysis_type = 'all' }) => { validator.log('info', `Iniciando análisis de competencia tipo: ${analysis_type}`); try { // Cargar datos reales de competencia const competitionData = await dataLoader.loadCompetitionData(); if (!competitionData) { return validator.generateInsufficientDataResponse( 'datos de competencia', 'El sistema de inteligencia competitiva no ha generado reportes recientes. Ejecuta el agente competitivo para obtener datos actualizados.' ); } const result = await businessCalculator.analyzeCompetition(competitionData, analysis_type); validator.log('info', 'Análisis de competencia completado exitosamente'); return result; } catch (error) { validator.log('error', `Error crítico en análisis de competencia: ${error.message}`); return validator.generateInsufficientDataResponse( 'análisis de competencia', 'Error interno del sistema. Contacta al administrador.' ); } } );
- src/business/calculator.js:462-623 (helper)Main computation logic for competition analysis: processes competitor data to extract price ranges, common services, market positioning, generates formatted report and recommendations.async analyzeCompetition(competitionData, analysisType = 'all') { if (!competitionData) { return validator.generateInsufficientDataResponse( 'datos de competencia', 'No se encontraron datos de competencia válidos' ); } try { validator.log('info', `Analizando competencia tipo: ${analysisType}`); // Extraer datos relevantes según el tipo de análisis const analysis = this.processCompetitionData(competitionData, analysisType); return { content: [{ type: 'text', text: this.formatCompetitionAnalysis(analysis, analysisType) }] }; } catch (error) { validator.log('error', `Error en análisis de competencia: ${error.message}`); return validator.generateInsufficientDataResponse( 'análisis de competencia', 'Error interno en el análisis. Contacta al administrador.' ); } } /** * Procesa datos de competencia según tipo de análisis */ processCompetitionData(data, analysisType) { const analysis = { totalCompetitors: 0, priceRange: { min: null, max: null, average: null }, services: [], positioning: 'medio', recommendations: [] }; // Procesar diferentes estructuras de datos de competencia let competitors = []; if (data.competitors) { competitors = Array.isArray(data.competitors) ? data.competitors : Object.values(data.competitors); } else if (data.establishments) { competitors = Array.isArray(data.establishments) ? data.establishments : Object.values(data.establishments); } else if (Array.isArray(data)) { competitors = data; } analysis.totalCompetitors = competitors.length; if (competitors.length > 0) { // Analizar precios si están disponibles const prices = competitors .map(c => c.price || c.tarifa || c.precio) .filter(p => p && typeof p === 'number') .sort((a, b) => a - b); if (prices.length > 0) { analysis.priceRange.min = prices[0]; analysis.priceRange.max = prices[prices.length - 1]; analysis.priceRange.average = Math.round(prices.reduce((a, b) => a + b, 0) / prices.length); } // Analizar servicios comunes const allServices = competitors .flatMap(c => c.services || c.servicios || []) .filter(s => s); const serviceCount = {}; allServices.forEach(service => { serviceCount[service] = (serviceCount[service] || 0) + 1; }); analysis.services = Object.entries(serviceCount) .sort(([,a], [,b]) => b - a) .slice(0, 5) .map(([service, count]) => ({ service, count })); // Determinar posicionamiento if (analysis.priceRange.average) { const treepodPrice = 80000; // Precio base estimado if (treepodPrice < analysis.priceRange.average * 0.8) { analysis.positioning = 'económico'; } else if (treepodPrice > analysis.priceRange.average * 1.2) { analysis.positioning = 'premium'; } } // Generar recomendaciones analysis.recommendations = this.generateCompetitionRecommendations(analysis); } return analysis; } /** * Formatea análisis de competencia */ formatCompetitionAnalysis(analysis, analysisType) { let content = `🔍 **ANÁLISIS DE COMPETENCIA TREEPOD**\n\n`; content += `📊 **Competidores analizados:** ${analysis.totalCompetitors}\n`; content += `🎯 **Posicionamiento:** ${analysis.positioning}\n\n`; if (analysis.priceRange.average) { content += `**💰 ANÁLISIS DE PRECIOS:**\n`; content += `• Precio mínimo: ${this.formatCurrency(analysis.priceRange.min)}\n`; content += `• Precio máximo: ${this.formatCurrency(analysis.priceRange.max)}\n`; content += `• Precio promedio: ${this.formatCurrency(analysis.priceRange.average)}\n\n`; } if (analysis.services.length > 0) { content += `**🏨 SERVICIOS MÁS COMUNES:**\n`; analysis.services.forEach(({ service, count }) => { content += `• ${service} (${count} competidores)\n`; }); content += `\n`; } if (analysis.recommendations.length > 0) { content += `**🎯 RECOMENDACIONES:**\n`; analysis.recommendations.forEach(rec => { content += `• ${rec}\n`; }); content += `\n`; } content += `*Análisis basado en datos reales del sistema de inteligencia competitiva*`; return content; } /** * Genera recomendaciones basadas en análisis de competencia */ generateCompetitionRecommendations(analysis) { const recommendations = []; if (analysis.positioning === 'económico') { recommendations.push('Oportunidad de aumentar precios manteniendo competitividad'); } else if (analysis.positioning === 'premium') { recommendations.push('Enfatizar valor diferencial para justificar precio premium'); } if (analysis.totalCompetitors < 5) { recommendations.push('Mercado con poca competencia, oportunidad de crecimiento'); } else if (analysis.totalCompetitors > 10) { recommendations.push('Mercado saturado, enfocarse en diferenciación'); } if (analysis.services.length > 0) { const topService = analysis.services[0].service; recommendations.push(`Considerar agregar/mejorar: ${topService}`); } return recommendations.length > 0 ? recommendations : ['Mantener estrategia competitiva actual']; }
- src/data/dataLoader.js:95-127 (helper)Loads real-world competition data from JSON report files generated by another agent, with caching, file existence validation, and JSON structure validation.async loadCompetitionData() { const cacheKey = 'competition_data'; if (this.isCacheValid(cacheKey)) { validator.log('info', 'Datos de competencia obtenidos del cache'); return this.cache.get(cacheKey); } // Buscar el reporte más reciente const reportFiles = [ 'competition-analysis.json', 'enhanced-competitive-data-2025-07-24.json', 'sernatur_real_data_report_2025-07-24.json' ]; for (const fileName of reportFiles) { const filePath = path.join(competitorPath, fileName); const fileExists = await validator.validateFileExists(filePath, `datos de competencia (${fileName})`); if (fileExists) { const validation = await validator.validateJsonData(filePath, [], 'datos de competencia'); if (validation.valid) { this.setCache(cacheKey, validation.data); validator.log('info', `Datos de competencia cargados desde: ${fileName}`); return validation.data; } } } validator.log('error', 'No se encontraron datos válidos de competencia'); return null; }