CCA-F Exam Blog · Technical Guides

9 MCP Server Design Mistakes and How to Avoid Them

MCP server design mistakes that break agents in production and on the CCA-F exam: vague descriptions, uniform errors, missing isError, tool sprawl, and fixes.

Updated

Most MCP server design mistakes come down to two things: the model cannot tell your tools apart, or it cannot tell what went wrong when one fails. Fix the descriptions and the error contract and you eliminate the majority of misrouting, pointless retries, and false “no results” answers that make agents look unreliable.

This is also the heart of Domain 2 of the Claude Certified Architect – Foundations exam (Tool Design & MCP Integration, 18%). The scenarios describe a server that behaves badly and ask which redesign is least bad. Below are nine mistakes that recur in production and in exam questions, each with the fix.

Which tool description mistakes cause misrouting?

Mistake 1: Tool descriptions that differ by one word

Three extraction tools described as “Extracts data from invoice documents,” “…from contract documents,” and “…from report documents” look distinct to a human. To the model they are near-identical strings, and in one measured system 30% of contracts were routed to the invoice tool. Execution accuracy was fine; selection was the problem.

Fix: write each description with purpose, input format, output, example uses, and an explicit boundary with a redirect. A working template:

{
  "name": "extract_invoice",
  "description": "Extracts line items, quantities, totals and payment terms from invoice PDFs. Input: file path to a PDF. Returns: JSON with vendor, line_items[], total, due_date. Use for: supplier invoices, bills, receipts. NOT for contracts (parties, obligations, signatures) - use extract_contract.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "file_path": { "type": "string", "description": "Absolute path to the invoice PDF" }
    },
    "required": ["file_path"]
  }
}

Forty to fifty words with a “NOT for” line consistently outperform five-word descriptions. See tool description as the selection mechanism and the three-field definition.

Mistake 2: Fixing overlap with keyword rules instead of descriptions

When two tools get confused, the reflex is to add a system-prompt rule: “when the user mentions refund, call process_refund.” Then “Where is my refund?” triggers a new refund instead of a status check. Removing keyword rules and relying on descriptions improved routing from 78% to 94% in one system.

Fix: measure which pairs misroute, expand only those descriptions, and reserve few-shot examples for the genuinely ambiguous remainder. Details in description overlap and misrouting and keyword sensitivity.

Mistake 3: One tool with hidden “modes”

A single analyze_document tool that extracts, summarizes, and verifies claims depending on a mode parameter forces the model to guess an operation the description barely explains. Parameter error rates around 35% are typical.

Fix: split into purpose-specific tools with focused schemas. Splitting is not tool sprawl when each tool has one job; it removes the mode-guessing.

Which error-handling mistakes cause bad retries and false answers?

Mistake 4: The uniform “Operation failed” error

If a timeout, an invalid date, a suspended account, and a policy limit all return the same isError: true with “Operation failed,” the agent has one strategy for all four: retry. Three of the four never succeed on retry. Watching an agent retry a permission error five times in thirty seconds while a customer waits is the classic symptom.

Fix: classify errors and say whether retrying can help.

{
  "content": [{ "type": "text",
    "text": "Validation error: 'date' must be ISO 8601 (YYYY-MM-DD). Received '15th of March, 2024'. Convert to '2024-03-15' and retry." }],
  "isError": true,
  "structuredContent": {
    "errorCategory": "validation",
    "isRetryable": true,
    "invalidField": "date",
    "expectedFormat": "YYYY-MM-DD"
  }
}

Transient errors are retryable; validation errors are retryable after a fix; business and permission errors are not, and should carry a customer-facing message and a suggested action. Recovery rates move from roughly 15% with generic errors to 78–95% with structured ones. Numeric error codes do not help; the model cannot look them up. See the isError flag, error type classification, and the uniform error anti-pattern.

Mistake 5: Disguising failures as empty results

The database is down, so the tool returns isError: false with “No results found.” The agent tells the customer their order does not exist. The customer has the confirmation email. In a research context, the same bug turns an outage into “no papers exist on this topic.”

Fix: if the query did not execute, return isError: true with what was attempted (“timeout looking up order_id=ORD-12345”). If it executed and matched nothing, isError: false is correct. The two outcomes look the same to a naive implementation and mean opposite things to the agent. See access failure vs valid empty and the Foundations article don’t disguise errors as empty results.

Which structural mistakes hurt selection and security?

Mistake 6: Exposing browsable content as tools

Five hundred knowledge-base articles as five hundred tools destroys selection. Even a single search_kb tool requires the agent to know what to search for.

Fix: use MCP Resources for read-only catalogs. The agent calls resources/list, sees what exists, then resources/read for the items it needs. Resources do not count toward the tool set the agent must choose from, so an agent with 3 tools and 500 resources still selects among 3. The rule of thumb: observation is a Resource, action with side effects is a Tool. See Resources vs Tools and the three primitives.

Mistake 7: Too many tools in front of one agent

Selection accuracy falls steeply with count: near 97% at 3 tools, roughly 82% at 8, and about half at 18. “Just in case” tools are not free. Over-provisioned agents also wander outside their role, such as a synthesis agent that starts re-searching because it happens to have search tools.

Fix: give each agent only its role’s tools, and when a system genuinely needs 15+ tools, spread them across specialized sub-agents behind a coordinator. Least privilege doubles as an accuracy optimization. See tool count vs reliability and cross-role scoped tools.

Mistake 8: Leaking secrets or picking the wrong scope

Team-shared servers belong in .mcp.json at the repo root, committed to git. Personal servers belong in ~/.claude.json. Neither belongs in CLAUDE.md, which is instructions, not configuration. And because .mcp.json is committed, a hardcoded token in it lives in git history forever. Adding the file to .gitignore “fixes” the leak by removing the sharing that was the point; base64 is obfuscation, not security.

Fix:

{
  "mcpServers": {
    "github": {
      "command": "github-mcp-server",
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}

Every developer sets their own variable locally; the shared file contains only the reference. See project vs user scope and environment variable expansion. Remember also that all configured servers connect at startup, so every server you add raises the total tool count the agent sees.

Mistake 9: Building custom what already exists

Writing your own GitHub or Jira server when an official or community one exists means you now own its bugs, its auth flow, and its upgrades. Forking has the same cost. Custom servers earn their keep for proprietary internal APIs and workflows nobody else has.

Fix: use community servers for standard integrations and pin versions if you need stability. See community vs custom servers. While you are at it, watch for the naming trap in the Foundations article on the camelCase field: MCP uses inputSchema, the Claude Messages API uses input_schema, and copy-pasting between them fails silently.

What is the exam really testing?

Almost every Domain 2 scenario reduces to one of three judgments: does the model have enough signal to pick the right tool, does it have enough signal to recover from failure, and is each capability exposed through the right primitive at the right scope. Distractor answers add stronger wording, more retries, or more tools. The rewarded answers improve descriptions, structure the errors, move catalogs to Resources, restrict tools per role, and keep secrets in the environment.

Next step

Read the Domain 2 study guide end to end; the error-handling task group is short and heavily tested. Then take the free mock exam, which draws Domain 2 scenarios in proportion to the official 18% weight, and review any misses against the articles linked above. Confirm current exam details such as the US$125 fee and 120-minute format on the official Anthropic / Pearson VUE page before you register.

Frequently asked questions

Should an MCP tool return an error as a JSON-RPC error or as isError: true?

expand_more

Runtime failures (timeouts, permission denied, not found) belong in a CallToolResult with isError: true so the model can see and reason about them. JSON-RPC errors are for protocol problems such as calling a tool that does not exist.

How many tools should one MCP server expose?

expand_more

There is no hard protocol limit, but selection accuracy drops as the tool count an agent sees grows. Aim for a small, focused set per agent, and move browsable content into Resources so it does not count against tool selection.

Where do MCP server credentials go in a team project?

expand_more

In each developer's environment, referenced from .mcp.json with ${ENV_VAR} syntax. The config file is committed; the token never is.

Put it into practice

Take the free 60-question Claude Certified Architect mock exam, or work through the CCA-F study guide domain by domain.

Certified Architect is an independent, community-built study site. Exam facts reflect public Anthropic / Pearson VUE information and can change — always confirm on the official pages before registering.

Related articles