← Blog
#mcp#agents

The MCP-server mistakes that make agents give up

May 27, 2026 · Selectorate team · 4 min read

An MCP server makes a promise. Agents can use this product directly, without writing integration code first. When it works, you move from product the agent writes code against to product the agent operates, and that jump is worth more than most features on your roadmap.

The catch is the reader. The agent working through your server cannot ping you on Slack when a tool name is confusing, and it never asks a follow-up question. It makes a guess, the guess burns a turn, and enough burned turns end the run. A half-working MCP server can hurt you more than having none at all, because every failed call spends budget and trust in the middle of a task you were winning. Here are the mistakes we see end runs most often.

1. Tool names that describe your architecture

Agents match intent to tools by name first, description second, schema last. The name is the headline, and the agent reads it the way your users read your homepage. execute_query_v2 says nothing about when to reach for it. search_customers answers the question before it gets asked.

The failure has a second form. Ship twelve overlapping tools and the agent faces a multiple-choice question with several plausible answers, and plausible is where runs go to die. One tool per job, named for the job, beats a toolbox that mirrors your internal service boundaries.

one intent, two tool lists
intent“refund the customer’s last order”
named for the architecture
execute_query_v2 ? batch_operation ? process_transaction_v3 ?
✗ three plausible answers, so the agent guesses or moves on
named for the task
search_orders refund_order matched get_refund_status
✓ the name answers when to use it
Fig. 1. The agent matches intent to tools by name first. Architecture names make every option plausible, and plausible is a guess.

2. Schemas that are technically valid and practically unusable

A parameter typed string with no description, no example, and no enum is a coin flip. The agent fills it with something plausible, the call fails or half-works, and the next guess starts from a worse position. The agent has never read your docs, and inside a tool call it cannot go read them now. The schema is the documentation.

Every field the agent must supply needs three things. A description written for a stranger, an example value it can pattern-match, and an enum wherever the valid values are enumerable. Optional fields deserve visible defaults. The work is tedious, and it is the difference between a first call that lands and a run that leaks away in retries.

one parameter, two schemas
technically valid
region string
no description, no example, no enum
agent sends "USA"
✗ a coin flip, and the next guess starts from a worse position
practically usable
region string · enum
datacenter region for the deployment
us-east | eu-west
example "us-east"
agent sends "us-east"
✓ the first call lands
Fig. 2. The schema is the documentation. A bare string is a coin flip, and a described field with an enum and an example is a pinned answer.

3. Errors that give no next move

A human sees 400: invalid request, sighs, and opens the docs. An agent sees it and retries the same call, then quits or switches. Inside a tool result, your error string is the only documentation guaranteed to be in the agent’s context, so it has to be the instruction. region is required; valid values are us-east, eu-west turns a dead end into a corrected call on the next turn.

We covered agent-facing errors in depth in the playbook, and the rules are identical inside a tool result. Name the field, state the constraint, show the corrected form.

4. Responses the agent cannot act on

The call succeeded, and the response is a four-thousand-line blob, or a page of HTML where JSON should be, or fifteen nested levels the agent has to spelunk through for one identifier. Parsing costs turns, summarizing costs context, and both spend the budget the agent was saving for the task itself. We have watched runs where every tool call worked and the responses still killed the task.

Return the shape the next step needs. If the agent asked for a customer, send the customer, with the identifiers the follow-up call will need sitting at the top level. Your response is a prompt for the agent’s next move, and every extra kilobyte is noise in it.

the call worked, then what
a blob to spelunk
4,000 lines, fifteen nested levels, sometimes HTML where JSON should be
✗ parsing costs turns, summarizing costs context
the shape the next step needs
{
  "id" "cus_814",
  "email" "a@ex.dev",
  "last_order_id" "ord_92",
  "status" "active"
}
the follow-up call’s identifiers sit at the top level
✓ the response is a prompt for the next move
Fig. 3. Both calls succeeded. One response is the next step’s input, and the other is a parsing job that spends the budget the task needed.

5. The server nobody calls

There is a failure mode that outranks all of these. The server is configured, the tools are listed in the agent’s context, and the agent never calls them once. It drives your REST API by hand with calls remembered from training, or writes SDK code instead, because your tool descriptions never told it when the tools apply and the remembered path looked shorter.

We see this constantly in audits. A working server, wired in and authenticated, with zero tool calls in the transcript. Adoption is the number to watch before any of the polish above matters, because a server the agent ignores may as well be absent, and you are back to competing on docs and memory. The fix is the description. Write every tool description as a when-to-use statement rather than a summary of what it wraps, so the match happens at the moment the agent plans.

run transcript · execution scenario
init>mcp server connected · yourapp, 3 tools listed
agent>curl api.yourapp.com/v1/customers
agent>curl api.yourapp.com/v1/orders
agent>writes SDK calls from memory of the old API
trace>mcp tool calls this run · 0
Fig. 4. The failure that outranks the others. The server was present and authenticated, and the agent drove the REST API from memory instead.

The test

Give an agent a realistic task, hand it your MCP server, and read the transcript with three questions. Did it call the server at all? Which call failed first, and what did the agent do next? Where did the budget actually go? The exact line where it hesitates, guesses, or gives up is your fix list, already ranked, because the earliest failure erases everything after it.

Running that test properly is its own discipline, with isolation, repeated trials, and instrumentation, and we broke it down in the playbook’s verification section. If you want the transcript for your server, request an audit. And if you do not have a server yet, we design and build them shaped around how agents reason, and every one runs through the same pipeline before it ships.