@@ -266,14 +266,21 @@ const config = {
266266async function connectWithAuthPrompt ( ) : Promise < {
267267 ok : boolean ;
268268 error ?: string ;
269+ authPending ?: boolean ;
269270} > {
270271 const result = await connectMCPServer ( config , {
271272 onAuthURL : ( ) => {
272273 authURLCount += 1 ;
273274 authEvents . push ( "authURL" ) ;
274275 } ,
275276 } ) ;
276- return result . ok ? { ok : true } : { ok : false , error : result . error } ;
277+ return result . ok
278+ ? { ok : true }
279+ : {
280+ ok : false ,
281+ error : result . error ,
282+ ...( result . authPending === true ? { authPending : true } : { } ) ,
283+ } ;
277284}
278285
279286describe ( "HTTP MCP re-auth loop prevention" , ( ) => {
@@ -755,6 +762,9 @@ describe("HTTP MCP re-auth loop prevention", () => {
755762 for ( let episode = 0 ; episode < 2 ; episode += 1 ) {
756763 const result = await connectWithAuthPrompt ( ) ;
757764 expect ( result . ok ) . toBe ( false ) ;
765+ // The cap is an unfinished authorization, not a dead server: the TUI
766+ // keeps the prompt-box auth marker rather than painting a failure row.
767+ expect ( result . authPending ) . toBe ( true ) ;
758768 expect ( result . error ) . toContain (
759769 `MCP authorization for linear failed after ${ MAX_BROWSER_AUTH_ATTEMPTS } ${ MAX_BROWSER_AUTH_ATTEMPTS === 1 ? "attempt" : "attempts" } ` ,
760770 ) ;
@@ -817,6 +827,7 @@ describe("HTTP MCP re-auth loop prevention", () => {
817827 expect ( await connectWithAuthPrompt ( ) ) . toEqual ( {
818828 ok : false ,
819829 error : expect . stringContaining ( "retrying paused" ) ,
830+ authPending : true ,
820831 } ) ;
821832 expect ( authURLCount ) . toBe ( MAX_BROWSER_AUTH_ATTEMPTS ) ;
822833
@@ -1008,14 +1019,26 @@ describe("HTTP MCP re-auth loop prevention", () => {
10081019 const result = await connectWithAuthPrompt ( ) ;
10091020
10101021 expect ( result . ok ) . toBe ( false ) ;
1022+ expect ( result . authPending ) . toBe ( true ) ;
10111023 expect ( result . error ) . toContain ( "timed out waiting for the browser" ) ;
10121024 expect ( result . error ) . toContain ( "disconnected" ) ;
10131025 expect ( authURLCount ) . toBe ( 1 ) ;
10141026 expect ( waitForCodeCalls ) . toBe ( 1 ) ;
10151027
10161028 const capped = await connectWithAuthPrompt ( ) ;
10171029 expect ( capped . ok ) . toBe ( false ) ;
1030+ expect ( capped . authPending ) . toBe ( true ) ;
10181031 expect ( capped . error ) . toContain ( "retrying paused" ) ;
10191032 expect ( authURLCount ) . toBe ( 1 ) ;
10201033 } ) ;
1034+
1035+ test ( "a failure that is not the authorization itself is not auth-pending" , async ( ) => {
1036+ connectFailuresLeft = Number . POSITIVE_INFINITY ;
1037+
1038+ const result = await connectWithAuthPrompt ( ) ;
1039+
1040+ expect ( result . ok ) . toBe ( false ) ;
1041+ expect ( result . error ) . toContain ( "finishAuth exploded" ) ;
1042+ expect ( result . authPending ) . toBeUndefined ( ) ;
1043+ } ) ;
10211044} ) ;
0 commit comments