Summary
When using Cursor in agent / tool mode pointed at VibeProxy's OpenAI-compatible endpoint with a Claude (OAuth) model, tool calling fails. Normal chat works, but any tool use breaks with errors like:
messages.N: user messages must have non-empty content
or silently fails.
Root cause
Cursor sends Anthropic-native content blocks to the OpenAI /v1/chat/completions endpoint:
user.content with { "type": "tool_result", "tool_use_id": ..., "content": ... }
assistant.content with { "type": "tool_use", "id": ..., "name": ..., "input": {...} }
- bare tool definitions
{ "name", "description", "input_schema" }
The OpenAI -> Claude translator expects standard OpenAI shapes (tool_calls, role:"tool", tools[].type=="function"), so these payloads are dropped. This is also tracked upstream in router-for-me/CLIProxyAPI#1165 and the Cursor forum report "Wrong tools handling on OpenAI compatible endpoint".
Today the only workaround is running an external request-rewriting proxy/shim in front of the proxy.
Upstream fix
I opened a PR against the core proxy that normalizes these Anthropic-native blocks into standard OpenAI shapes before translation (standard OpenAI payloads pass through untouched):
Once that lands in a release, bundling the updated cli-proxy-api binary in VibeProxy would let Cursor agent mode work out of the box with no shim.
Minor: stale reference
The README links to https://github.com/router-for-me/CLIProxyAPIPlus, which now 404s (it appears to have been consolidated into router-for-me/CLIProxyAPI). Worth updating the README and the bundled binary source accordingly.
Environment
- VibeProxy (latest), macOS
- Client: Cursor (agent mode)
- Model: Claude via OAuth
Summary
When using Cursor in agent / tool mode pointed at VibeProxy's OpenAI-compatible endpoint with a Claude (OAuth) model, tool calling fails. Normal chat works, but any tool use breaks with errors like:
or silently fails.
Root cause
Cursor sends Anthropic-native content blocks to the OpenAI
/v1/chat/completionsendpoint:user.contentwith{ "type": "tool_result", "tool_use_id": ..., "content": ... }assistant.contentwith{ "type": "tool_use", "id": ..., "name": ..., "input": {...} }{ "name", "description", "input_schema" }The OpenAI -> Claude translator expects standard OpenAI shapes (
tool_calls,role:"tool",tools[].type=="function"), so these payloads are dropped. This is also tracked upstream in router-for-me/CLIProxyAPI#1165 and the Cursor forum report "Wrong tools handling on OpenAI compatible endpoint".Today the only workaround is running an external request-rewriting proxy/shim in front of the proxy.
Upstream fix
I opened a PR against the core proxy that normalizes these Anthropic-native blocks into standard OpenAI shapes before translation (standard OpenAI payloads pass through untouched):
Once that lands in a release, bundling the updated
cli-proxy-apibinary in VibeProxy would let Cursor agent mode work out of the box with no shim.Minor: stale reference
The README links to
https://github.com/router-for-me/CLIProxyAPIPlus, which now 404s (it appears to have been consolidated intorouter-for-me/CLIProxyAPI). Worth updating the README and the bundled binary source accordingly.Environment