Namespaced MCP tool calls fail after deferred tool discovery because replayed function_call drops namespace

Open 💬 2 comments Opened May 21, 2026 by kting28

What version of Codex CLI is running?

0.132.0

What subscription do you have?

self hosted

Which model were you using?

gpt-5.5

What platform is your computer?

Linux 5.14.21-150400.24.147-default x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

tmux

Codex doctor report

Not relevant

What issue are you seeing?

When multiple MCP servers are enabled, Codex sometimes uses deferred tool discovery (tool_search / tool_search_output) before invoking an MCP tool.

In that path, the model emits a correctly namespaced function_call, the MCP tool executes successfully, but the next outbound request fails because the
replayed function_call is missing its namespace.

This appears to be a client/gateway serialization bug during history replay, not an MCP server bug.

#### Observed behavior

Failure sequence:

  1. Codex performs deferred tool discovery
  2. tool_search_output returns a namespaced tool
  3. model emits a function_call with a valid namespace
  4. MCP tool executes successfully
  5. follow-up request to the model backend fails with missing namespace

Backend error:

```json
{
"error": {
"code": "EXTERNAL_API_ERROR",
"message": "Azure stream failed to open - Body: {\n \"error\": {\n \"message\": \"Missing namespace for function_call '<tool_name>'. It does not exist
in the default namespace. Round-trip the model's function_call item with its namespace field included.\",\n \"type\": \"invalid_request_error\",\n
\"param\": \"input[7].namespace\",\n \"code\": null\n }\n}"
}
}




### What steps can reproduce the bug?


  This is not tied to one specific MCP server.

  What matters is:

  - multiple MCP servers enabled
  - deferred tool discovery path is used
  - the chosen tool is namespaced
  - the next request replays prior function_call history

  A smaller config with only a couple of MCP servers may avoid the problem because the model can directly emit the tool call without going through deferred tool
  discovery.

  #### Control case

  With only two small MCP servers enabled, the same namespaced tool call succeeds end-to-end.

  In that passing case:

  - no tool_search_output appears
  - the model directly emits the namespaced function_call
  - tool executes
  - follow-up turn succeeds

  This suggests the bug is specific to:

  tool_search_output -> function_call -> function_call_output -> replay

  rather than to namespaced MCP tools in general.

  #### Likely root cause

  A client or gateway layer is dropping namespace from prior function_call items when rebuilding the outbound request history.

  Most likely locations:

  1. conversation history normalization
  2. tool-call replay serialization
  3. provider bridge / gateway request transformation before Azure

  The backend appears to be correctly rejecting malformed input rather than generating the problem.

### What is the expected behavior?

  If a prior function_call item includes namespace, that field should be preserved exactly when conversation history is replayed into the next outbound model
  request.

  #### What makes this notable

  The local rollout JSONL shows the original function_call item is correct.

  Sanitized example:

  {
    "type": "function_call",
    "name": "lookup_term",
    "namespace": "mcp__server_a__",
    "arguments": "{\"term\":\"ABC\"}",
    "call_id": "call_123"
  }

  Then the tool runs successfully and produces function_call_output.

  The failure only occurs on the next outbound request, which strongly suggests the namespace is being dropped during request reconstruction / serialization.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗