openai / openai/codex

mcp_tool Stop hook fails open when MCP server is missing or cannot start

Open
#39,858 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI exec hooks mcp
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of Codex CLI is running?

codex-cli 0.149.0

What subscription do you have?

ChatGPT Pro

Which model were you using?

Default OpenAI model selected by Codex CLI.

What platform is your computer?

Linux 7.0.0-29-generic x86_64 x86_64 (Linux Mint 22.3)

What terminal emulator and version are you using?

Kitty on Linux; reproduced with non-interactive codex exec --ephemeral.

Codex doctor report

Redacted summary: overallStatus ok; Codex 0.149.0; installation and update target consistent; config loaded; MCP configuration locally consistent; provider HTTP and WebSocket checks pass; state databases healthy. The full report contains only local-path details and does not show a failing prerequisite.

What issue are you seeing?

An mcp_tool Stop hook works when its configured stdio MCP server is available, but fails open when that MCP server is unavailable.

Positive control on 0.149.0: the Stop hook successfully invoked two MCP tools in sequence and the second tool wrote a valid terminal-seal fixture. This confirms that the MCP hook executor is wired in this release.

Negative controls:

  1. The Stop hook references an MCP server name that is not registered.
  2. The referenced MCP server is registered, but its command points to a nonexistent executable and cannot start.

In both cases Codex emitted the requested agent message followed by turn.completed. There was no hook failure event in JSONL output and the Stop hook did not block completion.

This makes an MCP-backed validation, compliance, or release gate fail open precisely when its validator is unavailable.

What steps can reproduce the bug?

  1. Enable the stable hooks feature.
  2. Configure a Stop hook similar to:
{
  "hooks": {
    "Stop": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "repro_validator",
            "tool": "validate",
            "input": {},
            "timeout": 20
          }
        ]
      }
    ]
  }
}
  1. First register a working stdio server named repro_validator whose validate tool returns a successful Stop-hook response. Run:
codex exec --ephemeral --skip-git-repo-check --dangerously-bypass-hook-trust --json "Reply exactly POSITIVE_CONTROL"

Confirm the MCP tool is invoked. This positive control passes on 0.149.0.

  1. Remove repro_validator from the MCP configuration while leaving the hook enabled. Run the same command. The output still ends with turn.completed.

  2. Register repro_validator again with a nonexistent command, for example /__missing_mcp_server__, and run the same command. The output again ends with turn.completed.

Observed negative-control shape:

{"type":"item.completed","item":{"type":"agent_message","text":"..."}}
{"type":"turn.completed","usage":{}}

No successful MCP validation occurred in either negative control.

What is the expected behavior?

If an enabled mcp_tool Stop hook cannot resolve, start, or call its MCP server, Stop should fail closed. Codex should block completion or return a non-success terminal result that callers cannot mistake for a completed turn. JSONL output should identify the failed hook and MCP failure.

Additional information

The same fixture was also exercised with ten validator fault-injection cases; all validator-side cases pass. The remaining issue is specifically runtime behavior when the MCP hook dependency is missing or cannot start.

This is reproducible after a clean Canary rollback: the test hook and MCP registration were removed, and no production configuration or data is involved.

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 tracing the mcp_tool Stop-hook execution path and its handling of an unregistered or unstartable MCP server. Reproduce both negative controls with codex exec --ephemeral and inspect the JSONL events; done means completion is blocked or reported as unsuccessful and the failed hook identifies the MCP failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.