Skip to main content
Glama
multi-tenant-demo.tsβ€’6.96 kB
#!/usr/bin/env node import dotenv from 'dotenv'; import { UserSessionManager } from './user-session-manager.js'; dotenv.config(); async function demonstrateMultiTenantFunctionality() { console.log('πŸ§ͺ MULTI-TENANT AUTHENTICATION DEMO'); console.log('====================================='); console.log(`πŸ“… Demo Time: ${new Date().toISOString()}\n`); const baseURL = process.env.UMBRELLA_API_BASE_URL || 'https://api.umbrellacost.io/api/v1'; const sessionManager = new UserSessionManager(baseURL); // Test credentials from .env const user1 = { username: process.env.UMBRELLA_TEST_MSP_USERNAME || 'elisha@umbrellacost.cloud', password: process.env.UMBRELLA_TEST_MSP_PASSWORD || '6K2UX6DoYSgV%E' }; const user2 = { username: process.env.UMBRELLA_TEST_DIRECT_USERNAME || 'elisha@umbrellacost.net', password: process.env.UMBRELLA_TEST_DIRECT_PASSWORD || 'G37oi57Kp@cNzx' }; console.log('πŸ‘₯ TESTING MULTI-USER AUTHENTICATION'); console.log('=====================================\n'); // Test 1: Authenticate first user console.log(`1️⃣ Authenticating User 1: ${user1.username}`); const auth1 = await sessionManager.authenticateUser(user1); console.log(` Result: ${auth1.success ? 'βœ… Success' : '❌ Failed'}`); if (auth1.success) { console.log(` Session ID: ${auth1.sessionId}`); } else { console.log(` Error: ${auth1.error}`); } // Test 2: Authenticate second user console.log(`\n2️⃣ Authenticating User 2: ${user2.username}`); const auth2 = await sessionManager.authenticateUser(user2); console.log(` Result: ${auth2.success ? 'βœ… Success' : '❌ Failed'}`); if (auth2.success) { console.log(` Session ID: ${auth2.sessionId}`); } else { console.log(` Error: ${auth2.error}`); } // Test 3: Check session status console.log(`\n3️⃣ Checking Active Sessions`); const activeSessions = sessionManager.getActiveSessions(); console.log(` Active Sessions: ${activeSessions.length}`); activeSessions.forEach((session, index) => { console.log(` ${index + 1}. ${session.username} - Last active: ${session.lastActivity.toISOString()}`); }); // Test 4: Test API calls with different users console.log(`\n4️⃣ Testing API Calls with Different Users`); if (auth1.success) { console.log(`\n πŸ” User 1 (${user1.username}) - Service Names API:`); const session1 = sessionManager.getUserSessionByUsername(user1.username); if (session1) { try { const response1 = await session1.apiClient.makeRequest('/invoices/service-names/distinct', { limit: 5 }); if (response1.success) { console.log(` βœ… Success: ${Array.isArray(response1.data) ? response1.data.length : 'data'} items`); if (Array.isArray(response1.data) && response1.data.length > 0) { console.log(` πŸ“Š Sample: ${response1.data[0]}`); } } else { console.log(` ❌ Failed: ${response1.error}`); } } catch (error: any) { console.log(` πŸ’₯ Error: ${error.message}`); } } } if (auth2.success) { console.log(`\n πŸ” User 2 (${user2.username}) - Recommendations API:`); const session2 = sessionManager.getUserSessionByUsername(user2.username); if (session2) { try { const response2 = await session2.apiClient.makeRequest('/recommendations/report'); if (response2.success) { console.log(` βœ… Success: ${Array.isArray(response2.data) ? response2.data.length : 'data'} items`); if (Array.isArray(response2.data) && response2.data.length > 0) { console.log(` πŸ“Š Report: ${response2.data[0].reportName || 'Unnamed'}`); } } else { console.log(` ❌ Failed: ${response2.error}`); } } catch (error: any) { console.log(` πŸ’₯ Error: ${error.message}`); } } } // Test 5: Session statistics console.log(`\n5️⃣ Session Statistics`); const stats = sessionManager.getStats(); console.log(` Total Sessions: ${stats.totalSessions}`); console.log(` Active Sessions: ${stats.activeSessions}`); console.log(` Expired Sessions: ${stats.expiredSessions}`); // Test 6: Logout specific user console.log(`\n6️⃣ Testing Logout Functionality`); if (auth1.success) { console.log(` Logging out User 1: ${user1.username}`); const loggedOut = sessionManager.removeUserSession(user1.username); console.log(` Result: ${loggedOut ? 'βœ… Success' : '❌ Failed'}`); const updatedSessions = sessionManager.getActiveSessions(); console.log(` Remaining Active Sessions: ${updatedSessions.length}`); } // Test 7: Try to use logged out session console.log(`\n7️⃣ Testing Access After Logout`); const loggedOutSession = sessionManager.getUserSessionByUsername(user1.username); console.log(` User 1 Session After Logout: ${loggedOutSession ? '❌ Still exists' : 'βœ… Properly removed'}`); // Test 8: Session cleanup simulation console.log(`\n8️⃣ Testing Session Timeout (Simulated)`); if (auth2.success) { const session2 = sessionManager.getUserSessionByUsername(user2.username); if (session2) { // Simulate old activity session2.lastActivity = new Date(Date.now() - 35 * 60 * 1000); // 35 minutes ago console.log(` Simulated User 2 inactive for 35 minutes`); // Try to get session (should fail due to timeout) const expiredSession = sessionManager.getUserSession(session2.id); console.log(` Session retrieval after timeout: ${expiredSession ? '❌ Should have expired' : 'βœ… Properly expired'}`); } } // Cleanup console.log(`\n9️⃣ Final Cleanup`); sessionManager.shutdown(); console.log(` βœ… Session manager shutdown complete`); console.log(`\n${'='.repeat(50)}`); console.log('πŸŽ‰ MULTI-TENANT DEMO COMPLETED SUCCESSFULLY!'); console.log(`${'='.repeat(50)}`); console.log('\nπŸ’‘ KEY FEATURES DEMONSTRATED:'); console.log(' βœ… Multiple users can authenticate simultaneously'); console.log(' βœ… Each user has their own isolated session'); console.log(' βœ… API calls are properly scoped to individual users'); console.log(' βœ… Session management (create, retrieve, remove)'); console.log(' βœ… Automatic session timeout and cleanup'); console.log(' βœ… Graceful shutdown and resource cleanup'); console.log('\nπŸš€ PRODUCTION BENEFITS:'); console.log(' πŸ“Š Multiple Claude Desktop users can share one MCP server'); console.log(' πŸ”’ Each user sees only their own Umbrella Cost data'); console.log(' ⚑ Efficient resource usage with shared server infrastructure'); console.log(' πŸ›‘οΈ Automatic security through session isolation'); console.log(' 🧹 Built-in session cleanup prevents memory leaks'); } // Run the demo demonstrateMultiTenantFunctionality().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