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.
- package/build/src/tools/extensions.js +59 -41
- package/package.json +1 -1
|
@@ -448,7 +448,7 @@ export const toggleExtensionState = defineTool({
|
|
|
448
448
|
});
|
|
449
449
|
export const openExtensionPopup = defineTool({
|
|
450
450
|
name: 'open_extension_popup',
|
|
451
|
-
description: `
|
|
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
|
-
.
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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('❌
|
|
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
|
-
//
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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.
|
|
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",
|