@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 +25 -0
- package/README.md +12 -0
- package/package.json +1 -1
- package/scripts/install-claude-desktop.mjs +63 -5
- package/src/claude-bridge.mjs +1 -1
- package/src/index.mjs +1 -1
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
|
@@ -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:
|
|
40
|
-
CODEX_BRIDGE_ALLOWED_ROOTS:
|
|
41
|
-
CODEX_BRIDGE_APPROVAL:
|
|
42
|
-
CODEX_BRIDGE_APPROVAL_POLICY:
|
|
43
|
-
|
|
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.");
|
package/src/claude-bridge.mjs
CHANGED
|
@@ -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.
|
|
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.
|
|
22
|
+
const VERSION = "1.11.1";
|
|
23
23
|
const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
|
|
24
24
|
|
|
25
25
|
/**
|