@minhspark/codex-mcp-bridge 1.21.3 → 1.21.5

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-mcp-bridge",
3
- "version": "1.21.3",
3
+ "version": "1.21.5",
4
4
  "description": "Connect ChatGPT to your own Codex Desktop projects and conversations.",
5
5
  "author": {
6
6
  "name": "Bui Dang Minh"
package/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [SemVer](ht
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.21.5] - 2026-10-11
8
+
9
+ ### Fixed
10
+
11
+ - README npm download badges no longer show "rate limited by upstream service". The total and monthly badges are now rendered from the archived daily npm totals and served from the analytics branch, refreshed hourly, instead of shields.io.
12
+
13
+ ### Upgrade notes
14
+
15
+ - MCP behavior is unchanged.
16
+
17
+ ## [1.21.4] - 2026-10-11
18
+
19
+ ### Added
20
+
21
+ - Add the Glama ownership manifest to the repository and published package so the directory can identify the maintainer.
22
+ - Document Glama metadata synchronization, hosted usage limitations, and Docker infrastructure failures.
23
+
24
+ ### Upgrade notes
25
+
26
+ - MCP behavior is unchanged. Glama must synchronize the repository to detect the manifest; its Docker service must be available before a new hosted release can be built.
27
+
7
28
  ## [1.21.3] - 2026-10-10
8
29
 
9
30
  ### Changed
package/README.md CHANGED
@@ -7,8 +7,8 @@
7
7
  Local Desktop handoff guides: [daily workflow and directory verification](docs/daily-handoffs.md), [new-machine setup and permissions](docs/new-machine-setup.md), and [project onboarding](docs/project-onboarding.md).
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/@minhspark/codex-mcp-bridge?logo=npm&color=CB3837)](https://www.npmjs.com/package/@minhspark/codex-mcp-bridge)
10
- [![npm downloads](https://img.shields.io/npm/dt/@minhspark/codex-mcp-bridge?logo=npm&label=npm%20downloads&color=CB3837)](https://www.npmjs.com/package/@minhspark/codex-mcp-bridge)
11
- [![npm downloads / month](https://img.shields.io/npm/dm/@minhspark/codex-mcp-bridge?logo=npm&label=npm%20downloads%20%2F%20month&color=CB3837)](https://www.npmcharts.com/compare/%40minhspark%2Fcodex-mcp-bridge?minimal=true)
10
+ [![npm downloads](https://raw.githubusercontent.com/buidangminh23/codex-mcp-bridge/analytics/stats-npm-downloads.svg)](https://www.npmjs.com/package/@minhspark/codex-mcp-bridge)
11
+ [![npm downloads / month](https://raw.githubusercontent.com/buidangminh23/codex-mcp-bridge/analytics/stats-npm-downloads-month.svg)](https://www.npmcharts.com/compare/%40minhspark%2Fcodex-mcp-bridge?minimal=true)
12
12
  [![Used by repositories (Libraries.io)](https://img.shields.io/librariesio/dependent-repos/npm/@minhspark/codex-mcp-bridge?label=Used%20by&logo=github&color=0969da)](https://github.com/buidangminh23/codex-mcp-bridge/network/dependents)
13
13
  [![skills.sh installs](https://skills.sh/b/buidangminh23/codex-mcp-bridge?label=skills.sh)](https://skills.sh/buidangminh23/codex-mcp-bridge/codex-bridge)
14
14
  [![GitHub views / source window](https://raw.githubusercontent.com/buidangminh23/codex-mcp-bridge/analytics/stats-github-views.svg)](https://buidangminh23.github.io/codex-mcp-bridge/)
@@ -450,6 +450,14 @@ WHERE day >= (CURRENT_TIMESTAMP AT TIME ZONE 'UTC')::date - 29;
450
450
 
451
451
  ## Development
452
452
 
453
+ ### Glama directory
454
+
455
+ The repository includes [glama.json](glama.json) with the maintainer's GitHub username, using [Glama's server schema](https://glama.ai/mcp/schemas/server.json). After changing it, use the listing's **Sync Server** action or repeat the ownership claim to refresh Glama's copy. See [Glama's manifest documentation](https://glama.ai/blog/2025-07-08-what-is-glamajson).
456
+
457
+ Glama's recent usage signal measures calls observed by Glama, independently of npm downloads and the bridge's opt-in installation analytics. Use **Try in Browser** and the read-only `codex_bridge_status` tool to check a hosted release. A cloud container cannot access the Codex Desktop app or signed-in sessions on a user's machine; run the bridge locally for those workflows. Related servers are managed separately in Glama's listing.
458
+
459
+ If a Glama test reports `DockerBuildError` with HTTP `502 Bad Gateway` and an empty build log, the Docker service request failed without an application build log. Retry when that service recovers. If it persists, provide Glama support with the test ID, timestamp, and error details. Changing `npm ci` or the launcher cannot repair that upstream failure; investigate repository build steps only when their logs identify an application error.
460
+
453
461
  ### Shared project scope for Desktop Code conversations
454
462
 
455
463
  See [Desktop handoff design and recovery](docs/desktop-handoff-design.md) for the failure cases, integration with current upstream, and validation limits.
package/glama.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://glama.ai/mcp/schemas/server.json",
3
+ "maintainers": [
4
+ "buidangminh23"
5
+ ]
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhspark/codex-mcp-bridge",
3
- "version": "1.21.3",
3
+ "version": "1.21.5",
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",
@@ -43,6 +43,7 @@
43
43
  "mcp.json",
44
44
  ".codex-plugin",
45
45
  ".mcp.json",
46
+ "glama.json",
46
47
  "README.md",
47
48
  "LICENSE",
48
49
  "CHANGELOG.md",
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.21.3",
4
+ "version": "1.21.5",
5
5
  "description": "Connect ChatGPT to your own Codex Desktop projects and conversations.",
6
6
  "author": {
7
7
  "name": "Bui Dang Minh",
@@ -23,7 +23,7 @@ import { enableCodexFullAccess, fullAccessEnabled } from "../src/codex-full-acce
23
23
 
24
24
  exitForVersionRequest(import.meta.url);
25
25
 
26
- const VERSION = "1.21.3";
26
+ const VERSION = "1.21.5";
27
27
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
28
28
  const entry = path.join(root, "src", "mcp-supervisor.mjs");
29
29
  const entryArgs = ["native-relay-companion.mjs"];
@@ -121,11 +121,31 @@ export function renderGithubViewsBadge(data, { now = Date.now() } = {}) {
121
121
  const message = format(value) + age;
122
122
  const color = value == null ? '#555' : stale || undated ? '#92400e' : '#0369a1';
123
123
  const detail = `${validWindow ? `${start} to ${end} UTC` : 'Source window unavailable'}. Source: ${displayTime(time)}. Archived badge; freshness is relative to generation time.`;
124
+ return renderBadge(label, message, color, detail);
125
+ }
126
+
127
+ function renderBadge(label, message, color, detail) {
124
128
  const labelWidth = Math.ceil([...label].length * 7.2 + 16);
125
129
  const messageWidth = Math.ceil([...message].length * 7.2 + 16);
126
130
  const width = labelWidth + messageWidth;
127
131
  const accessible = `${label}: ${message}`;
128
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="24" viewBox="0 0 ${width} 24" role="img" aria-label="${escapeXml(accessible)}"><title>${escapeXml(`${accessible}. ${detail}`)}</title><rect width="${width}" height="24" rx="4" fill="#555"/><path d="M${labelWidth} 0H${width - 4}Q${width} 0 ${width} 4V20Q${width} 24 ${width - 4} 24H${labelWidth}Z" fill="${color}"/><g fill="#fff" font-family="DejaVu Sans Mono,monospace" font-size="12" text-anchor="middle"><text x="${labelWidth / 2}" y="16">${escapeXml(label)}</text><text x="${labelWidth + messageWidth / 2}" y="16">${escapeXml(message)}</text></g></svg>\n`;
132
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="24" viewBox="0 0 ${width} 24" role="img" aria-label="${escapeXml(accessible)}"><title>${escapeXml(`${accessible}. ${detail}`)}</title><rect width="${width}" height="24" rx="4" fill="#555"/><path d="M${labelWidth} 0H${width - 4}Q${width} 0 ${width} 4V20Q${width} 24 ${width - 4} 24H${labelWidth}Z" fill="${color}"/><g fill="#fff" font-family="DejaVu Sans Mono,monospace" font-size="12" text-anchor="middle"><text x="${labelWidth / 2}" y="16">${escapeXml(label)}</text><text x="${labelWidth + messageWidth / 2}" y="16">${escapeXml(message)}</text></g></svg>
133
+ `;
134
+ }
135
+
136
+ export function renderNpmDownloadsBadge(data, { now = Date.now(), period = 'archive' } = {}) {
137
+ const snapshot = [...data.snapshots].sort((a, b) => String(b.collectedAt).localeCompare(String(a.collectedAt))).find(row => row.npm);
138
+ const time = snapshot?.sourceCollectedAt?.npm;
139
+ const rows = period === 'window' ? snapshot?.npm?.downloads || [] : Object.entries(data.daily?.npm || {}).map(([day, row]) => ({ day, downloads: row.downloads }));
140
+ const days = rows.map(row => row.day).filter(Boolean).sort();
141
+ const value = rows.length && rows.every(row => row.downloads != null) ? rows.reduce((total, row) => total + row.downloads, 0) : null;
142
+ const label = period === 'window' ? `npm downloads / ${days.length ? `${days.length}d` : 'window'}` : 'npm downloads';
143
+ const undated = !date(time);
144
+ const stale = !undated && now - Date.parse(time) > staleAfter;
145
+ const message = format(value) + (value == null ? '' : undated ? ' · undated' : stale ? ' · stale' : '');
146
+ const color = value == null ? '#555' : stale || undated ? '#92400e' : '#CB3837';
147
+ const detail = `${days.length ? `${days[0]} to ${days.at(-1)} UTC` : 'Source window unavailable'}. Source: ${displayTime(time)}. Archived daily npm totals; freshness is relative to generation time.`;
148
+ return renderBadge(label, message, color, detail);
129
149
  }
130
150
 
131
151
  export function renderLiveDashboard(data) {
@@ -218,7 +238,7 @@ export function publicFiles(history, usage) {
218
238
  const table = ['| Date (UTC) | Views | Unique visitors | Clones | Unique cloners | npm downloads | Active installations |', '|---|---:|---:|---:|---:|---:|---:|', ...days.map(day => `| ${day} | ${[data.daily.views[day]?.count, data.daily.views[day]?.uniques, data.daily.clones[day]?.count, data.daily.clones[day]?.uniques, data.daily.npm[day]?.downloads, usageDays[day]].map(format).join(' | ')} |`)].join('\n');
219
239
  const readme = `# Public repository analytics\n\n![Repository dashboard](dashboard.svg)\n\n[Aggregate JSON history](data.json) · [Repository](https://github.com/${data.repo})\n\nAll dates and source windows use UTC. Source timestamps on the dashboard show when each metric was last available. Downloads and clones include automation and do not measure people. Unique visitors/cloners apply only to the source window; never sum daily unique counts across dates. Active installations cover consenting installations only, with distinct counts for each whole period. Operating system and version breakdowns cover 30 days; an installation may appear in multiple version groups after upgrading.\n\nThis branch contains only aggregate statistics. No installation identifiers, prompts, account details, credentials, private error messages, or local paths are published. Missing metrics mean unavailable, not zero.\n\n## Daily history\n\nEvery archived source day is listed below, newest first. Active installations count consenting installations that reported that UTC day.\n\n${table}\n`;
220
240
  const pagesUrl = `https://${data.repo.split('/')[0]}.github.io/${data.repo.split('/')[1]}/`;
221
- return { 'stats-github-views.svg': renderGithubViewsBadge(data), 'dashboard.svg': renderPublicDashboard(data), 'README.md': readme.replace('![Repository dashboard]', `[Live dashboard · refreshes every 30 seconds](${pagesUrl})\n\n![Repository dashboard]`), 'data.json': `${JSON.stringify(data, null, 2)}\n`, 'index.html': renderLiveDashboard(data) };
241
+ return { 'stats-github-views.svg': renderGithubViewsBadge(data), 'stats-npm-downloads.svg': renderNpmDownloadsBadge(data), 'stats-npm-downloads-month.svg': renderNpmDownloadsBadge(data, { period: 'window' }), 'dashboard.svg': renderPublicDashboard(data), 'README.md': readme.replace('![Repository dashboard]', `[Live dashboard · refreshes every 30 seconds](${pagesUrl})\n\n![Repository dashboard]`), 'data.json': `${JSON.stringify(data, null, 2)}\n`, 'index.html': renderLiveDashboard(data) };
222
242
  }
223
243
 
224
244
  export function githubEnvironment(token, env = process.env) {
@@ -29,7 +29,7 @@ import { registerProjectOnboardingTools } from "./project-onboarding-tools.mjs";
29
29
 
30
30
  exitForVersionRequest(import.meta.url);
31
31
 
32
- const VERSION = "1.21.3";
32
+ const VERSION = "1.21.5";
33
33
  void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
34
34
  const FORWARD_MIN_INTERVAL_MS = 5000;
35
35
  const FORWARD_MAX_PER_SESSION = 50;
package/src/index.mjs CHANGED
@@ -39,7 +39,7 @@ import { PROJECT_SETUP_TOOLS, registerProjectOnboardingTools } from "./project-o
39
39
 
40
40
  exitForVersionRequest(import.meta.url);
41
41
 
42
- const VERSION = "1.21.3";
42
+ const VERSION = "1.21.5";
43
43
  void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
44
44
  const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
45
45
 
@@ -36,7 +36,7 @@ import { NativeCreationReceipts, creationIdValid } from "./native-creation-recei
36
36
 
37
37
  exitForVersionRequest(import.meta.url);
38
38
 
39
- const VERSION = "1.21.3";
39
+ const VERSION = "1.21.5";
40
40
  const log = (msg) => process.stderr.write(`[native-relay] ${msg}\n`);
41
41
 
42
42
  function errorResponse(code, message, sent) {