@@ -333,6 +333,48 @@ describe('MCP server refresh route', () => {
333333 expect ( mockUpdate ) . not . toHaveBeenCalled ( )
334334 } )
335335
336+ it . each ( [ 'unavailable' , 'winner-cache' ] as const ) (
337+ 'preserves a newer cache invalidation over %s discovery tools' ,
338+ async ( state ) => {
339+ mockDiscoverServerTools . mockResolvedValueOnce ( {
340+ tools : [
341+ {
342+ name : 'stale-search' ,
343+ description : 'Search tool loaded before invalidation' ,
344+ inputSchema : { } ,
345+ serverId : 'server-1' ,
346+ serverName : 'OAuth Server' ,
347+ } ,
348+ ] ,
349+ state,
350+ } )
351+ const cacheInvalidatedServer = {
352+ ...initialServer ,
353+ lastToolsRefresh : new Date ( initialServer . lastToolsRefresh . getTime ( ) + 60_000 ) ,
354+ toolCount : 0 ,
355+ }
356+ mockSelect . mockReturnValueOnce ( selectRows ( [ cacheInvalidatedServer ] ) )
357+
358+ const request = new Request ( 'http://localhost/api/mcp/servers/server-1/refresh' , {
359+ method : 'POST' ,
360+ } ) as NextRequest
361+ const response = await POST ( request , { params : Promise . resolve ( { id : 'server-1' } ) } )
362+ const body = await response . json ( )
363+
364+ expect ( body . data ) . toEqual (
365+ expect . objectContaining ( {
366+ status : 'connected' ,
367+ error : null ,
368+ toolCount : 0 ,
369+ workflowsUpdated : 0 ,
370+ updatedWorkflowIds : [ ] ,
371+ } )
372+ )
373+ expect ( mockSelect ) . toHaveBeenCalledTimes ( 2 )
374+ expect ( mockUpdate ) . not . toHaveBeenCalled ( )
375+ }
376+ )
377+
336378 it ( 'preserves a newer successful refresh when discovery is superseded' , async ( ) => {
337379 mockDiscoverServerTools . mockResolvedValueOnce ( {
338380 tools : [ ] ,
0 commit comments