CCAR-F · module 4 of 5 · 18% of the exam

Tool design and MCP integration

Weight: 18 percent of the exam. Tests whether you can design tools an agent uses correctly on the first try, and wire them into a system through MCP with the right transport, scope, and safety gates.

What the exam expects

Every scenario gives you an agent that has tools, and something about those tools is making it behave badly: it picks the wrong one, passes the wrong parameter, retries a call that can never succeed, dumps forty thousand tokens of raw output into its own context, or executes something irreversible that a human should have approved.

The examinable insight is almost always the same: the tool definition is the interface between your system and the model's judgment, and most agent misbehaviour is a defect in that interface rather than a defect in the model. Answers that fix the schema, the description, the response shape, or the permission boundary beat answers that add a prompt instruction, a bigger model, a monitoring layer, or another agent. The sections below cover the surfaces those answers live on, ending with the MCP mechanics (transports, scopes, authentication, tool search, output limits) that the scenarios assume you know.

The tool definition is a contract, not documentation

A tool definition has three parts that carry weight: name, description, and input_schema. The API builds a system prompt from your tool definitions, so these are not comments sitting beside your code. They are the prompt.

Descriptions are the single highest leverage factor in tool use performance. Write at least three to four sentences, and more for complex tools, covering four things:

  1. What the tool does.
  2. When it should be used, and explicitly when it should not.
  3. What each parameter means and what format it takes.
  4. Caveats and limitations, including what the tool does not return.

That fourth item is the one candidates skip and the exam rewards. A get_stock_price tool described only as "Gets the stock price for a ticker" leaves the model guessing about which exchanges are covered, what currency comes back, and whether it can also ask for company fundamentals.

Names carry meaning too. When your tools span multiple services, prefix them with the service: github_list_prs, slack_send_message, crm_search_customers. Three MCP servers each exposing a tool called search is a design defect, and the fix is namespacing, not a system prompt that explains which is which. This matters even more once schemas are deferred and discovered on demand, because the name is often the first thing the model sees.

Parameter design: make invalid calls unrepresentable

The strongest control you have is the schema, because it constrains what the model can emit rather than merely advising it.

SituationWeak approachStrong approach
Fixed set of valid valuesString parameter described in proseenum with the exact accepted values
Complex nested inputLonger descriptioninput_examples with schema valid examples
Inputs must never be malformedPost hoc validation and retrystrict: true on the tool definition
Field may legitimately be absentRequired string, model invents a valueNullable type with an explicit meaning for null

input_examples is an optional array of example input objects, each of which must validate against the tool's input_schema (invalid examples return a 400). It is recommended for nested objects, optional parameters, or format sensitive inputs, and it is not supported on server side tools such as web search or code execution.

strict: true uses constrained decoding to guarantee that tool names and inputs conform to your schema. The exam framing: if a scenario says "about two percent of calls arrive malformed and we catch the exception and re-prompt," the answer is to make malformed calls impossible rather than to retry them more times.

tool_choice has four values: auto (default when tools are provided), any (must call some tool), tool (must call a named tool), and none. Two details are examinable: with any or tool the API prefills the assistant message, so the model emits no natural language before the tool_use block, and changing tool_choice invalidates cached message blocks, though tool definitions and system prompts stay cached.

Response shaping and errors agents can act on

A tool response is context the agent has to pay for and reason over. Two principles govern it.

Return only high signal information. Prefer semantic, stable identifiers (slugs, human readable names) over opaque references such as UUIDs, because agents hallucinate far less with readable identifiers and are much less likely to fabricate one. Include only the fields the agent needs to decide its next step. Add pagination, filtering, and truncation with sensible defaults, and when you truncate, say so and say how to get more.

Errors are part of the interface. An opaque "Error: 500" teaches the agent nothing, so it either retries a permanently failing call or gives up on a transient one. A good tool error states the category, what was wrong, and what to do instead: invalid input, the value looks like a tracking number rather than an order ID, call get_order_by_tracking_number. Distinguishing retryable from non retryable failures is what lets the agent decide rather than guess.

A failed tool call should come back to the model as a tool result marked as an error, not as a client side exception that terminates the agent loop, so the agent can retry, substitute a tool, or escalate. Returning a successful empty result on failure is the worst option, because it makes an outage indistinguishable from a legitimate "nothing found."

For mutating tools, add an idempotency key. When a call times out after the write succeeded upstream, a retry with the same key returns the original result instead of creating a duplicate order, refund, or ticket.

Composition, consolidation, and destructive actions

Consolidate related operations. Six tools named create_pr, review_pr, comment_on_pr, request_changes_on_pr, approve_pr, and merge_pr present the model with six near neighbours to discriminate between. One tool with an enum constrained action parameter presents one choice plus a validated action.

Consolidation also applies across steps. A flow of list_availability, then client side filtering, then create_booking has a race between the check and the write. A single schedule_event tool that checks and books atomically removes the race rather than narrowing it.

Destructive actions need a structural gate, not an instruction. A system prompt line saying "always confirm before closing an account" is not a control, because the model must interpret ambiguous user language against it, and a prompt injection can target that same instruction. The patterns that hold up:

  • A preview step that returns exactly what will change before anything commits.
  • A two step confirmation where the first call returns a confirmation token and only a second call carrying that token executes.
  • A human approval gate enforced by the tool, so the model proposes and a person commits.
  • Narrow explicit parameters (a specific account ID) instead of a free form description of what to remove.

Audit logging and soft deletes are worth having, but on the exam they are compensating controls: they help you recover after the damage, they do not prevent it. Similarly, a narrow dedicated tool beats a broad Bash grant whenever the real need is one well defined action, because the dedicated tool is auditable, rate limitable, and cannot reach anything else on the machine.

MCP: transports, scopes, and distribution

Protocol semantics are identical across transports; a transport is just a binding that defines framing and delivery.

TransportUse whenNotes
stdioThe server runs as a local subprocess needing filesystem or process accessThe client launches it; no network listener
Streamable HTTPThe server is remote or cloud hostedRecommended for remote servers; supports OAuth
SSEOnly when a service exposes nothing elseDeprecated; use HTTP where available
WebSocketRemote server that pushes events unpromptedHeader only auth, so no OAuth

Installation scopes are a reliable exam target:

ScopeLoads inSharedStored in
Local (default)Current project onlyNoUser's home config
ProjectCurrent project onlyYes, via version control.mcp.json in project root
UserAll the user's projectsNoUser's home config

Precedence runs local, then project, then user, and the winning definition is used whole: fields are not merged across scopes. Project scoped servers require interactive approval, and a freshly cloned repository cannot approve its own servers, because settings committed into the project are ignored until the workspace is trusted.

Two more mechanics worth holding. Tool search with deferred loading: when a tool library is large but any given task uses a handful, defer the schemas and let the agent discover what it needs; if you author a server, the server instructions field tells the agent when to go looking for your tools, and both descriptions and instructions are truncated at a size limit, so put critical detail first. Output limits: large MCP outputs trigger a warning and are capped by default, and raising the cap environment wide lets one badly shaped tool spend everyone's budget, so the better fix is a bounded, filtered response with a way to drill in. Per server timeouts belong on that server's entry, not on a global variable.

For authentication, OAuth is supported on HTTP servers and is the right answer when you want per user identity. For schemes that are not OAuth (Kerberos, short lived internal SSO tokens, CI runs with no browser), a headers helper command that mints headers at connection time is the designed mechanism. Committing a long lived token into .mcp.json is a durable leak, not a configuration.

How to think through the question

Domain 4 scenarios are dense, and the same reading procedure works on almost all of them.

Step 1: find the actual symptom. The scenario always tells you what is going wrong. "Picks the wrong tool" points at names and descriptions. "Passes the wrong parameter" points at the schema. "Context fills after three calls" points at response shaping. "Retries forever" points at error design. "Did something irreversible" points at confirmation flows and permissions.

Step 2: identify what the question is really asking. "What should they do FIRST" wants ordering, and measurement or root cause usually precedes remediation. "What is wrong with this design" wants the defect named, not a fix. "Which change most improves it" wants the highest leverage single change, so a partially helpful option can be correct in isolation and still wrong here.

Step 3: prefer the structural fix over the advisory one. Rank answers by where they act: schema and permission boundary beat tool description, which beats system prompt instruction, which beats monitoring after the fact. If two options both fix the problem, the one enforced by the tool wins over the one enforced by wording.

Step 4: eliminate over engineering and compensating controls. Options that add a subagent, a routing layer, a second reviewing model, or an audit log to work around a schema defect are distractors. So are options that raise a limit rather than fix what produces the volume.

Step 5: check the answer against the stated constraint. If a CI runner has no browser, any OAuth redirect answer is dead. If the server must be shared with the team and reviewed, local scope is dead.

Worked example. A support agent has an issue_refund tool that posts refunds immediately. A prompt injection in a customer attachment caused several unauthorized refunds. Which change most improves the design?

Step 1: the symptom is an irreversible financial action taken without authorization, so this is a confirmation and permission question. Step 2: "most improves" wants the highest leverage single change. Step 3: a strongly worded system prompt rule acts in the weakest layer, and it is the very channel the injection reaches, so it fails immediately; an audit log acts after the money moved; a max_amount cap is structural but only bounds each call, and an injected agent can issue many small refunds, which is roughly what happened; a human approval gate enforced by the tool means the model proposes and a person commits, which survives the injection. Step 4 confirms the audit log is the compensating control distractor. Step 5: nothing forbids a human in the loop. The answer is the approval gate.

Exam traps

  • "Add a system prompt instruction." Tempting because it is the fastest fix. Wrong whenever the schema, the tool contract, or a permission boundary could enforce the same thing structurally.
  • "Use a bigger model." Tempting because stronger models are more tolerant of weak schemas. Wrong because it pays forever to partially mask a defect that a description or enum fixes completely.
  • "Add monitoring or audit logging." Tempting because observability is good practice. Wrong when it detects damage instead of preventing it.
  • "Raise the limit." Tempting because the symptom is a limit being hit. Wrong when the real issue is a tool returning far more than the agent needs, and the raised limit applies environment wide.
  • "Retry it." Wrong for deterministic failures (malformed identifiers, permission denials) that fail identically forever, and dangerous for non idempotent writes without an idempotency key.
  • "Split the tool further for clarity." Tempting because narrow tools sound like least privilege. Wrong when the problem is selection ambiguity, since more near neighbours make discrimination harder.
  • "Deferred loading will fix it." Wrong when the problem is naming, authorization, or selection accuracy: deferring a schema changes when it enters context, not whether the tool is callable or distinguishable.
  • "SSE is better for streaming data." Tempting because the transport name sounds like a fit. Wrong because SSE is deprecated in favour of Streamable HTTP, and protocol semantics do not differ by transport.
  • "Return an empty result on failure." Wrong because it makes an outage look like a legitimate "nothing found" and produces confidently false answers.

Quick reference

  • Tool description: three to four sentences minimum, covering behaviour, when to use and not use, parameter meaning and format, and what is not returned. Namespace names by service.
  • Consolidate related operations into one tool with an enum constrained action parameter.
  • enum for fixed value sets, input_examples for complex or nested inputs, strict: true to guarantee schema conformance.
  • tool_choice: auto (default with tools), any, tool, none. Forcing suppresses natural language before the tool call and invalidates cached message blocks.
  • Shape responses: high signal fields only, semantic identifiers over UUIDs, pagination and filtering with sensible defaults.
  • Errors: state the category, what was wrong, and the corrective action. Return failures as error flagged tool results, not loop terminating exceptions. Mutating tools take an idempotency key.
  • Destructive actions: preview, confirmation token or human approval gate enforced by the tool, narrow explicit parameters.
  • Transports: stdio for local subprocesses, Streamable HTTP for remote (and for OAuth), SSE deprecated, WebSocket for unprompted server push with header only auth.
  • Scopes: local (default, private, current project), project (.mcp.json, shared via version control, needs approval and workspace trust), user (all the user's projects, private). Precedence: local, then project, then user, taken whole.
  • Fix oversized MCP output at the tool, not by raising the environment wide limit. Per server timeouts go on the server entry.

Ready to test this domain?

Drill mode gives instant feedback: pick a wrong answer and you immediately see why it is wrong.

Start the drill

Not an official source. This is a free, independent study resource from siasola, built by an engineer who sat these exams and wanted better prep material to exist. It is not affiliated with, endorsed by, or sponsored by Anthropic. Claude is a trademark of Anthropic, PBC. Exam facts follow the official exam guides; registration for the real exams happens through the Anthropic Partner Academy and Pearson VUE, not here.