diff --git a/src/react/useMcp.ts b/src/react/useMcp.ts index 6efab11..df1d6b2 100644 --- a/src/react/useMcp.ts +++ b/src/react/useMcp.ts @@ -19,7 +19,19 @@ const AUTH_TIMEOUT = 5 * 60 * 1000; // 5 minutes for user to complete auth in po * @param options Configuration options for connecting to the MCP server. * @returns State and functions for interacting with the MCP connection. */ +// Counter to track number of renders (for debugging infinite loops) +let renderCount = 0; +const MAX_RENDERS = 10; + export function useMcp(options: UseMcpOptions): UseMcpResult { + renderCount++; + console.log(`[useMcp] Hook rendered #${renderCount}`, Date.now()); + + // Stop infinite renders for debugging + if (renderCount > MAX_RENDERS) { + console.error('TOO MANY RENDERS DETECTED - STOPPING INFINITE LOOP'); + throw new Error('Infinite render loop detected in useMcp hook'); + } const { url, clientName, // Passed to BrowserOAuthClientProvider @@ -214,6 +226,14 @@ export function useMcp(options: UseMcpOptions): UseMcpResult { // ===== Connection Logic ===== const connect = useCallback(async () => { + console.log(`[useMcp] connect callback executed #${renderCount}`, Date.now()); + console.log(' → connect deps state:', { + url, + addLog: !!addLog, + failConnection: !!failConnection, + disconnect: !!disconnect, + state + }); if (connectingRef.current) { addLog('debug', 'Connection attempt already in progress, skipping.'); return; @@ -467,6 +487,13 @@ export function useMcp(options: UseMcpOptions): UseMcpResult { // Effect for handling auth callback messages from popup useEffect(() => { + console.log(`[useMcp] Auth callback effect executed #${renderCount}`, Date.now()); + console.log(' → Auth effect deps:', { + addLogChanged: !!addLog, + failConnectionChanged: !!failConnection, + disconnectChanged: !!disconnect, + connectChanged: !!connect + }); const messageHandler = (event: MessageEvent) => { // Security: Check origin if (event.origin !== window.location.origin) { @@ -511,6 +538,12 @@ export function useMcp(options: UseMcpOptions): UseMcpResult { // Effect for initial connection and auto-retry useEffect(() => { + console.log(`[useMcp] Initial connection effect executed #${renderCount}`, Date.now()); + console.log(' → Connect effect deps:', { + url, + storageKeyPrefix, + callbackUrl + }); // Store mount status isMountedRef.current = true; addLog('debug', 'Component mounted, initiating connection.'); @@ -536,6 +569,13 @@ export function useMcp(options: UseMcpOptions): UseMcpResult { // Effect for auto-retry logic useEffect(() => { + console.log(`[useMcp] Auto-retry effect executed #${renderCount}`, Date.now()); + console.log(' → Retry effect deps:', { + state, + autoRetry, + retry: !!retry, + addLog: !!addLog + }); let retryTimeoutId: number | null = null; if (state === 'failed' && autoRetry && connectAttemptRef.current > 0) { // Only retry if the *initial* connection or subsequent retries failed