openai / openai/codex

[Windows][Codex Replay 1.0.128] MCP crashes at startup on POSIX-only `fcntl` import

Open
#42,991 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app bug mcp skills windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

The OpenAI-curated codex-replay plugin release 1.0.128 is installed and offered by Codex Desktop on Windows, but its MCP server cannot start on Windows because mcp/server.py unconditionally imports the POSIX-only Python module fcntl.

Codex Desktop therefore reports a generic MCP handshake failure on every thread where the plugin is initialized. Running the packaged server directly reproduces the underlying exception immediately.

This appears to need either a Windows-compatible implementation or an explicit platform/capability gate so the MCP is not launched on unsupported hosts.

Environment

  • OS: Windows 11 x64, build 26200
  • Codex Desktop package: 26.901.5003.0
  • Desktop-managed Codex runtime: codex-cli 0.153.3
  • Curated plugin: codex-replay 1.0.128
  • Python selected by the plugin's python3 command: Windows CPython

Desktop symptom

Across multiple ordinary local threads, the app-server repeatedly reports:

server=codex-replay status=starting
MCP client for `codex-replay` failed to start: MCP startup failed:
handshaking with MCP server failed: connection closed: initialize response
server=codex-replay status=failed

The failure occurs before any Codex Replay tool is invoked.

Direct reproduction

From the installed plugin root, run the exact MCP command declared in .mcp.json:

python3 ./mcp/server.py

Actual result:

Traceback (most recent call last):
  File ".../codex-replay/1.0.128/mcp/server.py", line 5, in <module>
    import fcntl
ModuleNotFoundError: No module named 'fcntl'

The process exits immediately, which explains the app-server's connection closed: initialize response error.

Packaged definition

The plugin declares:

{
  "mcpServers": {
    "codex-replay": {
      "command": "python3",
      "args": ["./mcp/server.py"],
      "cwd": "."
    }
  }
}

mcp/server.py begins with an unconditional:

import fcntl

Additional Windows blockers in the same server

A conditional fcntl import alone does not appear sufficient for Windows support. The same packaged server also relies on POSIX-specific or POSIX-oriented lifecycle primitives, including:

fcntl.flock(...)
os.killpg(...)
os.getpgrp()
signal.SIGTERM
signal.SIGKILL
subprocess.Popen(..., start_new_session=True, pass_fds=(...))

Examples include:

  • _state_guard() and _historical_review_guard() using fcntl.flock for cross-process state locks.
  • _terminate_process_group() using os.killpg and POSIX signals.
  • controller launch passing a reserved socket FD to a child with pass_fds.
  • coordinator cancellation comparing against os.getpgrp() and signaling the process group.

The existing tests contain Windows-path redaction coverage, but I could not find equivalent Windows platform coverage for these MCP lifecycle paths.

Expected behavior

One of the following should hold:

  1. codex-replay supports Windows and uses Windows-compatible locking, child-process lifecycle, and controller/socket handoff; or
  2. the plugin manifest / Codex plugin loader marks the MCP unsupported on Windows and does not launch it.

In either case, opening an unrelated Windows thread should not spawn an MCP process that deterministically crashes before initialize.

Suggested fix areas

  • Add a platform/capability gate if Codex Replay is currently macOS/Linux-only.
  • If Windows is intended to be supported:
    • replace or abstract fcntl.flock with a cross-platform file-lock mechanism;
    • use a Windows-safe process-tree lifecycle rather than killpg/POSIX process groups;
    • replace inherited-FD controller socket handoff with a Windows-supported mechanism;
    • add Windows CI covering MCP initialize, controller startup, cancellation, and state locking.
  • Surface the server's stderr/root exception in plugin diagnostics so this is not reduced to a generic handshake error.

Privacy

Local usernames, absolute project paths, account details, thread IDs, credentials, prompts, and private session data are intentionally omitted.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running python3 ./mcp/server.py from the plugin root and inspect mcp/server.py, especially _state_guard(), _historical_review_guard(), _terminate_process_group(), coordinator cancellation, and controller launch. Review .mcp.json and the existing Windows-path redaction tests; done means Windows either completes MCP initialization with lifecycle and locking coverage, or the loader prevents unsupported startup without a generic handshake failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.