Skip to main content
Glama

TreePod Financial MCP Agent

by janetsep
dataLoader.js7.24 kB
#!/usr/bin/env node import fs from 'fs/promises'; import path from 'path'; import { validator } from '../utils/validator.js'; /** * 🗂️ Módulo de Carga de Datos TreePod Financial MCP * Implementa la Guía de Trabajo Fundamental: Sin datos hardcodeados, fuentes reales */ const basePath = '/Users/janetsepulvedacorrea/Desktop/AGENTES'; const dataPath = path.join(basePath, 'shared-data'); const webAppPath = path.join(basePath, 'TreePod-Sistema/app-treepod/data'); const competitorPath = path.join(basePath, 'treepod-competitive-agent/reports'); export class DataLoader { constructor() { this.cache = new Map(); this.cacheExpiry = new Map(); this.cacheDuration = 5 * 60 * 1000; // 5 minutos } /** * Carga datos financieros SOLO de fuentes reales */ async loadFinancialData() { const cacheKey = 'financial_data'; // Verificar cache válido if (this.isCacheValid(cacheKey)) { validator.log('info', 'Datos financieros obtenidos del cache'); return this.cache.get(cacheKey); } const filePath = path.join(webAppPath, 'sample-data.json'); // Validar que el archivo existe const fileExists = await validator.validateFileExists(filePath, 'datos financieros'); if (!fileExists) { validator.log('error', 'Archivo de datos financieros no encontrado'); return null; // NO devolver datos inventados } // Validar estructura de datos const requiredFields = ['ingresos_total', 'gastos_total', 'ocupacion_promedio', 'reservas_totales']; const validation = await validator.validateJsonData(filePath, requiredFields, 'datos financieros'); if (!validation.valid) { validator.log('error', `Datos financieros inválidos: ${validation.error || 'campos faltantes'}`); return null; } // Cache y retornar datos válidos this.setCache(cacheKey, validation.data); validator.log('info', 'Datos financieros cargados exitosamente desde fuente real'); return validation.data; } /** * Carga estado del negocio desde bus inter-agentes */ async loadBusinessStatus() { const cacheKey = 'business_status'; if (this.isCacheValid(cacheKey)) { validator.log('info', 'Estado del negocio obtenido del cache'); return this.cache.get(cacheKey); } const filePath = path.join(dataPath, 'inter-agent-bus.json'); const fileExists = await validator.validateFileExists(filePath, 'estado del negocio'); if (!fileExists) { validator.log('error', 'Archivo de estado del negocio no encontrado'); return null; } const validation = await validator.validateJsonData(filePath, [], 'estado del negocio'); if (!validation.valid) { validator.log('error', `Estado del negocio inválido: ${validation.error}`); return null; } this.setCache(cacheKey, validation.data); validator.log('info', 'Estado del negocio cargado exitosamente'); return validation.data; } /** * Carga datos de competencia desde reportes reales */ 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; } /** * Carga estado REAL de domos (elimina hardcodeo) * Intenta múltiples fuentes antes de fallar */ async loadDomosStatus() { const cacheKey = 'domos_status'; if (this.isCacheValid(cacheKey)) { validator.log('info', 'Estado de domos obtenido del cache'); return this.cache.get(cacheKey); } // Intentar cargar desde múltiples fuentes const sources = [ { path: path.join(dataPath, 'domos-status.json'), name: 'estado de domos dedicado' }, { path: path.join(webAppPath, 'sample-data.json'), name: 'datos principales', field: 'domos_status' }, { path: path.join(dataPath, 'inter-agent-bus.json'), name: 'bus inter-agentes', field: 'domos' } ]; for (const source of sources) { const fileExists = await validator.validateFileExists(source.path, source.name); if (fileExists) { const validation = await validator.validateJsonData(source.path, [], source.name); if (validation.valid) { let domosData = validation.data; // Si necesita extraer un campo específico if (source.field && domosData[source.field]) { domosData = domosData[source.field]; } // Validar que tiene estructura de domos if (this.isValidDomosData(domosData)) { this.setCache(cacheKey, domosData); validator.log('info', `Estado de domos cargado desde: ${source.name}`); return domosData; } } } } validator.log('error', 'No se pudo cargar estado real de domos desde ninguna fuente'); return null; // NO devolver datos hardcodeados } /** * Valida si los datos de domos tienen estructura correcta */ isValidDomosData(data) { if (!Array.isArray(data)) return false; return data.every(domo => domo.name && domo.status && ['occupied', 'available', 'maintenance', 'cleaning'].includes(domo.status) ); } /** * Sistema de cache con expiración */ isCacheValid(key) { if (!this.cache.has(key)) return false; const expiry = this.cacheExpiry.get(key); if (!expiry || Date.now() > expiry) { this.cache.delete(key); this.cacheExpiry.delete(key); return false; } return true; } setCache(key, data) { this.cache.set(key, data); this.cacheExpiry.set(key, Date.now() + this.cacheDuration); } /** * Limpia cache manualmente */ clearCache() { this.cache.clear(); this.cacheExpiry.clear(); validator.log('info', 'Cache limpiado manualmente'); } /** * Obtiene estadísticas del cache para debugging */ getCacheStats() { return { entries: this.cache.size, keys: Array.from(this.cache.keys()), lastAccess: Array.from(this.cacheExpiry.entries()).map(([key, expiry]) => ({ key, expiresIn: Math.max(0, expiry - Date.now()) })) }; } } // Instancia global del cargador de datos export const dataLoader = new DataLoader();

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