@minhspark/codex-mcp-bridge 1.11.0 → 1.11.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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [SemVer](https://semver.org/).
4
4
 
5
+ ## [1.11.1] - 2026-08-23
6
+
7
+ ### Fixed
8
+
9
+ - **Re-running `codex-mcp-bridge-install` deleted settings it does not write.** It assigned a whole new
10
+ entry over the old one, so `CODEX_BRIDGE_ALLOWED_THREADS`, a hand-added `CODEX_BRIDGE_THREAD_POLICY`
11
+ and any key from a later version were dropped, and `CODEX_BRIDGE_ALLOWED_ROOTS` was reset to the
12
+ install directory. Upgrading is exactly when people re-run it, so the command you reach for to keep
13
+ the bridge current was the command that silently broke it. Measured on a config carrying four custom
14
+ values: all four gone, roots narrowed from two projects to the install directory, other MCP servers
15
+ untouched.
16
+
17
+ Existing values are now the fallback rather than the casualty. Precedence, highest first: a variable
18
+ passed to this run, what the config already says, then the default. `command`, `args` and `CODEX_BIN`
19
+ are still resolved fresh — pointing the entry at the code installed now is the reason to re-run at
20
+ all. `--reset` discards inherited values for the rare case of wanting the defaults back.
21
+
22
+ ### Added
23
+
24
+ - The installer now writes `CODEX_BRIDGE_THREAD_POLICY` explicitly, and when it is left at `owned` it
25
+ says what that means: a thread opened in the Codex app or the VS Code extension will answer
26
+ `NOT AUTHORIZED`, because its id is assigned as it opens and cannot be allowlisted in advance. Shipping
27
+ 1.11.0 without this left the fix reachable only by reading the environment table — and the symptom
28
+ points nowhere near the setting responsible.
29
+
5
30
  ## [1.11.0] - 2026-08-23
6
31
 
7
32
  ### Added
package/README.md CHANGED
@@ -88,6 +88,16 @@ npm install -g git+https://github.com/buidangminh23/codex-mcp-bridge.git
88
88
 
89
89
  Either route puts four commands on your PATH — `codex-mcp-bridge` and `claude-mcp-bridge` are the two servers, `codex-mcp-bridge-install` and `claude-mcp-bridge-install` do the wiring in the steps below. Wherever this README runs `node scripts/install-claude-desktop.mjs`, an installed copy runs `codex-mcp-bridge-install` instead.
90
90
 
91
+ #### Upgrading an install you already have
92
+
93
+ ```bash
94
+ npm install -g @minhspark/codex-mcp-bridge@latest
95
+ ```
96
+
97
+ Then restart Claude Desktop or Claude Code — an MCP server only loads its code when the client spawns it. Check `codex_bridge_status` reports the version you expect. The config needs no edit: the global install path carries no version number, so the entry keeps pointing at the right file.
98
+
99
+ Re-running `codex-mcp-bridge-install` is **not** required to upgrade, and before 1.11.1 it actively hurt: it replaced the whole entry, discarding `CODEX_BRIDGE_ALLOWED_THREADS`, any hand-added `CODEX_BRIDGE_THREAD_POLICY`, and resetting `CODEX_BRIDGE_ALLOWED_ROOTS` to the install directory. From 1.11.1 it keeps what is already there — an environment variable you pass wins, the existing value is the fallback, and `--reset` gives you the defaults back.
100
+
91
101
  **Clone it** — right if you intend to read, test or change the code:
92
102
 
93
103
  ```bash
@@ -96,6 +106,8 @@ cd codex-mcp-bridge
96
106
  npm install
97
107
  ```
98
108
 
109
+ A clone upgrades with `git pull && npm ci`, then the same restart.
110
+
99
111
  Confirm the tree is healthy before wiring it into anything:
100
112
 
101
113
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhspark/codex-mcp-bridge",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "description": "Two-way MCP bridge between Claude and Codex: prompts into a live Codex thread, messages into a running Claude Code session.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -7,6 +7,7 @@ import { PLATFORM_LABEL, claudeDesktopConfigPath, resolveCodexBin } from "../src
7
7
 
8
8
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
9
  const cfgPath = process.env.CLAUDE_DESKTOP_CONFIG ?? claudeDesktopConfigPath();
10
+ const reset = process.argv.includes("--reset");
10
11
 
11
12
  /**
12
13
  * When the package is installed as a dependency its own directory is never a
@@ -31,16 +32,55 @@ fs.mkdirSync(path.dirname(cfgPath), { recursive: true });
31
32
 
32
33
  const cfg = fs.existsSync(cfgPath) ? JSON.parse(fs.readFileSync(cfgPath, "utf8")) : {};
33
34
  cfg.mcpServers = cfg.mcpServers ?? {};
35
+
36
+ /**
37
+ * Re-running the installer used to assign a whole new entry over the old one,
38
+ * which silently deleted every setting the installer does not itself write -
39
+ * CODEX_BRIDGE_ALLOWED_THREADS and a hand-added CODEX_BRIDGE_THREAD_POLICY
40
+ * among them - and reset CODEX_BRIDGE_ALLOWED_ROOTS back to the install
41
+ * directory. Upgrading is the moment people re-run this, so the command they
42
+ * reach for to keep the bridge current was the command that broke it.
43
+ *
44
+ * Existing values are now the fallback rather than the casualty. Precedence,
45
+ * highest first: an environment variable passed to this run, what the config
46
+ * already says, then the default. `--reset` drops the middle one for the rare
47
+ * case of wanting the defaults back.
48
+ */
49
+ const previousEnv = (reset ? {} : cfg.mcpServers["codex-bridge"]?.env) ?? {};
50
+ const settled = (name, fallback) => process.env[name] ?? previousEnv[name] ?? fallback;
51
+
52
+ const kept = Object.keys(previousEnv).filter(
53
+ (name) => process.env[name] === undefined && name !== "CODEX_BIN",
54
+ );
55
+
34
56
  cfg.mcpServers["codex-bridge"] = {
35
57
  command: nodeBin,
36
58
  args: [path.join(root, "src", "index.mjs")],
37
59
  env: {
60
+ /**
61
+ * Keys this installer knows nothing about survive too - a setting added by
62
+ * a later version, or by hand, is not this script's to throw away.
63
+ */
64
+ ...previousEnv,
65
+ /**
66
+ * These three are the point of re-running: they name where the code and
67
+ * the codex binary actually live now, so they are resolved fresh rather
68
+ * than inherited.
69
+ */
38
70
  CODEX_BIN: codexBin,
39
- CODEX_APP_SERVER_URL: process.env.CODEX_APP_SERVER_URL ?? "ws://127.0.0.1:8791",
40
- CODEX_BRIDGE_ALLOWED_ROOTS: process.env.CODEX_BRIDGE_ALLOWED_ROOTS ?? defaultRoots,
41
- CODEX_BRIDGE_APPROVAL: process.env.CODEX_BRIDGE_APPROVAL ?? "deny",
42
- CODEX_BRIDGE_APPROVAL_POLICY: process.env.CODEX_BRIDGE_APPROVAL_POLICY ?? "on-request",
43
- CODEX_BRIDGE_SANDBOX: process.env.CODEX_BRIDGE_SANDBOX ?? "workspace-write",
71
+ CODEX_APP_SERVER_URL: settled("CODEX_APP_SERVER_URL", "ws://127.0.0.1:8791"),
72
+ CODEX_BRIDGE_ALLOWED_ROOTS: settled("CODEX_BRIDGE_ALLOWED_ROOTS", defaultRoots),
73
+ CODEX_BRIDGE_APPROVAL: settled("CODEX_BRIDGE_APPROVAL", "deny"),
74
+ CODEX_BRIDGE_APPROVAL_POLICY: settled("CODEX_BRIDGE_APPROVAL_POLICY", "on-request"),
75
+ /**
76
+ * Written out even at its default so it is visible in the file. Left
77
+ * implicit, the one setting that decides whether the bridge can reach a
78
+ * thread a human opened is a variable you have to already know exists -
79
+ * and the symptom when you do not, every thread answering NOT AUTHORIZED,
80
+ * points nowhere near it.
81
+ */
82
+ CODEX_BRIDGE_THREAD_POLICY: settled("CODEX_BRIDGE_THREAD_POLICY", "owned"),
83
+ CODEX_BRIDGE_SANDBOX: settled("CODEX_BRIDGE_SANDBOX", "workspace-write"),
44
84
  ...(process.env.CODEX_BRIDGE_MODEL ? { CODEX_BRIDGE_MODEL: process.env.CODEX_BRIDGE_MODEL } : {}),
45
85
  ...(process.env.CODEX_BRIDGE_EFFORT ? { CODEX_BRIDGE_EFFORT: process.env.CODEX_BRIDGE_EFFORT } : {}),
46
86
  },
@@ -55,6 +95,14 @@ fs.writeFileSync(cfgPath, `${JSON.stringify(cfg, null, 2)}\n`, "utf8");
55
95
  console.log(`platform: ${PLATFORM_LABEL}`);
56
96
  console.log(`updated ${cfgPath}`);
57
97
  console.log(JSON.stringify(cfg.mcpServers["codex-bridge"], null, 2));
98
+
99
+ if (reset) {
100
+ console.log("\n--reset: existing values were discarded in favour of the defaults.");
101
+ } else if (kept.length) {
102
+ console.log(`\nkept from the existing entry: ${kept.join(", ")}`);
103
+ console.log("Pass the variable to override one, or --reset to drop them all.");
104
+ }
105
+
58
106
  const writtenRoots = cfg.mcpServers["codex-bridge"].env.CODEX_BRIDGE_ALLOWED_ROOTS;
59
107
  if (writtenRoots.split(path.delimiter).some((entry) => entry.split(path.sep).includes("node_modules"))) {
60
108
  console.log(
@@ -64,4 +112,14 @@ if (writtenRoots.split(path.delimiter).some((entry) => entry.split(path.sep).inc
64
112
  );
65
113
  }
66
114
 
115
+ if (cfg.mcpServers["codex-bridge"].env.CODEX_BRIDGE_THREAD_POLICY === "owned") {
116
+ console.log(
117
+ "\nNOTE: thread policy is `owned` - this bridge may only act on threads it created itself.\n" +
118
+ "A thread you open in the Codex app or the VS Code extension will answer NOT AUTHORIZED,\n" +
119
+ "because its id is assigned as it opens and cannot be allowlisted in advance. To let the\n" +
120
+ "bridge reach any thread working inside CODEX_BRIDGE_ALLOWED_ROOTS, re-run with:\n" +
121
+ " CODEX_BRIDGE_THREAD_POLICY=roots codex-mcp-bridge-install",
122
+ );
123
+ }
124
+
67
125
  console.log("\nRestart Claude Desktop to load the bridge.");
@@ -8,7 +8,7 @@ import { PLATFORM_LABEL } from "./platform.mjs";
8
8
  import { PeerEndpoint, findClaudeSession, listClaudeSessions, readTranscript } from "./peer-protocol.mjs";
9
9
  import { runTurn } from "./turn.mjs";
10
10
 
11
- const VERSION = "1.11.0";
11
+ const VERSION = "1.11.1";
12
12
  const FORWARD_MIN_INTERVAL_MS = 5000;
13
13
  const FORWARD_MAX_PER_SESSION = 50;
14
14
 
package/src/index.mjs CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  import { runTurn } from "./turn.mjs";
20
20
  import { BridgeSecurityPolicy } from "./security-policy.mjs";
21
21
 
22
- const VERSION = "1.11.0";
22
+ const VERSION = "1.11.1";
23
23
  const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
24
24
 
25
25
  /**