bidirectional-bridge-claude-codex

bidirectional-bridge-claude-codex

A local, repository-scoped MCP coordination bridge that lets Claude Code and Codex work together in the same checkout via tasks, leases, and evidence-based completion, preventing conflicting edits and enabling bounded delegation.

Category
访问服务器

README

Claude Code ↔ Codex coordination bridge

Status: Experimental · Pre-1.0 · under active development · not production-certified. This is the first experimental open-source release. APIs, MCP tool shapes, persisted state, and workflows may change without notice and without a migration path. Use it only in trusted local repositories on work you can review.

A local, repository-scoped coordination bridge that lets Claude Code and Codex work in the same checkout without stepping on each other. It gives both agents one shared control plane for tasks, ownership, write-scope leases, artifacts, verification evidence, recovery, and runtime telemetry, exposed to each client as a native project-scoped MCP server.

The bridge is a coordination layer. It does not choose the better model, split work automatically, or merge code for you.

Table of contents

What problem it solves

Running two coding agents in one repository creates coordination problems that neither client solves on its own. The bridge addresses them with explicit mechanisms:

Coordination problem Implemented mechanism
Conflicting edits Expiring leases over repo-relative path globs
Duplicate ownership Explicit task claim and owner checks
Premature work Dependency gate before WORKING
Unverifiable completion Passing evidence required for COMPLETE
Lost handoffs Structured deliverables and hashed artifacts
Interrupted runtimes Persisted opaque handles and strict same-task resume
Recursive delegation Parent/depth validation, ancestor checks, and deadlines
Runtime observability One normalized final telemetry record per attempt
Claude profile drift Bridge-owned opus / high launch profile with actual-model validation
Caller spoofing Identity bound when the MCP process starts

Project status and honest limits

Demonstrated on this implementation

  • real Claude Code → bridge → Codex delegation;
  • real Codex → bridge → Claude Code delegation;
  • native project-scoped MCP integration for both clients;
  • task ownership and time-bounded write-scope leases;
  • structured deliverables with real verification evidence;
  • persisted Claude and Codex execution handles;
  • same-task, same-runtime-session recovery after interruption;
  • runtime-reported token telemetry for both workers;
  • startup-bound caller identity and anti-spoofing checks;
  • server-side delegation allow/deny;
  • parent/depth validation and ancestor-loop protection;
  • deterministic regression coverage (npm test).

Explicitly not established

  • superiority over single-agent workflows;
  • token savings or economic efficiency of any kind;
  • production security or production readiness;
  • large-scale, multi-user, or long-horizon reliability;
  • benchmark advantage over either agent alone;
  • optimal or automatic routing of work between models.

Controlled Claude-alone versus Codex-alone versus bridged benchmarking is planned but has not been completed. This repository makes no performance, cost, or security claim beyond what its committed tests and redacted evidence show.

Architecture

flowchart LR
  Claude[Claude Code] -->|project .mcp.json / stdio| ClaudeBridge[Native bridge<br/>caller=claude]
  Codex[Codex] -->|project .codex/config.toml / stdio| CodexBridge[Native bridge<br/>caller=codex]
  ClaudeBridge --> Core[Agent-neutral MCP core]
  CodexBridge --> Core
  Core --> Control[Task and lease control plane]
  Control --> SQLite[(Local .bridge/bridge.db)]
  ClaudeBridge --> ClaudeAdapter[Claude adapter]
  CodexBridge --> CodexAdapter[Codex adapter]
  ClaudeAdapter --> ClaudeRuntime[Claude Code CLI]
  CodexAdapter --> CodexRuntime[Codex App Server or MCP client]

Each client launches the same composition root, scripts/native-bridge-mcp.mjs, with a different startup-bound caller. The two processes coordinate through one repository-local SQLite database. The neutral dependency direction is:

@bridge/protocol
        ↓
@bridge/control-plane
        ↓
@bridge/mcp-server-core
        ↓
Claude and Codex adapters

Details: docs/architecture.md. Normative wire contract: docs/PROTOCOL.md.

Requirements

  • Node.js >= 22.13.0 — required, because node:sqlite is used without an experimental CLI flag. The engines field in package.json enforces the same floor.
  • npm (workspaces) and Git.
  • Claude Code and Codex installed and authenticated, for real delegations.
  • A trusted local checkout. The bridge launches coding runtimes that can read, write, and run shell commands.

Installation

The supported workflow is deterministic and uses the committed lockfile:

npm ci          # deterministic install from package-lock.json
npm run build   # tsc --build; required before a client opens the bridge
npm test        # vitest run; the deterministic regression suite

npm ci (not npm install) is what makes the dependency tree reproducible. The native launcher imports compiled workspace packages, so npm run build must succeed before you open the bridge from a client. Run the suite yourself rather than trusting a recorded test count in prose.

Optional checks: npm run typecheck forces a clean type build, and npm run links:check inspects workspace package links (use npm run links:fix only when it reports a break).

More detail: docs/installation.md.

Quick start

  1. Clone the repository and cd into it.
  2. Run npm ci && npm run build && npm test.
  3. Verify MCP discovery from the repository root:
    claude mcp list     # expect a "bridge" server, caller=claude
    codex mcp list      # expect a "bridge" server, caller=codex
    
    On Windows without a global Codex on PATH, use .\node_modules\.bin\codex.cmd mcp list.
  4. Launch either client from the repository root and approve the project-scoped MCP server when prompted. Inside Claude Code, /mcp shows the active connections.
  5. Ask the client to use the using-bridge skill for one bounded delegation, then read the two worked examples in Bounded delegation.

Project-scoped MCP configuration

Both configuration files are committed, repository-relative, and contain no credentials. Neither creates a global MCP registration.

Claude Code — .mcp.json:

{
  "mcpServers": {
    "bridge": {
      "type": "stdio",
      "command": "node",
      "args": [
        "${CLAUDE_PROJECT_DIR:-.}/scripts/native-bridge-mcp.mjs",
        "--caller", "claude",
        "--delegation", "allow",
        "--workspace", "${CLAUDE_PROJECT_DIR:-.}"
      ],
      "env": {}
    }
  }
}

Codex — .codex/config.toml:

[mcp_servers.bridge]
command = "node"
args = ["scripts/native-bridge-mcp.mjs", "--caller", "codex", "--delegation", "allow"]
cwd = "."
startup_timeout_sec = 30
tool_timeout_sec = 1800

Caller identity is bound when the server process starts. A tool call that contradicts the bound caller is rejected; an omitted caller field resolves to it. Starting the launcher with --delegation deny keeps inspection and telemetry available while refusing bridge_delegate server-side.

Review both files before granting project trust, and never hand-edit client trust state.

The using-bridge skill

The same bounded-coordination skill is committed for both native clients:

Open a client from this repository and ask it to use the using-bridge skill when a bounded delegation, independent review, recovery, or telemetry lookup is genuinely useful. The skill keeps the current client responsible for the user's request, defaults to one child with zero retries, and explicitly does not treat "use both models" as a reason to delegate. Only these shared skill files are versioned; other client-local state stays ignored.

Bounded delegation

A delegation is one bounded request and one structured answer — never an open conversation between agents. Every DelegationRequest carries a deadline, the root run_id, the parent task_id, and a depth. Inputs are artifact IDs, not transcripts.

Example: Codex → Claude

Ask Codex, running from the repository root:

Use the bridge MCP. Confirm caller=codex, then create and claim one depth-0 root task for "review the lease-expiry logic". Delegate exactly one depth-1 child to Claude with scope (no-write)/**, a 10-minute deadline, max_attempts: 0, and the verification criterion "cites concrete file:line evidence". Consume the child's structured deliverable, verify it yourself, then submit the root deliverable. Report lineage, final states, and worker telemetry without exposing execution handles.

Example: Claude → Codex

Ask Claude Code, running from the repository root:

Use the bridge MCP. Confirm caller=claude, then create and claim one depth-0 root task for "add a regression test for expired-lease renewal". Delegate exactly one depth-1 child to Codex with write scope shared/control-plane/src/**, a 15-minute deadline, max_attempts: 0, and the verification criterion "npm test passes". Consume the child's structured deliverable, verify it yourself, then submit the root deliverable. Report lineage, final states, and worker telemetry without exposing execution handles.

In both directions the manager stays responsible for the user's request, bridge_server_info is confirmed once per native session, and bridge_snapshot is used only when concurrent ownership is plausible. If the target runtime is unavailable, report the runtime failure — do not create a replacement child task.

Claude worker profile

The bridge runtime, not the manager and not the skill, owns Claude model selection. Every bridge-created Claude worker — fresh or resumed — is launched through Claude Code's supported interface with --model opus --effort high. A delegation payload cannot override that profile. If Claude Code reports an actual non-Opus model, the attempt fails with RUNTIME_PROFILE_MISMATCH; if it reports no model at all, telemetry keeps the actual model null rather than inventing one.

Claude turn ceilings are finite: minimum 1, conservative default 12, maximum 64, with 32 as the recommended starting value for a bounded repository audit. Set TaskSpec.max_turns only when the default is genuinely too small; the value persists with the task and is reused on strict recovery.

Full workflow: docs/usage.md.

Ownership and leases

  • Exactly one agent owns a task. Claiming a task is not permission to write.
  • Before editing files, the owner acquires a lease over repo-relative glob patterns (*, **, ?). An overlapping live lease held by a different agent is refused with SCOPE_CONFLICT.
  • Overlap detection is deliberately conservative: when two patterns cannot be proven disjoint, the bridge reports a conflict. A false conflict costs a retry; a false clearance costs corrupted files.
  • Leases are time-bounded and expire lazily against an injected clock, so a crashed agent cannot deadlock the repository and tests stay deterministic. Renewing a lapsed lease is refused, because the scope may already belong to someone else.
  • A read-only task declares (no-write)/** and returns changed_scope: [].

These are coordination contracts enforced by the control plane. They are not an operating-system sandbox: a delegated runtime with shell access can still write outside its declared scope, which is why the bridge is for trusted local repositories only.

Recovery

Adapters persist an opaque runtime handle (a Claude session id, a Codex thread id) as soon as the session exists — not on completion, because the only time anyone needs it is when the run died. bridge_resume_task takes the durable task ID, derives owner, lineage, scope, and handle from SQLite, rejects live or conflicting leases, takes a fresh lease, creates the adjacent attempt, and requires strict resume of that exact runtime session. It never accepts a caller-supplied handle and never opens a replacement task or thread.

See docs/recovery.md.

Telemetry

The bridge records one normalized final record per attempt: worker identity, lineage, timing, token, cache, cost, turn, artifact, and termination fields — but only when the runtime reports them authoritatively. Unknown values stay null; missing manager tokens are never estimated, and cached token counts are subdimensions of input, not extra tokens to add again. Raw prompts, responses, authentication data, and execution handles are outside the durable telemetry schema.

Runtime-reported cost is not confirmed billing. See docs/telemetry.md.

Troubleshooting

Common first stops: the bridge is not listed by claude mcp list / codex mcp list, the server starts but tools fail, SCOPE_CONFLICT on every lease, a task is stranded after an interrupted run, or telemetry fields are null. Each case, with the exact check to run, is in docs/troubleshooting.md.

Security and privacy

The bridge is local-first, but it launches powerful coding runtimes. Leases stop cooperating agents from claiming overlapping scopes; they do not confine shell commands at the operating system level, and nothing here has been audited for production use.

Never commit or publish:

  • .bridge/ SQLite databases or WAL/SHM sidecars;
  • Claude or Codex trust state;
  • raw handles, prompts, transcripts, runtime frames, or credentials;
  • logs, temporary task directories, node_modules, coverage, or build output.

Review git status, staged paths, and secret-scan results before any push. To report a suspected vulnerability, see docs/security.md.

Contributing

Contributions are welcome, with small, local, evidence-backed changes preferred. Read CONTRIBUTING.md before opening a pull request; it covers the local gates, the evidence standard, the claim discipline this project applies to itself, and repository hygiene rules.

Release policy

Pre-1.0 and experimental: no compatibility guarantee, no support commitment, no security certification. Breaking changes may land in any release and are recorded in CHANGELOG.md. The stability rules, versioning scheme, and what would have to be true before a 1.0 are in docs/release-policy.md.

The project is licensed under the MIT License. Package manifests remain private because this release publishes source on GitHub, not packages to the npm registry.

Documentation map

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选