chrome-devtools-mcp-for-extension 0.8.8 → 0.8.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -448,7 +448,7 @@ export const toggleExtensionState = defineTool({
448
448
  });
449
449
  export const openExtensionPopup = defineTool({
450
450
  name: 'open_extension_popup',
451
- description: `Select an already-opened Chrome extension popup window for testing. The user should manually click the extension icon first to open the popup, then this tool will detect and select it. After selection, you can use take_snapshot, click, evaluate_script, etc. on the popup.`,
451
+ description: `Select an already-opened Chrome extension popup window for testing. If no extension name is provided, it will automatically detect and select the currently active popup window. If an extension name is provided, it will search for that specific extension's popup. After selection, you can use take_snapshot, click, evaluate_script, etc. on the popup.`,
452
452
  annotations: {
453
453
  category: ToolCategories.EXTENSION_DEVELOPMENT,
454
454
  readOnlyHint: false,
@@ -456,12 +456,68 @@ export const openExtensionPopup = defineTool({
456
456
  schema: {
457
457
  extensionName: z
458
458
  .string()
459
- .describe('The name or partial name of the extension'),
459
+ .optional()
460
+ .describe('(Optional) The name or partial name of the extension. If omitted, will use the currently active popup.'),
460
461
  },
461
462
  handler: async (request, response, context) => {
462
463
  const page = context.getSelectedPage();
463
464
  const { extensionName } = request.params;
464
465
  await context.waitForEventsAfterAction(async () => {
466
+ const browser = page.browser();
467
+ if (!browser) {
468
+ response.appendResponseLine('❌ Failed to get browser instance.');
469
+ return;
470
+ }
471
+ // If no extension name provided, check if current page is already a popup
472
+ if (!extensionName) {
473
+ const currentUrl = page.url();
474
+ if (currentUrl.startsWith('chrome-extension://')) {
475
+ response.appendResponseLine('✅ Already on an extension popup window');
476
+ response.appendResponseLine(`📄 Popup URL: ${currentUrl}`);
477
+ response.appendResponseLine('');
478
+ response.appendResponseLine('💡 You can now use take_snapshot, click, evaluate_script, etc. on the popup');
479
+ return;
480
+ }
481
+ // Check for iframe-embedded popup in current page
482
+ const iframePopups = await page.evaluate(() => {
483
+ return Array.from(document.querySelectorAll('iframe'))
484
+ .filter((iframe) => iframe.src.startsWith('chrome-extension://'))
485
+ .map((iframe) => ({
486
+ src: iframe.src,
487
+ id: iframe.id,
488
+ className: iframe.className,
489
+ }));
490
+ });
491
+ if (iframePopups.length > 0) {
492
+ response.appendResponseLine('✅ Extension popup found (embedded as iframe)');
493
+ response.appendResponseLine(`📄 Popup URL: ${iframePopups[0].src}`);
494
+ response.appendResponseLine('');
495
+ response.appendResponseLine('💡 This popup is embedded in the current page as an iframe.');
496
+ response.appendResponseLine(' You can interact with it using regular page tools:');
497
+ response.appendResponseLine(' - take_snapshot (includes iframe content)');
498
+ response.appendResponseLine(' - click on elements');
499
+ response.appendResponseLine(' - fill forms');
500
+ response.appendResponseLine(' - evaluate_script');
501
+ return;
502
+ }
503
+ // If not on popup or iframe, try to find any open popup window
504
+ const pages = await browser.pages();
505
+ for (let i = 0; i < pages.length; i++) {
506
+ const p = pages[i];
507
+ const url = p.url();
508
+ if (url.startsWith('chrome-extension://')) {
509
+ context.setSelectedPageIdx(i);
510
+ response.appendResponseLine('✅ Found and selected open popup window');
511
+ response.appendResponseLine(`📄 Popup URL: ${url}`);
512
+ response.appendResponseLine('');
513
+ response.appendResponseLine('💡 You can now use take_snapshot, click, evaluate_script, etc. on the popup');
514
+ return;
515
+ }
516
+ }
517
+ response.appendResponseLine('❌ No extension popup window found.');
518
+ response.appendResponseLine('💡 Please manually click the extension icon to open the popup first.');
519
+ return;
520
+ }
465
521
  // First, get extension ID
466
522
  await page.goto('chrome://extensions/', { waitUntil: 'networkidle0' });
467
523
  const extensionInfo = await page.evaluate((searchName) => {
@@ -515,6 +571,32 @@ export const openExtensionPopup = defineTool({
515
571
  }
516
572
  }
517
573
  if (!popupPage) {
574
+ // Check for iframe-embedded popup with this extension ID
575
+ response.appendResponseLine('🔧 Checking for iframe-embedded popup...');
576
+ // Go back to the original page to check for iframes
577
+ await page.goBack();
578
+ const iframePopups = await page.evaluate((extId) => {
579
+ return Array.from(document.querySelectorAll('iframe'))
580
+ .filter((iframe) => iframe.src.includes(extId))
581
+ .map((iframe) => ({
582
+ src: iframe.src,
583
+ id: iframe.id,
584
+ className: iframe.className,
585
+ }));
586
+ }, extensionInfo.id);
587
+ if (iframePopups.length > 0) {
588
+ response.appendResponseLine('');
589
+ response.appendResponseLine(`✅ Extension popup found (embedded as iframe): ${extensionInfo.name}`);
590
+ response.appendResponseLine(`📄 Popup URL: ${iframePopups[0].src}`);
591
+ response.appendResponseLine('');
592
+ response.appendResponseLine('💡 This popup is embedded in the current page as an iframe.');
593
+ response.appendResponseLine(' You can interact with it using regular page tools:');
594
+ response.appendResponseLine(' - take_snapshot (includes iframe content)');
595
+ response.appendResponseLine(' - click on elements');
596
+ response.appendResponseLine(' - fill forms');
597
+ response.appendResponseLine(' - evaluate_script');
598
+ return;
599
+ }
518
600
  response.appendResponseLine('❌ Popup window not found.');
519
601
  response.appendResponseLine('💡 Please manually click the extension icon to open the popup first.');
520
602
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-devtools-mcp-for-extension",
3
- "version": "0.8.8",
3
+ "version": "0.8.10",
4
4
  "description": "MCP server for Chrome extension development with Web Store automation. Fork of chrome-devtools-mcp with extension-specific tools.",
5
5
  "type": "module",
6
6
  "bin": "./build/src/index.js",