Repository navigation
fix(cursor): client tool calls from Claude Code 2.1.30x never reach the client — model narrates failures instead #7609
Description
Follow-up to #6640. With Claude Code 2.1.30x (tested 2.1.304) on a Cursor-backed model (cursor/claude-opus-5-5) via /v1/messages, no tool call ever reaches the client: the CC transcript contains zero tool_use blocks while the model narrates tool failures in text. All other providers on the same gateway (OpenAI, GLM, xAI) work fine from the same client.
Summary
Claude Code 2.1.30x advertises a new-generation toolset — Agent, TodoWrite, ToolSearch, AskUserQuestion, EnterPlanMode, ExitPlanMode, SendMessage, Skill, ListAgents. The bare-name preservation added in #6640 (CLAUDE_CLIENT_BARE_TOOL_NAMES, src/adapters/cursor/tool-naming.ts) still lists only the pre-2.x names (Task, Todo, EnterMode, ExitMode, GetDynamicTools, …). The new names are therefore absent from the list, so isCursorBareClientToolWireAliased → cursorToolWireName prefixes them with ocx_client_ (CURSOR_CLIENT_TOOL_WIRE_PREFIX, same file) while the old names stay bare.
The result is a self-contradictory catalog on the Cursor wire: the model's system prompt describes one tool list while its function definitions use mixed naming. Per the mechanism #6640 established, the model falls back to Cursor-native execution frames; the proxy answers with the cursorNativeExecRedirectHint denial ("re-issue through ocx_client_* … do not narrate"), which frontier Claude models treat as a prompt-injection directive: they refuse to execute and narrate the refusal instead. The client then receives a text-only turn with no tool_use at all.
The root cause is on the proxy side: the same request shape sent directly to the gateway with classic full tool definitions returns tool_use correctly, so the break is in the cursor adapter's tool-naming step, not in the Cursor upstream and not in the gateway generally.
Evidence
- Real CC session (2026-10-22): 10 assistant events, 0
tool_useblocks. The model's thinking states verbatim: "There's a mismatch between the tools listed and what's actually available in my function definitions, so I can't call things like Bash, Edit, or ocx_client" — naming the proxy's own wire prefix. - After the failed attempts the model reports being redirected toward
ocx_client_PowerShell/ocx_client_Agent— i.e. the renamed/prefixed namespace, denied becausenativeLocalExecis off. - Isolation experiment: replaying the same conversation history via direct
curlto/v1/messageswith classic full tool definitions (including the new names) returnstool_usecorrectly. Seven request-shape variants all pass through the same path — streaming, thinking,{"type":"adaptive"}thinking, the full beta list, 128kmax_tokens, poisoned history,CLAUDE_CODE_INLINE_TOOLS=1— so the failure is specific to what the real CC client sends, most likely (unverified) how its deferred/ToolSearch-era tool declaration interacts with the adapter.
Repro
claude -p "Use the Read tool to read <any file>, then quote its first line." \
--model cursor/claude-opus-5-5 --allowedTools "Read"
CC points at the gateway via ANTHROPIC_BASE_URL=http://127.0.0.1:10100 with the cursor provider enabled (PKCE login). Expected: tool_use blocks surface to the client and Read executes client-side. Actual: a text-only turn narrating that native Read/Shell are unavailable and suggesting ocx_client_* tools; the transcript contains no tool_use.
- Windows 11 build 26200, Claude Code 2.1.304, opencodex 2.90.0 and 2.91.0 (latest at time of writing — both reproduce); first observed on 2.86.0.
Suggested fix
- Extend the bare-name preservation to the current Claude Code toolset — ideally version-adaptive rather than a hardcoded list; and/or
- Register deferred client tools declared via
ToolSearch/advanced-tool-usesocursorToolAllowedByChoiceand the catalog budget see them on the cursor wire.
Related: #7452, #7453 (tool discovery). Happy to provide full session jsonl excerpts and curl payloads.
Activity
github-actions commentedon Oct 23, 2026
Issue closed: use an issue template
Thanks for taking the time to submit this issue. It was closed automatically because it was not opened with a recognized issue template (Bug report, Feature request, Documentation, or Provider compatibility). Freeform and API-opened issues cannot skip this check.
Please edit the issue to add:
See the Contributing guide for details.
Once the report passes the automated checks, it will be reopened automatically unless a maintainer has changed its state.