Skip to content
CCAF Preparation

Domain 2 · 18% of exam

Tool Design & MCP Integration cheat sheet

2.1 — Tool interface design

  • Tool descriptions are THE selection mechanism — not metadata. Misrouting fix order: expand descriptions first, never few-shot examples, a routing classifier, or consolidation as step one.
  • Five elements of a production description: purpose · inputs w/formats · example queries · edge cases/limits · boundaries vs similar tools.
  • Messages API tool name regex: ^[a-zA-Z0-9_-]{1,64}$. Required fields: name, description, input_schema.
  • MCP tool fields: name, description, inputSchema + optional title, outputSchema, annotations. Discovery/exec: tools/list / tools/call.
  • Build workflow tools, not API wrappers: schedule_event not list_events+create_event. Namespace by service (asana_search) or resource (asana_projects_search).
  • Claude Code truncates tool descriptions/server instructions at 2KB each. Tool search (default on) defers MCP tool defs until needed.

2.2 — Structured error responses

CategoryRetryable?Recovery
Transient (timeout, rate limit)YesRetry after delay
Validation (bad input)YesFix input, retry
Business (policy violation)NoEscalate / alt workflow
Permission (access denied)NoEscalate / different credentials
  • MCP's two error mechanisms: protocol errors (JSON-RPC: unknown tool, bad args) vs tool execution errors (isError: true inside a successful result).
  • Messages API equivalent: tool_result.is_error; MCP connector: mcp_tool_result.is_error.
  • structuredContent carries structured JSON output; if outputSchema is declared, server MUST conform, client SHOULD validate.
  • Access failure (isError:true, couldn't reach data) ≠ valid empty result (isError:false, resultCount:0, reached data + found nothing). Confusing these = wasted retries. This is the #1 tested distinction in this task.
  • Claude auto-retries a malformed tool call 2-3× with corrections — different from your tool's isRetryable flag, which governs agent-level retry after execution failure.
  • Multi-agent propagation: local recovery for transient failures first; propagate only unresolvable errors + partial results + what was attempted. Never silently suppress (empty-as-success) or kill the whole workflow on one failure.

2.3 — Tool distribution & tool_choice

  • 4-5 tools per agent, scoped to its role. Bloated/overlapping tool sets are a named Anthropic failure mode (ambiguous decision points + wasted context).
  • Scoped cross-role tool: give a high-frequency simple capability (e.g. verify_fact) directly to the agent; route complex cases through the coordinator.
  • Replace generic tools with constrained ones: fetch_urlload_document (validates document URLs only) = least privilege.
tool_choice.typeBehaviourDefault when
autoModel decides tool vs texttools provided
anyMust call some tool
toolMust call the named tool: {"type":"tool","name":"…"}
noneMay not call any toolno tools provided
  • Forced (any/tool) prefills the assistant message — no text commentary before tool_use, even if asked.
  • Manual extended thinking works only with auto/none; any/tool error out.
  • disable_parallel_tool_use lives inside tool_choice, not top-level. With auto: at most one call. With any/tool: exactly one call.
  • Changing tool_choice between turns invalidates cached message blocks (tool defs/system prompt stay cached).

2.4 — MCP server integration

claude mcp add --transport http <name> <url>            # remote HTTP
claude mcp add [opts] <name> -- <command> [args...]      # local stdio (-- required)
claude mcp add-json <name> '<json>'                       # from JSON
ScopeStorageShared?Notes
local (default)~/.claude.json, nested under project pathNoWas called "project" in older versions
project.mcp.json in project rootYes (VCS)Team-shared, requires approval before use
user~/.claude.jsonNoAll your projects; was called "global"
  • Precedence on name collision: local > project > user > plugin servers > claude.ai connectors — whole entry wins, never merged.
  • MCP "local scope" (~/.claude.json) ≠ general local settings (.claude/settings.local.json) — classic exam trap.
  • Env var expansion: ${VAR} and ${VAR:-default}, valid in command/args/env/url/headers.
  • Transports: stdio (subprocess, stdin/stdout) and Streamable HTTP (spec standard); standalone SSE deprecated in Claude Code. type: "streamable-http" aliases "http". SDK heuristic: command → stdio, URL → HTTP/SSE, own code → SDK MCP server.
  • /mcp = check status / OAuth login. claude mcp list|get|remove. Project-server approval resets via claude mcp reset-project-choices.
  • MCP resource @-mention: @server:protocol://resource/path. MCP prompt slash command: /mcp__servername__promptname.
  • MCP tool output: warns >10,000 tokens, caps at 25,000 by default (MAX_MCP_OUTPUT_TOKENS).
  • Tool naming: mcp__<server>__<tool>. Permission rules: mcp__server / mcp__server__* / mcp__server__tool.
  • Use community servers first (Jira, GitHub, Slack, Notion); build custom only for team-specific workflows or proprietary systems.
  • Sparse MCP descriptions lose to detailed built-in descriptions (agent prefers Grep over an under-described MCP search tool) — enhance the description, don't rename to mimic a built-in.

2.5 — Built-in tools

ToolSearches / does
GrepFile contents (patterns, calls, imports)
GlobFile paths by naming pattern
ReadFull file load
WriteFull file output
EditTargeted change via unique old_string match
BashShell commands
WebFetchExternal URL content (domain: permission rules)
Agent (was Task)Spawns subagents — renamed in Claude Code v2.1.63
  • Edit fails on a non-unique match (safety, not a bug). Recovery order: widen old_string with context → replace_all: trueRead + Write is the last resort, not the default.
  • Incremental exploration: Grep → Read → Grep again (wrappers/barrels) → Read only what's justified. Never read all files upfront.
  • Deprecation-tracing pattern: Grep (find callers) → Glob (find sibling test files) → Grep again (catch wrapper/indirect consumers). Not Glob first.
  • SDK tools option scopes built-in availability: tools:["Read","Grep"] keeps only those; tools:[] removes all built-ins (MCP tools unaffected).
  • --allowedTools skips prompts; --tools restricts availability. --disallowedTools: bare name removes the tool entirely; scoped rule (Bash(rm *)) leaves it available, denies only matches.
  • Bash prefix matching: Bash(git diff *) — the trailing space matters (without it, Bash(git diff*) also matches git diff-index).
  • WebFetch(domain:*.example.com) matches subdomains, not the apex domain.