codex-control-chrome-mcp 1.4.0 → 1.4.2

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/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ This project follows semantic versioning.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.4.2] - 2026-11-11
10
+
11
+ ### Fixed
12
+
13
+ - `attach` now carries `networkPolicy: { constraints: [] }`. Extension 1.26.1102.11740 passes `e.networkPolicy` to `ar.getInstance().attach(tabId, e.networkPolicy)`, and that installer reads `options.timeoutMs` before any validation, so a request without the field threw `Cannot read properties of undefined (reading 'timeoutMs')` and the debugger never attached. Every CDP tool (`chrome_navigate`, `chrome_evaluate`, `chrome_screenshot`, `chrome_cdp_send`, `chrome_attach_tab`) failed on it. Empty constraints normalize to `defaultAction: "allow"` with no rules, and the installer returns before touching declarativeNetRequest, so the field adds no policy side effect. Verified against the live extension: plain `attach` fails, `attach` with the empty policy succeeds, `Page.navigate` and `Runtime.evaluate` run.
14
+
15
+ ## [1.4.1] - 2026-07-04
16
+
17
+ ### Fixed
18
+
19
+ - The self-heal now recognizes every string the extension uses for a lost debugger attachment, not just Chrome's `Debugger is not attached`. A concurrency race soak (`scripts/concurrency-check.mjs --inject-detach`, which detaches a tab mid-command) surfaced two more that were slipping through unhealed: `Debugger unattached` (the extension's own `se`-map check) and `Detached while handling command.` (detached mid-command). `isNotAttachedError` now matches all three, so `withSession` recovers them too. Under the race soak this took unrecovered "not attached" failures from a handful to zero.
20
+
9
21
  ## [1.4.0] - 2026-07-04
10
22
 
11
23
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-control-chrome-mcp",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "MCP server and native host bridge for controlling Chrome through the Codex Chrome extension.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/mcp-server.js CHANGED
@@ -347,7 +347,13 @@ export function registerTools(server, runtime) {
347
347
  * doubles as a liveness probe that surfaces a stale attach as "not attached".
348
348
  */
349
349
  async function ensureAttached(runtime, tabId) {
350
- await runtime.request("attach", { tabId });
350
+ // The extension's attach handler passes `networkPolicy` straight to its
351
+ // declarativeNetRequest policy installer, which reads `options.timeoutMs`
352
+ // before checking anything. Omitting the field throws a TypeError and the
353
+ // attach never happens. Empty constraints normalize to defaultAction "allow"
354
+ // with no rules, which the installer returns from without installing
355
+ // anything, so this keeps the request free of side effects.
356
+ await runtime.request("attach", { tabId, networkPolicy: { constraints: [] } });
351
357
  try {
352
358
  await executeCdp(runtime, {
353
359
  tabId,
@@ -400,8 +406,13 @@ export async function withSession(runtime, tabId, run) {
400
406
  }
401
407
  }
402
408
 
409
+ // The extension surfaces a lost debugger attachment with several distinct
410
+ // strings, all of which are recoverable by a detach + re-attach:
411
+ // - "Debugger is not attached to the tab with id: N" (Chrome, via sendCommand)
412
+ // - "Debugger unattached" (extension's own se-check)
413
+ // - "Detached while handling command." (detached mid-command)
403
414
  export function isNotAttachedError(error) {
404
- return /not attached/i.test(error?.message ?? String(error ?? ""));
415
+ return /not attached|unattached|detached while/i.test(error?.message ?? String(error ?? ""));
405
416
  }
406
417
 
407
418
  async function executeCdp(runtime, { tabId, method, params = {}, timeoutMs }) {