Skip to main content
Glama
targeted-account-test.tsβ€’9.82 kB
#!/usr/bin/env node import dotenv from 'dotenv'; import { UmbrellaAuth } from './auth.js'; import { UmbrellaApiClient } from './api-client.js'; import { getTestCredentialSets } from './auth-helper.js'; dotenv.config(); // Specific accounts discovered from the account discovery test const DISCOVERED_ACCOUNTS = { MSP: [ 'mspprodtest_tenant_multicloud', 'mspprodtest_tenant_azure', 'AZURE--e39985', 'AzureS-da18a0', 'DDCT-G-faed5b', 'Dedica-a7a822', 'mspprodtest_tenant_gcp', 'GCP-SH-b35635' ], DIRECT: [ 'umbrellatestnet_tenant_multicloud', 'umbrellatestnet_tenant_aws', '322609219825', // This looks like a real AWS account ID 'umbrellatestnet_tenant_azure', 'umbrellatestnet_tenant_gcp', 'Manual-b7a983', 'Umbrel-2e4e6f' ] }; // Key endpoints that should work with proper account IDs const KEY_ENDPOINTS = [ { path: '/invoices/caui', method: 'GET', description: 'Cost and Usage Interface - Main cost analysis endpoint', requiresAccount: true, testParams: { startDate: '2024-01-01', endDate: '2024-01-31', costType: ['unblended'], groupBy: ['service'], periodGranLevel: 'daily' } }, { path: '/invoices/cost-and-usage', method: 'GET', description: 'Public cost and usage API', requiresAccount: false, testParams: { startDate: '2024-01-01', endDate: '2024-01-31' } }, { path: '/budgets', method: 'GET', description: 'Budget information and alerts', requiresAccount: true, testParams: {} }, { path: '/usage/ec2/instances', method: 'GET', description: 'EC2 instance usage and costs', requiresAccount: true, testParams: { startDate: '2024-01-01', endDate: '2024-01-31' } } ]; class TargetedAccountTester { private auth: UmbrellaAuth; private apiClient: UmbrellaApiClient; private baseURL: string; constructor(baseURL: string) { this.baseURL = baseURL; this.auth = new UmbrellaAuth(baseURL); this.apiClient = new UmbrellaApiClient(baseURL); } async authenticate(credentials: { username: string; password: string }): Promise<boolean> { try { await this.auth.authenticate(credentials); const authHeaders = this.auth.getAuthHeaders(); this.apiClient.setAuthToken(authHeaders); return true; } catch (error: any) { console.error(`❌ Authentication failed: ${error.message}`); return false; } } async testEndpointWithSpecificAccount(endpoint: any, accountId: string): Promise<any> { const testParams = { ...endpoint.testParams }; if (endpoint.requiresAccount) { testParams.accountId = accountId; } console.log(` πŸ” Testing ${endpoint.path} with account: ${accountId}`); console.log(` πŸ”§ Params: ${Object.keys(testParams).join(', ')}`); try { const startTime = Date.now(); const response = await this.apiClient.makeRequest(endpoint.path, testParams); const responseTime = Date.now() - startTime; if (response.success) { let dataInfo = 'Success'; if (response.data) { if (Array.isArray(response.data)) { dataInfo = `${response.data.length} array items`; } else if (typeof response.data === 'object') { dataInfo = `object with ${Object.keys(response.data).length} keys`; } } console.log(` βœ… SUCCESS: ${dataInfo} (${responseTime}ms)`); return { success: true, data: response.data, responseTime, accountId, endpoint: endpoint.path }; } else { console.log(` ❌ FAILED: ${response.error} (${responseTime}ms)`); return { success: false, error: response.error, responseTime, accountId, endpoint: endpoint.path }; } } catch (error: any) { console.log(` πŸ’₯ ERROR: ${error.message}`); return { success: false, error: error.message, accountId, endpoint: endpoint.path }; } } async runTargetedAccountTest( credentials: { username: string; password: string }, accountType: 'MSP' | 'DIRECT' ): Promise<void> { console.log(`\n${'='.repeat(80)}`); console.log(`🎯 TARGETED ACCOUNT TESTING: ${credentials.username} (${accountType})`); console.log(`${'='.repeat(80)}`); // Authenticate const authSuccess = await this.authenticate(credentials); if (!authSuccess) { return; } console.log(`βœ… Authentication successful`); const accounts = DISCOVERED_ACCOUNTS[accountType]; console.log(`\nπŸ“‹ Testing ${KEY_ENDPOINTS.length} key endpoints with ${accounts.length} discovered accounts`); const results: any[] = []; // Test each endpoint with each account for (const endpoint of KEY_ENDPOINTS) { console.log(`\nπŸ“Š Testing endpoint: ${endpoint.path}`); console.log(` πŸ“ ${endpoint.description}`); const endpointResults = []; for (const accountId of accounts) { const result = await this.testEndpointWithSpecificAccount(endpoint, accountId); results.push(result); endpointResults.push(result); // Brief pause between requests await new Promise(resolve => setTimeout(resolve, 300)); } // Summary for this endpoint const successful = endpointResults.filter(r => r.success).length; const total = endpointResults.length; console.log(` πŸ“ˆ Endpoint Summary: ${successful}/${total} accounts worked (${((successful/total)*100).toFixed(1)}%)`); if (successful > 0) { const workingAccounts = endpointResults.filter(r => r.success).map(r => r.accountId); console.log(` βœ… Working accounts: ${workingAccounts.join(', ')}`); } } // Final summary console.log(`\n${'='.repeat(80)}`); console.log(`πŸ“ˆ TARGETED TEST SUMMARY FOR ${accountType}`); console.log(`${'='.repeat(80)}`); const totalSuccessful = results.filter(r => r.success).length; const totalTests = results.length; const overallSuccessRate = (totalSuccessful / totalTests) * 100; console.log(`\n🎯 OVERALL RESULTS:`); console.log(` βœ… Successful tests: ${totalSuccessful}/${totalTests} (${overallSuccessRate.toFixed(1)}%)`); console.log(` πŸ“Š Endpoints tested: ${KEY_ENDPOINTS.length}`); console.log(` 🏒 Accounts tested: ${accounts.length}`); // Success by endpoint console.log(`\nπŸ“Š SUCCESS BY ENDPOINT:`); KEY_ENDPOINTS.forEach(endpoint => { const endpointResults = results.filter(r => r.endpoint === endpoint.path); const successful = endpointResults.filter(r => r.success).length; const rate = (successful / endpointResults.length) * 100; const status = rate > 0 ? 'βœ…' : '❌'; console.log(` ${status} ${endpoint.path}: ${successful}/${endpointResults.length} (${rate.toFixed(1)}%)`); }); // Success by account console.log(`\n🏒 SUCCESS BY ACCOUNT:`); accounts.forEach(accountId => { const accountResults = results.filter(r => r.accountId === accountId); const successful = accountResults.filter(r => r.success).length; const rate = (successful / accountResults.length) * 100; const status = rate > 0 ? 'βœ…' : '❌'; console.log(` ${status} ${accountId}: ${successful}/${accountResults.length} (${rate.toFixed(1)}%)`); }); // Show working combinations const workingCombinations = results.filter(r => r.success); if (workingCombinations.length > 0) { console.log(`\nπŸŽ‰ WORKING ENDPOINT + ACCOUNT COMBINATIONS:`); workingCombinations.forEach(result => { console.log(` βœ… ${result.endpoint} + ${result.accountId}`); }); } else { console.log(`\n⚠️ NO WORKING COMBINATIONS FOUND`); console.log(` This suggests the account IDs may need different formatting or additional parameters`); } } } async function main() { console.log('🎯 TARGETED ACCOUNT TESTING FOR UMBRELLA MCP'); console.log('============================================='); console.log(`πŸ“… Test Time: ${new Date().toISOString()}`); console.log('\n🎯 Strategy: Test key endpoints with all discovered account IDs'); const baseURL = process.env.UMBRELLA_API_BASE_URL || 'https://api.umbrellacost.io/api/v1'; const credentialSets = getTestCredentialSets(); if (!credentialSets) { console.error('❌ No test credentials available'); process.exit(1); } const testConfigs = [ { creds: credentialSets[0], type: 'MSP' as const, name: 'MSP Account' }, { creds: credentialSets[1], type: 'DIRECT' as const, name: 'Direct Account' } ]; for (const config of testConfigs) { try { const tester = new TargetedAccountTester(baseURL); await tester.runTargetedAccountTest(config.creds, config.type); } catch (error: any) { console.error(`❌ Test failed for ${config.name}: ${error.message}`); } // Pause between different credential types await new Promise(resolve => setTimeout(resolve, 2000)); } console.log(`\n🏁 TARGETED ACCOUNT TESTING COMPLETED!`); console.log('\nπŸ’‘ Next steps:'); console.log(' 1. If no combinations work, account IDs may need different formatting'); console.log(' 2. Try adding organizationId parameter alongside accountId'); console.log(' 3. Some endpoints may require specific date ranges or other context'); console.log(' 4. Consider testing with more recent date ranges (last 30 days)'); } // Run main function if this file is executed directly if (import.meta.url === `file://${process.argv[1]}`) { main().catch(console.error); }

Latest Blog Posts

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/daviddraiumbrella/invoice-monitoring'

If you have feedback or need assistance with the MCP directory API, please join our Discord server