Cursor provider: Codex tools only reachable via GetDynamicTools/CallDynamicTool, but native-exec denial guidance points to a top-level `exec` the model cannot see
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
- Domain
- backend-api-design, devtools
Research direction
Start with src/adapters/cursor/native-exec.ts and tool-guidance.ts to trace the denial redirect and code-mode guidance, then read src/adapters/cursor/tool-naming.ts for existing dynamic-tool handling. Check how GetDynamicTools and CallDynamicTool expose the opencodex-responses namespace; the issue gives no test path, so locate relevant coverage before changing behavior. Done means deferred tools are reachable through the guidance or registered at the top level, without claiming unavailable top-level tools.
Written by the indexing model from the issue text.
Description
Client or integration
Codex App
Provider or upstream service
cursor
OpenCodex version
2.96.0 (same as main @ 684ad75)
Endpoint or capability
/v1/responses - tool calls (Cursor native-exec redirect / MCP tool registration, code mode)
Current behaviour
With Codex App (code mode) routed to cursor/claude-opus-5-5, the top-level tool list the model sees contains only Cursor-native tools (Read, Write, StrReplace, Shell, Glob, Grep, ...) plus GetDynamicTools / CallDynamicTool. The Codex client tools (exec, wait, ...) are not registered at the top level; they only appear inside the deferred dynamic namespace opencodex-responses.
Every Cursor-native call is denied (nativeLocalExec unset = "off", as designed). The redirect text from cursorCodeModeExecRedirectHint() (src/adapters/cursor/native-exec.ts) and the code-mode notes in tool-guidance.ts tell the model to "Re-issue this operation NOW through the exec tool" and that "Every other tool this turn lists remains callable at the top level as usual". The model cannot see a top-level exec, so it keeps retrying native Read/Shell/Write, and every file/shell operation fails until it happens to discover the tool through GetDynamicTools.
Once discovered, CallDynamicTool(namespace="opencodex-responses", toolName="exec", arguments={input: "..."}) works: nested tools.exec_command runs on the Codex host (git, PowerShell and network downloads all succeeded). Execution plumbing is fine; only discovery/guidance is broken.
Expected behaviour
When Cursor defers MCP tools behind GetDynamicTools/CallDynamicTool, OpenCodex should either (a) get the Codex client tools registered at the top level again, or (b) detect the deferred mode and make the denial redirect and tool guidance name the real call path, e.g. "call CallDynamicTool with namespace opencodex-responses, toolName exec", instead of a bare top-level exec.
Minimal redacted request or reproduction
# OpenCodex 2.96.0 (same as main @ 684ad75), Windows, Codex App, proxy on 127.0.0.1:10100
# ~/.codex/config.toml (redacted)
model = "cursor/claude-opus-5-5"
openai_base_url = "http://127.0.0.1:10100/v1"
model_catalog_json = "<user>/.codex/opencodex-catalog.json"
# ~/.opencodex/config.json providers.cursor: nativeLocalExec not set (default "off")
# In Codex App, ask the model to read any file in the workspace.
# 1. Model calls Cursor-native Read / Shell / Write / Glob / Grep -> all denied.
# 2. GetDynamicTools(namespace="opencodex-responses") lists exec, wait, ...
# 3. CallDynamicTool(namespace="opencodex-responses", toolName="exec",
# arguments={input: 'text(await tools.exec_command({cmd: "git --version"}))'})
# -> succeeds.
Actual response or error
Every Cursor-native Read/Write/Shell/Glob/Grep call returns the OpenCodex denial, which lists the catalog
("available tool names are exactly exec, wait, mcp__cua_repl__js, ...") and says
"Cursor-native Read/Glob/Grep/LS/Shell/Write/Fetch are not available in this request".
Native Shell is rejected in ~240 ms, i.e. nothing is executed.
Top-level tools actually visible to the model: Read, Write, StrReplace, Shell, Glob, Grep,
AskQuestion, GetDynamicTools, CallDynamicTool, ... (no exec / wait).
Upstream documentation
No public Cursor specification for the deferred dynamic-tool channel (GetDynamicTools / CallDynamicTool) that I know of. Related OpenCodex devlog: devlog/_fin/260711_cursor_browser_bridge/004_fix_mcp_tools_channel.md verified top-level registration via AgentRunRequest.mcp_tools with cursor/gpt-5.6-luna and cursor/claude-4.5-sonnet. This report suggests newer models (cursor/claude-opus-5-5) get MCP tools deferred instead (inference, not confirmed against Cursor docs).
Suggested mapping or implementation notes
- src/adapters/cursor/tool-naming.ts only knows GetDynamicTools as an entry in CLAUDE_CLIENT_BARE_TOOL_NAMES (collision avoidance); no code path treats it as the route to client tools.
- No detection in src/adapters/cursor for "client tools deferred behind a dynamic namespace" (searched GetDynamicTools, CallDynamicTool, dynamic tool, deferred tool).
- Possible fix: when the model is in a deferred-MCP mode (by model id, or observed from the first GetDynamicTools call), switch cursorCodeModeExecRedirectHint() and the code-mode tool guidance to name CallDynamicTool + namespace
opencodex-responses+ toolNameexec, and drop the "remains callable at the top level" sentence. - Not a good workaround: nativeLocalExec="on" bypasses the Codex sandbox/approval, and rejectNativeFileMutations still blocks native writes when apply_patch is advertised.
Additional context and attachments
The denial wording is consistent for models where MCP tools are top-level; the problem is specific to models where Cursor defers them. Happy to provide more traces if useful.
Checks
- I searched existing provider and compatibility issues.
- The request and response were redacted.
- The expected behaviour is based on an upstream specification or a concrete client requirement.
- Dominant language
- TypeScript
- Stars
- 16.9k
- Forks
- 1.3k
- Avg merge
- 18h 28m
- Merged PRs (30d)
- 697
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lidge-jun/opencodex
-
account-pool bug gui
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
lidge-jun/opencodex#8131 · 2 comments ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
lidge-jun/opencodex#8115 · 1 comment ·
Maintainers usually reply within 1 day
-
account-pool bug
Difficulty 5/5 Over a week Newbie friendliness 35/100
lidge-jun/opencodex#8113 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
account-pool bug
Difficulty 3/5 1-2 days Newbie friendliness 66/100
lidge-jun/opencodex#8110 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
account-pool bug
Difficulty 4/5 3-5 days Newbie friendliness 48/100
lidge-jun/opencodex#8107 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
All issues in lidge-jun/opencodex
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
-
bug needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
DSpace/dspace-angular#6511 ·
Maintainers usually reply within 1 day
-
area: frontend area:byok bug severity:low
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
Phone app shows Unknown for a remote machine whose key changedPossibly taken @janicduplessis claimed this today. Openarea: mobile priority: P3 type: bug
Difficulty 1/5 Under an hour Newbie friendliness 78/100
appandflow/stim#5006 · 1 comment ·
Maintainers usually reply within 1 day
-
Area - Local to Cloud Bug
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
microsoft/vscode-mssql#23209 ·
Maintainers usually reply within 1 day