DEV Community

Jeff
Jeff

Posted on Originally published at powerduck.com

When Cursor's Agent Ignores the MCP Tool and Writes a Raw fetch

Quick answer: If your agent has a working MCP tool for an API but the model still hand-writes a fetch, the failure is usually one of three things: the tool's description did not make it the obvious choice, the tool failed once and the agent learned to route around it, or the request shape looked slightly off-schema. Do not accept the raw fetch; fix the tool so it is the path of least resistance, because a hand-written request bypasses every contract and auth guarantee the MCP server provides.

I watched this happen on a code review where the agent was supposed to create a ticket through an MCP-exposed issue tracker. The first generated code called the tool correctly. On a later task, the agent instead built a fetch with a hardcoded URL, a manually assembled bearer token, and a payload that used a field name the API had renamed two releases earlier. It had tried the tool once, hit a transient timeout, and silently decided the direct call was more reliable. The fetch looked plausible and the tests did not exercise it, so it nearly merged with a guaranteed 400 baked in.

Why the agent abandons a good tool

Models choose the path that the surrounding context makes most likely to succeed. A raw fetch is the generic fallback, so it wins whenever the dedicated tool does not clearly present itself as the better option. The recurring causes are:

  • Weak tool descriptions. If the tool says "manage issues" without naming the resource and action, the agent may not map "create a ticket" onto it.
  • A prior failure. One timeout or error during the session makes the agent treat the tool as unreliable and route around it.
  • Schema mismatch. If the data the agent holds does not fit the input schema, it may bypass the tool rather than adapt the data.
  • Too many tools. A long list of similarly named operations hides the right one and nudges the model toward the generic primitive it knows.

What the two paths actually guarantee

The difference is not stylistic. The MCP tool carries the auth, base URL, and validated schema; the raw fetch throws all of that away. The table below is how I frame the trade-off in review.

Concern Hand-written fetch MCP tool call
Endpoint URL Hardcoded; drifts on rename Resolved from the gateway and spec
Auth Manual token handling, leak risk Credential injected by the gateway
Payload shape Guessed; can use stale fields Validated against the input schema
Retry behavior Whatever the agent invents Consistent with the tool's contract
Observability Often invisible to tool logs Recorded with the other tool calls

Make the tool the obvious choice

Start with the description, because that is the cheapest fix and the most effective. Name the resource and the action explicitly, and describe when the tool should be used so the agent can match its intent without guessing.

Keep the exposed tool set tight and well named. A handful of purposeful operations with crisp descriptions beats a large surface where the right tool is buried.

Fix the failure that taught the bad habit

If the agent routed around the tool after an error, chase that error rather than patching the output. A timeout usually means the tool needs a reasonable limit and a structured retryable error, not that direct calls are better. When the tool returns a clear, recoverable error, the agent learns to retry the tool rather than abandon it. For a schema mismatch, adapt the input to the validated schema; if the legitimate data genuinely cannot be represented, extend the schema deliberately rather than escaping to a fetch.

Enforce the boundary and test for it

Add a review rule that flags any direct HTTP call to a host already covered by an MCP tool, and write tests that assert the feature uses the tool. Then verify the generated requests against the contract so a stale field cannot hide. The combination makes the tool the easy path and the raw fetch the one that fails the build, which is the reliable way to keep an agent from quietly bypassing the contract.

FAQ

Why does the agent write a fetch when a tool exists?

Because the generic fetch is the model's fallback and it wins whenever the tool is not clearly the best path: a vague description, a previous tool failure, a schema mismatch, or a cluttered tool list. Fix the tool rather than accepting the fetch.

Is a hand-written fetch ever acceptable?

Only for a host with no MCP coverage. Once a tool exists for that API, a direct call bypasses the gateway's auth, schema validation, and logging, so it should be removed and replaced with the tool.

How do I stop the agent from abandoning a tool after one error?

Make the tool return structured, retryable errors with sensible timeouts so the agent recovers within the tool. Then investigate the underlying failure; do not let the model treat a transient error as proof the tool is unreliable.

What is the fastest fix?

Improve the tool description to name the resource and action and state when it should be used. That single change often redirects the model immediately, after which you can tighten the tool set and add enforcement.

This is part of the Powerduck vs Cursor hub — start there for the full comparison of contract tools alongside an AI editor.

Top comments (0)