Skip to main content
Glama

TreePod Financial MCP Agent

by janetsep
server-fixed.js7.71 kB
#!/usr/bin/env node import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; // Get __dirname equivalent in ES modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Importar módulos que implementan la Guía de Trabajo Fundamental import { validator } from './src/utils/validator.js'; import { dataLoader } from './src/data/dataLoader.js'; import { businessCalculator } from './src/business/calculator.js'; // Rutas a los datos const dataPath = path.join(__dirname, 'data'); const webAppPath = path.join(__dirname, '../treepod-financial-webapp'); const competitorPath = path.join(__dirname, '../treepod-competitive-agent/reports'); /** * 🏕️ TreePod Glamping - Agente Financiero MCP * Agente inteligente que responde consultas sobre el negocio TreePod * directamente dentro de Claude Desktop. */ const server = new McpServer({ name: 'treepod-financial', version: '1.0.0', }); // --- Herramienta: analyze_finances --- server.registerTool( 'analyze_finances', { title: 'Analizar finanzas', description: 'Analiza las finanzas actuales de TreePod Glamping con métricas clave basado en datos reales', inputSchema: z.object({ period: z.string().default('current'), }), }, async ({ period }) => { validator.log('info', `Iniciando análisis financiero para período: ${period}`); try { // Usar módulo de cálculo sin hardcodeo const result = await businessCalculator.analyzeFinancialMetrics(period); validator.log('info', 'Análisis financiero completado exitosamente'); return result; } catch (error) { validator.log('error', `Error crítico en análisis financiero: ${error.message}`); return validator.generateInsufficientDataResponse( 'análisis financiero', 'Error interno del sistema. Contacta al administrador.' ); } } ); // --- Herramienta: calculate_tariff --- server.registerTool( 'calculate_tariff', { title: 'Calcular tarifa', description: 'Calcula tarifas para reservas según temporada, personas y canal basado en configuración real', inputSchema: z.object({ checkin_date: z.string(), checkout_date: z.string(), guests: z.number().min(1).max(4), channel: z.string().optional().default('directo'), }), }, async ({ checkin_date, checkout_date, guests, channel = 'directo' }) => { validator.log('info', `Iniciando cálculo de tarifa: ${guests} huéspedes, ${checkin_date} a ${checkout_date}, canal ${channel}`); try { // Usar módulo de cálculo sin hardcodeo const result = await businessCalculator.calculateTariff(checkin_date, checkout_date, guests, channel); validator.log('info', 'Cálculo de tarifa completado exitosamente'); return result; } catch (error) { validator.log('error', `Error crítico en cálculo de tarifa: ${error.message}`); return validator.generateInsufficientDataResponse( 'cálculo de tarifa', 'Error interno del sistema. Contacta al administrador.' ); } } ); // --- Herramienta: get_business_status --- server.registerTool( 'get_business_status', { title: 'Estado del negocio', description: 'Estado general actual del negocio con alertas y KPIs', inputSchema: z.object({}), }, async () => { try { const financialData = await loadFinancialData(); const businessStatus = await loadBusinessStatus(); const alerts = await checkAlerts(); const revenue = financialData.ingresos_total || 5200000; const expenses = financialData.gastos_total || 3400000; const profit = revenue - expenses; const margin = (profit / revenue * 100).toFixed(1); const occupancy = businessStatus.occupancy || 67; let overallStatus = '🟢 Excelente'; if (profit < 1500000 || occupancy < 60) { overallStatus = '🔴 Requiere atención'; } else if (profit < 2000000 || occupancy < 70) { overallStatus = '🟡 Bueno'; } return { content: [{ type: 'text', text: `🎯 **ESTADO GENERAL TREEPOD GLAMPING**\n\n` + `💼 **Estado del Negocio:** ${overallStatus}\n` + `📅 **Última actualización:** ${new Date().toLocaleDateString('es-CL')}\n\n` + `**📊 KPIs PRINCIPALES:**\n` + `• 💰 Ingresos: ${formatCurrency(revenue)}\n` + `• 📈 Utilidad: ${formatCurrency(profit)} (${margin}%)\n` + `• 🏠 Ocupación: ${occupancy}%\n` + `• 📅 Reservas: ${financialData.reservas_totales || 18}\n\n` + `**🚨 ALERTAS ACTIVAS:**\n` + `${alerts.length > 0 ? alerts.map(alert => `• ${alert}`).join('\n') : '✅ Sin alertas críticas'}\n\n` + `**🎯 PROGRESO HACIA METAS:**\n` + `• Ingresos: ${((revenue/6000000)*100).toFixed(1)}% de $6M\n` + `• Utilidad: ${((profit/2000000)*100).toFixed(1)}% de $2M\n` + `• Ocupación: ${((occupancy/70)*100).toFixed(1)}% de 70%\n\n` + `**⚡ ACCIONES RECOMENDADAS:**\n` + `${getActionRecommendations(revenue, profit, occupancy)}` }] }; } catch (error) { return { content: [{ type: 'text', text: `❌ Error obteniendo estado del negocio: ${error.message}` }] }; } } ); // --- Métodos auxiliares --- async function loadFinancialData() { try { const filePath = path.join(webAppPath, 'sample-data.json'); const data = await fs.readFile(filePath, 'utf8'); return JSON.parse(data); } catch (error) { return { ingresos_total: 5200000, gastos_total: 3400000, ocupacion_promedio: 67, reservas_totales: 18 }; } } async function loadBusinessStatus() { try { const filePath = path.join(dataPath, 'inter-agent-bus.json'); const data = await fs.readFile(filePath, 'utf8'); return JSON.parse(data); } catch (error) { return { occupancy: 67 }; } } async function checkAlerts() { const alerts = []; const financialData = await loadFinancialData(); const revenue = financialData.ingresos_total || 5200000; const profit = revenue - (financialData.gastos_total || 3400000); const occupancy = financialData.ocupacion_promedio || 67; if (revenue < 5500000) alerts.push('🟡 Ingresos por debajo de la meta'); if (profit < 1800000) alerts.push('🟡 Utilidad por debajo de la meta'); if (occupancy < 65) alerts.push('🟡 Ocupación baja - considerar promociones'); return alerts; } function getActionRecommendations(revenue, profit, occupancy) { const actions = []; if (revenue < 5500000) actions.push('1. Intensificar marketing digital y promociones'); if (profit < 1800000) actions.push('2. Revisar gastos operacionales y optimizar costos'); if (occupancy < 65) actions.push('3. Lanzar campaña de último momento para fechas disponibles'); if (actions.length === 0) actions.push('• Mantener estrategia actual - métricas positivas'); return actions.join('\n'); } function formatCurrency(amount) { return new Intl.NumberFormat('es-CL', { style: 'currency', currency: 'CLP', minimumFractionDigits: 0 }).format(amount); } // --- Iniciar el servidor MCP --- const transport = new StdioServerTransport(); server.connect(transport).then(() => { console.error('🏕️ TreePod Financial Agent MCP iniciado y listo para consultas'); }).catch(console.error);

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