#!/usr/bin/env node
/**
* CloudWatch Costs - UI Format Match
* Using the exact same parameters as the UI request
*/
const { spawn } = require('child_process');
class CloudWatchUIFormat {
constructor() {
this.server = null;
this.requestId = 1;
this.responses = [];
}
async startServer() {
console.log('๐ฏ CLOUDWATCH COSTS - MATCHING UI FORMAT');
console.log('Using exact parameters from UI request');
console.log('=' .repeat(80));
return new Promise((resolve, reject) => {
this.server = spawn('node', ['dist/index.js'], {
stdio: ['pipe', 'pipe', 'pipe'],
cwd: process.cwd(),
env: {
...process.env,
UMBRELLA_API_BASE_URL: 'https://api-front.umbrellacost.io/api/v1'
}
});
this.server.stdout.on('data', (data) => {
const lines = data.toString().split('\n').filter(line => line.trim());
for (const line of lines) {
try {
const response = JSON.parse(line);
this.responses.push(response);
} catch (e) {}
}
});
this.server.stderr.on('data', (data) => {
const message = data.toString().trim();
if (message.includes('๐') || message.includes('Successfully authenticated') || message.includes('API REQUEST')) {
console.log('SERVER:', message);
}
});
this.server.on('error', reject);
setTimeout(resolve, 3000);
});
}
async sendRequest(method, params = {}) {
return new Promise((resolve) => {
const request = {
jsonrpc: "2.0",
id: this.requestId++,
method,
params
};
this.server.stdin.write(JSON.stringify(request) + '\n');
const startTime = Date.now();
const startResponseCount = this.responses.length;
const checkForResponse = () => {
const newResponses = this.responses.slice(startResponseCount);
const matchingResponse = newResponses.find(r => r.id === request.id);
if (matchingResponse) {
resolve(matchingResponse);
} else if (Date.now() - startTime > 45000) {
resolve(null);
} else {
setTimeout(checkForResponse, 500);
}
};
setTimeout(checkForResponse, 500);
});
}
formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2
}).format(amount);
}
formatDate(dateString) {
return new Date(dateString).toLocaleDateString('en-US', {
month: 'short',
day: '2-digit'
});
}
analyzeCloudWatchData(data) {
console.log('\n๐ CLOUDWATCH COST CALCULATION:');
console.log('=' .repeat(60));
if (!data || !Array.isArray(data)) {
console.log('โ No data to analyze');
return 0;
}
console.log(`๐ Total CloudWatch records: ${data.length}`);
// Calculate total cost
let totalCost = 0;
const dailyCosts = {};
const serviceCosts = {};
data.forEach((item, index) => {
const cost = item.total_cost || 0;
totalCost += cost;
// Daily breakdown
if (item.usage_date) {
const date = this.formatDate(item.usage_date);
dailyCosts[date] = (dailyCosts[date] || 0) + cost;
}
// Service breakdown
const service = item.service_name || item.resource_name || 'CloudWatch';
serviceCosts[service] = (serviceCosts[service] || 0) + cost;
// Show first few records
if (index < 3) {
console.log(`\n๐ Record ${index + 1}:`);
console.log(` Date: ${item.usage_date}`);
console.log(` Cost: ${this.formatCurrency(cost)}`);
console.log(` Service: ${item.service_name || 'N/A'}`);
console.log(` Usage Type: ${item.usage_type || 'N/A'}`);
console.log(` Resource: ${item.resource_name || 'N/A'}`);
}
});
console.log('\n๐ฐ TOTAL CALCULATION:');
console.log(` Sum of all daily costs = ${this.formatCurrency(totalCost)}`);
console.log('\n๐
DAILY BREAKDOWN:');
Object.entries(dailyCosts)
.sort(([a], [b]) => new Date(a) - new Date(b))
.forEach(([date, cost]) => {
console.log(` ${date}: ${this.formatCurrency(cost)}`);
});
console.log('\n๐ง SERVICE COMPONENTS:');
Object.entries(serviceCosts)
.sort(([,a], [,b]) => b - a)
.forEach(([service, cost]) => {
const percentage = ((cost / totalCost) * 100).toFixed(1);
console.log(` ${service}: ${this.formatCurrency(cost)} (${percentage}%)`);
});
return totalCost;
}
async runCloudWatchUITest() {
try {
await this.startServer();
// Authenticate first
console.log('\n๐ AUTHENTICATING...');
const authResponse = await this.sendRequest('tools/call', {
name: 'authenticate_user',
arguments: {
username: 'david+saola@umbrellacost.com',
password: 'Dsamsung1!'
}
});
if (!authResponse?.result?.content?.[0]?.text?.includes('Successfully authenticated')) {
console.log('โ Authentication failed');
return;
}
console.log('โ
Authentication successful');
console.log('\n๐ UI REQUEST ANALYSIS:');
console.log('Original UI URL:');
console.log('https://api-front.umbrellacost.io/api/v1/invoices/caui');
console.log('?groupBy=service&groupBy=usagedate');
console.log('&startDate=2025-07-16&endDate=2025-08-24');
console.log('&periodGranLevel=day');
console.log('&costType=cost&costType=discount');
console.log('&filters[service]=AmazonCloudWatch');
console.log('&filters[linkedaccid]=932213950603');
console.log('&isAmortized=true');
// Convert UI parameters to MCP format - simplified first
const uiParams = {
startDate: "2025-07-16",
endDate: "2025-08-24",
periodGranLevel: "day",
costType: ["cost", "discount"], // Array format
groupBy: "service", // Single groupBy first
isAmortized: true,
// MCP requires accountId instead of filters[linkedaccid]
accountId: "932213950603" // Account ID (converted from filters[linkedaccid])
};
console.log('\n๐ค CONVERTED MCP PARAMETERS:');
console.log(JSON.stringify(uiParams, null, 2));
const response = await this.sendRequest('tools/call', {
name: 'api___invoices_caui',
arguments: uiParams
});
if (response?.result?.content?.[0]?.text) {
const text = response.result.content[0].text;
console.log('\nโ
CLOUDWATCH DATA RECEIVED');
const jsonMatch = text.match(/```json\n([\s\S]*?)\n```/);
if (jsonMatch) {
try {
const data = JSON.parse(jsonMatch[1]);
const totalCost = this.analyzeCloudWatchData(data);
console.log('\n' + '=' .repeat(80));
console.log('๐ฏ CLOUDWATCH COST SUMMARY (39 days):');
console.log(` ${this.formatCurrency(totalCost)}`);
console.log('=' .repeat(80));
// Calculate daily average and 30-day projection
const days = (new Date('2025-08-24') - new Date('2025-07-16')) / (1000 * 60 * 60 * 24) + 1;
const avgDaily = totalCost / days;
const thirtyDayProjection = avgDaily * 30;
console.log('\n๐ PROJECTIONS:');
console.log(` Average daily cost: ${this.formatCurrency(avgDaily)}`);
console.log(` 30-day projection: ${this.formatCurrency(thirtyDayProjection)}`);
} catch (e) {
console.log('โ Could not parse JSON data:', e.message);
console.log('Response preview:', text.substring(0, 500));
}
} else {
console.log('โ No JSON data found');
console.log('Full response:', text);
}
} else if (response?.error) {
console.log('โ ERROR:', JSON.stringify(response.error, null, 2));
} else {
console.log('โ No response received - request may have timed out');
}
} catch (error) {
console.error('๐ฅ TEST ERROR:', error);
} finally {
this.cleanup();
}
}
cleanup() {
if (this.server) {
this.server.kill();
}
}
}
// Run the UI format test
const tester = new CloudWatchUIFormat();
tester.runCloudWatchUITest().catch(console.error);