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.
|
|
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
|
-
.
|
|
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.
|
|
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",
|