@minhspark/codex-mcp-bridge 1.26.8 → 1.26.9
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/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/install-antigravity-bridge.mjs +3 -5
- package/scripts/install-codex-mcp.mjs +2 -5
- package/scripts/install-native-relay.mjs +4 -7
- package/scripts/setup.mjs +2 -1
- package/scripts/update.mjs +20 -11
- package/src/claude-bridge.mjs +1 -1
- package/src/codex-mcp-registration.mjs +21 -0
- package/src/index.mjs +1 -1
- package/src/native-relay-companion.mjs +1 -1
- package/src/setup.mjs +18 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,26 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [SemVer](ht
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.26.9] - 2026-11-03
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Shorten the "Applying managed settings" step of `npx @minhspark/codex-mcp-bridge@latest`. Each Codex `mcp` command takes several seconds to start on a machine with many MCP servers and plugins, and one update ran about sixteen of them. The Codex installers now read their own entry with one `codex mcp get` instead of listing every server first, the verification reads all three registrations from a single `codex mcp list`, and the updater no longer runs a second, separate verification process after setup has already verified the saved settings.
|
|
12
|
+
- Show which component the updater is configuring while managed settings are applied, instead of a single line that looked frozen for a minute or more.
|
|
13
|
+
- Stop reporting `MCP registration is missing` for `claude-bridge`, `codex-native-relay` and `antigravity-bridge` when Codex CLI was merely too slow to answer. A slow inventory now says so, and the three registrations are reported as not checked. Codex `mcp` commands used by setup may take up to 120 seconds instead of 30, so a busy computer no longer fails an otherwise complete update.
|
|
14
|
+
|
|
15
|
+
### Verification
|
|
16
|
+
|
|
17
|
+
- Regression coverage checks that verification makes exactly one Codex inventory call, that only Codex's own "No MCP server named" error counts as an absent entry, that a timed-out inventory is reported as unchecked, and that the updater runs setup once and relays only its progress lines.
|
|
18
|
+
|
|
19
|
+
### Upgrade
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
npx.cmd -y @minhspark/codex-mcp-bridge@latest
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This command runs the 1.26.9 updater itself, so the shorter sequence applies to this update.
|
|
26
|
+
|
|
7
27
|
## [1.26.8] - 2026-11-03
|
|
8
28
|
|
|
9
29
|
### Fixed
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "codex-mcp-bridge",
|
|
4
|
-
"version": "1.26.
|
|
4
|
+
"version": "1.26.9",
|
|
5
5
|
"description": "Connect ChatGPT to your own Codex Desktop projects and conversations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Bui Dang Minh",
|
|
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { applyStdioMcpRegistration, stdioMcpRegistration } from "../src/codex-mcp-registration.mjs";
|
|
7
|
+
import { applyStdioMcpRegistration, CODEX_MCP_TIMEOUT_MS, readCodexMcpServer, stdioMcpRegistration } from "../src/codex-mcp-registration.mjs";
|
|
8
8
|
import { bridgeEntrypointConflict, isBridgeSource, isMainModule, isNodeLauncher, stableInstallPath, stableNodeBin } from "../src/install-paths.mjs";
|
|
9
9
|
import { backupRegularConfigFile } from "../src/project-policy.mjs";
|
|
10
10
|
import { homeDir, resolveCodexBin, spawnEnv } from "../src/platform.mjs";
|
|
@@ -256,10 +256,8 @@ export function runAntigravityInstaller(args = process.argv.slice(2), { prepareR
|
|
|
256
256
|
let codexExisting = null;
|
|
257
257
|
if (options.targets.includes("codex")) {
|
|
258
258
|
const codexBin = validateCodexExecutable(resolveCodexBin(process.env.CODEX_EXE));
|
|
259
|
-
run = (command) => execFileSync(codexBin, command, { encoding: "utf8", env: spawnEnv(), windowsHide: true, shell: false, timeout:
|
|
260
|
-
|
|
261
|
-
if (!Array.isArray(inventory)) throw new Error("Codex returned an invalid MCP inventory");
|
|
262
|
-
if (inventory.some((item) => item.name === NAME)) codexExisting = JSON.parse(run(["mcp", "get", NAME, "--json"]));
|
|
259
|
+
run = (command) => execFileSync(codexBin, command, { encoding: "utf8", env: spawnEnv(), windowsHide: true, shell: false, timeout: CODEX_MCP_TIMEOUT_MS, stdio: "pipe" });
|
|
260
|
+
codexExisting = readCodexMcpServer(run, NAME);
|
|
263
261
|
}
|
|
264
262
|
const plan = planAntigravityInstallation({ ...options, home, root, node, codexExisting });
|
|
265
263
|
if (!options.remove) {
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { PLATFORM_LABEL, resolveCodexBin, spawnEnv } from "../src/platform.mjs";
|
|
8
8
|
import { exitForVersionRequest } from "../src/cli-version.mjs";
|
|
9
9
|
import { desktopTasksConfigured } from "../src/native-relay.mjs";
|
|
10
|
-
import { applyStdioMcpRegistration, codexMcpRegistration } from "../src/codex-mcp-registration.mjs";
|
|
10
|
+
import { applyStdioMcpRegistration, codexMcpRegistration, readCodexMcpServer } from "../src/codex-mcp-registration.mjs";
|
|
11
11
|
import { createReleaseSnapshot, snapshotRoot } from "../src/release-snapshot.mjs";
|
|
12
12
|
import { codexAccessPaths, enableCodexFullAccess, fullAccessEnabled } from "../src/codex-full-access.mjs";
|
|
13
13
|
import { stableInstallPath, stableNodeBin } from "../src/install-paths.mjs";
|
|
@@ -37,10 +37,7 @@ if (remove) {
|
|
|
37
37
|
process.exit(0);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const
|
|
41
|
-
if (!Array.isArray(servers)) throw new Error("Codex returned an invalid MCP inventory; existing configuration was not changed");
|
|
42
|
-
const existing = servers.some((server) => server.name === serverName)
|
|
43
|
-
? JSON.parse(run(["mcp", "get", serverName, "--json"])) : null;
|
|
40
|
+
const existing = readCodexMcpServer(run, serverName);
|
|
44
41
|
const registration = codexMcpRegistration({ name: serverName, existing, node: nodeBin, entry, entryArgs, env: process.env, desktopOnly: desktopTasksConfigured() });
|
|
45
42
|
createReleaseSnapshot(root, { cache: snapshotRoot({ ...process.env, ...registration.environment }) });
|
|
46
43
|
const applied = applyStdioMcpRegistration({ name: serverName, registration, existing, run, configPath: codexAccessPaths().config });
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
spawnEnv,
|
|
18
18
|
} from "../src/platform.mjs";
|
|
19
19
|
import { exitForVersionRequest } from "../src/cli-version.mjs";
|
|
20
|
-
import { applyStdioMcpRegistration, stdioMcpRegistration } from "../src/codex-mcp-registration.mjs";
|
|
20
|
+
import { applyStdioMcpRegistration, readCodexMcpServer, stdioMcpRegistration } from "../src/codex-mcp-registration.mjs";
|
|
21
21
|
import { createReleaseSnapshot, snapshotRoot } from "../src/release-snapshot.mjs";
|
|
22
22
|
import { codexAccessPaths, enableCodexFullAccess, fullAccessEnabled } from "../src/codex-full-access.mjs";
|
|
23
23
|
import { stableInstallPath } from "../src/install-paths.mjs";
|
|
@@ -25,7 +25,7 @@ import { removeRelayFile } from "../src/native-relay-files.mjs";
|
|
|
25
25
|
|
|
26
26
|
exitForVersionRequest(import.meta.url);
|
|
27
27
|
|
|
28
|
-
const VERSION = "1.26.
|
|
28
|
+
const VERSION = "1.26.9";
|
|
29
29
|
const root = stableInstallPath(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."));
|
|
30
30
|
const entry = path.join(root, "src", "mcp-supervisor.mjs");
|
|
31
31
|
const entryArgs = ["native-relay-companion.mjs"];
|
|
@@ -69,10 +69,7 @@ if (!IS_MACOS && !IS_WINDOWS) {
|
|
|
69
69
|
console.log("claude-bridge will keep using the app-server path here.");
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
if (!Array.isArray(servers)) throw new Error("Codex returned an invalid MCP inventory; existing configuration was not changed");
|
|
74
|
-
const existingServer = servers.some((server) => server.name === serverName)
|
|
75
|
-
? JSON.parse(run(["mcp", "get", serverName, "--json"])) : null;
|
|
72
|
+
const existingServer = readCodexMcpServer(run, serverName);
|
|
76
73
|
/**
|
|
77
74
|
* Registering under whichever Node happens to run this installer is what made
|
|
78
75
|
* the companion unreachable on macOS: Codex Desktop rejects a peer whose
|
|
@@ -105,7 +102,7 @@ if (runtime.source === "process.execPath" && hasCodexDesktopApp()) {
|
|
|
105
102
|
console.log("runtime shipped inside Codex Desktop if that happens.");
|
|
106
103
|
}
|
|
107
104
|
console.log(`registered MCP server "${serverName}" with Codex (${applied.mode === "retarget" ? "existing entry retargeted in place; its other settings were kept" : "codex mcp add"}):`);
|
|
108
|
-
console.log(run(["mcp", "get", serverName]));
|
|
105
|
+
if (!process.argv.includes("--setup")) console.log(run(["mcp", "get", serverName]));
|
|
109
106
|
if (applied.notice) console.log(`NOTE: ${applied.notice}`);
|
|
110
107
|
else if (ensureEnvVars.length) console.log(`env_vars includes ${ensureEnvVars.join(", ")}; the temporary pipe path itself is never saved.`);
|
|
111
108
|
|
package/scripts/setup.mjs
CHANGED
|
@@ -4,7 +4,8 @@ import { printSetup, runSetup, setupFailureResult } from "../src/setup.mjs";
|
|
|
4
4
|
|
|
5
5
|
exitForVersionRequest(import.meta.url);
|
|
6
6
|
try {
|
|
7
|
-
const
|
|
7
|
+
const onProgress = process.argv.includes("--progress") ? (step) => process.stderr.write(`setup-progress: ${step}\n`) : undefined;
|
|
8
|
+
const result = runSetup({ args: process.argv.slice(2), onProgress });
|
|
8
9
|
printSetup(result, { json: process.argv.includes("--json") });
|
|
9
10
|
if (result.configured === false && !result.dryRun) process.exitCode = 1;
|
|
10
11
|
} catch (error) {
|
package/scripts/update.mjs
CHANGED
|
@@ -65,9 +65,18 @@ export function resolveUpdateNpm(env = process.env) {
|
|
|
65
65
|
throw failure("UPDATE_NPM_NOT_FOUND", "A supported npm CLI could not be located. Run this updater through npm exec.", "preflight");
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
const SETUP_PROGRESS = /^setup-progress: ([^\u0000-\u001f\u007f]{1,120})$/;
|
|
69
|
+
|
|
70
|
+
function execute(command, args, { onStderrLine, ...options }) {
|
|
69
71
|
return new Promise(resolve => {
|
|
70
|
-
execFile(command, args, options, (error, stdout, stderr) => resolve({ status: error ? 1 : 0, error, stdout, stderr }));
|
|
72
|
+
const child = execFile(command, args, options, (error, stdout, stderr) => resolve({ status: error ? 1 : 0, error, stdout, stderr }));
|
|
73
|
+
if (!onStderrLine || !child.stderr) return;
|
|
74
|
+
let pending = "";
|
|
75
|
+
child.stderr.on("data", chunk => {
|
|
76
|
+
const lines = (pending + chunk).split(/\r?\n/);
|
|
77
|
+
pending = lines.pop();
|
|
78
|
+
for (const line of lines) onStderrLine(line);
|
|
79
|
+
});
|
|
71
80
|
});
|
|
72
81
|
}
|
|
73
82
|
|
|
@@ -141,11 +150,11 @@ export async function runUpdate({ args = [], env = process.env, platform = proce
|
|
|
141
150
|
const prefixArgs = userPrefix ? ["--prefix", userPrefix] : [];
|
|
142
151
|
let cwd = neutralDirectory([root], env);
|
|
143
152
|
let childEnv = Object.fromEntries(Object.entries(env).filter(([name]) => !/^AGENT_RELAY_(?!DIRECTORY$)/i.test(name)));
|
|
144
|
-
const command = async (arguments_, phase, timeout = 600000, environment = childEnv, setupCommand = false) => {
|
|
153
|
+
const command = async (arguments_, phase, timeout = 600000, environment = childEnv, setupCommand = false, onStderrLine) => {
|
|
145
154
|
let result;
|
|
146
155
|
try {
|
|
147
156
|
result = await run(process.execPath, arguments_, { env: environment, cwd, encoding: "utf8", windowsHide: true,
|
|
148
|
-
shell: false, timeout, maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] });
|
|
157
|
+
shell: false, timeout, maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"], ...(onStderrLine ? { onStderrLine } : {}) });
|
|
149
158
|
} catch (error) { throw childFailure({ error, stdout: error.stdout, stderr: error.stderr }, phase, setupCommand); }
|
|
150
159
|
if (result?.error || (result?.status ?? result?.exitCode ?? 0) !== 0) throw childFailure(result, phase, setupCommand);
|
|
151
160
|
return String(result?.stdout ?? "");
|
|
@@ -203,13 +212,13 @@ export async function runUpdate({ args = [], env = process.env, platform = proce
|
|
|
203
212
|
await command([npm, "install", "--global", "--prefix", prefix, `${PACKAGE}@${version}`, "--ignore-scripts"],
|
|
204
213
|
"installation", 600000, { ...childEnv, CODEX_BRIDGE_SKIP_SETUP: "1" });
|
|
205
214
|
if (packageVersion(globalRoot) !== version) throw failure("UPDATE_VERSION_MISMATCH", "The global package version does not match the updater version. Rerun the same update command.", "verification");
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
onProgress("Applying and verifying managed settings from the installed bridge. Each step can take up to a minute while Codex CLI reads its configuration.");
|
|
216
|
+
const setupProgress = line => { const step = SETUP_PROGRESS.exec(line)?.[1]; if (step) onProgress(` ${step}`); };
|
|
217
|
+
let setup;
|
|
218
|
+
try { setup = JSON.parse(await command([path.join(globalRoot, "scripts", "setup.mjs"), "--json", "--progress"], "verification", 600000, childEnv, true, setupProgress)); }
|
|
219
|
+
catch (error) { if (error?.code) throw error; throw failure("UPDATE_SETUP_INCOMPLETE", `Global setup did not return a verifiable result. ${SETUP_INSPECTION} ${RETRY}`, "verification"); }
|
|
220
|
+
if (setup?.configured !== true) throw failure("UPDATE_SETUP_INCOMPLETE", `The global bridge settings are incomplete. ${setupFailureSummary(setup) ?? SETUP_INSPECTION} ${RETRY}`, "verification");
|
|
221
|
+
onProgress("Verifying the owned relay runtime.");
|
|
213
222
|
const service = await awaitService(globalRoot, false, "verification");
|
|
214
223
|
return { updated: true, configured: true, version, previousVersion, migrated, service, opensApps: false, opensChats: false };
|
|
215
224
|
}
|
package/src/claude-bridge.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import { BACKGROUND_WORKER_GUIDANCE, registerBackgroundTools } from "./backgroun
|
|
|
31
31
|
|
|
32
32
|
exitForVersionRequest(import.meta.url);
|
|
33
33
|
|
|
34
|
-
const VERSION = "1.26.
|
|
34
|
+
const VERSION = "1.26.9";
|
|
35
35
|
void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
|
|
36
36
|
const FORWARD_MIN_INTERVAL_MS = 5000;
|
|
37
37
|
const FORWARD_MAX_PER_SESSION = 50;
|
|
@@ -6,6 +6,27 @@ import { backupRegularConfigFile } from "./project-policy.mjs";
|
|
|
6
6
|
|
|
7
7
|
const PRESERVED_FIELDS = ["enabled", "disabled_reason", "enabled_tools", "disabled_tools", "startup_timeout_sec", "tool_timeout_sec"];
|
|
8
8
|
|
|
9
|
+
export const CODEX_MCP_TIMEOUT_MS = 120000;
|
|
10
|
+
|
|
11
|
+
function missingServerError(error, name) {
|
|
12
|
+
const output = `${error?.stderr ?? ""}\n${error?.stdout ?? ""}\n${error?.message ?? ""}`;
|
|
13
|
+
return output.includes(`No MCP server named '${name}' found`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function readCodexMcpServer(run, name) {
|
|
17
|
+
let output;
|
|
18
|
+
try { output = run(["mcp", "get", name, "--json"]); }
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (missingServerError(error, name)) return null;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
const entry = JSON.parse(output);
|
|
24
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry) || entry.name !== name) {
|
|
25
|
+
throw new Error(`Codex returned an invalid ${name} entry; existing configuration was not changed`);
|
|
26
|
+
}
|
|
27
|
+
return entry;
|
|
28
|
+
}
|
|
29
|
+
|
|
9
30
|
function sameEnvironment(left = {}, right = {}) {
|
|
10
31
|
const keys = (value) => Object.keys(value ?? {}).sort();
|
|
11
32
|
return JSON.stringify(keys(left)) === JSON.stringify(keys(right)) && keys(left).every((key) => left[key] === right[key]);
|
package/src/index.mjs
CHANGED
|
@@ -44,7 +44,7 @@ import { BACKGROUND_WORKER_GUIDANCE, registerBackgroundTools } from "./backgroun
|
|
|
44
44
|
|
|
45
45
|
exitForVersionRequest(import.meta.url);
|
|
46
46
|
|
|
47
|
-
const VERSION = "1.26.
|
|
47
|
+
const VERSION = "1.26.9";
|
|
48
48
|
void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
|
|
49
49
|
const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
|
|
50
50
|
|
|
@@ -43,7 +43,7 @@ import { remoteCodexSocketPath, remoteNativeAdapter, remoteRequestResponse } fro
|
|
|
43
43
|
|
|
44
44
|
exitForVersionRequest(import.meta.url);
|
|
45
45
|
|
|
46
|
-
const VERSION = "1.26.
|
|
46
|
+
const VERSION = "1.26.9";
|
|
47
47
|
const log = (msg) => process.stderr.write(`[native-relay] ${msg}\n`);
|
|
48
48
|
|
|
49
49
|
function errorResponse(code, message, sent, details) {
|
package/src/setup.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { resolveCodexBin, resolvePackagedCodexBin } from "./platform.mjs";
|
|
|
8
8
|
import { readRegularConfigFile } from "./project-policy.mjs";
|
|
9
9
|
import { stableInstallPath } from "./install-paths.mjs";
|
|
10
10
|
import { resolveClaudeDesktopConfigRoot } from "./desktop-account-context.mjs";
|
|
11
|
+
import { CODEX_MCP_TIMEOUT_MS } from "./codex-mcp-registration.mjs";
|
|
11
12
|
|
|
12
13
|
const ROOT = stableInstallPath(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."));
|
|
13
14
|
const CODEX_PACKAGE = "@openai/codex@0.166.0";
|
|
@@ -64,7 +65,7 @@ export function setupFailureSummary(value) {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export function setupArguments(args) {
|
|
67
|
-
const allowed = new Set(["--postinstall", "--check", "--dry-run", "--json", "--no-download", "--help"]);
|
|
68
|
+
const allowed = new Set(["--postinstall", "--check", "--dry-run", "--json", "--no-download", "--progress", "--help"]);
|
|
68
69
|
if (args.some((arg) => !allowed.has(arg))) throw new Error("Unknown setup option; use codex-bridge-setup --help");
|
|
69
70
|
if (args.includes("--check") && args.includes("--dry-run")) throw new Error("Use --check or --dry-run, not both");
|
|
70
71
|
return Object.fromEntries([...allowed].map((arg) => [arg.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()), args.includes(arg)]));
|
|
@@ -148,6 +149,13 @@ export function setupEnvironment(env, paths, codex) {
|
|
|
148
149
|
CLAUDE_DESKTOP_CONFIG: paths.desktop, CODEX_EXE: codex, CODEX_BIN: codex };
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
function codexInventoryFailure(error) {
|
|
153
|
+
const detail = error?.message?.includes("ETIMEDOUT") || error?.code === "ETIMEDOUT"
|
|
154
|
+
? `Codex CLI did not list its MCP servers within ${CODEX_MCP_TIMEOUT_MS / 1000} seconds; the computer may be busy. Rerun the check when it is idle`
|
|
155
|
+
: error?.message ?? String(error);
|
|
156
|
+
return Object.assign(new Error(detail), error?.code ? { code: error.code } : {});
|
|
157
|
+
}
|
|
158
|
+
|
|
151
159
|
function configurationCheck(label, check, components) {
|
|
152
160
|
try { const details = check(); components.push({ name: label, status: "configured", ...details }); }
|
|
153
161
|
catch (error) { components.push(failedComponent(label, error)); }
|
|
@@ -171,15 +179,16 @@ export function checkSetup({ env = process.env, platform = process.platform, roo
|
|
|
171
179
|
let inventory;
|
|
172
180
|
configurationCheck("Codex CLI", () => {
|
|
173
181
|
codex = ensureSetupCodex({ env, paths, platform, download: false, run, resolve }).binary;
|
|
174
|
-
inventory = JSON.parse(run(codex, ["mcp", "list", "--json"], setupEnvironment(env, paths, codex),
|
|
175
|
-
|
|
182
|
+
try { inventory = JSON.parse(run(codex, ["mcp", "list", "--json"], setupEnvironment(env, paths, codex), CODEX_MCP_TIMEOUT_MS)); }
|
|
183
|
+
catch (error) { throw codexInventoryFailure(error); }
|
|
184
|
+
if (!Array.isArray(inventory)) { inventory = undefined; throw new Error("Codex returned an invalid MCP inventory"); }
|
|
176
185
|
}, components);
|
|
177
186
|
const native = platform === "win32" || platform === "darwin";
|
|
178
187
|
for (const [name, worker] of [["claude-bridge", "claude-bridge.mjs"], ...(native ? [["codex-native-relay", "native-relay-companion.mjs"]] : []), ["antigravity-bridge", "antigravity-bridge.mjs"]]) {
|
|
179
188
|
configurationCheck(`Codex / ${name}`, () => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
189
|
+
if (!inventory) throw new Error("Not checked because Codex CLI did not report its MCP servers; the registration may still be present");
|
|
190
|
+
const entry = inventory.find((server) => server?.name === name);
|
|
191
|
+
if (!entry) throw new Error("MCP registration is missing");
|
|
183
192
|
const details = assertEntry({ ...entry.transport, enabled: entry.enabled }, worker, root, name === "antigravity-bridge" ? { caller: "codex" } : {});
|
|
184
193
|
if (name === "codex-native-relay" && !entry.transport.env_vars?.includes("CODEX_APP_TOOLS_PIPE_PATH")) throw new Error("Native pipe forwarding is missing");
|
|
185
194
|
return details;
|
|
@@ -228,7 +237,7 @@ export function checkSetup({ env = process.env, platform = process.platform, roo
|
|
|
228
237
|
return { configured: components.every((item) => item.status === "configured"), liveVerified: false, components };
|
|
229
238
|
}
|
|
230
239
|
|
|
231
|
-
export function runSetup({ args = [], env = process.env, platform = process.platform, root = ROOT, run = execute, resolve = resolveCodexBin } = {}) {
|
|
240
|
+
export function runSetup({ args = [], env = process.env, platform = process.platform, root = ROOT, run = execute, resolve = resolveCodexBin, onProgress = () => {} } = {}) {
|
|
232
241
|
const options = setupArguments(args);
|
|
233
242
|
if (options.help) return { help: `Usage: codex-bridge-setup [--check|--dry-run] [--json] [--no-download]\nUpdate the package and apply managed settings in an interactive terminal with: ${platform === "win32" ? "npx.cmd" : "npx"} -y @minhspark/codex-mcp-bridge@latest\nThe updater installs the package with lifecycle scripts disabled, then directly configures Claude Desktop, Claude Code, Codex, Antigravity and the independent worker relay. CODEX_BRIDGE_SKIP_SETUP=1 opts out. Saved configuration, background relay health and loaded native app connections are verified separately.` };
|
|
234
243
|
if (options.postinstall && !automaticSetupEnabled(env)) return { skipped: true, reason: "Automatic configuration runs only for a global npm install; use codex-bridge-setup for manual setup." };
|
|
@@ -243,6 +252,7 @@ export function runSetup({ args = [], env = process.env, platform = process.plat
|
|
|
243
252
|
const base = setupEnvironment(env, paths, runtime.binary);
|
|
244
253
|
const components = [];
|
|
245
254
|
const install = (name, script, arguments_, environment = base) => {
|
|
255
|
+
onProgress(name);
|
|
246
256
|
try {
|
|
247
257
|
const output = run(process.execPath, [path.join(root, "scripts", script), ...arguments_], environment, 180000);
|
|
248
258
|
let details = {};
|
|
@@ -265,6 +275,7 @@ export function runSetup({ args = [], env = process.env, platform = process.plat
|
|
|
265
275
|
install("Codex / claude-bridge", "install-codex-mcp.mjs", ["--setup"]);
|
|
266
276
|
if (code) install("Antigravity / all components", "install-antigravity-bridge.mjs", ["--all", "--setup"]);
|
|
267
277
|
install("Independent background relay", "setup-background-relay.mjs", ["--json"]);
|
|
278
|
+
onProgress("Verifying saved settings");
|
|
268
279
|
const inspection = checkSetup({ env: base, platform, root, run, resolve: () => runtime.binary });
|
|
269
280
|
return { configured: components.every((item) => item.status === "configured") && inspection.configured, liveVerified: false,
|
|
270
281
|
cliInstalled: runtime.installed, components, verification: inspection.components,
|