@@ -7,6 +7,7 @@ import fs from 'node:fs/promises';
77import  os  from  'node:os' ; 
88import  path  from  'node:path' ; 
99
10+ import  { extractUrlLikeFromDevToolsTitle ,  urlsEqual }  from  './DevtoolsUtils.js' ; 
1011import  type  { ListenerMap }  from  './PageCollector.js' ; 
1112import  { NetworkCollector ,  PageCollector }  from  './PageCollector.js' ; 
1213import  { Locator }  from  './third_party/index.js' ; 
@@ -40,8 +41,8 @@ export interface TextSnapshot {
4041} 
4142
4243interface  McpContextOptions  { 
43-   // Whether the DevTools windows are exposed as pages. 
44-   devtools : boolean ; 
44+   // Whether the DevTools windows are exposed as pages for debugging of DevTools . 
45+   experimentalDevToolsDebugging : boolean ; 
4546} 
4647
4748const  DEFAULT_TIMEOUT  =  5_000 ; 
@@ -82,6 +83,7 @@ export class McpContext implements Context {
8283
8384  // The most recent page state. 
8485  #pages: Page [ ]  =  [ ] ; 
86+   #pageToDevToolsPage =  new  Map < Page ,  Page > ( ) ; 
8587  #selectedPageIdx =  0 ; 
8688  // The most recent snapshot. 
8789  #textSnapshot: TextSnapshot  |  null  =  null ; 
@@ -324,19 +326,50 @@ export class McpContext implements Context {
324326   * Creates a snapshot of the pages. 
325327   */ 
326328  async  createPagesSnapshot ( ) : Promise < Page [ ] >  { 
327-     this . #pages =  ( await  this . browser . pages ( ) ) . filter ( page  =>  { 
328-       if  ( page . url ( ) . startsWith ( 'devtools://' ) )  { 
329-         return  this . #options. devtools ; 
329+     const  allPages  =  await  this . browser . pages ( ) ; 
330+ 
331+     this . #pages =  allPages . filter ( page  =>  { 
332+       // If we allow debugging DevTools windows, return all pages. 
333+       if  ( this . #options. experimentalDevToolsDebugging )  { 
334+         return  true ; 
330335      } 
331-       return  true ; 
336+       // If we are in regular mode, the user should only see non-DevTools page. 
337+       return  ! page . url ( ) . startsWith ( 'devtools://' ) ; 
332338    } ) ; 
339+ 
340+     await  this . #detectOpenDevToolsWindows( allPages ) ; 
341+ 
333342    return  this . #pages; 
334343  } 
335344
345+   async  #detectOpenDevToolsWindows( pages : Page [ ] )  { 
346+     this . #pageToDevToolsPage =  new  Map < Page ,  Page > ( ) ; 
347+     for  ( const  devToolsPage  of  pages )  { 
348+       if  ( devToolsPage . url ( ) . startsWith ( 'devtools://' ) )  { 
349+         const  session  =  await  devToolsPage . createCDPSession ( ) ; 
350+         const  data  =  await  session . send ( 'Target.getTargetInfo' ) ; 
351+         const  devtoolsPageTitle  =  data . targetInfo . title ; 
352+         const  urlLike  =  extractUrlLikeFromDevToolsTitle ( devtoolsPageTitle ) ; 
353+         if  ( ! urlLike )  { 
354+           continue ; 
355+         } 
356+         for  ( const  page  of  this . #pages)  { 
357+           if  ( urlsEqual ( page . url ( ) ,  urlLike ) )  { 
358+             this . #pageToDevToolsPage. set ( page ,  devToolsPage ) ; 
359+           } 
360+         } 
361+       } 
362+     } 
363+   } 
364+ 
336365  getPages ( ) : Page [ ]  { 
337366    return  this . #pages; 
338367  } 
339368
369+   getDevToolsPage ( page : Page ) : Page  |  undefined  { 
370+     return  this . #pageToDevToolsPage. get ( page ) ; 
371+   } 
372+ 
340373  /** 
341374   * Creates a text snapshot of a page. 
342375   */ 
0 commit comments