Skip to main content
Glama
debug-live-issue.js•6.5 kB
#!/usr/bin/env node import dotenv from 'dotenv'; import { JiraOAuthManager } from './dist/src/auth/oauth-manager.js'; // Load environment variables dotenv.config(); /** * Live Issue Debugger * Simulates the exact issue happening in production */ async function debugLiveIssue() { console.log('šŸ” ============ LIVE ISSUE DEBUGGING ============'); console.log('Analyzing why "Invalid or expired OAuth state parameter" still occurs...\n'); try { // Simulate the exact flow that's failing console.log('šŸ“‹ Step 1: Simulating OAuth URL Generation (start_oauth tool)...'); // This simulates what happens when user runs start_oauth const config = { companyUrl: 'https://codegenie.atlassian.net', userEmail: 'chiragbolarworkspace@gmail.com', authMethod: 'oauth' }; const oauthConfig = { clientId: process.env.OAUTH_CLIENT_ID || process.env.JIRA_OAUTH_CLIENT_ID, clientSecret: process.env.OAUTH_CLIENT_SECRET || process.env.JIRA_OAUTH_CLIENT_SECRET, redirectUri: process.env.OAUTH_REDIRECT_URI || `${process.env.SERVER_URL || 'http://localhost:3000'}/oauth/callback`, }; console.log('šŸ”§ OAuth Config:', { clientId: oauthConfig.clientId ? 'Present' : 'Missing', clientSecret: oauthConfig.clientSecret ? 'Present' : 'Missing', redirectUri: oauthConfig.redirectUri }); const oauthManager1 = JiraOAuthManager.getInstance(config.companyUrl, oauthConfig); const { authUrl, state } = oauthManager1.generateAuthUrl(config.userEmail); console.log(`āœ… Generated OAuth URL with state: ${state}`); console.log(`šŸ”— Redirect URI in URL: ${oauthConfig.redirectUri}`); console.log('\nšŸ“‹ Step 2: Simulating time delay (user completes OAuth in browser)...'); // Simulate the time that passes while user completes OAuth await new Promise(resolve => setTimeout(resolve, 1000)); console.log('\nšŸ“‹ Step 3: Simulating OAuth Callback (what happens when Atlassian redirects)...'); // This simulates what happens in the OAuth callback const simulatedCode = 'test_authorization_code_123'; const simulatedState = state; // Same state from URL generation console.log(`šŸ“ Callback receives - Code: ${simulatedCode}, State: ${simulatedState}`); // Create a NEW OAuth manager instance (this is what happens in callback) // This simulates the potential issue - different process/instance console.log('\nšŸ”§ Creating NEW OAuth manager for callback (simulating separate process)...'); const callbackOAuthManager = JiraOAuthManager.getInstance(process.env.JIRA_URL || 'https://codegenie.atlassian.net', { clientId: process.env.OAUTH_CLIENT_ID || process.env.JIRA_OAUTH_CLIENT_ID, clientSecret: process.env.OAUTH_CLIENT_SECRET || process.env.JIRA_OAUTH_CLIENT_SECRET, redirectUri: process.env.OAUTH_REDIRECT_URI || `${process.env.SERVER_URL || 'http://localhost:3000'}/oauth/callback`, }); const sameInstance = oauthManager1 === callbackOAuthManager; console.log(`šŸ”— Same OAuth manager instance: ${sameInstance}`); if (!sameInstance) { console.log('āš ļø POTENTIAL ISSUE: Different OAuth manager instances detected!'); console.log(' This could indicate separate processes/containers in Smithery'); } console.log('\nšŸ“‹ Step 4: Testing session lookup...'); // Try to find the session - this is where the error happens try { // This will trigger the detailed session lookup logging const tokenResponse = await callbackOAuthManager.exchangeCodeForToken(simulatedCode, simulatedState); console.log('āœ… Token exchange would succeed'); } catch (error) { console.log('āŒ Token exchange failed with error:', error.message); if (error.message.includes('Invalid or expired OAuth state parameter')) { console.log('\nšŸŽÆ ROOT CAUSE IDENTIFIED: OAuth state parameter not found during callback'); console.log('\nPossible reasons:'); console.log('1. Sessions stored in URL generation process not accessible in callback process'); console.log('2. Different OAuth manager instances not sharing session store'); console.log('3. Session TTL expired between URL generation and callback'); console.log('4. Environment variables different between processes'); console.log('5. File/memory storage not persistent across Smithery containers'); } } console.log('\nšŸ“‹ Step 5: Analyzing session storage state...'); // Check all storage locations const memoryStore = JiraOAuthManager.sessionStore || new Map(); console.log(`šŸ’¾ Memory store size: ${memoryStore.size}`); console.log(`šŸ’¾ Memory sessions: [${Array.from(memoryStore.keys()).join(', ')}]`); const envSessions = Object.keys(process.env).filter(key => key.startsWith('OAUTH_SESSION_')); console.log(`šŸŒ Environment sessions: ${envSessions.length}`); console.log(`šŸŒ Environment states: [${envSessions.map(key => key.replace('OAUTH_SESSION_', '')).join(', ')}]`); const globalSessions = globalThis.oauthSessions; console.log(`🌐 Global sessions: ${globalSessions ? globalSessions.size : 0}`); // Check for session expiry const sessionAge = Date.now() - Date.now(); // This session was just created const TTL = 15 * 60 * 1000; // 15 minutes console.log(`ā° Session age: ${sessionAge}ms (TTL: ${TTL}ms)`); console.log('\nšŸ“‹ Step 6: Environment analysis...'); console.log(`šŸŒ NODE_ENV: ${process.env.NODE_ENV || 'not set'}`); console.log(`šŸŒ SMITHERY_HOSTNAME: ${process.env.SMITHERY_HOSTNAME || 'not set'}`); console.log(`šŸŒ SERVER_URL: ${process.env.SERVER_URL || 'not set'}`); console.log(`šŸŒ Process PID: ${process.pid}`); console.log('\nšŸŽÆ RECOMMENDATIONS:'); console.log('1. Check Smithery logs for "TOKEN EXCHANGE DEBUG START" messages'); console.log('2. Look for "SESSION STORAGE DEBUG" during start_oauth execution'); console.log('3. Verify same redirect URI in both URL generation and callback'); console.log('4. Confirm OAuth manager singleton working across processes'); console.log('5. Check if Smithery uses separate containers for MCP vs HTTP'); } catch (error) { console.error('\nāŒ Debug simulation failed:', error); } } // Run the live issue debugger debugLiveIssue().catch(console.error);

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/CHIBOLAR/jira_mcp_sprinthealth'

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