Repository navigation
Fix Codex initialize compatibility in the CLI bridge - #261
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The workaround is narrowly scoped, preserves unrelated traffic, and has comprehensive regression coverage.
Review effort: Balanced
Findings: None
What changed in this PR
Adds a focused CLI compatibility workaround for Codex initialization while preserving standard MCP traffic.
Changes:
- Buffers complete newline-delimited stdin frames with a 10 MiB limit.
- Removes only Codex’s unsupported object-valued capability.
- Adds regression coverage and terminates on oversized frames.
| File | Description |
|---|---|
CLI/MCPInitializeCompatibility.swift |
Implements normalization and framing. |
CLI/StdioProxy.swift |
Forwards complete normalized frames. |
CLI/MCPServiceLoop.swift |
Terminates after framing failures. |
CLITests/MCPInitializeCompatibilityTests.swift |
Covers normalization, framing, and size limits. |
iMCP.xcodeproj/project.pbxproj |
Adds compatibility tests to the test target. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Thanks for opening this PR, @barissglc! When I ran the tests locally, |
|
Thanks for catching this, @mattt! Fixed in I reproduced the issue before the fix: 4 of 10 executions of the two reported tests failed. After the change, all 26 tests passed in each of 10 separately relaunched test processes (260 executions, zero failures). The PR is updated. |
|
Thanks for the fix, and for adding the regression test, @barissglc! This is now available in 1.6.4. |
Codex 0.160.0 sends an object-valued
codex/auth-changecapability during MCP initialization. The Swift MCP SDK 0.12.0 pinned by iMCP decodes experimental capabilities as strings, so the original bridge returns-32603and Codex cannot discover tools. A simpler client handshake can still succeed, which makes this look like a chat-routing problem.This adds a narrow compatibility workaround to
imcp-server: assemble complete newline-delimited stdin frames and remove only the unsupported object-valuedparams.capabilities.experimental["codex/auth-change"]entry from initialize requests. Normalized initialization uses.sortedKeysso repeated calls emit identical bytes. Client identity, other capabilities and subsequent requests are preserved. Oversized frames terminate the proxy instead of triggering the reconnect loop.Closes #258.
Validation
imcp-serverTests: 26 tests passed in each of 10 separately relaunched test processes (260 executions, zero failures), including 11 new compatibility/framing regression tests.git diff --checkpassed.The 1.6.2 local installation was also verified end to end: the original bridge failed the Codex-shaped initialize request, the patched bridge listed 19 tools, and a real public-place
maps_searchsucceeded in Tinycast's Codex chat route. This PR is rebased onto current main (8d232819, iMCP 1.6.3). It does not replace the original iMCP GUI or alter connection approvals, macOS permissions, Codex configuration or Tinycast configuration.Scope
This is an interim Codex-specific workaround, not a general decoder fix for arbitrary experimental capabilities. The SDK-level issue is tracked in swift-sdk #287. An upstream SDK correction and subsequent dependency update remain the long-term solution. Validation was performed with Xcode 27 locally; the repository's Xcode 26 CI is a separate check.
Deterministic-output regression verification
Before the
.sortedKeyschange, the two reported framing tests ran five times in separately relaunched processes: 4 of 10 test executions failed. With the change, all 26 tests passed in each of 10 separately relaunched processes. The new canonical-output regression additionally checks the full normalized JSON bytes 100 times per process (1,000 comparisons total), without deriving its expected output from another normalization call.