diff --git a/mcp/packages/browser-extension/README.md b/mcp/packages/browser-extension/README.md index c9d4a0943d..06a997fe36 100644 --- a/mcp/packages/browser-extension/README.md +++ b/mcp/packages/browser-extension/README.md @@ -17,6 +17,15 @@ for the plugin to answer again, and then runs the task. The popup turns waking on or off and lists the paired sessions and server connections. +The icon is the Penpot logo; `public/icons/icon.svg` is its source. To redraw the PNGs after +changing it: + +```sh +for size in 16 32 48 128; do + rsvg-convert -w $size -h $size public/icons/icon.svg -o public/icons/icon-$size.png +done +``` + ## How a tab is woken - **Chrome** unfreezes the page in place: the extension attaches the debugger to the tab, diff --git a/mcp/packages/browser-extension/public/icons/icon-128.png b/mcp/packages/browser-extension/public/icons/icon-128.png new file mode 100644 index 0000000000..a545f42dd5 Binary files /dev/null and b/mcp/packages/browser-extension/public/icons/icon-128.png differ diff --git a/mcp/packages/browser-extension/public/icons/icon-16.png b/mcp/packages/browser-extension/public/icons/icon-16.png new file mode 100644 index 0000000000..3e6eb3e20e Binary files /dev/null and b/mcp/packages/browser-extension/public/icons/icon-16.png differ diff --git a/mcp/packages/browser-extension/public/icons/icon-32.png b/mcp/packages/browser-extension/public/icons/icon-32.png new file mode 100644 index 0000000000..31f2fe30e5 Binary files /dev/null and b/mcp/packages/browser-extension/public/icons/icon-32.png differ diff --git a/mcp/packages/browser-extension/public/icons/icon-48.png b/mcp/packages/browser-extension/public/icons/icon-48.png new file mode 100644 index 0000000000..f92dd70100 Binary files /dev/null and b/mcp/packages/browser-extension/public/icons/icon-48.png differ diff --git a/mcp/packages/browser-extension/public/icons/icon.svg b/mcp/packages/browser-extension/public/icons/icon.svg new file mode 100644 index 0000000000..b12e54c10e --- /dev/null +++ b/mcp/packages/browser-extension/public/icons/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mcp/packages/browser-extension/scripts/manifest.mjs b/mcp/packages/browser-extension/scripts/manifest.mjs index 6fab3ff8bd..29fb4bdc2c 100644 --- a/mcp/packages/browser-extension/scripts/manifest.mjs +++ b/mcp/packages/browser-extension/scripts/manifest.mjs @@ -1,6 +1,13 @@ /** Browsers the extension is built for, one directory of `dist/` each. */ export const BROWSERS = ["chrome", "firefox"]; +const ICONS = { + 16: "icons/icon-16.png", + 32: "icons/icon-32.png", + 48: "icons/icon-48.png", + 128: "icons/icon-128.png", +}; + const CONTENT_SCRIPTS = [ { matches: ["https://design.penpot.app/*", "https://localhost/*", "http://localhost/*"], @@ -23,9 +30,11 @@ export function createManifest(browser) { name: "Penpot MCP Wake", version: "0.1.0", description: "Wakes a background Penpot tab when an MCP task needs it.", + icons: ICONS, action: { default_title: "Penpot MCP Wake", default_popup: "popup.html", + default_icon: { 16: ICONS[16], 32: ICONS[32] }, }, content_scripts: CONTENT_SCRIPTS, }; diff --git a/mcp/packages/browser-extension/src/manifest.test.ts b/mcp/packages/browser-extension/src/manifest.test.ts index 82f2c04fc3..520abd32c6 100644 --- a/mcp/packages/browser-extension/src/manifest.test.ts +++ b/mcp/packages/browser-extension/src/manifest.test.ts @@ -1,4 +1,5 @@ import assert from "node:assert/strict"; +import { access } from "node:fs/promises"; import test from "node:test"; import { BROWSERS, createManifest } from "../scripts/manifest.mjs"; @@ -56,6 +57,24 @@ test("runs the content script on Penpot and on local development instances", () test("opens the popup from the toolbar button", () => { for (const manifest of [chrome, firefox]) { - assert.deepEqual(manifest.action, { default_title: "Penpot MCP Wake", default_popup: "popup.html" }); + assert.deepEqual(manifest.action, { + default_title: "Penpot MCP Wake", + default_popup: "popup.html", + default_icon: { 16: "icons/icon-16.png", 32: "icons/icon-32.png" }, + }); + } +}); + +test("has icons for the toolbar, the extensions page and the stores, all in public/", async () => { + for (const manifest of [chrome, firefox]) { + assert.deepEqual(manifest.icons, { + 16: "icons/icon-16.png", + 32: "icons/icon-32.png", + 48: "icons/icon-48.png", + 128: "icons/icon-128.png", + }); + for (const path of Object.values(manifest.icons as Record)) { + await access(new URL(`../public/${path}`, import.meta.url)); + } } });