@mehmoodqureshi/chrome-mcp 0.9.0 → 0.9.1

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/README.md CHANGED
@@ -126,8 +126,8 @@ npx -y @mehmoodqureshi/chrome-mcp --extension-path
126
126
 
127
127
  Then `chrome://extensions` → enable **Developer mode** → **Load unpacked** →
128
128
  pick `chrome-mcp-extension` in your home folder. After upgrading the package the
129
- server refreshes the files on its next boot; click **Reload** on
130
- `chrome://extensions` to pick them up. `CHROME_MCP_EXTENSION_DIR` moves the
129
+ server refreshes the files on its next boot and the extension reloads itself
130
+ within 30 seconds; nothing to click. `CHROME_MCP_EXTENSION_DIR` moves the
131
131
  folder somewhere else. (Working from a git clone instead? Run
132
132
  `npm install && npm run build:ext` first — `extension-dist/` is gitignored, and
133
133
  the server mirrors it to the same home folder.)
@@ -142,7 +142,7 @@ run? It re-checks every 30 seconds and pairs as soon as the file appears.
142
142
  **Where to see the badge:** it sits on the extension's icon in Chrome's
143
143
  toolbar, not on the `chrome://extensions` page. Chrome hides new extensions
144
144
  behind the puzzle-piece button at the right of the address bar, so click that,
145
- find **Chrome MCP Bridge**, and click the pin next to it once; the icon then
145
+ find **MCP Extension for Chrome**, and click the pin next to it once; the icon then
146
146
  stays in the toolbar. Hover it for the status in words.
147
147
 
148
148
  | Badge | Meaning |
package/SETUP.md CHANGED
@@ -47,8 +47,9 @@ It prints `~/chrome-mcp-extension` (on Windows `%USERPROFILE%\chrome-mcp-extensi
47
47
  Verify with `ls` (or `dir`) that the folder holds `manifest.json` and
48
48
  `background.js`. Record the path; the human needs it in step 4. The install is
49
49
  small and downloads no browser: the server drives the Chrome the human already
50
- has. The server refreshes this folder on every boot, so upgrades need no
51
- re-copy, only a Reload on `chrome://extensions`.
50
+ has. The server refreshes this folder on every boot and the loaded extension
51
+ reloads itself when the version changes, so upgrades need nothing from the
52
+ human.
52
53
 
53
54
  ## Step 3 — Wire the server into this MCP client
54
55
 
@@ -107,7 +108,7 @@ You cannot do this step yourself. Give the human these exact instructions:
107
108
  2. Turn on **Developer mode** (top right).
108
109
  3. Click **Load unpacked** and choose the `chrome-mcp-extension` folder in
109
110
  their home directory (the path from step 2).
110
- 4. Confirm an extension named **Chrome MCP Bridge** now appears in the list.
111
+ 4. Confirm an extension named **MCP Extension for Chrome** now appears in the list.
111
112
 
112
113
  Wait for the human to confirm before continuing.
113
114
 
@@ -137,7 +138,7 @@ new extensions behind the puzzle-piece button at the right of the address bar,
137
138
  so give them these exact steps:
138
139
 
139
140
  1. Click the puzzle-piece button at the right of the address bar.
140
- 2. Find **Chrome MCP Bridge** in the list and click the pin icon next to it.
141
+ 2. Find **MCP Extension for Chrome** in the list and click the pin icon next to it.
141
142
  The extension icon now stays in the toolbar.
142
143
  3. Look at the small badge on that icon. Hovering it shows the status in words.
143
144
 
@@ -158,7 +159,7 @@ printing the token,
158
159
  node -e "console.log(require(require('os').homedir()+'/.chrome-mcp/handshake.json').port)"
159
160
  ```
160
161
 
161
- then have the human open **Details** on Chrome MCP Bridge, then **Extension
162
+ then have the human open **Details** on MCP Extension for Chrome, then **Extension
162
163
  options**, enter that **Port**, open `~/.chrome-mcp/handshake.json` in a text
163
164
  editor and paste its `token` into the **Token** field, leave **Profile** as
164
165
  `default`, and click **Save**. The status line should read **connected** within
package/dist/src/cli.js CHANGED
@@ -67,7 +67,7 @@ function installExtension() {
67
67
  (0, server_2.logErr)(`extension installed at ${r.dir} — chrome://extensions -> Load unpacked -> pick that folder`);
68
68
  }
69
69
  else if (r.copied.length > 0) {
70
- (0, server_2.logErr)(`extension files updated at ${r.dir} — click Reload on chrome://extensions to pick up the new version`);
70
+ (0, server_2.logErr)(`extension files updated at ${r.dir} — a loaded extension reloads itself within 30 s`);
71
71
  }
72
72
  return r.dir;
73
73
  }
@@ -1609,6 +1609,21 @@
1609
1609
  await chrome.storage.local.set({ wsPort: bundled.wsPort, token: bundled.token, pairingSource: "auto" });
1610
1610
  return true;
1611
1611
  }
1612
+ async function reloadIfFilesChanged() {
1613
+ try {
1614
+ const res = await fetch(chrome.runtime.getURL("manifest.json"), { cache: "no-store" });
1615
+ if (!res.ok) return;
1616
+ const onDisk = await res.json();
1617
+ const loaded = chrome.runtime.getManifest().version;
1618
+ if (typeof onDisk.version !== "string" || onDisk.version === loaded) return;
1619
+ const { reloadedFor } = await chrome.storage.local.get("reloadedFor");
1620
+ if (reloadedFor === onDisk.version) return;
1621
+ await chrome.storage.local.set({ reloadedFor: onDisk.version });
1622
+ console.info(`[chrome-mcp] extension files updated on disk (${loaded} -> ${onDisk.version}); reloading`);
1623
+ chrome.runtime.reload();
1624
+ } catch {
1625
+ }
1626
+ }
1612
1627
  async function getConfig() {
1613
1628
  const { wsPort, token, profile } = await chrome.storage.local.get(["wsPort", "token", "profile"]);
1614
1629
  if (typeof wsPort === "number" && wsPort > 0 && typeof token === "string" && token.length > 0) {
@@ -1618,10 +1633,10 @@
1618
1633
  return null;
1619
1634
  }
1620
1635
  var BADGE = {
1621
- connected: { text: "\u25CF", color: "#16a34a", title: "Chrome MCP \u2014 connected" },
1622
- connecting: { text: "\u2026", color: "#ca8a04", title: "Chrome MCP \u2014 connecting" },
1623
- unauthorized: { text: "!", color: "#dc2626", title: "Chrome MCP \u2014 rejected (bad/stale token; re-pair)" },
1624
- idle: { text: "\u25CB", color: "#6b7280", title: "Chrome MCP \u2014 not connected (open options to pair)" }
1636
+ connected: { text: "\u25CF", color: "#16a34a", title: "MCP Extension for Chrome \u2014 connected" },
1637
+ connecting: { text: "\u2026", color: "#ca8a04", title: "MCP Extension for Chrome \u2014 connecting" },
1638
+ unauthorized: { text: "!", color: "#dc2626", title: "MCP Extension for Chrome \u2014 rejected (bad/stale token; re-pair)" },
1639
+ idle: { text: "\u25CB", color: "#6b7280", title: "MCP Extension for Chrome \u2014 not connected (open options to pair)" }
1625
1640
  };
1626
1641
  function reflectBadge(state) {
1627
1642
  const b = BADGE[state] ?? BADGE.idle;
@@ -1644,6 +1659,7 @@
1644
1659
  }
1645
1660
  async function keepalivePulse() {
1646
1661
  await chrome.storage.local.get("connState");
1662
+ await reloadIfFilesChanged();
1647
1663
  if (!ws.isConnected() && !await getConfig()) await adoptBundledPairing();
1648
1664
  await ensureConnected();
1649
1665
  }
@@ -1668,6 +1684,7 @@
1668
1684
  });
1669
1685
  async function bootstrap() {
1670
1686
  await chrome.alarms.create(KEEPALIVE_ALARM, { periodInMinutes: 0.5 });
1687
+ await reloadIfFilesChanged();
1671
1688
  if (!await adoptBundledPairing()) await ensureConnected();
1672
1689
  }
1673
1690
  void bootstrap();
Binary file
Binary file
Binary file
Binary file
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "manifest_version": 3,
3
- "name": "Chrome MCP Bridge",
4
- "version": "0.9.0",
3
+ "name": "MCP Extension for Chrome",
4
+ "version": "0.9.1",
5
5
  "description": "Lets a local chrome-mcp server drive this browser. Pair it with the server's handshake token.",
6
+ "homepage_url": "https://github.com/Mehmoodqureshi/chrome-mcp",
6
7
  "minimum_chrome_version": "116",
8
+ "icons": {
9
+ "16": "icon16.png",
10
+ "32": "icon32.png",
11
+ "48": "icon48.png",
12
+ "128": "icon128.png"
13
+ },
7
14
  "background": {
8
15
  "service_worker": "background.js"
9
16
  },
@@ -22,6 +29,12 @@
22
29
  ],
23
30
  "options_page": "options.html",
24
31
  "action": {
25
- "default_title": "Chrome MCP — open options to pair"
32
+ "default_title": "MCP Extension for Chrome — open options to pair",
33
+ "default_icon": {
34
+ "16": "icon16.png",
35
+ "32": "icon32.png",
36
+ "48": "icon48.png",
37
+ "128": "icon128.png"
38
+ }
26
39
  }
27
40
  }
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title>Chrome MCP — Pairing</title>
5
+ <title>MCP Extension for Chrome — Pairing</title>
6
6
  <style>
7
7
  body { font: 14px/1.5 system-ui, sans-serif; max-width: 32rem; margin: 2rem auto; padding: 0 1rem; }
8
8
  h1 { font-size: 1.2rem; }
@@ -17,7 +17,7 @@
17
17
  "connState",
18
18
  "pairingSource"
19
19
  ]);
20
- sourceEl.textContent = pairingSource === "auto" ? "Paired automatically from the pairing.json the server wrote into this extension folder. Saving here overrides it." : pairingSource === "manual" ? "Paired by hand. Saved values take precedence over the bundled pairing.json." : "Not paired yet. If you loaded this extension from the chrome-mcp package folder, start the server once and it pairs itself; otherwise paste the values below.";
20
+ sourceEl.textContent = pairingSource === "auto" ? "Paired automatically from the pairing.json the server wrote into this extension folder. Saving here overrides it." : pairingSource === "manual" ? "Paired by hand. Saved values take precedence over the bundled pairing.json." : typeof wsPort === "number" && wsPort > 0 && connState !== "idle" ? "Paired with values saved by an earlier version. Saving here keeps them manual." : "Not paired yet. If you loaded this extension from the chrome-mcp package folder, start the server once and it pairs itself; otherwise paste the values below.";
21
21
  portEl.value = typeof wsPort === "number" && wsPort > 0 ? String(wsPort) : String(DEFAULT_WS_PORT);
22
22
  profileEl.value = typeof profile === "string" ? profile : "";
23
23
  render(typeof connState === "string" ? connState : "idle");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mehmoodqureshi/chrome-mcp",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Drive your real Chrome browser over MCP — real logins, real cookies. A stdio MCP server (CLI) plus an MV3 extension, driving Chrome via chrome.scripting/chrome.tabs. Multi-tab batch automation, accessibility snapshots, deny-all security by default.",
5
5
  "author": "Mehmood Ur Rehman Qureshi",
6
6
  "license": "MIT",
@@ -51,6 +51,7 @@
51
51
  "scripts": {
52
52
  "build": "tsc -p tsconfig.json",
53
53
  "build:ext": "node extension/scripts/build-ext.mjs",
54
+ "pack:ext": "npm run build:ext && rm -f chrome-mcp-extension-$npm_package_version.zip && cd extension-dist && zip -q -r ../chrome-mcp-extension-$npm_package_version.zip . -x pairing.json '.*' && cd .. && ls -la chrome-mcp-extension-$npm_package_version.zip",
54
55
  "typecheck": "tsc -p tsconfig.json --noEmit",
55
56
  "typecheck:ext": "tsc -p tsconfig.ext.json",
56
57
  "clean": "rimraf dist extension-dist",