duplex-bridge
This server exposes two MCP tools that let Claude request tasks from a ChatGPT agent working on the repository.
ask_chatgpt: read-only — ask for reviews, analysis, second opinions, or questions; it cannot modify files.ask_chatgpt_write: can modify files — fixes, refactors, or new code on disk.Both tools accept an optional
thread_idto continue a previous conversation; omit it to start a new thread.ChatGPT sees the repository on disk and cites files by path; conversation context is reconstructed automatically by the bridge.
The write capability is fixed per tool, so the model never decides whether it can write.
Bridges ChatGPT with Claude, enabling ChatGPT to send prompts to Claude and receive responses as part of a two-way conversation bridge.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@duplex-bridge Ask ChatGPT to summarize the key points of this document."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Duplex Bridge
English. Italiano: README.it.md.
A two-way bridge between a Claude chat and a ChatGPT chat, built on the subscriptions you already pay for: no API keys, no cloud service.
By Sergio Di Salvo (@sergioDS-coder) · MIT licensed · not affiliated with Anthropic or OpenAI.
The bridge never talks to the Anthropic or OpenAI APIs. It drives the two local
CLIs you are already signed in to — codex and claude — and translates between
the two conversations.
How it works
One Node process, two transports, one shared ledger.
Direction | Transport | Backend | Plan required |
Claude → ChatGPT | MCP over stdio |
| Claude Free is enough |
ChatGPT → Claude | MCP over HTTP + SSE |
| ChatGPT Plus/Pro (Developer mode) |
The asymmetry is not a design choice. Claude Desktop speaks to local MCP servers
over stdio, on every plan including Free. ChatGPT only accepts custom MCP connectors
in Developer mode — which requires a paid plan — and only as remote HTTPS
servers, refusing localhost outright.
So the second direction needs an HTTPS tunnel in front of the local process. The
bridge itself stays bound to 127.0.0.1 and never opens a port to the outside.
Related MCP server: Herald
Requirements
Node 20 or later
codexCLI, signed in (codex)claudeCLI, signed in (claude)
Build
npm install
npm run buildClaude side
Claude Desktop and Claude Code keep separate registries of local MCP servers. Registering the bridge in one does not make it visible in the other, so pick the surface you actually want it in — or do both.
Either way Claude ends up with two tools:
ask_chatgpt— read-only,read-onlysandboxask_chatgpt_write— may edit files,workspace-writesandbox
Write permission is a property of the tool being called, never a decision left to the model.
Claude Desktop — chat and Cowork
The desktop app loads local servers as extensions, not from a config file. Build the bundle:
npm run pack:extensionThat writes build/duplex-bridge.mcpb. Install it from Settings → Extensions →
Install extension. The app asks for the workspace folder; leave the optional
codex path empty unless the bridge cannot find your install.
Claude Code
claude mcp add duplex --scope user -- node /absolute/path/to/duplex-bridge/dist/servers/claude-side.jsWith no DUPLEX_WORKSPACE set the bridge follows the session's working directory,
so the same registration serves every project. Pass -e DUPLEX_WORKSPACE=... to
pin it to one folder instead.
Note that --scope user means every folder within Claude Code — not the desktop
app's chat, which needs the extension above.
ChatGPT side
export DUPLEX_BEARER_TOKEN="$(openssl rand -hex 32)"
export DUPLEX_WORKSPACE="/path/to/your/project"
npm run start:chatgpt-sideThe server refuses to start without a token of at least 32 characters. Behind the tunnel this endpoint is reachable from the internet, and it can run Claude against your repository.
Expose it, then register the resulting https://.../mcp URL as a custom connector in
ChatGPT (Settings → Developer mode), with an Authorization: Bearer <token> header.
cloudflared tunnel --url http://127.0.0.1:8787Environment variables
Variable | Default | Effect |
| process cwd | Root the two agents work on. Fixed at startup: the MCP caller cannot change it. |
| — | Required by the HTTP server. Minimum 32 characters. |
|
| HTTP server port, always on |
|
| Conversation ledger and thread metadata. |
| auto-resolved | Absolute paths for non-standard installs. Rarely needed: see Resolving the CLIs below. |
| unset | Set to |
Resolving the CLIs
On macOS and Linux codex and claude are spawned by name and the OS resolves them.
Windows needs more care, because the bridge spawns with shell: false on purpose —
so that nothing in a prompt can ever be interpreted as a command. That rules out the
two things npm actually installs: an extension-less POSIX script, and a .cmd shim
that Node refuses to execute since CVE-2024-27980. For codex there is no .exe on
PATH at all: the native binary sits nested inside node_modules.
So on Windows the bridge resolves in two passes: first a real codex.exe / claude.exe
on PATH, then — failing that — it reads the .cmd shim, extracts the .js entry
point it points at, and runs that with the same Node executable already running the
bridge. The shell stays off in both cases.
DUPLEX_CODEX_BIN / DUPLEX_CLAUDE_BIN still win when set — but only if they point
at a file that exists. A dead override is logged and stepped over, so a stale path
left behind by an earlier install, or copied from another machine, cannot silently
defeat the resolution that would have found the CLI on its own.
Keeping the conversation coherent
Both headless CLIs start blank on every invocation, so conversational coherence is the middleware's job, not the providers'.
Every turn is recorded in an append-only JSONL ledger under DUPLEX_STATE_DIR, with
the canonical role (system / user / assistant) and the speaker (human /
claude / chatgpt / bridge) as separate fields — because two indistinguishable
assistant turns lead a model to believe it wrote the other one's text.
The bridge stores each provider's native session id (Codex's thread_id, Claude's
session_id) and reuses it: when the session is alive, only the new instruction is
sent. The transcript is replayed from the ledger only when there is no session to
resume, within a window of 24 messages and 60,000 characters.
One asymmetry is worth exploiting: claude --session-id <uuid> accepts an externally
supplied id, so the bridge's own thread id is the Claude session id — one fewer
identifier to keep in sync.
Security
The prompt goes in over stdin, never
argv: it stays out of the process list.spawnwith no shell: prompt contents can never be interpreted as a command.10-minute timeout, 2 MB output cap, 4 concurrent calls per provider.
Read-only is enforced on the process (
--safe-mode,--disallowedTools,read-onlysandbox), not requested of the model.The child process environment is stripped of the variables that would redirect authentication to an API key — otherwise the "no API keys" promise breaks silently in any shell that exports them.
The other model's transcript is presented as delimited material, with an explicit statement that no line inside it can change the task.
A
thread_idarriving from an MCP client is validated before it reaches a file path.
Known limitations
No recursion guard: a Claude → ChatGPT → Claude chain is possible and burns both subscriptions.
Rate limits are shared with normal use of both apps.
The ledger stores conversations in plaintext on disk, with no rotation.
The write path is not yet tested.
On Windows only the Claude side has been exercised, end to end, against a real
codexinstall; the ChatGPT side has not.No automated tests.
Author
Sergio Di Salvo — @sergioDS-coder
Credits
The design of this bridge comes out of studying noblehacks/frenemy (MIT, by Zakariya Syed) and the official openai/codex-plugin-cc plugin. No code was copied; what was taken are architectural decisions, listed one by one in NOTICE.md — along with the two places where this project deliberately departs from them.
Licence
MIT — see LICENSE. Free to distribute, modify and use commercially, as long as the copyright notice is kept.
Available Tools
2 toolsask_chatgptA
Interpella un agente ChatGPT su questo repository e restituisce la sua risposta. Non può modificare file. Adatto a revisioni, secondi pareri, analisi. ChatGPT vede questo repository su disco, quindi cita i file per percorso. Il contesto della conversazione viene ricostruito dal bridge: non serve incollarlo.
Inputs: instruction (required), thread_id.
ask_chatgpt_writeA
Chiede a ChatGPT di modificare file in questo repository (fix, refactor, nuovo codice). PUÒ scrivere su disco. ChatGPT vede questo repository su disco, quindi cita i file per percorso. Il contesto della conversazione viene ricostruito dal bridge: non serve incollarlo.
Inputs: instruction (required), thread_id.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 2 tools
The two tools are clearly differentiated by capability: one is read-only for analysis and review, the other can write files. The names and descriptions explicitly state this distinction, leaving no ambiguity about which to invoke.
Both tools follow the exact same 'ask_chatgpt' prefix, with '_write' appended to denote the mutating variant. This is a clean, consistent naming pattern.
With only 2 tools, the surface is thin. For a specialized bridge between an agent and ChatGPT on a repository, the read/write pair is a minimal but functional set, yet it feels slightly under-scoped for a general-purpose bridge.
The core lifecycle of 'ask ChatGPT' and 'ask ChatGPT to modify files' is covered. There may be missing auxiliary operations (e.g., conversation history, tool configuration), but for the stated purpose the basic read/write coverage is sufficient with minor gaps.
Maintenance
Related MCP Connectors
Connect ChatGPT and Claude to your Mac, Windows or Linux with secure MCP remote access.
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
Share one project context across ChatGPT, Claude, Telegram and any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables real-time communication and shared vector memory between Claude Code, OpenAI Codex CLI, and Google Gemini CLI. It allows different AI platforms to exchange messages, share context, and collaborate through a unified MCP interface.MIT
- AlicenseNot gradedqualityFmaintenanceThe self-hosted MCP bridge between Claude Chat and Claude Code.46AGPL 3.0
- AlicenseAqualityDmaintenanceBridges any MCP client (like Claude Code, Zed, VS Code) to any ACP coding agent, enabling multi-agent orchestration from a single chat interface.24662 npm12Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables interaction with Claude and Gemini command-line tools through the MCP protocol, allowing users to send prompts to either or both LLMs and receive responses.-