CCDV-F · Tools and MCPs
How to implement tools, who runs them, how they fail and how many to give
A developer writes a dispatcher branch for web search and never receives a single call. Another team has an agent with 38 tools that picks the wrong one among three similar searches and once deleted an account. A third returns a 120-line stack trace to the model. All three situations come from not being clear on how tool use (function calling) works.
Who runs each tool
| Type | Who runs it | What your code does |
|---|---|---|
| Client tools: your own and those with Anthropic-defined schemas, such as bash or the text editor | Your application | Receives stop_reason: tool_use, runs each tool_use block and returns a tool_result with its tool_use_id |
| Server tools: web search, web fetch, code execution | Anthropic, on its infrastructure | Nothing: the result arrives in the same response |
Two exam rules follow from this:
- You don’t write a handler for a server tool: you will never receive a
tool_useto run. - A server tool doesn’t reach into your private network. To query an internal service behind a VPN, you define your own tool that your code runs inside the network (or you expose it with an MCP server).
Descriptions that choose well
Claude decides which tool to use from its name and its tool description. A good description says what it does, when to use it and when not to, what each parameter means and what it returns. If two tools look alike, either merge them or make each description clarify which case it covers. To keep parameters always matching the schema, there is strict mode (strict: true).
Errors that help recovery
When the tool fails, the error comes back as a tool_result with is_error set to true and a short message saying what failed and what to do next: “unit number doesn’t exist; ask the user for the 6-digit number” or “service unavailable; retry in a minute”. A raw stack trace wastes context and tells the model nothing useful; an empty result makes it believe there was no data.
Approvals in the harness, not in the prompt
If an action needs human approval, the approval pattern goes in the code that runs the tool: the harness intercepts refund_order, lets small amounts through and holds large ones as pending until a supervisor approves. A rule in the system prompt (“ask for approval above a certain amount”) fails in some percentage of cases.
A healthy tool set
- Only what the role needs: a helpdesk agent doesn’t carry account-deletion or payroll tools.
- No tools that overlap with each other.
- Credentials and connections to external systems on your code’s side, never in the prompt.
The usual traps
- Writing a handler for web search, or expecting a server tool to reach an internal API.
- Returning raw exceptions or empty results instead of
is_errorwith a clear message. - Making approval a prompt rule.
- Adding tools “just in case”, admin tools included.
- Fixing a poor tool choice by switching models instead of improving the descriptions.
On the exam
First work out who runs the tool in the scenario: that rules out several options. If the model chooses badly, look for clearer descriptions or fewer tools. If it fails and doesn’t recover, look for is_error with an instructive message. And if there is a policy on amounts or approvals, look for the harness.
Quick question
A practice exam question on this domain. It counts towards your progress.
A property-management company has a maintenance assistant on the Claude API with a create_work_order tool. When the backend rejects a request, the tool handler currently catches the exception and returns the full Java stack trace as a normal tool result, about 120 lines long.
Logs show that in these cases Claude often tells tenants their request was submitted, or retries with exactly the same arguments several times. The most common failure is an invalid unit number, followed by the maintenance backend being briefly unavailable. The assistant handles around 900 requests a day across 40 buildings.
How should the tool handler report these failures?