Module 3

MCP and Tool Design

Agents pick tools from descriptions, fail well when errors are structured, and fabricate less when a tool's inputs are clearly sourced.

MCP in one paragraph

Confirmed in official docs
Plain language

MCP (Model Context Protocol) is a standard way to plug outside systems into an AI agent. One MCP server can offer three different kinds of things: tools the model can actively call to take an action (like 'process this refund'), resources you manually attach with an @-mention (data, not actions), and prompts — saved templates you invoke yourself, the same way you'd invoke a slash command. Knowing which of the three a question is really about is often the whole answer.

Technical

An MCP server can expose tools (model-callable actions), resources (@-mentionable data attachments), and prompts (user-invoked templates surfaced in Claude Code as slash commands, e.g. /mcp__servername__promptname, with arguments passed after the command name).

Why it matters

The three primitives serve genuinely different purposes (agent-initiated action vs. user-attached data vs. user-invoked template) — conflating them leads to picking a mechanism that technically can't do what's needed (e.g. expecting a 'resource' to be auto-invoked like a tool).

Tools are chosen by their descriptions

Confirmed in official docs
Plain language

The model decides which tool to use mostly by reading each tool's description, the same way you'd pick a document off a shelf by reading its label. If the model keeps grabbing the wrong tool, the usual fix isn't scolding it — it's that the label (description) is vague or under-sells what the tool actually does. If two tools do overlapping things, the cleanest fix is often to merge them into one tool with a parameter, so there's no longer a choice to get wrong.

Technical

Tool selection is driven substantially by the tool's description field. Vague descriptions cause the model to default to a more thoroughly-described competing tool. The structural fix for two semantically overlapping tools is consolidation into a single tool with a discriminating parameter, removing the ambiguous choice rather than just wording around it.

Why it matters

Fixing wording is cheap and immediate; fixing the underlying overlap (consolidation) is what prevents the same misselection from recurring as more tools get added.

Give the agent structured, instructive errors

Confirmed in official docs
Plain language

A generic 'Operation failed' message leaves the agent guessing, so it tends to either give up too fast, retry pointlessly, or ask the user something unhelpful. A much better error tells the agent what kind of problem this is (temporary glitch? bad input? not allowed?), whether trying again is even worth it, and ideally what to try instead — e.g. 'Order not found — try searching by phone number.'

Technical

Return structured error metadata: a category (transient / validation / permission), a retryable boolean, and a short cause. Anthropic's documented recommendation goes further: write instructive, type-specific messages describing what went wrong and what to try next, not just a category flag.

Why it matters

Structured, instructive errors let the agent choose the right recovery deterministically instead of guessing — this is explicitly called out as Anthropic's documented best practice for tool design.

Preventing fabricated tool arguments

Per study guide
Plain language

If the agent invents a fake ID instead of looking one up first, the real problem is usually that nothing ever told it where that value is supposed to come from. Spelling it out directly in the tool's description — 'this ID must come from a prior lookup call, never assumed' — fixes the behavior at the source instead of patching it after the fact.

Technical

Fabricated parameters typically trace back to a tool description that doesn't state the parameter's required provenance. The fix is to explicitly document the dependency (e.g., 'order_id must be obtained from a prior lookup_order call and must never be assumed') so the model is directed to call the prerequisite tool first.

Why it matters

This is another instance of the 'fix the root cause, not the symptom' pattern — validating or rejecting the fabricated value after the fact treats the symptom, while documenting provenance in the description prevents the fabrication from happening at all.

Worked examples for this module

See all 58 →
#9 / #10

MCP Prompts Surface as Slash Commands

Situation

A custom MCP server exposes MCP prompts (like a deploy checklist and an incident-response template) plus tools. How do those prompts become usable inside Claude Code?

Recommended approach

They appear as slash commands in the form /mcp__servername__promptname, with arguments passed after the command name.

Why it works

MCP prompts are user-invoked templates. Surfacing them as slash commands keeps them explicit and user-triggered — distinct from tools, which the model calls on its own, and resources, which are attached via @-mention.

Weaker approaches people try — and why they fall short

  • Added to the tool registry and invoked automatically by the model.That describes MCP tools, not prompts — prompts are invoked by the user, not auto-called by the model.
  • Auto-prepended to every conversation as system context.Prompts aren't silently injected into every conversation.
  • Surfaced as @-mentionable resources attached when referenced.That describes MCP resources, not prompts.
Takeaway — MCP has three surfaces: tools (the model calls them), resources (you @-mention them), prompts (you invoke them as slash commands). (This example merges two duplicate entries from the source guide, numbered 9 and 10.)

Plain-language notes on the technical terms above

MCP prompt
A saved template you invoke yourself, the same way you'd use a slash command.
MCP tool
An action the model can actively choose to call, like 'look up this order' or 'send this refund.'
MCP resource
A piece of data you manually attach to the conversation with an @-mention — not something the model calls on its own.
#18

Better Tool Descriptions Improve Selection

Situation

An MCP tool for analyzing code dependencies exists and works fine, but the agent keeps using a general search tool instead for 'code dependencies' questions — because the MCP tool's description is terse while the search tool's description is detailed.

Recommended approach

Expand the MCP tool's description to spell out its capabilities and outputs in detail.

Why it works

The model chooses tools largely from their descriptions. A detailed competing description makes that tool look more capable than a vague one. Rewriting the description to state exactly what it returns (direct imports, transitive dependencies, cycles) makes it the obviously better match — fix the description, fix the selection.

Weaker approaches people try — and why they fall short

  • Split the dependency-analysis tool into three more granular tools.Adds more surface area and new overlap without addressing the underlying vague description.
  • Add routing instructions in the system prompt to send dependency questions to the MCP tool.System-prompt routing is a brittle patch layered on top of the real cause.
  • Remove the general search tool whenever the MCP server is connected.Cripples a generally useful tool just to mask a description problem.
Takeaway — Agents pick tools by their descriptions. Weak selection usually means weak descriptions — make them specific about capability and output.

Plain-language notes on the technical terms above

MCP tool
An action the model can actively choose to call, like 'look up this order' or 'send this refund.'
#46

Structured Error Metadata for Correct Recovery

Situation

A support agent receives uniform errors from its tools — just 'isError: true, Operation failed' — so it can't tell a temporary glitch from a validation problem from a permissions issue, leading to over-retrying, escalating too soon, or asking the wrong clarifying question.

Recommended approach

Enhance error responses with structured metadata: an error category (transient, validation, or permission), a retryable boolean flag, and a short cause description.

Why it works

The agent behaves inconsistently because the errors are opaque. Structured metadata gives the agent exactly what it needs to choose the right action — retry transient errors, don't retry validation or permission errors, and escalate appropriately. Fixing the information fixes the behavior.

Weaker approaches people try — and why they fall short

  • Add a separate error-analysis tool the agent calls after any failure.An extra round-trip to derive information the failing tool could simply return directly.
  • Add few-shot examples showing how to interpret error message patterns.Parsing free-text error patterns is brittle and still guesses at categories the tool already knows internally.
  • Retry every error with exponential backoff at the server level.Wastes time retrying permanent errors, like a non-existent order, that will never succeed no matter how many times they're retried.
Takeaway — Give agents structured error metadata (category, retryable flag, cause) so they can pick the right recovery deterministically.

Plain-language notes on the technical terms above

Structured error metadata
An error message that tells the agent what kind of failure this was and whether trying again is even worth it, instead of just 'something went wrong.'
#48 / #49

Consolidate Overlapping Tools to Fix Selection

Situation

As a tool set grew from 4 tools to 10, tool-selection accuracy dropped noticeably. The errors cluster around semantically overlapping tools — one tool for issuing a credit and a separate one for processing a refund, and a delivery-status tool that duplicates data another lookup tool already returns.

Recommended approach

Merge the overlapping tools: combine the credit and refund tools into one tool with an action parameter, and fold the delivery-status tool into the existing lookup tool behind an include-tracking flag.

Why it works

Merging semantically overlapping tools into one tool with a parameter (and folding a redundant tool into an existing one) removes the ambiguous choice entirely — there's no longer a 'wrong' overlapping tool to pick, because there's only one right tool for the job. Removing the fork beats teaching the agent to navigate it.

Weaker approaches people try — and why they fall short

  • Split the tools across two sub-agents with a coordinator.Relocates the ambiguity behind a coordinator without removing the overlapping tool definitions themselves.
  • Enable deferred/lazy loading for the newer tools.Manages how many tools are visible at once, but the overlapping semantics remain once they're loaded.
  • Add few-shot examples for each ambiguous tool pair.Helps the agent choose more often, but doesn't structurally eliminate the overlap itself.
Takeaway — Overlapping tools cause selection errors — consolidate them into one tool plus a parameter to remove the ambiguous choice at its source. (This example merges two duplicate entries from the source guide, numbered 48 and 49.)

Plain-language notes on the technical terms above

Tool consolidation
Merging two tools that do overlapping things into one tool with an option, so there's no longer a wrong choice to make.
MCP tool
An action the model can actively choose to call, like 'look up this order' or 'send this refund.'
#53

Structured, Non-Retryable Errors Plus a Friendly Message

Situation

A refund tool returns both transient technical errors (like a timeout, about 5% of calls) and permanent business errors (like 'exceeds the 30-day window', about 12% of calls) — both as plain text, so the agent wastes several turns retrying the permanent business errors that will never succeed.

Recommended approach

Return structured errors with an explicit is_retryable:false flag for business errors, plus a customer-friendly explanation the agent can use directly in its reply.

Why it works

This solves two problems at once: the explicit retryable flag stops the agent wasting turns on permanent business errors, and the customer-friendly explanation improves what the customer actually sees — marking retryability explicitly rather than making the model guess at it.

Weaker approaches people try — and why they fall short

  • Auto-retry technical errors at the tool level, and pass business errors through untouched.Helps reliability for the technical errors, but leaves the customer-facing message quality completely unaddressed.
  • Add a mandatory eligibility-check tool that must run before the refund tool.Adds an extra round-trip, and still needs structured results itself to actually be useful.
  • Add few-shot examples teaching the model to distinguish retryable from non-retryable errors by parsing the text.Parsing error text is brittle, and doesn't improve the customer-facing explanation either.
Takeaway — Return structured errors with an explicit retryable flag and a user-friendly message — this stops wasted retries and improves customer replies together.

Plain-language notes on the technical terms above

Structured error metadata
An error message that tells the agent what kind of failure this was and whether trying again is even worth it, instead of just 'something went wrong.'
#57

Tool Description Prevents Parameter Fabrication

Situation

For a request like 'refund for my recent purchase,' the agent calls the refund tool immediately with a fabricated order ID instead of first looking the order up — and the refund fails on the fake ID.

Recommended approach

Update the refund tool's description to state explicitly that its order ID parameter must come from a prior lookup call, and must never be assumed or invented.

Why it works

The root cause is that the tool's description never told the model where that ID actually has to come from, so it invented one. Stating the dependency directly in the description instructs the model to call the lookup tool first — fixing the tool's contract fixes the behavior at its source.

Weaker approaches people try — and why they fall short

  • Pre-parse incoming messages for order IDs and inject any found into context.Only helps when an ID happens to be present in the message — here there isn't one to extract.
  • Switch tool_choice from 'auto' to 'any' so some tool call is always forced.Just forces some tool call — it wouldn't stop the model from fabricating the parameter itself.
  • Add server-side validation that the order ID exists, returning an error if it doesn't.Catches the bad ID after the fact, but doesn't stop the agent from fabricating and failing repeatedly.
Takeaway — Parameter fabrication is usually a tool-description gap — state where each parameter must come from, and that it must not be invented.

Plain-language notes on the technical terms above

MCP tool
An action the model can actively choose to call, like 'look up this order' or 'send this refund.'
#58

Instructive, Type-Specific Error Messages

Situation

An order-lookup tool catches every exception and returns the same flat message: 'Tool execution failed.' The agent either retries identically until it hits the turn limit, or escalates immediately — neither of which fits every situation.

Recommended approach

Return error-type-specific messages, such as 'Order not found — try looking up by customer or searching by phone' versus 'Database query timeout (transient) — retry should succeed.'

Why it works

The documented recommendation is to write instructive error messages that say what went wrong and what to try next. Type-specific messages — a 'not found' error suggesting an alternative path, versus a 'transient timeout' error indicating a retry will likely work — give the model the exact cues needed to choose the right recovery.

Weaker approaches people try — and why they fall short

  • Remove the error flag and return the message as normal content instead.Hides the fact that a failure actually occurred, which can confuse how the loop handles it.
  • Add a loop step that intercepts errors, classifies them into categories, and appends a recommendation.Works, but isn't what the documentation actually prescribes, and moves judgment out of the message the model directly reads.
  • Retry with exponential backoff inside the tool itself, surfacing only the final failure.Handles transient errors fine, but leaves an 'order not found' case with no actionable guidance for the model at all.
Takeaway — Follow the documented guidance: return instructive, error-type-specific messages telling the model what happened and what to try next.

Plain-language notes on the technical terms above

Structured error metadata
An error message that tells the agent what kind of failure this was and whether trying again is even worth it, instead of just 'something went wrong.'