chrome-devtools-mcp-for-extension 0.8.7 → 0.8.9

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: `Open a Chrome extension's popup in a testable context. The popup will be opened as a page that can be interacted with using standard tools like take_snapshot, click, and evaluate_script.`,
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,46 @@ 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
+ // If not on popup, try to find any open popup
482
+ const pages = await browser.pages();
483
+ for (let i = 0; i < pages.length; i++) {
484
+ const p = pages[i];
485
+ const url = p.url();
486
+ if (url.startsWith('chrome-extension://')) {
487
+ context.setSelectedPageIdx(i);
488
+ response.appendResponseLine('✅ Found and selected open popup window');
489
+ response.appendResponseLine(`📄 Popup URL: ${url}`);
490
+ response.appendResponseLine('');
491
+ response.appendResponseLine('💡 You can now use take_snapshot, click, evaluate_script, etc. on the popup');
492
+ return;
493
+ }
494
+ }
495
+ response.appendResponseLine('❌ No extension popup window found.');
496
+ response.appendResponseLine('💡 Please manually click the extension icon to open the popup first.');
497
+ return;
498
+ }
465
499
  // First, get extension ID
466
500
  await page.goto('chrome://extensions/', { waitUntil: 'networkidle0' });
467
501
  const extensionInfo = await page.evaluate((searchName) => {
@@ -494,54 +528,38 @@ export const openExtensionPopup = defineTool({
494
528
  }
495
529
  response.appendResponseLine(`🔍 Found extension: ${extensionInfo.name} (${extensionInfo.id})`);
496
530
  try {
497
- // Find service worker target
498
531
  const browser = page.browser();
499
532
  if (!browser) {
500
533
  response.appendResponseLine('❌ Failed to get browser instance.');
501
534
  return;
502
535
  }
503
- const targets = await browser.targets();
504
- const workerTarget = targets.find((target) => target.type() === 'service_worker' &&
505
- target.url().includes(extensionInfo.id));
506
- if (!workerTarget) {
507
- response.appendResponseLine('❌ Service worker not found. Extension may not have a service worker (MV2 extensions are not supported).');
508
- return;
509
- }
510
- const worker = await workerTarget.worker();
511
- if (!worker) {
512
- response.appendResponseLine('❌ Failed to get service worker context.');
513
- return;
514
- }
515
- response.appendResponseLine('🔧 Opening popup via service worker...');
516
- // Open popup
517
- await worker.evaluate('chrome.action.openPopup();');
518
- // Wait for popup target
519
- const popupTarget = await browser.waitForTarget((target) => target.type() === 'page' &&
520
- target.url().includes(extensionInfo.id) &&
521
- target.url().includes('popup'), { timeout: 5000 });
522
- if (!popupTarget) {
523
- response.appendResponseLine('❌ Popup did not open within timeout.');
524
- return;
536
+ response.appendResponseLine('🔧 Looking for open popup window...');
537
+ // Get all pages
538
+ const pages = await browser.pages();
539
+ // Find popup page by URL (contains extension ID)
540
+ let popupPage = null;
541
+ let popupIndex = -1;
542
+ for (let i = 0; i < pages.length; i++) {
543
+ const p = pages[i];
544
+ const url = p.url();
545
+ if (url && url.includes(extensionInfo.id)) {
546
+ popupPage = p;
547
+ popupIndex = i;
548
+ break;
549
+ }
525
550
  }
526
- const popupPage = await popupTarget.page();
527
551
  if (!popupPage) {
528
- response.appendResponseLine('❌ Failed to get popup page reference.');
552
+ response.appendResponseLine('❌ Popup window not found.');
553
+ response.appendResponseLine('💡 Please manually click the extension icon to open the popup first.');
529
554
  return;
530
555
  }
531
- // Add popup page to context and select it
532
- const pages = await browser.pages();
533
- const popupIndex = pages.indexOf(popupPage);
534
- if (popupIndex !== -1) {
535
- context.setSelectedPageIdx(popupIndex);
536
- response.appendResponseLine('');
537
- response.appendResponseLine(`✅ Popup opened: ${extensionInfo.name}`);
538
- response.appendResponseLine(`📄 Popup URL: ${popupPage.url()}`);
539
- response.appendResponseLine('');
540
- response.appendResponseLine('💡 You can now use take_snapshot, click, evaluate_script, etc. on the popup');
541
- }
542
- else {
543
- response.appendResponseLine('⚠️ Popup opened but could not be selected automatically.');
544
- }
556
+ // Select the popup page
557
+ context.setSelectedPageIdx(popupIndex);
558
+ response.appendResponseLine('');
559
+ response.appendResponseLine(`✅ Popup window selected: ${extensionInfo.name}`);
560
+ response.appendResponseLine(`📄 Popup URL: ${popupPage.url()}`);
561
+ response.appendResponseLine('');
562
+ response.appendResponseLine('💡 You can now use take_snapshot, click, evaluate_script, etc. on the popup');
545
563
  }
546
564
  catch (error) {
547
565
  response.appendResponseLine(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-devtools-mcp-for-extension",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
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",