codex - 💡(How to fix) Fix Codex wraps MCP tools in type:"namespace" for custom/local providers — backends with strict tools schemas cannot unwrap, MCP unusable

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When Codex uses a custom model_providers.X with wire_api = "responses" (transport responses_http), it emits MCP-server tools wrapped in a proprietary Responses-API extension:

{"type":"namespace","name":"mcp__<server>__","description":"...","tools":[...]}

This wrapper has no equivalent in the Chat-Completions schema that most OpenAI-compatible backends use internally (llama.cpp, LM Studio, Ollama, DeepSeek). When they translate the request, anything whose type is not function is dropped or rejected. The MCP tools never reach the model. The user sees "no MCP tools" with no error from either side.

Related: #19871 — same problem, but bisected as a Codex regression. The cross-backend framing makes it clearer that this is a protocol-shape issue, not just a Codex-internal regression.

Error Message

This wrapper has no equivalent in the Chat-Completions schema that most OpenAI-compatible backends use internally (llama.cpp, LM Studio, Ollama, DeepSeek). When they translate the request, anything whose type is not function is dropped or rejected. The MCP tools never reach the model. The user sees "no MCP tools" with no error from either side.

Root Cause

When Codex uses a custom model_providers.X with wire_api = "responses" (transport responses_http), it emits MCP-server tools wrapped in a proprietary Responses-API extension:

{"type":"namespace","name":"mcp__<server>__","description":"...","tools":[...]}

This wrapper has no equivalent in the Chat-Completions schema that most OpenAI-compatible backends use internally (llama.cpp, LM Studio, Ollama, DeepSeek). When they translate the request, anything whose type is not function is dropped or rejected. The MCP tools never reach the model. The user sees "no MCP tools" with no error from either side.

Related: #19871 — same problem, but bisected as a Codex regression. The cross-backend framing makes it clearer that this is a protocol-shape issue, not just a Codex-internal regression.

Fix Action

Fix / Workaround

Tool-call dispatch then routes back through the same path; no reverse map needed if the namespaced name is preserved end-to-end.

Code Example

{"type":"namespace","name":"mcp__<server>__","description":"...","tools":[...]}

---

[
  {"type":"function","name":"exec_command", ...},
  ... 13 native codex tools ...,
  {"type":"web_search"},
  {"type":"namespace","name":"mcp__open_websearch__",
   "tools":[
     {"type":"function","name":"fetchWebContent","parameters":{...}},
     {"type":"function","name":"search","parameters":{...}}]}
]

---

{"type":"function","function":{"name":"mcp__<server>__<tool>","parameters":{...},"description":"..."}}
RAW_BUFFERClick to expand / collapse

Summary

When Codex uses a custom model_providers.X with wire_api = "responses" (transport responses_http), it emits MCP-server tools wrapped in a proprietary Responses-API extension:

{"type":"namespace","name":"mcp__<server>__","description":"...","tools":[...]}

This wrapper has no equivalent in the Chat-Completions schema that most OpenAI-compatible backends use internally (llama.cpp, LM Studio, Ollama, DeepSeek). When they translate the request, anything whose type is not function is dropped or rejected. The MCP tools never reach the model. The user sees "no MCP tools" with no error from either side.

Related: #19871 — same problem, but bisected as a Codex regression. The cross-backend framing makes it clearer that this is a protocol-shape issue, not just a Codex-internal regression.

Evidence

A codex exec --profile local session against llama-server with one MCP server registered. Codex's outbound /v1/responses tools[] contains:

[
  {"type":"function","name":"exec_command", ...},
  ... 13 native codex tools ...,
  {"type":"web_search"},
  {"type":"namespace","name":"mcp__open_websearch__",
   "tools":[
     {"type":"function","name":"fetchWebContent","parameters":{...}},
     {"type":"function","name":"search","parameters":{...}}]}
]

The same Codex session against ChatGPT (responses_websocket) sends an identical namespace shape, but the ChatGPT backend understands and unwraps it server-side. Custom backends can't.

Affected backends

  • llama.cpp — PR ggml-org/llama.cpp#23041 silently skips namespace (see ggml-org/llama.cpp#20156).
  • LM Studio — rejects with invalid_request_error (lmstudio-ai/lmstudio-bug-tracker#1810).
  • DeepSeek via CLIProxyAPI — silently returns plain text, no function_call (router-for-me/CLIProxyAPI#3298).
  • Ollama Responses API — same, see #19871.

Proposed fix

When the transport is not the ChatGPT websocket (i.e. anytime the wire peer is a generic Responses-compatible server), flatten MCP namespaces into top-level function tools on the codex side:

{"type":"function","function":{"name":"mcp__<server>__<tool>","parameters":{...},"description":"..."}}

Tool-call dispatch then routes back through the same path; no reverse map needed if the namespaced name is preserved end-to-end.

Doing the flattening on the codex side fixes every downstream backend at once. Asking every backend to teach itself the namespace extension is the slower path.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Codex wraps MCP tools in type:"namespace" for custom/local providers — backends with strict tools schemas cannot unwrap, MCP unusable