#!/usr/bin/env node
const { spawn } = require('child_process');
class BankHapoalimMonthlyAccuracy {
constructor() {
this.server = null;
this.requestId = 1;
}
async start() {
console.log('π¦ BANK HAPOALIM - MONTHLY ACCURACY 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 getCostData() {
try {
console.log('π§ Initialize and Authenticate');
await this.sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: { name: 'Monthly Accuracy 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 (from the 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 with Cost Only, Exclude Tax (closest match)
console.log('π Fetching MCP data (Cost only, excluding tax)...\n');
const resp = await this.sendRequest('tools/call', {
name: 'api___invoices_caui',
arguments: {
startDate: '2025-01-01',
endDate: '2025-08-31',
costType: ['cost'], // Cost only, no discount
groupBy: 'none',
periodGranLevel: 'month',
excludeFilters: { chargetype: ['Tax'] }, // Exclude 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('π MONTH-BY-MONTH ACCURACY ANALYSIS');
console.log('===================================\n');
console.log('Month | UI Amount | MCP Amount | Difference | Accuracy | Status');
console.log('---------|---------------|---------------|-------------|-----------|--------');
let perfectMatches = 0;
let nearMatches = 0;
let totalDiff = 0;
mcpData.forEach((item, index) => {
const uiAmount = uiData[index]?.cost || 0;
const mcpAmount = item.total_cost;
const diff = mcpAmount - uiAmount;
const absDiff = Math.abs(diff);
const accuracy = ((1 - absDiff / uiAmount) * 100);
let status = '';
if (absDiff < 0.01) {
status = 'β
EXACT';
perfectMatches++;
} else if (absDiff < 1) {
status = 'β
<$1 diff';
nearMatches++;
} else if (absDiff < 10) {
status = 'π‘ <$10 diff';
} else {
status = 'π΄ >$10 diff';
}
totalDiff += diff;
console.log(
`${item.usage_date} | $${uiAmount.toFixed(2).padEnd(12)} | $${mcpAmount.toFixed(2).padEnd(12)} | ${diff >= 0 ? '+' : ''}$${diff.toFixed(2).padEnd(10)} | ${accuracy.toFixed(3)}% | ${status}`
);
});
console.log('---------|---------------|---------------|-------------|-----------|--------');
const uiTotal = uiData.reduce((sum, item) => sum + item.cost, 0);
const mcpTotal = mcpData.reduce((sum, item) => sum + item.total_cost, 0);
const totalAccuracy = ((1 - Math.abs(totalDiff) / uiTotal) * 100);
console.log(
`TOTAL | $${uiTotal.toFixed(2).padEnd(11)} | $${mcpTotal.toFixed(2).padEnd(11)} | ${totalDiff >= 0 ? '+' : ''}$${totalDiff.toFixed(2).padEnd(9)} | ${totalAccuracy.toFixed(3)}% |`
);
console.log('\nπ ACCURACY SUMMARY');
console.log('==================');
console.log(`β
Perfect matches (< $0.01): ${perfectMatches}/8 months`);
console.log(`β
Near matches (< $1.00): ${nearMatches}/8 months`);
console.log(`π Overall accuracy: ${totalAccuracy.toFixed(3)}%`);
console.log('\nπ‘ ANALYSIS:');
if (perfectMatches >= 6) {
console.log('β
EXCELLENT: Most months are perfect or near-perfect matches!');
} else if (totalAccuracy > 99.5) {
console.log('β
VERY GOOD: Overall accuracy is above 99.5%');
} else if (totalAccuracy > 99) {
console.log('π‘ GOOD: Overall accuracy is above 99%');
} else {
console.log('π΄ NEEDS INVESTIGATION: Accuracy below 99%');
}
// Identify pattern in differences
console.log('\nπ DIFFERENCE PATTERN:');
const negDiffs = mcpData.filter((item, i) => item.total_cost < uiData[i].cost).length;
const posDiffs = mcpData.filter((item, i) => item.total_cost > uiData[i].cost).length;
if (negDiffs > posDiffs) {
console.log(`MCP tends to show LOWER amounts (${negDiffs}/8 months)`);
console.log('Possible cause: UI might include additional cost categories');
} else if (posDiffs > negDiffs) {
console.log(`MCP tends to show HIGHER amounts (${posDiffs}/8 months)`);
console.log('Possible cause: MCP might include costs that UI filters out');
} else {
console.log('No consistent pattern in differences');
}
}
}
} catch (error) {
console.error('β Error:', error.message);
}
}
async cleanup() {
if (this.server) {
this.server.kill();
}
}
async run() {
try {
await this.start();
await this.getCostData();
} finally {
await this.cleanup();
console.log('\nπ Monthly Accuracy Analysis Complete');
}
}
}
const costQuery = new BankHapoalimMonthlyAccuracy();
costQuery.run();