Skip to main content
Glama
final-test-corrected-tool.cjs11.6 kB
#!/usr/bin/env node // Final test with corrected tool name after identifying the exact issue 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 FinalCorrectedTest { constructor() { this.username = 'david+allcloud@umbrellacost.com'; this.password = 'Dsamsung1!'; this.accessToken = null; this.server = null; this.port = 3006; // Different port to avoid conflicts this.codeVerifier = null; } async startCallbackServer() { return new Promise((resolve) => { const app = express(); app.get('/', (req, res) => { res.send(` <html> <head><title>Final Corrected Tool Test</title></head> <body style="font-family: Arial; text-align: center; padding: 50px;"> <h1>🎯 Testing api__api_v2_recommendations_list</h1> <p><strong>Final test with correct tool name</strong></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>Testing with correct tool name...</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: 'Final Corrected Tool Test Client', 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: 'final_corrected_test', 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(`📤 ${description}`); console.log(` Tool Name: ${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 runFinalTest() { if (!this.accessToken) { console.log('❌ No bearer token available'); return false; } console.log(`\n🎯 FINAL TEST: Corrected Tool Name`); console.log(`🔑 Bearer Token: ${this.accessToken.substring(0, 50)}...`); console.log(`\n🔧 Testing with CORRECT tool name: api__api_v2_recommendations_list`); try { // Test 1: Bank Leumi BL Test Env specific query console.log('\n📍 TEST 1: Bank Leumi BL Test Env Query'); const recommendationsData = await this.makeApiCall('api__api_v2_recommendations_list', { userQuery: 'show me recommendations for Bank Leumi BL Test Env', filters: { date_range: { start_date: '2024-08-01', end_date: '2024-12-31' } }, sort: [{ by: 'potential_savings', order: 'desc' }], page_size: 25 }, 'Bank Leumi BL Test Env recommendations (CORRECT TOOL)'); if (recommendationsData) { console.log('\n📊 RESULT ANALYSIS:'); if (recommendationsData.result && recommendationsData.result.content) { const text = recommendationsData.result.content[0]?.text || ''; console.log('✅ Recommendations received successfully!'); console.log(`📄 Response length: ${text.length} characters`); // Check for customer detection success const customerMatch = text.match(/\*\*Customer:\*\* ([^\n]+)/); if (customerMatch) { console.log(`🎯 Detected Customer: ${customerMatch[1]}`); if (customerMatch[1].includes('BL Test Env')) { console.log(`✅ SUCCESS: Correctly identified BL Test Env!`); } else { console.log(`⚠️ Customer detected but not BL Test Env: ${customerMatch[1]}`); } } // Check for recommendations content const recsMatch = text.match(/Total Recommendations:\*\* (\d+)/); if (recsMatch) { console.log(`📊 Total Recommendations: ${recsMatch[1]}`); } // Show first part of response console.log('\n📄 Response Preview:'); console.log(text.substring(0, 500) + '...'); } else { console.log('❌ No content in recommendations response'); console.log('Full response:', JSON.stringify(recommendationsData, null, 2)); } } else { console.log('❌ No recommendations data received'); } // Test 2: List available tools to confirm correct name console.log('\n📍 TEST 2: List Available Tools'); const toolsData = await this.makeApiCall('tools/list', {}, 'List all available tools'); if (toolsData && toolsData.result && toolsData.result.tools) { console.log('\n🔧 AVAILABLE RECOMMENDATION TOOLS:'); toolsData.result.tools .filter(tool => tool.name.includes('recommendation')) .forEach(tool => { console.log(` ✅ ${tool.name}: ${tool.description}`); }); } console.log('\n✅ Final Test Complete!'); return true; } catch (error) { console.log('❌ Test Error:', error.message); return false; } } cleanup() { if (this.server) { this.server.close(); } } async run() { try { console.log('🎯 Final Corrected Tool Test 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.runFinalTest(); } } } 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 test = new FinalCorrectedTest(); test.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