Skip to main content
Glama
janetsep

TreePod Financial MCP Agent

by janetsep

Comparar competencia

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
NameRequiredDescriptionDefault
analysis_typeNoall

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.'
          );
        }
      }
    );
  • 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'];
    }
  • 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;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the tool compares based on 'datos reales' (real data), implying it accesses external or live data sources, but does not specify behavioral traits like data sources, update frequency, rate limits, authentication needs, or output format. For a tool with no annotations, this leaves significant gaps in understanding how it operates and what to expect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence: 'Compara precios y servicios con la competencia basado en datos reales'. It is front-loaded with the core purpose and efficiently conveys the tool's function without unnecessary words. Every part of the sentence contributes to understanding, making it appropriately sized and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (involving competitive analysis with real data), lack of annotations, no output schema, and minimal parameter documentation, the description is incomplete. It does not cover key aspects like data sources, result format, or usage constraints, leaving users with insufficient information to effectively invoke the tool. The description should provide more context to compensate for the missing structured data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has one parameter 'analysis_type' with 0% description coverage, and the tool description does not mention any parameters or their semantics. Since there is only one parameter, the baseline is 4, but the description adds no value beyond the schema, not explaining what 'analysis_type' means or its possible values. This results in a score of 3, as the schema provides structure but the description fails to enhance understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Compara precios y servicios con la competencia basado en datos reales' (Compares prices and services with the competition based on real data). It specifies the verb 'compara' (compares) and resources 'precios y servicios' (prices and services), but does not explicitly differentiate it from sibling tools like 'optimize_pricing' or 'analyze_finances', which might involve similar competitive analysis. This makes it clear but not fully distinguished from alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It does not mention any context, prerequisites, or exclusions, such as when to choose 'compare_competition' over 'optimize_pricing' or 'analyze_finances' from the sibling list. Without such information, users must infer usage based on the tool name alone, which is insufficient for effective tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/janetsep/treepod-financial-mcp'

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