mcp-browser-extension 0.9.25 → 0.9.26

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.
Files changed (40) hide show
  1. package/README.md +32 -35
  2. package/SETUP.md +20 -20
  3. package/dist/shared/protocol.d.ts +1 -1
  4. package/dist/shared/tab-border.d.ts +1 -1
  5. package/dist/shared/tab-border.js +1 -1
  6. package/dist/src/access.js +2 -1
  7. package/dist/src/auto-update.d.ts +6 -6
  8. package/dist/src/auto-update.js +9 -8
  9. package/dist/src/bridge/auth.d.ts +3 -3
  10. package/dist/src/bridge/auth.js +5 -4
  11. package/dist/src/bridge/datadir.d.ts +1 -1
  12. package/dist/src/bridge/datadir.js +1 -1
  13. package/dist/src/bridge/evict.d.ts +7 -7
  14. package/dist/src/bridge/evict.js +13 -13
  15. package/dist/src/bridge/peer.d.ts +4 -4
  16. package/dist/src/bridge/peer.js +4 -4
  17. package/dist/src/bridge/server.d.ts +6 -6
  18. package/dist/src/bridge/server.js +11 -11
  19. package/dist/src/cli.d.ts +1 -1
  20. package/dist/src/cli.js +13 -12
  21. package/dist/src/compat.d.ts +4 -0
  22. package/dist/src/compat.js +28 -0
  23. package/dist/src/config.d.ts +4 -4
  24. package/dist/src/config.js +27 -26
  25. package/dist/src/extension-command.js +3 -3
  26. package/dist/src/extension-install.d.ts +4 -4
  27. package/dist/src/extension-install.js +8 -6
  28. package/dist/src/mcp/log.js +2 -2
  29. package/dist/src/mcp/server.d.ts +1 -1
  30. package/dist/src/mcp/server.js +1 -1
  31. package/dist/src/mcp/tools.js +1 -1
  32. package/dist/src/native-host.d.ts +1 -1
  33. package/dist/src/native-host.js +1 -1
  34. package/dist/src/telemetry.d.ts +3 -3
  35. package/dist/src/telemetry.js +7 -6
  36. package/docs/BLUEPRINT.md +11 -11
  37. package/extension-dist/background.js +6 -6
  38. package/extension-dist/manifest.json +1 -1
  39. package/extension-dist/options.html +1 -1
  40. package/package.json +24 -5
@@ -7,13 +7,13 @@
7
7
  * folders deep under `npm root -g`, and an npx run hides it in a cache. So on
8
8
  * every boot (and on `--extension-path`) the server mirrors the bundled
9
9
  * `extension-dist/` into a plain, visible folder directly under the home
10
- * directory — `~/chrome-mcp-extension` — and that is the folder the docs, the
10
+ * directory — `~/mcp-browser-extension` — and that is the folder the docs, the
11
11
  * pairing file, and `--extension-path` all point at.
12
12
  *
13
13
  * The copy is a one-way mirror of top-level regular files, written only when
14
14
  * content differs, so an unchanged boot touches nothing. It never deletes: the
15
15
  * target may hold `pairing.json` (ours) and, if the operator pointed
16
- * CHROME_MCP_EXTENSION_DIR somewhere of their own, files that are not ours to
16
+ * MCP_BROWSER_EXTENSION_EXTENSION_DIR somewhere of their own, files that are not ours to
17
17
  * remove. It never throws — a read-only home just falls back to the bundled
18
18
  * folder, which still works for Load unpacked.
19
19
  */
@@ -27,18 +27,20 @@ const node_os_1 = require("node:os");
27
27
  const node_path_1 = require("node:path");
28
28
  const node_fs_1 = require("node:fs");
29
29
  const atomic_file_1 = require("./atomic-file");
30
+ const compat_1 = require("./compat");
30
31
  /** Folder name under the home directory. */
31
- exports.EXTENSION_DIR_NAME = 'chrome-mcp-extension';
32
+ exports.EXTENSION_DIR_NAME = 'mcp-browser-extension';
32
33
  /** The auto-pairing file the server writes; never copied, never overwritten by the mirror. */
33
34
  exports.PAIRING_FILE = 'pairing.json';
34
35
  /** `dist/src/extension-install.js` -> `<pkg>/extension-dist`, which the tarball ships. */
35
36
  function bundledExtensionDir() {
36
37
  return (0, node_path_1.resolve)(__dirname, '..', '..', 'extension-dist');
37
38
  }
38
- /** Where the extension is mirrored for Load unpacked. `CHROME_MCP_EXTENSION_DIR` overrides. */
39
+ /** Where the extension is mirrored for Load unpacked. `MCP_BROWSER_EXTENSION_EXTENSION_DIR` overrides. */
39
40
  function extensionInstallDir() {
40
- const override = process.env.CHROME_MCP_EXTENSION_DIR;
41
- return override && override.trim() ? (0, node_path_1.resolve)(override.trim()) : (0, node_path_1.join)((0, node_os_1.homedir)(), exports.EXTENSION_DIR_NAME);
41
+ const override = (0, compat_1.runtimeEnv)('EXTENSION_DIR');
42
+ return override && override.trim() ? (0, node_path_1.resolve)(override.trim())
43
+ : (0, compat_1.renamedDirectory)((0, node_os_1.homedir)(), exports.EXTENSION_DIR_NAME, 'chrome-mcp-extension');
42
44
  }
43
45
  function readManifest(path) {
44
46
  const value = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
@@ -32,12 +32,12 @@ function getLogLevel() {
32
32
  function logErr(message) {
33
33
  if (logLevel === 'silent')
34
34
  return;
35
- process.stderr.write(`[chrome-mcp] ${message}\n`);
35
+ process.stderr.write(`[mcp-browser-extension] ${message}\n`);
36
36
  }
37
37
  /** Verbose tracing: emitted only at `--log-level debug`. */
38
38
  function logDebug(message) {
39
39
  if (logLevel !== 'debug')
40
40
  return;
41
- process.stderr.write(`[chrome-mcp] [debug] ${message}\n`);
41
+ process.stderr.write(`[mcp-browser-extension] [debug] ${message}\n`);
42
42
  }
43
43
  //# sourceMappingURL=log.js.map
@@ -2,7 +2,7 @@
2
2
  * src/mcp/server.ts — MCP server bootstrap over stdio.
3
3
  *
4
4
  * Wires the SDK `Server` to a `StdioServerTransport` so an MCP host (Claude)
5
- * drives chrome-mcp over JSON-RPC on stdin/stdout. CRITICAL: in stdio mode
5
+ * drives mcp-browser-extension over JSON-RPC on stdin/stdout. CRITICAL: in stdio mode
6
6
  * NOTHING may be written to stdout except the JSON-RPC stream — all diagnostics
7
7
  * go to stderr via `logErr`.
8
8
  */
@@ -3,7 +3,7 @@
3
3
  * src/mcp/server.ts — MCP server bootstrap over stdio.
4
4
  *
5
5
  * Wires the SDK `Server` to a `StdioServerTransport` so an MCP host (Claude)
6
- * drives chrome-mcp over JSON-RPC on stdin/stdout. CRITICAL: in stdio mode
6
+ * drives mcp-browser-extension over JSON-RPC on stdin/stdout. CRITICAL: in stdio mode
7
7
  * NOTHING may be written to stdout except the JSON-RPC stream — all diagnostics
8
8
  * go to stderr via `logErr`.
9
9
  */
@@ -387,7 +387,7 @@ function capabilityStatus(policy) {
387
387
  disabledCapabilities: off,
388
388
  capabilityHint: 'These tools are not available in this session because their capability is off. ' +
389
389
  'If the user asks for one of them, tell them to add the listed flag to the MCP Browser Extension ' +
390
- "server's entry (chrome-mcp) in their MCP config and restart the client.",
390
+ "server's entry (mcp-browser-extension) in their MCP config and restart the client.",
391
391
  };
392
392
  }
393
393
  /** The names actually advertised, in catalog order. */
@@ -14,7 +14,7 @@
14
14
  * - `registerNativeHost()`: the server writes the host's launcher script and
15
15
  * its manifest into each installed browser's NativeMessagingHosts folder
16
16
  * (the registry on Windows). Best-effort and idempotent.
17
- * - `runNativeHost()`: what `chrome-mcp --native-host` runs when Chrome starts
17
+ * - `runNativeHost()`: what `mcp-browser-extension --native-host` runs when Chrome starts
18
18
  * the host: read one message, answer with the pairing, exit.
19
19
  */
20
20
  /** The host's name, as the extension addresses it. */
@@ -15,7 +15,7 @@
15
15
  * - `registerNativeHost()`: the server writes the host's launcher script and
16
16
  * its manifest into each installed browser's NativeMessagingHosts folder
17
17
  * (the registry on Windows). Best-effort and idempotent.
18
- * - `runNativeHost()`: what `chrome-mcp --native-host` runs when Chrome starts
18
+ * - `runNativeHost()`: what `mcp-browser-extension --native-host` runs when Chrome starts
19
19
  * the host: read one message, answer with the pairing, exit.
20
20
  */
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,7 +1,7 @@
1
1
  /**
2
- * src/telemetry.ts — anonymous usage statistics from the chrome-mcp SERVER.
2
+ * src/telemetry.ts — anonymous usage statistics from the mcp-browser-extension SERVER.
3
3
  *
4
- * What it sends, to PostHog: a random per-install id, the chrome-mcp version,
4
+ * What it sends, to PostHog: a random per-install id, the mcp-browser-extension version,
5
5
  * OS, CPU architecture and Node major version, whether this session owns the
6
6
  * port or shares it, how many browsers are paired (and, when none, which of a
7
7
  * few fixed reasons applies), per-tool call and error
@@ -12,7 +12,7 @@
12
12
  * The browser extension sends nothing; this lives only in the npm server.
13
13
  *
14
14
  * On by default with a one-time notice on first run. Off with
15
- * CHROME_MCP_TELEMETRY=0 (or false/off), DO_NOT_TRACK=1, or --no-telemetry.
15
+ * MCP_BROWSER_EXTENSION_TELEMETRY=0 (or false/off), DO_NOT_TRACK=1, or --no-telemetry.
16
16
  * Every failure is swallowed: telemetry can never break or slow a tool call.
17
17
  */
18
18
  /** PostHog project key. Public by design: it can only WRITE events, never read them. */
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  /**
3
- * src/telemetry.ts — anonymous usage statistics from the chrome-mcp SERVER.
3
+ * src/telemetry.ts — anonymous usage statistics from the mcp-browser-extension SERVER.
4
4
  *
5
- * What it sends, to PostHog: a random per-install id, the chrome-mcp version,
5
+ * What it sends, to PostHog: a random per-install id, the mcp-browser-extension version,
6
6
  * OS, CPU architecture and Node major version, whether this session owns the
7
7
  * port or shares it, how many browsers are paired (and, when none, which of a
8
8
  * few fixed reasons applies), per-tool call and error
@@ -13,7 +13,7 @@
13
13
  * The browser extension sends nothing; this lives only in the npm server.
14
14
  *
15
15
  * On by default with a one-time notice on first run. Off with
16
- * CHROME_MCP_TELEMETRY=0 (or false/off), DO_NOT_TRACK=1, or --no-telemetry.
16
+ * MCP_BROWSER_EXTENSION_TELEMETRY=0 (or false/off), DO_NOT_TRACK=1, or --no-telemetry.
17
17
  * Every failure is swallowed: telemetry can never break or slow a tool call.
18
18
  */
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -31,6 +31,7 @@ const node_fs_1 = require("node:fs");
31
31
  const node_os_1 = require("node:os");
32
32
  const node_path_1 = require("node:path");
33
33
  const tool_categories_1 = require("./mcp/tool-categories");
34
+ const compat_1 = require("./compat");
34
35
  /** PostHog project key. Public by design: it can only WRITE events, never read them. */
35
36
  exports.POSTHOG_KEY = 'phc_CG5QX5JEkRokfUN87rZQnPa3URdLWePCZnfqW6MCyCdU';
36
37
  exports.POSTHOG_HOST = 'https://us.i.posthog.com';
@@ -54,13 +55,13 @@ const MCP_SESSION_IDLE_MS = 30 * 60_000;
54
55
  const SEND_TIMEOUT_MS = 3_000;
55
56
  const STATE_FILE = 'telemetry.json';
56
57
  exports.TELEMETRY_NOTICE = 'MCP Browser Extension collects anonymous usage statistics (version, OS, tool call and error counts; never URLs, ' +
57
- 'page content or arguments) to see how it is used. Turn it off with CHROME_MCP_TELEMETRY=0 or DO_NOT_TRACK=1. ' +
58
- 'Details: https://github.com/Mehmoodqureshi/chrome-mcp#telemetry';
58
+ 'page content or arguments) to see how it is used. Turn it off with MCP_BROWSER_EXTENSION_TELEMETRY=0 or DO_NOT_TRACK=1. ' +
59
+ 'Details: https://github.com/Mehmoodqureshi/mcp-browser-extension#telemetry';
59
60
  /** Whether the user has turned telemetry off, by env or flag. */
60
61
  function telemetryDisabled(env, disabledByFlag = false) {
61
62
  if (disabledByFlag)
62
63
  return true;
63
- const own = (env.CHROME_MCP_TELEMETRY ?? '').trim().toLowerCase();
64
+ const own = ((0, compat_1.runtimeEnv)('TELEMETRY', env) ?? '').trim().toLowerCase();
64
65
  if (['0', 'false', 'off', 'no'].includes(own))
65
66
  return true;
66
67
  const dnt = (env.DO_NOT_TRACK ?? '').trim().toLowerCase();
package/docs/BLUEPRINT.md CHANGED
@@ -21,11 +21,11 @@ over **stdio**; the extension speaks the canonical frame protocol over a
21
21
  ```
22
22
  ┌──────────────────────────────────────────────────────────────┐
23
23
  WORLD 1 │ MCP HOST (Claude Desktop / Claude Code) │
24
- (the model)│ spawns: npx chrome-mcp │
24
+ (the model)│ spawns: npx mcp-browser-extension │
25
25
  └───────────────┬──────────────────────────────────────────────┘
26
26
  │ JSON-RPC over stdio (stdout = SACRED)
27
27
  ┌───────────────▼──────────────────────────────────────────────┐
28
- WORLD 2 │ chrome-mcp CLI (one Node process) │
28
+ WORLD 2 │ mcp-browser-extension CLI (one Node process) │
29
29
  (server) │ │
30
30
  │ ┌────────────┐ ┌──────────────────┐ ┌─────────────────┐ │
31
31
  │ │ MCP Server │──▶│ tools.ts │──▶│ ExecutorManager │ │
@@ -70,13 +70,13 @@ takes over from CDP and vice-versa on disconnect.
70
70
 
71
71
  ## 2. Repository Layout
72
72
 
73
- Single sibling repo `chrome-mcp/` (NOT a workspace). Two build roots in one git
73
+ Single sibling repo `mcp-browser-extension/` (NOT a workspace). Two build roots in one git
74
74
  repo so the wire protocol version-locks between server and extension. The shared
75
75
  `protocol.ts` lives at the top so both builds import the *same file*.
76
76
 
77
77
  ```
78
- chrome-mcp/
79
- ├── package.json # bin: chrome-mcp -> dist/cli.js; deps sdk, ws, playwright
78
+ mcp-browser-extension/
79
+ ├── package.json # bin: mcp-browser-extension -> dist/cli.js; deps sdk, ws, playwright
80
80
  ├── tsconfig.json
81
81
  ├── README.md
82
82
  ├── .gitignore # dist/, extension-dist/, test-targets.json, *.handshake
@@ -107,7 +107,7 @@ chrome-mcp/
107
107
  │ │ ├── server.ts # BridgeServer: ws on 127.0.0.1, token gate, id-correlation, heartbeat
108
108
  │ │ ├── connection.ts # ExtensionConnection: pending-map, timeouts, reject-all-on-close
109
109
  │ │ ├── auth.ts # token gen, atomic 0600 handshake.json, hashed constant-time compare
110
- │ │ └── datadir.ts # Electron-free CHROME_MCP_DATA || ~/.chrome-mcp
110
+ │ │ └── datadir.ts # Electron-free MCP_BROWSER_EXTENSION_DATA || ~/.mcp-browser-extension
111
111
  │ └── security/
112
112
  │ └── policy.ts # Policy type, loadPolicy, assertUrlAllowed (default-deny, gates reads)
113
113
  │
@@ -331,8 +331,8 @@ export type ExecutorErrorCode =
331
331
  ```
332
332
 
333
333
  **Auth handshake (the canonical, ONLY model):** [RESOLVED — security blocker 1, minor 7]
334
- 1. Server, at boot, generates a **fresh 256-bit token every boot**, never persisted/reused: `crypto.randomBytes(32).toString('base64url')`. It writes `{ v, port, token, pid, ts, expectedExtensionId? }` **atomically** (tmp + `rename`) to `$CHROME_MCP_DATA/handshake.json` with mode **0600**, verifies the mode after write, and **fails closed** if it cannot. The token is **never** written to stdout or stderr or any log. A test asserts this.
335
- 2. The extension acquires `{port, token}` from the handshake file via a **native-messaging trampoline** (`extension/src/nm/`) — the only component that can read a 0600 file the model/attacker cannot. v1 ships a **manual fallback**: the user runs `npx chrome-mcp --print-pairing` which prints a **redacted confirmation + the file path** (`handshake.json written to …; open the extension and click Pair`) and the trampoline reads it. **No token on stdout/stderr, no `/connect` HTTP endpoint.** [RESOLVED — security blocker 3]
334
+ 1. Server, at boot, generates a **fresh 256-bit token every boot**, never persisted/reused: `crypto.randomBytes(32).toString('base64url')`. It writes `{ v, port, token, pid, ts, expectedExtensionId? }` **atomically** (tmp + `rename`) to `$MCP_BROWSER_EXTENSION_DATA/handshake.json` with mode **0600**, verifies the mode after write, and **fails closed** if it cannot. The token is **never** written to stdout or stderr or any log. A test asserts this.
335
+ 2. The extension acquires `{port, token}` from the handshake file via a **native-messaging trampoline** (`extension/src/nm/`) — the only component that can read a 0600 file the model/attacker cannot. v1 ships a **manual fallback**: the user runs `npx mcp-browser-extension --print-pairing` which prints a **redacted confirmation + the file path** (`handshake.json written to …; open the extension and click Pair`) and the trampoline reads it. **No token on stdout/stderr, no `/connect` HTTP endpoint.** [RESOLVED — security blocker 3]
336
336
  3. Extension dials `ws://127.0.0.1:<port>` (port read from handshake via trampoline; see §6 for re-read-on-reconnect) and sends `hello` within 5000ms.
337
337
  4. Server compares tokens by **hashing both sides to SHA-256 and `timingSafeEqual`-ing the digests** (no length precondition, no length leak). Match → `welcome`, flip to ACTIVE; mismatch / `v!==1` / timeout → send `unauthorized` then close **4401**. No `command`/`result`/`event` is processed before `welcome`.
338
338
 
@@ -456,7 +456,7 @@ truth). The extension learns both via the native-messaging trampoline. **Wheneve
456
456
  a WS dial FAILS** (server restarted → fresh token + possibly fresh port), the SW
457
457
  re-invokes the trampoline to re-read `{port, token}` before the next dial. This
458
458
  makes ephemeral ports work: the extension never holds a stale port. The single
459
- default fixed port is **`38017`** (override `CHROME_MCP_WS_PORT`); ephemeral
459
+ default fixed port is **`38017`** (override `MCP_BROWSER_EXTENSION_WS_PORT`); ephemeral
460
460
  port `0` is supported precisely because the extension re-reads on failure. The
461
461
  port is **not** a security boundary — the token is.
462
462
 
@@ -529,7 +529,7 @@ or `launchPersistentContext(userDataDir)` (self-spawn). **Lifted from
529
529
  Decisions:
530
530
  - **Ownership flag `launched`**: `dispose()` closes the context only when `launched===true`; attach mode drops refs only.
531
531
  - **Do NOT set `PLAYWRIGHT_BROWSERS_PATH`** (rely on the postinstall cache; respect a pre-set override). Drop the Electron `useBundledBrowsersIfPackaged` branch.
532
- - **Self-launch profile dir must NOT be the user's real Chrome profile** (`CHROME_MCP_USERDATA` || `~/.chrome-mcp/cdp-profile`) — it would conflict with the real Chrome the extension drives.
532
+ - **Self-launch profile dir must NOT be the user's real Chrome profile** (`MCP_BROWSER_EXTENSION_USERDATA` || `~/.mcp-browser-extension/cdp-profile`) — it would conflict with the real Chrome the extension drives.
533
533
  - `screenshot` → `page.screenshot({fullPage})` → base64; `eval` → `page.evaluate` wrapped so a page throw becomes `{ok:false}` not a transport-killing throw.
534
534
  - **tabId stamping**: CDP guids are prefixed `cdp:<sessionId>:<guid>`; extension ids `ext:<sessionId>:<targetId>`. A handle whose prefix doesn't match the current backend/session → `STALE_TAB` ('call tabs_list again'). [RESOLVED — mv3 major tabId / integration]
535
535
 
@@ -588,7 +588,7 @@ Build: `manifest.json`, `sw/background.ts` (top-level listeners, keepalive inter
588
588
  Build: server-side `extract_links`/`read_as_markdown`/`fill_form` over `Runtime.evaluate`; server-side CDP-fetch `download_file` with sanitized names/size cap; policy enforced at executor + router. *Verify:* `test/hitl/` (cloned harness, Executor handle) — read steps free; mutating steps (`download_file`, `fill_form+submit`, `eval`-side-effect) behind classification + `--include-mutating` + literal `yes` + `test-targets.json` allowlist. Human verdict gate; never CI.
589
589
 
590
590
  **Phase 6 — Packaging & docs.**
591
- Build: `files` whitelist incl. `extension-dist/`, `--print-pairing`/`--print-extension-path`, `.mcp.json` snippet, README (banner caveat, load-unpacked-only, policy/safe-mode defaults, kill switch). *Verify:* `npx chrome-mcp` from a packed tarball boots, prints the pairing file path (no token leak), and a fresh Chrome load-unpacked round-trips one navigate→get_text.
591
+ Build: `files` whitelist incl. `extension-dist/`, `--print-pairing`/`--print-extension-path`, `.mcp.json` snippet, README (banner caveat, load-unpacked-only, policy/safe-mode defaults, kill switch). *Verify:* `npx mcp-browser-extension` from a packed tarball boots, prints the pairing file path (no token leak), and a fresh Chrome load-unpacked round-trips one navigate→get_text.
592
592
 
593
593
  ---
594
594
 
@@ -2464,7 +2464,7 @@
2464
2464
  },
2465
2465
  onPolicy: (policy) => {
2466
2466
  currentPolicy = policy;
2467
- void syncObserverScript(policy, (m) => console.debug("[chrome-mcp]", m));
2467
+ void syncObserverScript(policy, (m) => console.debug("[mcp-browser-extension]", m));
2468
2468
  void onAllowlist(policy);
2469
2469
  },
2470
2470
  // Shown on the Options page, so you can tell which name this browser got.
@@ -2472,13 +2472,13 @@
2472
2472
  onGranted: (granted) => void chrome.storage.local.set({ grantedSites: granted }),
2473
2473
  onBlocked: (host, method) => void rememberBlocked(host, method),
2474
2474
  onLatestExtension: (version) => void chrome.storage.local.set({ latestExtension: version }),
2475
- log: (m) => console.debug("[chrome-mcp]", m)
2475
+ log: (m) => console.debug("[mcp-browser-extension]", m)
2476
2476
  });
2477
2477
  var router = new CommandRouter({
2478
2478
  exec: executor,
2479
2479
  send: (frame) => ws.send(frame),
2480
2480
  getPolicy: () => currentPolicy,
2481
- log: (m) => console.debug("[chrome-mcp]", m),
2481
+ log: (m) => console.debug("[mcp-browser-extension]", m),
2482
2482
  border
2483
2483
  });
2484
2484
  async function readBundledPairing() {
@@ -2512,7 +2512,7 @@
2512
2512
  const { reloadedFor } = await chrome.storage.local.get("reloadedFor");
2513
2513
  if (reloadedFor === onDisk.version) return;
2514
2514
  await chrome.storage.local.set({ reloadedFor: onDisk.version });
2515
- console.info(`[chrome-mcp] extension files updated on disk (${loaded} -> ${onDisk.version}); reloading`);
2515
+ console.info(`[mcp-browser-extension] extension files updated on disk (${loaded} -> ${onDisk.version}); reloading`);
2516
2516
  chrome.runtime.reload();
2517
2517
  } catch {
2518
2518
  }
@@ -2677,9 +2677,9 @@
2677
2677
  }
2678
2678
  async function syncProxy() {
2679
2679
  try {
2680
- await applyProxy((m) => console.debug("[chrome-mcp]", m));
2680
+ await applyProxy((m) => console.debug("[mcp-browser-extension]", m));
2681
2681
  } catch (err) {
2682
- console.warn("[chrome-mcp] could not apply the proxy setting", err);
2682
+ console.warn("[mcp-browser-extension] could not apply the proxy setting", err);
2683
2683
  }
2684
2684
  }
2685
2685
  async function bootstrap() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "MCP Browser Extension",
4
- "version": "0.9.25",
4
+ "version": "0.9.26",
5
5
  "description": "Lets your AI agent (Claude, Cursor, Codex) use the Chrome you are signed into, through a local MCP server. Deny-all by default.",
6
6
  "homepage_url": "https://mcp-browser-extension.com",
7
7
  "minimum_chrome_version": "116",
@@ -53,7 +53,7 @@
53
53
  <p class="hint" id="manual-intro">Or pair by hand:</p>
54
54
  <p class="hint" id="source">Checking pairing source…</p>
55
55
  <p class="hint">
56
- Manual pairing: run <code>npx -y @mehmoodqureshi/chrome-mcp@latest --print-pairing</code>,
56
+ Manual pairing: run <code>npx -y mcp-browser-extension@latest --print-pairing</code>,
57
57
  open the printed <code>handshake.json</code>, and paste its <code>port</code>
58
58
  and <code>token</code> below.
59
59
  </p>
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "mcp-browser-extension",
3
- "mcpName": "io.github.Mehmoodqureshi/chrome-mcp",
4
- "version": "0.9.25",
5
- "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.",
3
+ "mcpName": "io.github.Mehmoodqureshi/mcp-browser-extension",
4
+ "version": "0.9.26",
5
+ "description": "Drive your real Chrome browser over MCP \u2014 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.",
6
6
  "author": "Mehmood Ur Rehman Qureshi",
7
7
  "license": "MIT",
8
8
  "homepage": "https://mcp-browser-extension.com",
@@ -17,8 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "bin": {
20
- "mcp-browser-extension": "dist/src/cli.js",
21
- "chrome-mcp": "dist/src/cli.js"
20
+ "mcp-browser-extension": "dist/src/cli.js"
22
21
  },
23
22
  "files": [
24
23
  "dist/src/**/*.js",
@@ -50,11 +49,31 @@
50
49
  "claude",
51
50
  "claude-code"
52
51
  ],
52
+ "scripts": {
53
+ "build": "tsc -p tsconfig.json",
54
+ "build:ext": "node extension/scripts/build-ext.mjs",
55
+ "pack:ext": "npm run build:ext && node extension/scripts/pack-ext.mjs",
56
+ "typecheck": "tsc -p tsconfig.json --noEmit",
57
+ "typecheck:ext": "tsc -p tsconfig.ext.json",
58
+ "clean": "rimraf dist",
59
+ "test": "npm run clean && npm run build && npm run build:ext && node --test dist/test/*.test.js",
60
+ "test:hitl": "npm run build && node dist/hitl/index.js",
61
+ "prepack": "npm run clean && npm run build && npm run build:ext"
62
+ },
53
63
  "dependencies": {
54
64
  "@modelcontextprotocol/sdk": "^1.29.0",
55
65
  "ws": "^8.18.0",
56
66
  "zod": "^4.4.3"
57
67
  },
68
+ "devDependencies": {
69
+ "@types/chrome": "^0.0.287",
70
+ "@types/node": "^20.17.10",
71
+ "@types/ws": "^8.5.13",
72
+ "esbuild": "^0.24.0",
73
+ "playwright": "^1.49.1",
74
+ "rimraf": "^5.0.10",
75
+ "typescript": "^5.7.2"
76
+ },
58
77
  "engines": {
59
78
  "node": ">=18.0.0"
60
79
  }