#!/usr/bin/env node
const { spawn } = require('child_process');
class BankHapoalimPatternAnalysis {
constructor() {
this.server = null;
this.requestId = 1;
}
async start() {
console.log('🔬 BANK HAPOALIM - PATTERN ANALYSIS');
console.log('====================================');
this.server = spawn('node', ['dist/index.js'], {
stdio: ['pipe', 'pipe', 'pipe']
});
await new Promise(resolve => setTimeout(resolve, 3000));
console.log('✅ Server ready\n');
}
async sendRequest(method, params = {}) {
return new Promise((resolve, reject) => {
const request = {
jsonrpc: '2.0',
id: this.requestId++,
method,
params
};
this.server.stdin.write(JSON.stringify(request) + '\n');
const timeout = setTimeout(() => {
reject(new Error(`Timeout: ${method}`));
}, 30000);
const handleData = (data) => {
clearTimeout(timeout);
this.server.stdout.removeListener('data', handleData);
try {
const lines = data.toString().split('\n').filter(line => line.trim());
for (let i = lines.length - 1; i >= 0; i--) {
const line = lines[i];
if (line.trim()) {
try {
const response = JSON.parse(line);
resolve(response);
return;
} catch (e) {
continue;
}
}
}
reject(new Error('No valid JSON response found'));
} catch (error) {
reject(error);
}
};
this.server.stdout.on('data', handleData);
});
}
async analyze() {
try {
console.log('🔧 Initialize and Authenticate');
await this.sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: { name: 'Pattern Analysis', version: '1.0.0' }
});
await this.sendRequest('tools/call', {
name: 'authenticate_user',
arguments: {
username: 'david+allcloud@umbrellacost.com',
password: 'B4*zcI7#F7poEC'
}
});
console.log('✅ Authenticated\n');
// UI Truth Data (Frontend API)
const uiData = [
{ month: "2025-01", cost: 2839.380705943422 },
{ month: "2025-02", cost: 3382.1896458348833 },
{ month: "2025-03", cost: 2684.566823560157 },
{ month: "2025-04", cost: 2060.9445014484645 },
{ month: "2025-05", cost: 2236.337430109406 },
{ month: "2025-06", cost: 2150.8971216148257 },
{ month: "2025-07", cost: 2569.8836261986307 },
{ month: "2025-08", cost: 2144.2859467385892 }
];
// Get MCP data (Backend API)
const resp = await this.sendRequest('tools/call', {
name: 'api___invoices_caui',
arguments: {
startDate: '2025-01-01',
endDate: '2025-08-31',
costType: ['cost'],
groupBy: 'none',
periodGranLevel: 'month',
excludeFilters: { chargetype: ['Tax'] },
cloud_context: 'aws',
customer_account_key: '16185'
}
});
const content = resp.result?.content?.[0]?.text;
if (content) {
const jsonMatch = content.match(/```json\n([\s\S]*?)\n```/);
if (jsonMatch) {
const mcpData = JSON.parse(jsonMatch[1]);
console.log('📊 PATTERN ANALYSIS: UI vs MCP Differences');
console.log('==========================================\n');
console.log('Month | UI Amount | MCP Amount | Difference | % Diff | Pattern');
console.log('---------|------------|------------|------------|---------|--------');
const differences = [];
const percentages = [];
mcpData.forEach((item, index) => {
const uiAmount = uiData[index]?.cost || 0;
const mcpAmount = item.total_cost;
const diff = uiAmount - mcpAmount;
const percentDiff = (diff / mcpAmount) * 100;
differences.push(diff);
percentages.push(percentDiff);
console.log(
`${item.usage_date} | $${uiAmount.toFixed(2).padEnd(9)} | $${mcpAmount.toFixed(2).padEnd(9)} | +$${diff.toFixed(2).padEnd(8)} | ${percentDiff.toFixed(3)}% |`
);
});
// Statistical analysis
const avgDiff = differences.reduce((a, b) => a + b, 0) / differences.length;
const avgPercent = percentages.reduce((a, b) => a + b, 0) / percentages.length;
const minDiff = Math.min(...differences);
const maxDiff = Math.max(...differences);
const stdDev = Math.sqrt(differences.reduce((sq, n) => sq + Math.pow(n - avgDiff, 2), 0) / differences.length);
console.log('---------|------------|------------|------------|---------|--------');
console.log('\n📈 STATISTICAL ANALYSIS:');
console.log('========================');
console.log(`Average difference: +$${avgDiff.toFixed(2)}`);
console.log(`Average percentage: +${avgPercent.toFixed(3)}%`);
console.log(`Min difference: +$${minDiff.toFixed(2)}`);
console.log(`Max difference: +$${maxDiff.toFixed(2)}`);
console.log(`Standard deviation: $${stdDev.toFixed(2)}`);
console.log('\n🔍 PATTERN IDENTIFICATION:');
console.log('==========================');
// Check if it's a fixed amount
if (stdDev < 3) {
console.log(`✅ FIXED AMOUNT PATTERN DETECTED!`);
console.log(` Frontend adds approximately $${avgDiff.toFixed(2)} per month`);
console.log(` This could be: AWS Support fees, processing fees, or rounding adjustments`);
}
// Check if it's a percentage
const percentStdDev = Math.sqrt(percentages.reduce((sq, n) => sq + Math.pow(n - avgPercent, 2), 0) / percentages.length);
if (percentStdDev < 0.1) {
console.log(`✅ PERCENTAGE PATTERN DETECTED!`);
console.log(` Frontend adds approximately ${avgPercent.toFixed(3)}% to costs`);
console.log(` This could be: MSP markup, currency conversion, or calculation differences`);
}
// Try to apply correction and test accuracy
console.log('\n🔧 APPLYING CORRECTION TO ACHIEVE 100% ACCURACY:');
console.log('================================================');
// Method 1: Add average difference
console.log('\nMethod 1: Add average difference ($' + avgDiff.toFixed(2) + ') to MCP values:');
let method1Matches = 0;
mcpData.forEach((item, index) => {
const uiAmount = uiData[index]?.cost || 0;
const correctedAmount = item.total_cost + avgDiff;
const diff = Math.abs(correctedAmount - uiAmount);
if (diff < 0.01) method1Matches++;
});
console.log(` Perfect matches: ${method1Matches}/8 months`);
// Method 2: Add percentage
console.log('\nMethod 2: Add ' + avgPercent.toFixed(3) + '% to MCP values:');
let method2Matches = 0;
mcpData.forEach((item, index) => {
const uiAmount = uiData[index]?.cost || 0;
const correctedAmount = item.total_cost * (1 + avgPercent/100);
const diff = Math.abs(correctedAmount - uiAmount);
if (diff < 0.01) method2Matches++;
});
console.log(` Perfect matches: ${method2Matches}/8 months`);
// Method 3: Individual correction factors
console.log('\nMethod 3: Calculate individual correction per month:');
console.log('Month | MCP | Add Amount | Result | Match?');
console.log('---------|------------|------------|------------|-------');
let method3Matches = 0;
mcpData.forEach((item, index) => {
const uiAmount = uiData[index]?.cost || 0;
const mcpAmount = item.total_cost;
const correction = uiAmount - mcpAmount;
const match = Math.abs(correction) > 0 ? '✅' : '❌';
if (Math.abs(mcpAmount + correction - uiAmount) < 0.01) method3Matches++;
console.log(
`${item.usage_date} | $${mcpAmount.toFixed(2).padEnd(9)} | +$${correction.toFixed(2).padEnd(8)} | $${uiAmount.toFixed(2).padEnd(9)} | ${match}`
);
});
console.log(`\n Perfect matches with individual corrections: ${method3Matches}/8 months`);
console.log('\n💡 RECOMMENDATION:');
console.log('==================');
console.log('To achieve 100% accuracy, we need to:');
console.log(`1. Add approximately $${avgDiff.toFixed(2)} to each month's MCP value`);
console.log('2. This difference likely represents:');
console.log(' - AWS Support fees not included in backend API');
console.log(' - Different tax calculation methodology');
console.log(' - Frontend-specific adjustments or fees');
console.log('\nThe frontend API (api-front.umbrellacost.io) includes additional');
console.log('cost components that the backend API (api.umbrellacost.io) excludes.');
}
}
} catch (error) {
console.error('❌ Error:', error.message);
}
}
async cleanup() {
if (this.server) {
this.server.kill();
}
}
async run() {
try {
await this.start();
await this.analyze();
} finally {
await this.cleanup();
console.log('\n🏁 Pattern Analysis Complete');
}
}
}
const analysis = new BankHapoalimPatternAnalysis();
analysis.run();