Skip to main content
Glama
trace-api-key-generation.cjs12.6 kB
#!/usr/bin/env node /** * TRACE API KEY GENERATION FOR BANK LEUMI TEST ENV * * This script traces how the API key is generated for Bank Leumi BL Test Env * to understand why it's not being created with the expected value: * 57ade50e-c9a8-49f3-8ce7-28d44536a669:24223:1 */ const fetch = require('node-fetch'); const https = require('https'); const { spawn } = require('child_process'); const express = require('express'); const crypto = require('crypto'); // Disable SSL verification for local testing process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; const LOCAL_MCP_URL = 'https://localhost:3003'; function base64URLEncode(str) { return str.toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=/g, ''); } function generateCodeChallenge() { const codeVerifier = base64URLEncode(crypto.randomBytes(32)); const codeChallenge = base64URLEncode(crypto.createHash('sha256').update(codeVerifier).digest()); return { codeVerifier, codeChallenge }; } class ApiKeyTracer { constructor() { this.username = 'david+allcloud@umbrellacost.com'; this.password = 'Dsamsung1!'; this.accessToken = null; this.server = null; this.port = 3004; this.codeVerifier = null; } async startCallbackServer() { return new Promise((resolve) => { const app = express(); app.get('/', (req, res) => { res.send(` <html> <head><title>API Key Tracer</title></head> <body style="font-family: Arial; text-align: center; padding: 50px;"> <h1>🔍 Tracing API Key Generation</h1> <p>For Bank Leumi BL Test Env</p> </body> </html> `); }); app.get('/callback', (req, res) => { const { code, error } = req.query; if (error) { res.send(`<html><body>Error: ${error}</body></html>`); return; } if (code) { res.send(` <html> <body style="font-family: Arial; text-align: center; padding: 50px;"> <h1 style="color: green;">✅ OAuth Success!</h1> <p>Tracing API key generation...</p> <script>setTimeout(() => window.close(), 2000);</script> </body> </html> `); resolve(code); } }); this.server = app.listen(this.port, () => { console.log(`📡 Callback server listening on port ${this.port}`); }); }); } async registerOAuthClient() { const redirectUri = `http://localhost:${this.port}/callback`; const clientData = { client_name: 'API Key Tracer', redirect_uris: [redirectUri], grant_types: ['authorization_code'], response_types: ['code'], scope: 'openid profile email' }; const response = await fetch(`${LOCAL_MCP_URL}/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(clientData), agent: new https.Agent({ rejectUnauthorized: false }) }); if (!response.ok) { throw new Error(`Client registration failed: ${response.status}`); } const client = await response.json(); console.log(`✅ Client registered: ${client.client_id}`); return { clientId: client.client_id, redirectUri }; } async performOAuthFlow(clientId, redirectUri) { const { codeVerifier, codeChallenge } = generateCodeChallenge(); this.codeVerifier = codeVerifier; const authUrl = `${LOCAL_MCP_URL}/authorize?` + new URLSearchParams({ response_type: 'code', client_id: clientId, redirect_uri: redirectUri, state: 'api_key_trace', code_challenge: codeChallenge, code_challenge_method: 'S256', scope: 'openid profile email' }); console.log('🌐 Opening browser for authentication...'); this.openBrowser(authUrl); return true; } openBrowser(url) { const platform = process.platform; let command; if (platform === 'darwin') { command = 'open'; } else if (platform === 'win32') { command = 'start'; } else { command = 'xdg-open'; } spawn(command, [url], { detached: true, stdio: 'ignore' }); } async exchangeCodeForToken(authorizationCode, clientId, redirectUri) { const response = await fetch(`${LOCAL_MCP_URL}/oauth/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: authorizationCode, redirect_uri: redirectUri, client_id: clientId, code_verifier: this.codeVerifier }), agent: new https.Agent({ rejectUnauthorized: false }) }); if (response.ok) { const tokenData = await response.json(); this.accessToken = tokenData.access_token; console.log(`✅ Token obtained successfully`); return tokenData; } else { const error = await response.text(); throw new Error(`Token exchange failed: ${error}`); } } async makeApiCall(toolName, args, description) { const request = { jsonrpc: '2.0', method: 'tools/call', params: { name: toolName, arguments: args }, id: Math.floor(Math.random() * 1000) }; console.log(`\n📤 ${description}`); console.log(` Tool: ${toolName}`); console.log(` Arguments:`, JSON.stringify(args, null, 2)); const startTime = Date.now(); const response = await fetch(`${LOCAL_MCP_URL}/mcp`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.accessToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json, text/event-stream' }, body: JSON.stringify(request), agent: new https.Agent({ rejectUnauthorized: false }) }); const time = Date.now() - startTime; if (!response.ok) { console.log(`❌ ${description} FAILED: ${response.status}`); const error = await response.text(); console.log(' Error:', error); return null; } let data; const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('text/event-stream')) { const responseText = await response.text(); const lines = responseText.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { const jsonStr = line.substring(6).trim(); if (jsonStr && jsonStr !== '[DONE]') { try { data = JSON.parse(jsonStr); break; } catch (parseError) {} } } } } else { data = await response.json(); } console.log(`✅ ${description} SUCCESS (${time}ms)`); return data; } async traceApiKeyGeneration() { if (!this.accessToken) { console.log('❌ No bearer token available'); return false; } console.log(`\n🔍 TRACING API KEY GENERATION`); console.log(`🔑 Bearer Token: ${this.accessToken.substring(0, 50)}...`); console.log(`\n📋 Expected Result:`); console.log(` API Key: 57ade50e-c9a8-49f3-8ce7-28d44536a669:24223:1`); console.log(` Account Key: 24223`); console.log(` Division ID: 1`); console.log(` Customer: Bank Leumi BL Test Env`); try { // Step 1: Call the recommendations endpoint with specific query console.log('\n=== STEP 1: Call Recommendations with Bank Leumi Query ==='); const recommendationsData = await this.makeApiCall('api__api_v2_recommendations_list', { userQuery: 'show me recommendations for Bank Leumi BL Test Env', daysBack: 30, pageSize: 5, includeClosedAndDone: false }, 'Get recommendations with Bank Leumi query'); if (recommendationsData && recommendationsData.result && recommendationsData.result.content) { const text = recommendationsData.result.content[0]?.text || ''; // Extract detected customer info const customerMatch = text.match(/\*\*Customer:\*\* ([^\n]+)/); const accountMatch = text.match(/account[^0-9]*([0-9]+)/i); if (customerMatch) { console.log(`\n🎯 Detected Customer: ${customerMatch[1]}`); } if (accountMatch) { console.log(`🔑 Detected Account Key: ${accountMatch[1]}`); } } // Step 2: Check available customers from plain-sub-users console.log('\n=== STEP 2: Get Available Customers ==='); const customersData = await this.makeApiCall('api__users_plain_sub_users', { userQuery: 'Bank Leumi' }, 'Get customer divisions for Bank Leumi'); if (customersData && customersData.result && customersData.result.content) { const text = customersData.result.content[0]?.text || ''; console.log('\n📊 Customer Data:'); // Extract Bank Leumi accounts const bankLeumiSection = text.match(/Bank Leumi[^\n]*\n([^]*?)(?=\n\n|\n\*\*|$)/); if (bankLeumiSection) { console.log(bankLeumiSection[0]); } } // Step 3: Try different parameter combinations console.log('\n=== STEP 3: Test Different Parameter Combinations ==='); // Test with customer_account_key directly console.log('\n--- Test A: With customer_account_key=24223 ---'); await this.makeApiCall('api__api_v2_recommendations_list', { customer_account_key: '24223', customer_division_id: '1', daysBack: 30, pageSize: 5 }, 'Test with explicit customer_account_key'); // Test with accountId and divisionId console.log('\n--- Test B: With accountId and divisionId ---'); await this.makeApiCall('api__api_v2_recommendations_list', { accountId: '009671033607', // AWS account ID for Bank Leumi divisionId: '1', daysBack: 30, pageSize: 5 }, 'Test with accountId and divisionId'); // Step 4: Check what the server logs show console.log('\n=== STEP 4: Analysis ==='); console.log('🔍 Check the server logs for:'); console.log(' 1. [MSP-CHECK] messages to see if customer detection runs'); console.log(' 2. [CUSTOMER-DETECTION] messages to see pattern matching'); console.log(' 3. [API-KEY] messages to see how the key is built'); console.log(' 4. "Using API key" messages to see final key format'); console.log('\n📝 Key Questions:'); console.log(' - Is authMethod set correctly for OAuth sessions?'); console.log(' - Is customer detection logic running?'); console.log(' - Are customer_account_key and customer_division_id being passed to API client?'); console.log(' - Is getAuthHeaders receiving the customer parameters?'); console.log('\n✅ API Key Trace Complete!'); console.log('📋 Check server logs for detailed trace information'); return true; } catch (error) { console.log('❌ Trace Error:', error.message); return false; } } cleanup() { if (this.server) { this.server.close(); } } async run() { try { console.log('🔍 API Key Generation Tracer Starting...\n'); const serverPromise = this.startCallbackServer(); const { clientId, redirectUri } = await this.registerOAuthClient(); const flowStarted = await this.performOAuthFlow(clientId, redirectUri); if (!flowStarted) { throw new Error('Failed to start OAuth flow'); } console.log('⏳ Waiting for authentication...'); console.log(' Please login with: david+allcloud@umbrellacost.com'); const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('OAuth timeout after 5 minutes')), 300000) ); const authorizationCode = await Promise.race([serverPromise, timeoutPromise]); if (authorizationCode) { const tokenData = await this.exchangeCodeForToken(authorizationCode, clientId, redirectUri); if (tokenData) { await this.traceApiKeyGeneration(); } } } catch (error) { console.error('❌ Error:', error.message); } finally { this.cleanup(); } } } // Handle graceful shutdown process.on('SIGINT', () => { console.log('\n🛑 Interrupted - cleaning up...'); process.exit(0); }); const tracer = new ApiKeyTracer(); tracer.run();

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