diff --git a/.changeset/mcp-oauth-popup-close-delay.md b/.changeset/mcp-oauth-popup-close-delay.md new file mode 100644 index 000000000..7fdcc46ad --- /dev/null +++ b/.changeset/mcp-oauth-popup-close-delay.md @@ -0,0 +1,5 @@ +--- +"@truefoundry/trueforge-ui": patch +--- + +Stop the MCP OAuth opener from closing the popup as soon as the callback broadcasts, so the success/failure screen can show before the popup closes itself. diff --git a/packages/trueforge-ui/src/hooks/useMcpAuth.ts b/packages/trueforge-ui/src/hooks/useMcpAuth.ts index a7d52c735..5839a1d4c 100644 --- a/packages/trueforge-ui/src/hooks/useMcpAuth.ts +++ b/packages/trueforge-ui/src/hooks/useMcpAuth.ts @@ -104,16 +104,21 @@ export const useMCPAuth = ({ callbackPath }: UseMCPAuthOptions = {}) => { }) => { const channel = new BroadcastChannel(MCP_AUTH_POPUP_CHANNEL); let popup: Window | null = null; - const cleanup = () => { + // Close the channel on result; leave the popup open so the callback screen can show + // success/failure and close itself. + const cleanupChannel = () => { channel.close(); + popupCleanupRef.current.delete(cleanupWithPopup); + }; + const cleanupWithPopup = () => { + cleanupChannel(); popup?.close(); - popupCleanupRef.current.delete(cleanup); }; channel.onmessage = (event: MessageEvent) => { if (!isPopupMessage(event.data) || event.data.popupUid !== popupUid) return; const { isSuccess } = event.data; - cleanup(); + cleanupChannel(); if (!isSuccess) { if (activeAttemptsRef.current.delete(attempt)) callback(false); return; @@ -122,11 +127,11 @@ export const useMCPAuth = ({ callbackPath }: UseMCPAuthOptions = {}) => { activeAttemptsRef.current.delete(attempt); }); }; - popupCleanupRef.current.add(cleanup); + popupCleanupRef.current.add(cleanupWithPopup); popup = window.open(authorizationEndpoint, '_blank', 'popup=true'); if (!popup) { - cleanup(); + cleanupWithPopup(); throw new Error('Popup blocked. Please allow pop-ups to authorize the MCP server.'); } diff --git a/packages/trueforge-ui/test/hooks/useMcpAuth.test.ts b/packages/trueforge-ui/test/hooks/useMcpAuth.test.ts index cd1e89386..c8fde6e37 100644 --- a/packages/trueforge-ui/test/hooks/useMcpAuth.test.ts +++ b/packages/trueforge-ui/test/hooks/useMcpAuth.test.ts @@ -215,7 +215,7 @@ describe('useMCPAuth', () => { expect(callback).toHaveBeenCalledOnce(); expect(callback).toHaveBeenCalledWith(true); expect(channel.close).toHaveBeenCalledOnce(); - expect(close).toHaveBeenCalledOnce(); + expect(close).not.toHaveBeenCalled(); expect(showError).not.toHaveBeenCalled(); });