codex-mcp-proxy
by rengarcia
README.md
# codex-mcp-proxy
Use a remote MCP server that you have already authenticated in **Codex** from **Claude Code**, without going through the server's OAuth flow a second time.
Some MCP servers only allow OAuth clients that the vendor has registered (Codex, ChatGPT, and so on), so Claude Code's own login fails or is blocked by an admin policy. This tool sidesteps that: Claude Code launches `codex-mcp-proxy` as a plain stdio MCP server, and the proxy forwards every JSON-RPC message to the remote server using the OAuth tokens Codex stored when you logged in there.
```
Claude Code --stdio--> codex-mcp-proxy --HTTPS + Bearer <Codex token>--> remote MCP server
```
## How it works
- **Server definition** comes from Codex's `~/.codex/config.toml` (`[mcp_servers.<name>]` with a `url`).
- **Tokens** come from where Codex keeps them: the macOS Keychain item with service `Codex MCP Credentials` and account `<name>|<sha256 prefix>`, or the file fallback `~/.codex/.credentials.json`. The hash input is undocumented, so the proxy enumerates the keychain items by the `<name>|` prefix when its guess misses, and `add` bakes the resolved account into the Claude Code registration so later launches go straight to it.
- **Transport** is Streamable HTTP, with automatic fallback to the older SSE transport when the server answers the first POST with 404/405.
- **Refresh**: when the access token is about to expire the proxy refreshes it with the stored refresh token and client id, then writes the new tokens back into Codex's store so both tools stay in sync (disable with `--no-write-back`).
- **No interactive login**: if refresh fails, the proxy reports a clear error telling you to log in again in Codex.
The proxy is transparent: `initialize`, tools, prompts, resources, notifications, and server-initiated requests all pass through unchanged.
## Requirements
- Node.js 20+
- Codex installed, with the MCP server already logged in there (run `codex`, then `/mcp`)
- macOS for keychain access; on other platforms Codex uses the credentials file, which is also supported
## Install
```bash
cd mcp-proxy
npm install
npm run build
npm link # puts `codex-mcp-proxy` on your PATH
```
## Usage
```bash
# 1. See which Codex MCP servers can be proxied
codex-mcp-proxy list
# 2. Verify credentials are found and the server answers
codex-mcp-proxy check glean_default
# 3. Register it with Claude Code (runs `claude mcp add` for you)
codex-mcp-proxy add glean_default --name glean --scope user
```
Then restart Claude Code (or run `/mcp`) and the server's tools appear under the name you chose.
The first time the proxy reads a Codex keychain item, macOS shows a keychain prompt. Choose **Always Allow** so Claude Code can start the proxy without prompting again. A separate prompt appears for each server's item.
### Commands
| Command | Purpose |
| --- | --- |
| `codex-mcp-proxy <server>` | Run the stdio proxy. This is what Claude Code executes. |
| `codex-mcp-proxy list` | List remote MCP servers from Codex's config. |
| `codex-mcp-proxy check <server>` | Load credentials, connect, and list the server's tools. |
| `codex-mcp-proxy add <server>` | Register the proxy with Claude Code via `claude mcp add`. |
| `codex-mcp-proxy key <server>` | Print the keychain account names that will be looked up. |
### Options
| Option | Meaning |
| --- | --- |
| `--codex-home <dir>` | Codex home (default `$CODEX_HOME` or `~/.codex`). |
| `--url <url>` | Connect to a different URL than the one in Codex's config. |
| `--account <name>` | Read exactly this keychain account instead of deriving it. |
| `--transport auto\|http\|sse` | Force a transport (default `auto`). |
| `--no-write-back` | Keep refreshed tokens in memory only. |
| `--name`, `--scope`, `--dry-run` | For `add`: Claude Code server name, config scope, or print the command only. |
| `-v, --verbose` | Debug logging on stderr. |
### Manual registration
If you prefer to edit config yourself, the equivalent of `add` is:
```bash
claude mcp add --transport stdio --scope user glean -- codex-mcp-proxy glean_default
```
## Troubleshooting
- **"No Codex OAuth credentials found"**: log in to the server in Codex first with `codex mcp login <server>` (or `/mcp` inside Codex). Run `codex-mcp-proxy key <server>` to see which keychain accounts are checked; `--account` overrides the derivation.
- **"could not be refreshed"**: the refresh token was rejected, so Codex's own session is dead too. Run `codex mcp login <server>`; the proxy picks up the new tokens on its next start. Confirm with `codex-mcp-proxy check <server>`.
- **Keychain prompt every time**: choose *Always Allow* in the macOS prompt, or the proxy has to ask on each launch.
- **Server-side 4xx after connecting**: run `check <server> -v` to see the HTTP status and transport used; `--transport sse` forces the legacy transport.
## Development
```bash
npm run build # compile to dist/
node scripts/smoke.mjs glean_default # drive the proxy over stdio like an MCP client
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues