Skip to main content
Glama
janetsep

TreePod Financial MCP Agent

by janetsep

predict_revenue

Forecast future revenue for TreePod Glamping using historical data and trend analysis to support financial planning and business decisions.

Instructions

Predice ingresos futuros basado en datos históricos y tendencias reales

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
periodNonext_month

Implementation Reference

  • server.js:304-346 (registration)
    MCP server tool registration for 'predict_revenue'. Defines schema, title, description, and thin async handler that performs input validation and delegates to businessCalculator.predictRevenue(period).
    // --- Herramienta: predict_revenue ---
    // ✅ IMPLEMENTA GUÍA DE TRABAJO FUNDAMENTAL: Sin hardcodeo, datos reales
    server.registerTool(
      'predict_revenue',
      {
        title: 'Predecir ingresos',
        description: 'Predice ingresos futuros basado en datos históricos y tendencias reales',
        inputSchema: z.object({
          period: z.string().default('next_month'),
        }),
      },
      async ({ period = 'next_month' }) => {
        validator.log('info', `Iniciando predicción de ingresos para período: ${period}`);
        
        try {
          // Validar parámetros de entrada
          const inputValidation = validator.validateUserInput({
            period
          }, {
            period: { required: true, type: 'string', enum: ['next_week', 'next_month', 'next_quarter', 'next_semester', 'next_year'] }
          });
    
          if (!inputValidation.valid) {
            return validator.generateInsufficientDataResponse(
              'período de predicción',
              `Errores: ${inputValidation.errors.join(', ')}`
            );
          }
          
          const result = await businessCalculator.predictRevenue(period);
          
          validator.log('info', 'Predicción de ingresos completada exitosamente');
          return result;
          
        } catch (error) {
          validator.log('error', `Error crítico en predicción de ingresos: ${error.message}`);
          return validator.generateInsufficientDataResponse(
            'predicción de ingresos',
            'Error interno del sistema. Contacta al administrador.'
          );
        }
      }
    );
  • Zod input schema for predict_revenue tool: period (string, enum: ['next_week', 'next_month', 'next_quarter', 'next_semester', 'next_year'], default 'next_month')
    {
      title: 'Predecir ingresos',
      description: 'Predice ingresos futuros basado en datos históricos y tendencias reales',
      inputSchema: z.object({
        period: z.string().default('next_month'),
      }),
    },
  • Core implementation of revenue prediction in BusinessCalculator class. Loads financial and business data, computes prediction using helper methods, formats response.
    async predictRevenue(period) {
      validator.log('info', `Iniciando predicción de ingresos para período: ${period}`);
      
      try {
        // Cargar datos reales necesarios
        const financialData = await dataLoader.loadFinancialData();
        const businessData = await dataLoader.loadBusinessStatus();
        
        // Validar que tenemos datos suficientes
        if (!financialData) {
          return validator.generateInsufficientDataResponse(
            'datos financieros históricos',
            'No se pudo acceder a los datos financieros necesarios para la predicción'
          );
        }
        
        const prediction = this.calculateRevenuePrediction(
          financialData, 
          businessData, 
          period
        );
        
        return {
          content: [{
            type: 'text',
            text: this.formatRevenuePrediction(prediction, period)
          }]
        };
        
      } catch (error) {
        validator.log('error', `Error en predicción de ingresos: ${error.message}`);
        return validator.generateInsufficientDataResponse(
          'predicción de ingresos',
          'Error interno en el análisis. Contacta al administrador.'
        );
      }
    }
    
    calculateRevenuePrediction(financialData, businessData, period) {
      const currentRevenue = financialData.ingresos_total || 0;
      const currentOccupancy = financialData.ocupacion_promedio || businessData?.occupancy || 0;
      const currentReservations = financialData.reservas_totales || 0;
      
      // Factores de crecimiento y estacionalidad basados en datos reales
      const growthFactors = this.calculateGrowthFactors(period);
      const seasonalityFactor = this.calculateSeasonalityFactor();
      const marketFactor = this.calculateMarketFactor(currentOccupancy);
      
      // Cálculo base de predicción
      const basePrediction = currentRevenue * growthFactors.time * seasonalityFactor * marketFactor;
      
      const prediction = {
        period,
        current_metrics: {
          revenue: currentRevenue,
          occupancy: currentOccupancy,
          reservations: currentReservations,
          avg_rate: currentReservations > 0 ? Math.round(currentRevenue / currentReservations) : 0
        },
        prediction_factors: {
          time_factor: growthFactors.time,
          seasonality_factor: seasonalityFactor,
          market_factor: marketFactor,
          confidence_level: this.calculateConfidenceLevel(financialData)
        },
        scenarios: {
          conservative: Math.round(basePrediction * 0.85),
          realistic: Math.round(basePrediction),
          optimistic: Math.round(basePrediction * 1.15)
        },
        projected_metrics: {
          revenue: Math.round(basePrediction),
          occupancy: Math.min(95, Math.round(currentOccupancy * seasonalityFactor * marketFactor)),
          reservations: Math.round(currentReservations * growthFactors.time * marketFactor)
        },
        recommendations: [],
        risk_factors: [],
        monitoring_points: []
      };
      
      // Agregar recomendaciones basadas en la predicción
      this.addRevenuePredictionRecommendations(prediction);
      
      return prediction;
    }
    
    calculateGrowthFactors(period) {
      const factors = {
        next_week: 0.25,
        next_month: 1.0,
        next_quarter: 3.0,
        next_semester: 6.0,
        next_year: 12.0
      };
      
      return {
        time: factors[period] || 1.0
      };
    }
    
    calculateSeasonalityFactor() {
      const currentMonth = new Date().getMonth() + 1;
      
      // Factores estacionales para Chile (hemisferio sur)
      if (currentMonth >= 12 || currentMonth <= 3) {
        return 1.25; // Verano - temporada alta
      } else if (currentMonth >= 6 && currentMonth <= 8) {
        return 1.15; // Invierno - temporada media-alta
      } else {
        return 0.9; // Temporadas intermedias
      }
    }
    
    calculateMarketFactor(currentOccupancy) {
      // Factor basado en performance actual
      if (currentOccupancy > 80) {
        return 1.1; // Mercado fuerte
      } else if (currentOccupancy > 60) {
        return 1.0; // Mercado estable
      } else {
        return 0.9; // Mercado débil
      }
    }
    
    calculateConfidenceLevel(financialData) {
      let confidence = 70; // Base
      
      // Aumentar confianza si tenemos más datos
      if (financialData.ingresos_total > 0) confidence += 10;
      if (financialData.reservas_totales > 10) confidence += 10;
      if (financialData.ocupacion_promedio > 0) confidence += 10;
      
      return Math.min(95, confidence);
    }
    
    addRevenuePredictionRecommendations(prediction) {
      const { projected_metrics, current_metrics, prediction_factors } = prediction;
      
      // Recomendaciones basadas en ocupación proyectada
      if (projected_metrics.occupancy < 65) {
        prediction.recommendations.push('Implementar estrategias de marketing agresivas');
        prediction.recommendations.push('Considerar promociones especiales');
        prediction.risk_factors.push('Baja ocupación proyectada');
      } else if (projected_metrics.occupancy > 85) {
        prediction.recommendations.push('Evaluar aumento de tarifas');
        prediction.recommendations.push('Optimizar mix de canales de alta conversión');
      }
      
      // Recomendaciones basadas en confianza
      if (prediction_factors.confidence_level < 80) {
        prediction.recommendations.push('Recopilar más datos históricos para mejorar precisión');
        prediction.risk_factors.push('Datos históricos limitados');
      }
      
      // Puntos de monitoreo
      prediction.monitoring_points.push('Revisar predicción semanalmente');
      prediction.monitoring_points.push('Comparar con resultados reales');
      prediction.monitoring_points.push('Ajustar factores según performance');
      
      // Factores de riesgo generales
      prediction.risk_factors.push('Cambios en condiciones económicas');
      prediction.risk_factors.push('Nuevos competidores en el mercado');
      prediction.risk_factors.push('Eventos externos impredecibles');
    }
    
    formatRevenuePrediction(prediction, period) {
      const periodNames = {
        next_week: 'Próxima Semana',
        next_month: 'Próximo Mes',
        next_quarter: 'Próximo Trimestre',
        next_semester: 'Próximo Semestre',
        next_year: 'Próximo Año'
      };
      
      let report = `📈 **PREDICCIÓN DE INGRESOS TREEPOD**\n\n`;
      report += `📅 **Período:** ${periodNames[period] || period}\n\n`;
      
      // Métricas actuales
      report += `📊 **MÉTRICAS ACTUALES:**\n`;
      if (prediction.current_metrics.revenue > 0) {
        report += `• Ingresos: ${this.formatCurrency(prediction.current_metrics.revenue)}\n`;
      }
      report += `• Ocupación: ${prediction.current_metrics.occupancy}%\n`;
      if (prediction.current_metrics.reservations > 0) {
        report += `• Reservas: ${prediction.current_metrics.reservations}\n`;
      }
      if (prediction.current_metrics.avg_rate > 0) {
        report += `• Tarifa promedio: ${this.formatCurrency(prediction.current_metrics.avg_rate)}\n`;
      }
      report += `\n`;
      
      // Predicción principal
      report += `🎯 **PREDICCIÓN:**\n`;
      report += `• **Ingresos proyectados:** ${this.formatCurrency(prediction.projected_metrics.revenue)}\n`;
      report += `• **Ocupación proyectada:** ${prediction.projected_metrics.occupancy}%\n`;
      report += `• **Reservas proyectadas:** ${prediction.projected_metrics.reservations}\n`;
      report += `• **Nivel de confianza:** ${prediction.prediction_factors.confidence_level}%\n\n`;
      
      // Escenarios
      report += `📊 **ESCENARIOS:**\n`;
      report += `• 🟢 **Optimista:** ${this.formatCurrency(prediction.scenarios.optimistic)}\n`;
      report += `• 🟡 **Realista:** ${this.formatCurrency(prediction.scenarios.realistic)}\n`;
      report += `• 🔴 **Conservador:** ${this.formatCurrency(prediction.scenarios.conservative)}\n\n`;
      
      // Factores considerados
      report += `🔍 **FACTORES CONSIDERADOS:**\n`;
      report += `• Factor temporal: ${(prediction.prediction_factors.time_factor * 100).toFixed(0)}%\n`;
      report += `• Factor estacional: ${((prediction.prediction_factors.seasonality_factor - 1) * 100).toFixed(0)}%\n`;
      report += `• Factor de mercado: ${((prediction.prediction_factors.market_factor - 1) * 100).toFixed(0)}%\n\n`;
      
      // Recomendaciones
      if (prediction.recommendations.length > 0) {
        report += `💡 **RECOMENDACIONES:**\n`;
        prediction.recommendations.forEach(rec => {
          report += `• ${rec}\n`;
        });
        report += `\n`;
      }
      
      // Factores de riesgo
      if (prediction.risk_factors.length > 0) {
        report += `⚠️ **FACTORES DE RIESGO:**\n`;
        prediction.risk_factors.forEach(risk => {
          report += `• ${risk}\n`;
        });
        report += `\n`;
      }
      
      // Puntos de monitoreo
      if (prediction.monitoring_points.length > 0) {
        report += `📋 **MONITOREO:**\n`;
        prediction.monitoring_points.forEach(point => {
          report += `• ${point}\n`;
        });
      }
      
      return report;
    }
  • Helper method that calculates the revenue prediction metrics, scenarios (conservative, realistic, optimistic), factors (time, seasonality, market), and projected metrics.
    calculateRevenuePrediction(financialData, businessData, period) {
      const currentRevenue = financialData.ingresos_total || 0;
      const currentOccupancy = financialData.ocupacion_promedio || businessData?.occupancy || 0;
      const currentReservations = financialData.reservas_totales || 0;
      
      // Factores de crecimiento y estacionalidad basados en datos reales
      const growthFactors = this.calculateGrowthFactors(period);
      const seasonalityFactor = this.calculateSeasonalityFactor();
      const marketFactor = this.calculateMarketFactor(currentOccupancy);
      
      // Cálculo base de predicción
      const basePrediction = currentRevenue * growthFactors.time * seasonalityFactor * marketFactor;
      
      const prediction = {
        period,
        current_metrics: {
          revenue: currentRevenue,
          occupancy: currentOccupancy,
          reservations: currentReservations,
          avg_rate: currentReservations > 0 ? Math.round(currentRevenue / currentReservations) : 0
        },
        prediction_factors: {
          time_factor: growthFactors.time,
          seasonality_factor: seasonalityFactor,
          market_factor: marketFactor,
          confidence_level: this.calculateConfidenceLevel(financialData)
        },
        scenarios: {
          conservative: Math.round(basePrediction * 0.85),
          realistic: Math.round(basePrediction),
          optimistic: Math.round(basePrediction * 1.15)
        },
        projected_metrics: {
          revenue: Math.round(basePrediction),
          occupancy: Math.min(95, Math.round(currentOccupancy * seasonalityFactor * marketFactor)),
          reservations: Math.round(currentReservations * growthFactors.time * marketFactor)
        },
        recommendations: [],
        risk_factors: [],
        monitoring_points: []
      };
      
      // Agregar recomendaciones basadas en la predicción
      this.addRevenuePredictionRecommendations(prediction);
      
      return prediction;
    }
  • Helper method that formats the revenue prediction into a detailed markdown report with sections for metrics, prediction, scenarios, factors, recommendations, risks, and monitoring points.
    formatRevenuePrediction(prediction, period) {
      const periodNames = {
        next_week: 'Próxima Semana',
        next_month: 'Próximo Mes',
        next_quarter: 'Próximo Trimestre',
        next_semester: 'Próximo Semestre',
        next_year: 'Próximo Año'
      };
      
      let report = `📈 **PREDICCIÓN DE INGRESOS TREEPOD**\n\n`;
      report += `📅 **Período:** ${periodNames[period] || period}\n\n`;
      
      // Métricas actuales
      report += `📊 **MÉTRICAS ACTUALES:**\n`;
      if (prediction.current_metrics.revenue > 0) {
        report += `• Ingresos: ${this.formatCurrency(prediction.current_metrics.revenue)}\n`;
      }
      report += `• Ocupación: ${prediction.current_metrics.occupancy}%\n`;
      if (prediction.current_metrics.reservations > 0) {
        report += `• Reservas: ${prediction.current_metrics.reservations}\n`;
      }
      if (prediction.current_metrics.avg_rate > 0) {
        report += `• Tarifa promedio: ${this.formatCurrency(prediction.current_metrics.avg_rate)}\n`;
      }
      report += `\n`;
      
      // Predicción principal
      report += `🎯 **PREDICCIÓN:**\n`;
      report += `• **Ingresos proyectados:** ${this.formatCurrency(prediction.projected_metrics.revenue)}\n`;
      report += `• **Ocupación proyectada:** ${prediction.projected_metrics.occupancy}%\n`;
      report += `• **Reservas proyectadas:** ${prediction.projected_metrics.reservations}\n`;
      report += `• **Nivel de confianza:** ${prediction.prediction_factors.confidence_level}%\n\n`;
      
      // Escenarios
      report += `📊 **ESCENARIOS:**\n`;
      report += `• 🟢 **Optimista:** ${this.formatCurrency(prediction.scenarios.optimistic)}\n`;
      report += `• 🟡 **Realista:** ${this.formatCurrency(prediction.scenarios.realistic)}\n`;
      report += `• 🔴 **Conservador:** ${this.formatCurrency(prediction.scenarios.conservative)}\n\n`;
      
      // Factores considerados
      report += `🔍 **FACTORES CONSIDERADOS:**\n`;
      report += `• Factor temporal: ${(prediction.prediction_factors.time_factor * 100).toFixed(0)}%\n`;
      report += `• Factor estacional: ${((prediction.prediction_factors.seasonality_factor - 1) * 100).toFixed(0)}%\n`;
      report += `• Factor de mercado: ${((prediction.prediction_factors.market_factor - 1) * 100).toFixed(0)}%\n\n`;
      
      // Recomendaciones
      if (prediction.recommendations.length > 0) {
        report += `💡 **RECOMENDACIONES:**\n`;
        prediction.recommendations.forEach(rec => {
          report += `• ${rec}\n`;
        });
        report += `\n`;
      }
      
      // Factores de riesgo
      if (prediction.risk_factors.length > 0) {
        report += `⚠️ **FACTORES DE RIESGO:**\n`;
        prediction.risk_factors.forEach(risk => {
          report += `• ${risk}\n`;
        });
        report += `\n`;
      }
      
      // Puntos de monitoreo
      if (prediction.monitoring_points.length > 0) {
        report += `📋 **MONITOREO:**\n`;
        prediction.monitoring_points.forEach(point => {
          report += `• ${point}\n`;
        });
      }
      
      return report;
    }

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