Originally created by: imshaikot
Cursor CLI shipped as the sixth side-panel agent in [#25], in beta. Its only recording against the real CLI is a turn that says "hello from cursor"; it has never made a tool call through Browsentic. An audit of all eight runners on 1 Oct nearly froze it on that evidence. Reading the CLI itself says otherwise: Cursor has none of the ceilings that hold Vibe, Grok and Antigravity back, and the two gaps it does have can be closed on Browsentic's side.
This issue is to bring Cursor to the same standard as Claude Code — measured end to end — and take it out of beta.
cursor-agent 2026.09.18-9a7762b ships as readable JavaScript (~/.local/share/cursor-agent/versions/<version>/index.js).
| What the bundle shows | Against Claude Code | |
|---|---|---|
| Tools | MCP tools go to the model as they are. No tool_search, no proxy tool, no schema file read first — unlike Codex exec, Grok and Antigravity |
Same |
| Pictures | McpToolResultContentItem is text or McpImageContent { data, mime_type }; an MCP image block is converted, not dropped — unlike Vibe |
Same, to be confirmed with a real turn |
| Call timeout | client.callTool({ name, arguments }) passes no options, so the MCP SDK's timeout ?? 6e4 applies: 60 s per call, resetTimeoutOnProgress false, no setting and no environment variable |
Claude Code waits far longer |
| Result size | Text results over fileOutputThresholdBytes — default 4e4, and the CLI passes undefined — are written to ~/.cursor/projects/<workspace>/agent-tools/<uuid>.txt, and the model is handed only the path |
Claude Code takes 25k tokens inline |
| Tool count | ChatConfig carries max_mcp_tools and warn_mcp_tools, set by Cursor's server. The client never reads them, so any cap is applied server-side |
Unknown until measured |
60 seconds. A run's approval card waits on the user. Past 60 s, Cursor gives up on the call and the model sees a timeout — but the daemon keeps the card up, and a late Allow still runs the action after the model has moved on. awaitDecision (src/daemon/agent/service.ts) never expires for an interactive run, and the MCP server's CallTool handler (src/daemon/server.ts) ignores the request's cancel signal, so nothing tells the daemon the caller left. The same 60 s ends page_awaitMonitor (2 min by default), page_solveCaptcha (2 min) and page_pickElement (1 min) early. Vibe has the same 60 s default; this part of the fix helps every CLI.
40 KB. Typical page_getPageInfo results are 6–15 KB, but page_extractText takes maxLength up to 200,000 characters, and a heavy page passes 40 KB. When it does, the model gets a path to a file — and a Cursor run denies Read(**), where deny beats allow, so it most likely cannot open it.
1. Measure first, with a stand-in MCP server and the runner's own plan (cursorRunner.stream() through drive.ts), on the default Auto model:
| Turn | Settles |
|---|---|
52 tools t01…t52; call t52, then t01 |
whether Cursor's server caps the tool list |
| A 60 KB result with a codeword at the end | inline, a path, or a refused read |
| A solid-colour PNG | whether a picture reaches the model |
| A call that sleeps 70 s | the 60 s cut, and whether notifications/cancelled arrives |
AGENTS.md changed between a turn and its --resume |
whether a follow-up sees the new prompt, or keepsFirstPrompt is needed |
"run ls", with the user's own Shell(ls) allow in place |
that the run's deny still wins |
| A one-shot handed a PNG, then a PDF | what goes in opens |
The streams are recorded as fixtures/cursor/2026.09.18-*.jsonl, and the results are posted here.
2. Build
Runner.limits — { callMs, resultBytes }, declared by a runner whose CLI imposes them; Cursor declares 60_000 and 40_000.callMs − 10 s, the call returns APPROVAL_PENDING and the card stays up. The same call made again rejoins the same card, with no second timeline row; any other call withdraws it, and a late Allow does nothing.timeoutMs is held under the limit, and the model calls again.RESULT_TOO_LARGE and the ways to ask for less, never cut. page_extractText's maxLength is held to a third of the limit so a long read pages through instead.opens, keepsFirstPrompt, a smaller tool list.3. A real side-panel conversation on Cursor: a heavy page, a screenshot, an approval left past a minute then allowed, one abandoned, an A-Eye pick on a follow-up, Stop, and a follow-up after a daemon restart.
4. Docs, then beta comes off Cursor's catalog entry.
inactive run in daemon.logdocs/guide/agents.md, docs/reference/errors.md and the loopback-agent skill say what changed; Cursor is no longer betaVibe (60 s, measured) and Grok (results cut at 20 KB) could each declare limits in one line, but both stay frozen for now. No release.
Originally posted by: imshaikot
Measured, 1 Oct 2026
cursor-agent2026.09.18-9a7762b on theAutomodel. The runner's own plan ran throughdrive.ts, with a stand-in MCP server in place ofbrowsentic mcpthat logs every start, list and call. That is 6 real turns..cursor/mcp.jsonisnot loaded (needs approval), and the run's model saw no browser tools at all. It searched, grepped and tried the shell until Cursor stopped it with Agent Looping Detected. Every Cursor run since [#25] has gone without the browsercursor-agent mcp enable browsentic, run in the run's folder. It takes 0.26–0.35 s and writes one key to~/.cursor/projects/<folder>/mcp-approvals.json. The key isbrowsentic-plus a hash of{ folder, server config }, and that config includesBROWSENTIC_AGENT_RUN, so every turn needs its own approval.--approve-mcpswould approve every server the user has, so it stays forbiddenGetMcpTools, searching by pattern or fetching one tool's schema by name, before each new tool: one or two extra round trips, like Codex exec'stool_search. No client switch turns it offt52andt01both answered~/.cursor/projects/<folder>/agent-tools/<uuid>.txt; the model is handed the path,Readis denied, the shell is denied, and it answered with the path instead of the codewordMCP error -32001: Request timed out; the server does receive the cancelAGENTS.mdchangedkeepsFirstPrompt, like Claude Code and Codex)ls, with the user's ownShell(ls)allow in~/.cursor/cli-config.jsongreppointed outside the folderopenscan be text, PDF and imageFound on the way:
plugin-<plugin>-<server>, and the runner denies only the servers in~/.cursor/mcp.json.Mcp(...)rules glob the server name, so aMcp(plugin-*:*)deny closes that.mcpToolCallwithproviderIdentifier: "browsentic"and noserverkey, so the timeline draws each one twice. Cursor's own tools never get atoolResult. The closingusageadds up every request in the turn (about 20k per request here), so it cannot fill the context card.That adds four items to the plan above, ahead of the 60 s and 40 KB work: approve the run's server before every turn (vetted like any other argv), deny plugin servers, the prompt section that names the tools to look up in one go, and the reader fixes. Plus
keepsFirstPromptandopens: text, pdf, image.Related
Tickets:
#25