Chapter 2. Tools and MCP
Learning objectives
- Design tools that are hard for agents to misuse and economical with tokens, and verify improvements through evaluation.
- Manage tool result size through pagination, filters, truncation and references.
- Explain MCP host, client and server roles and the stateless model in the 2026-07-28 specification.
- Distinguish protocol errors from tool execution errors and design error responses that guide recovery actions.
- Handle tool annotations, authentication and scopes according to trust boundaries, granting least privilege.
Introduction
Imagine giving a new employee a 300-page internal systems manual and saying, “Everything you need is here.” All the information is present, but they will spend their first week opening the wrong screens, confusing similarly named menus and getting stuck on error codes. This is what happens when an agent receives dozens of tools that merely wrap existing APIs.
Tools are an agent's window onto the world and its means of acting. This chapter first covers which tools to build and how to design their names, parameters, results and errors. It then explains MCP's structure, changes in the 2026-07-28 specification, and drawing permission boundaries through annotations, authentication and scopes. The deeper discussion examines strategies for hundreds of tools and calling tools through code.
Key concepts
Tools are interfaces for agents
Just as designing screens for people concerns HCI (human-computer interfaces), Anthropic calls designing tools and descriptions for agents ACI (agent-computer interfaces), and recommends investing as much care as in HCI. The same article says that when building its SWE-bench agent, the team spent more time optimizing tools than the overall prompt.
A representative technique is poka-yoke: designing mistakes out of the interface. When the model repeatedly got relative paths wrong after leaving the root directory, the team changed the tool to accept only absolute paths, which the model used without difficulty. Instead of adding “be careful with paths” to the instructions, they removed the error-prone input itself. It is the same idea as cutting one corner off a SIM card so it cannot be inserted backward.
The checks are simple. Is usage clear from the description and parameters alone? Are there examples and boundary cases? Would a new developer understand it without confusion? Then test many inputs to see where the model makes mistakes.
Choosing appropriate tools
Anthropic's “Writing effective tools for agents” emphasizes that more tools do not necessarily improve results. A common mistake is wrapping every API endpoint individually. It recommends a small number of tools aligned with important workflows, combining several steps: for contacts, use search_contacts or message_contact instead of list_contacts, which returns everything; for calendars, use one schedule_event tool that finds availability and books the event.
The boundary question is, “Would a human operator handle this as one task?” Excessive fragmentation increases calls by making the model compose operations. Overly broad tools need many parameters and become easy to call incorrectly. Merge overlapping tools, and distinguish tools that appear similar but serve different purposes through their names and descriptions.
Names, descriptions and parameters
When tools from several services are used together, names provide the first selection clue. The article recommends namespacing with service or resource prefixes (asana_search, jira_search, asana_projects_search). Parameter names should make their meaning clear: user_id is better than user.
Descriptions should state what a tool does and does not do, input formats and units, and the meaning of results. Consider how much clearer an update tool described as “modifies a record,” accepting only id and value, becomes when redesigned as follows.
{
"name": "shipment_set_weight",
"description": "Record a shipment's measured weight before dispatch. Dispatched shipments cannot be changed. Weight is in kilograms, to one decimal place.",
"inputSchema": {
"type": "object",
"properties": {
"shipment_number": { "type": "string", "description": "Example: SH-2026-004211" },
"weight_kg": { "type": "number", "minimum": 0.1, "maximum": 30000 }
},
"required": ["shipment_number", "weight_kg"],
"additionalProperties": false
}
}
The redesign puts the unit in the parameter name, constrains the permitted range in the schema, and states when changes are prohibited. For values models often mishandle, such as time zones, eliminate mistakes through format requirements: require ISO 8601 with an explicit time zone, or accept UTC only. Check business rules that schemas cannot enforce, such as not dispatching more than available stock, on the server. A structurally valid call can still violate business rules.
Returning meaningful results
Tool results are the material for the next action. The article recommends returning fields an agent can use directly, such as names, rather than low-level identifiers such as uuid, 256px_image_url and mime_type. It reports improved retrieval accuracy after replacing opaque identifiers with readable language. If an ID is essential for the next call, return it alongside the name.
You can also let the agent choose response detail. An enum parameter such as response_format with “concise” and “detailed” lets it use concise responses normally and detailed responses only when IDs are needed. In the article's example, the detailed response was 206 tokens and the concise response 72—about one third as much.
Managing tool result size
Larger results consume context and accelerate the context rot discussed in Chapter 3. The article recommends pagination, range selection, filtering and truncation with sensible defaults. It notes that Claude Code limits tool responses to 25,000 tokens by default.
| Technique | Design example |
|---|---|
| Default count and pages | Default limit of 20; return a next-page cursor |
| Server-side filters | Parameters to narrow by date range, status and assignee first |
| Field selection | A fields parameter selecting only needed columns |
| Truncation notice | “Showing 20 of 1,240 results. Narrow the date range or filter by status” |
| References | Store large artifacts as files or resources and return their locations |
When truncating, always state that truncation occurred and its extent in the result. Otherwise, the agent assumes the 20 records it received are everything. MCP tools can return a URI in a resource_link for later reading, and defining an outputSchema enables structured results through structuredContent. With an output schema, the server MUST return conforming results, and the client SHOULD validate them. For backward compatibility, the specification also recommends including the same JSON in a text block.
Errors are recovery instructions
The MCP specification divides tool errors into two categories.
| Type | Examples | Delivery | Model's recovery prospects |
|---|---|---|---|
| Protocol error | Unknown tool, malformed request, server error | JSON-RPC error |
Low |
| Tool execution error | API failure, input validation failure, business rule violation | isError: true and an explanation in the result |
High: correct arguments and retry |
The specification says clients SHOULD pass tool execution errors to the model so it can correct them. Execution errors are returned using the same structure as normal results. In the 2026-07-28 revision, every result has a resultType identifying its kind; a completed result uses "complete".
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"resultType": "complete",
"content": [{ "type": "text", "text": "The delivery date must be after today. Today is 2026-10-20." }],
"isError": true
}
}
Good error messages indicate the next action. Distinguish whether to correct input, wait and retry, obtain more permission or hand the matter to a person. One case needs special care: errors where execution status is unknown, such as timeouts. A payment might have been processed while only its response was lost. The correct instruction is then “check the processing result,” rather than “retry.” Do not include internal stack traces or sensitive values in errors.
Tools with side effects: preview and commit
A mistaken lookup call costs tokens, but a mutation tool changes an external system's state. For hard-to-reverse changes, separating preview from commit is effective.
- A preparation tool calculates and returns the targets, new values and impact—amount, recipients or record count—and issues a short-lived preview identifier.
- A person or policy check reviews the preview.
- The commit tool accepts only the preview identifier. The server executes exactly the content identified by it.
- Committing twice with the same identifier produces the effect only once: idempotency.
This closes the gap between approved and executed content and prevents retries from causing duplicate execution. Accepting absolute values (“set the daily budget to KRW 300,000”) rather than relative ones (“increase it by 10%”) is another form of poka-yoke: repeating the request produces the same result.
MCP components
MCP (Model Context Protocol) is an open protocol connecting LLM applications with external data and tools. Messages use JSON-RPC 2.0, and there are three participants.
| Role | Description |
|---|---|
| Host | The LLM application initiating connections |
| Client | A connector within the host communicating with one server |
| Server | A service providing context and capabilities |
Servers provide three capabilities: resources (context and data for users or models), prompts (template messages and workflows for users), and tools (functions executed by the model). Clients can provide elicitation, through which a server requests additional information from a user. The 2026-07-28 revision marks Roots, Sampling and Logging as Deprecated. They still work for now, but new implementations should avoid adopting them. The suggested alternatives are passing directories through tool parameters or server configuration, integrating directly with LLM provider APIs, and logging through standard error or OpenTelemetry, respectively.
The specification's safety principles say tools should be treated as arbitrary code execution. Hosts SHOULD obtain explicit user consent before tool invocation and allow people to deny calls.
The 2026-07-28 specification: statelessness and handles
The biggest change is that MCP is now a stateless protocol. All information needed for processing is in the request. Servers MUST NOT derive context such as protocol version, client capabilities or identity from previous requests on the same connection. Every client request must therefore include io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities in _meta. If missing, the server rejects the request with an invalid parameters error (-32602). Including client name and version (io.modelcontextprotocol/clientInfo) is recommended, but these self-reported values must not be used for security decisions. The previous initialize handshake and session ID header are gone. server/discover now lets servers report supported versions and capabilities. An open stdio process is not a conversation or session either.
When state must span calls—a cart, an open browser or a database transaction—a creation tool returns an explicit handle, and subsequent calls accept it as an argument. The specification's non-normative guidance is as follows.
- On authenticated servers, a handle is a name, not a permission. Check the caller's permissions against the handle on every call.
- Make handles opaque identifiers that reveal no internal structure, and state their retention period in the creation tool's description.
- For expired or unknown handles, return a tool execution error stating that fact so the model can create a new one.
If processing needs more user input, use multi-round-trip requests (MRTR). The server returns a resultType: "input_required" result containing the needed requests and opaque requestState. The client fills in the responses and resends the original request with a new ID. Because requestState passes through the client, the server treats it as potentially manipulated input and MUST protect its integrity if it affects permissions or business logic. Elicitation has a form mode using input forms in the client UI and a URL mode sending users to an external page. Form mode must not request passwords, API keys, tokens or payment information. Collect such information through URL mode, bypassing the client.
Caution
A stateless protocol does not mean servers cannot hold business data or long-running task state. State is allowed, but must be tied to explicit identifiers rather than connections. Revisions through 2025-11-25 used the initialize handshake, and Streamable HTTP servers could issue session IDs. Check the other party's version first.
Transports, cancellation and long-running tasks
MCP has two standard transports: stdio, where the client launches the server as a subprocess and communicates through standard input and output, and Streamable HTTP, for HTTP communication with remote servers. The earlier HTTP+SSE transport is deprecated.
Cancellation and timeouts differ by transport. With Streamable HTTP, closing a request's response stream constitutes cancellation, and the server must treat client disconnection as cancellation of that request. The 2026-07-28 revision removed stream resumption, so interrupted requests must be resent with a new ID. With stdio, send notifications/cancelled. The specification recommends timeouts on all requests. A timeout may be reset when progress notifications arrive, but a maximum timeout SHOULD always be enforced, regardless of progress notifications.
Tying work that lasts minutes or hours to a single connection makes it vulnerable to proxy timeouts and client restarts. The official Tasks extension lets a server return a durable task handle instead of a result. Clients query state (working, input_required, completed, failed, cancelled) through tasks/get, continuing with the same ID after a restart. Both parties must advertise support to use the extension.
Tool annotations and trust
Tool definitions include name, title, description, inputSchema, outputSchema and annotations. Names are recommended to be 1–128 characters long, using only English letters, digits, underscores, hyphens and dots. Names can collide when tools from several servers are combined. The specification recommends a disambiguation strategy such as server identifier prefixes, warning against relying on the server name in serverInfo, which is not guaranteed to be unique.
Annotations are hints describing tool behavior.
| Annotation | Meaning | Default |
|---|---|---|
readOnlyHint |
Does not modify its environment | false |
destructiveHint |
May make destructive changes; meaningful only when not read-only | true |
idempotentHint |
Repeated calls with the same arguments have no additional effect; meaningful only when not read-only | false |
openWorldHint |
May interact with an open external world, such as web search | true |
Notice the conservative defaults. A tool with no annotations is assumed to modify its environment, potentially cause destruction and interact with the outside world. The specification also warns that clients MUST regard annotations as untrusted unless they come from a trusted server. An annotation is the server's self-description, not a guarantee. Permission decisions such as automatic approval must depend on server trust level and host policy.
Authentication and least privilege
The specification's authentication scope differs by transport. HTTP-based transports SHOULD follow the MCP Authorization specification. stdio implementations are advised not to follow that specification, but to obtain credentials from the execution environment.
The security best practices document gives these central rules.
| Risk | Rule |
|---|---|
| Token passthrough | MCP servers MUST NOT accept tokens not issued for them. Passing received tokens unchanged to downstream APIs undermines controls such as audit trails and rate limits |
| Confused deputy | Proxy servers using a static client ID with a third-party API must obtain per-client consent before proceeding to third-party authorization |
| Handle theft | Do not treat possession of a handle as authentication. Bind handles to authenticated users on the server |
| Excessive scopes | Start with minimum scopes and escalate incrementally through scope requirements in WWW-Authenticate when a privileged action is first attempted. Avoid broad scopes such as * and all |
| Local servers | Clients supporting one-click installation must display the complete execution command without truncation and obtain explicit approval. Execution in a least-privilege sandbox is recommended |
A scope defines the actions a token permits. Giving only the key to the room currently needed, then more keys as needed, limits damage from loss compared with a master key. tools/list must not vary by connection, but may vary by request authorization. A server can show only tools permitted by the caller's scopes. Hiding tools is only a convenience; actual enforcement comes from server-side permission checks on every call.
Human approval and security requirements
Tool security requirements assign different responsibilities to servers and clients.
| Party | Requirements |
|---|---|
| Server (MUST) | Validate all inputs, enforce appropriate access control, rate-limit calls and sanitize outputs |
| Client (SHOULD) | Obtain user confirmation before sensitive operations; show the actual inputs before calls to prevent unintended disclosure; validate results before passing them to the model; apply timeouts and keep audit logs |
Chapter 5 covers which calls need human confirmation. Here, remember that the confirmation screen must show the actual inputs to be sent. Asking only “Send the email?” can approve a call whose recipient has changed.
Going deeper
When tools grow into the hundreds
Connecting several MCP servers can fill a substantial share of context with tool definitions alone. MCP's client best practices recommends progressive discovery. The host receives definitions but does not immediately insert them into context. A lightweight search_tools meta-tool discovers needed tools and loads their full definitions. The document describes three layers: listing (names and one-line descriptions), detail (one tool's full schema) and execution. It recommends switching when definitions exceed a certain share of the context window, for example 1–5%. Search may use keywords, embeddings, selection by a small model or a combination. Some model providers offer built-in tool search.
The trap is prompt caching. Most providers cache the prompt prefix, including the tools array. Adding, removing or reordering definitions during a conversation invalidates the cache. The document recommends appending newly discovered definitions after the cache boundary, or routing every call through one fixed call_tool meta-tool that accepts a tool name and arguments, keeping the array unchanged. This also explains why the specification recommends a deterministic ordering for tools/list.
When models call tools through code
With direct tool calling, the entire result of every call passes through the model. To read thousands of log lines and create a ticket for each unique error, the model must read all those lines. In programmatic tool calling (code mode), the model writes code that calls tools. The code runs in a sandbox, and only the final result returns to the model. Intermediate data stays out of context, greatly reducing tokens and latency.
This introduces a new attack surface: code execution. MCP documentation gives six conditions. Deny direct sandbox network access and route all communication through a host broker; keep credentials with the host and out of generated code; do not treat approval of a script as approval of every call within it; treat one server's results as untrusted input to another; limit execution time and memory; and validate and truncate sandbox output before passing it to the model. For interactive tasks with only one or two calls, complexity may outweigh benefits. Start with tasks that filter and aggregate large datasets.
Managing tool changes as contracts
Even with an unchanged schema, one line of description or one result field's meaning can change agent behavior. Version names, descriptions, schemas and business semantics together, keep a change history and evaluate before deployment. Anthropic recommends measuring execution time, tool calls, tokens and tool errors on real tasks, then checking a held-out test set to avoid overfitting the evaluation set. Its research system article reports a 40% reduction in subsequent task completion time from an agent that rewrote tool descriptions. Servers can announce list changes through notifications/tools/list_changed; clients should then discard and refresh their cached list.
At work
Rolling Wave Ads: safeguarding budget changes
The advertising agency Rolling Wave Ads used an operations agent with tools that directly wrapped 11 advertising platform APIs. The previous quarter had two types of incidents: nine changes applied to the wrong similarly named campaign ('AutumnSale_Search' and 'AutumnSale_Search_Returning'), and three cases where retrying after a timeout applied “increase daily budget by 20%” twice.
The team considered three alternatives. Adding more cautionary text to the system prompt was rejected because they had already tried that the previous quarter. Keeping all 11 tools and improving only descriptions was rejected because it did not eliminate relative increases and duplicate execution. They chose tool redesign.
Lookups were combined into campaigns_find(query, status), returning campaign name, ID, current daily budget and owner. Changes were split in two. budget_change_preview(campaign_id, new_daily_budget_krw) accepts only absolute values and returns before-and-after amounts, projected monthly spending and a preview ID valid for ten minutes. budget_change_apply(preview_id) accepts only that ID and applies it once even if called twice. Increases above 50% return isError: true with “Owner approval required. Use the approval request tool.” After a timeout, the agent checks application status by preview ID instead of retrying.
They evaluated 40 tasks derived from the 12 previous incidents and a separate held-out set of 25 new tasks. Both sets had zero wrong-campaign changes and duplicate increases. Tool calls per task fell from 4.8 to 2.6.
Blue Software: redrawing deployment MCP permissions
The development platform company Blue Software built a remote MCP server to let an agent inspect deployment status and roll back problems. The first version prioritized speed. It accepted users' CI system tokens and passed them directly to the CI API, used one scope, deploy:*, and allowed rolling back anyone's deployment given its ID.
Security review identified three issues. The server accepted and forwarded tokens not issued for it: token passthrough. Read-only users also had rollback privileges: excessive scopes. Deployment IDs functioned as permissions: treating handles as authentication.
The redesigned server accepts only its own tokens issued through MCP authorization and validates their audience. It accesses the CI API with its own credentials, but checks the user's deployment permissions against the internal authorization system on every call and records the actual user identifier in downstream audit records. Initially it requests only deploy:read; the first rollback attempt requires deploy:rollback, triggering incremental escalation. tools/list hides the rollback tool according to scopes, but every rollback call is checked again on the server. The rollback tool has destructiveHint: true. The host registers the internal server as trusted and uses the annotation to display a confirmation screen.
The rejected alternative was adding “roll back carefully” to the tool description. A description advises the model; it does not define a permission boundary.
Common mistakes
- “Expose every API as a tool and the agent will choose.” Wrapping existing APIs is quick, but pushes composition onto the model and confuses similar tools. Prefer a few workflow-level tools.
- “Errors should always be protocol errors.” This resembles ordinary API practice, but business errors the model can correct need
isErrorand specific explanations to support recovery. - “It has
readOnlyHint, so it is safe.” A specification-defined field may look like an official guarantee, but annotations are server claims. Do not base permission decisions on annotations from untrusted servers. - “Passing received tokens directly to downstream APIs is convenient.” This shortcut constitutes token passthrough, which is prohibited by the specification. It undermines audit trails, rate limiting and trust boundaries together.
- “Truncating results solves the size problem.” It reduces tokens, but without a truncation notice and extent, the agent treats a subset as the whole and draws conclusions from it.
- “MCP is stateless now, so servers cannot hold state.” Despite the name, state is permitted. Bind it to explicit handles rather than connections and check permissions for each handle.
- “A tool hidden from the list cannot be called.” Disappearing from view looks like blocking, but list filtering is a convenience. Server-side permission checks on every call provide actual enforcement.
Summary at a glance
- Tools are ACI. Eliminate error-prone inputs through format: absolute paths, absolute values and names containing units.
- Build a small number of workflow-level tools, rather than endpoint-level ones, and distinguish them with namespaces.
- Return fields useful for the next action. Control detail through
response_format, and size through pages, filters, truncation notices and references. - Return business errors with
isErrorand recovery instructions. When execution status is unknown, query before retrying. - Split hard-to-reverse changes into preview and commit, and make them idempotent.
- MCP 2026-07-28 is stateless. Version and capabilities in
_metaare mandatory; state uses handles; handles are not permissions. - Enforce a maximum timeout regardless of progress notifications, and consider the Tasks extension for long work.
- Annotation defaults are conservative. Do not trust annotations from untrusted servers.
- No token passthrough. Start with minimal scopes, escalate incrementally and check permissions on the server for every call.
Check the official docs
- Anthropic: Writing effective tools for agents — tool selection, namespaces, meaningful results, token efficiency, errors and evaluation-driven improvement
- Anthropic: Building effective agents — ACI and poka-yoke in the appendix
- MCP 2026-07-28: Specification — components and safety principles
- MCP 2026-07-28: Base protocol — stateless model,
_meta, authentication scope - MCP 2026-07-28: Tools — definitions, results, errors, state handles and security requirements
- MCP 2026-07-28: Key changes — changes from earlier revisions and deprecated capabilities
- MCP: Security best practices — token passthrough prohibition, minimal scopes, handle theft and local servers
- MCP: Client best practices — progressive discovery, caching and programmatic tool calling
Self-check
2-1. Explain why an API convenient for human developers can differ from a good agent tool, considering context cost and selection errors.
2-2. What problem does a response detail parameter such as response_format solve, and when should an agent select a detailed response?
2-3. State two pieces of information a truncated tool result must include, and explain the mistake an agent makes without them.
2-4. Name three kinds of information a server must not derive from previous requests on the same connection under the 2026-07-28 specification, and state where that information is carried instead.
2-5. What assumptions does a client make about a tool with no annotations? Explain using the specification's defaults.
2-6. Explain in one sentence each why token passthrough undermines audit trails and rate limits.
2-7. Design an agent tool for extending a loan in an internal library system. To make the tool difficult to misuse, specify a name, parameters including formats, one business error and its message, and a condition requiring human confirmation.
Hands-on tasks
Exercise
Redesign and measure one tool (60 minutes)
- Choose a tool an agent uses frequently or often misuses.
- Select 20 tasks from actual usage: 15 for improvement and five for validation.
- Run them with the current tool, recording tool calls, tokens and tool errors per task.
- Redesign it using this chapter's principles: workflow-level operations, parameter names with units, default counts and truncation notices, and errors with recovery instructions.
- Rerun both improvement and validation tasks and compare the three metrics.
Done when: At least two of the three metrics improve on validation tasks without lowering task success rate. If they do not, you must have a record of finding where the model misunderstood the tool in the transcript and correcting the description.
Exercise
Build a permission table and server-side checks (45 minutes)
- List all tools in one MCP server or tool collection in operation.
- For each, tabulate whether it reads or writes, reversibility, required scopes and annotations to apply.
- Separate the minimum scopes at initial connection from scopes requiring escalation.
- Choose one write tool. Write a server-side check comparing the caller's permissions with the target resource, and define an error message for unauthorized calls.
Done when: A test confirms that the server rejects an unauthorized user's call, and the table contains scopes and annotations for every tool.