# Claude Agent SDK - Complete Tool System Documentation

**SDK Version**: 0.1.22
**Source**: `sdk-tools.d.ts`

---

## Table of Contents

1. [Overview](#overview)
2. [Tool Categories](#tool-categories)
3. [All 17 Tools Detailed](#all-17-tools-detailed)
4. [Tool Input Schemas](#tool-input-schemas)
5. [Tool Execution Patterns](#tool-execution-patterns)
6. [Tool Restrictions](#tool-restrictions)
7. [Permission System](#permission-system)
8. [MCP Tool Integration](#mcp-tool-integration)
9. [Custom Tool Creation](#custom-tool-creation)
10. [Performance Characteristics](#performance-characteristics)
11. [Real-World Usage Patterns](#real-world-usage-patterns)
12. [Gotchas & Best Practices](#gotchas--best-practices)

---

## Overview

The Claude Agent SDK includes **17 built-in tools** for file operations, execution, web access, agent management, and MCP integration.

### Tool Type Union (from source)

```typescript
/** 
 * JSON Schema definitions for Claude CLI tool inputs 
 * This file was automatically generated by json-schema-to-typescript.
 */
export type ToolInputSchemas = 
  | AgentInput
  | BashInput
  | BashOutputInput
  | ExitPlanModeInput
  | FileEditInput
  | FileReadInput
  | FileWriteInput
  | GlobInput
  | GrepInput
  | KillShellInput
  | ListMcpResourcesInput
  | McpInput
  | NotebookEditInput
  | ReadMcpResourceInput
  | TodoWriteInput
  | WebFetchInput
  | WebSearchInput;
```

---

## Tool Categories

### File Operations (6 tools)
- **FileRead** - Read file contents
- **FileWrite** - Write/create files
- **FileEdit** - Edit existing files
- **Glob** - Find files by pattern
- **Grep** - Search file contents
- **NotebookEdit** - Edit Jupyter notebooks

### Execution (3 tools)
- **Bash** - Execute shell commands
- **BashOutput** - Retrieve background shell output
- **KillShell** - Terminate background shells

### Agent Management (2 tools)
- **Agent** (Task) - Invoke subagents
- **TodoWrite** - Manage task lists

### Planning (1 tool)
- **ExitPlanMode** - Exit planning mode

### Web Operations (2 tools)
- **WebFetch** - Fetch and process web content
- **WebSearch** - Perform web searches

### MCP Integration (3 tools)
- **ListMcpResources** - List MCP resources
- **ReadMcpResource** - Read MCP resource
- **McpInput** - Generic MCP tool invocation

---

## All 17 Tools Detailed

### 1. FileRead

**Purpose**: Read file contents with optional pagination

**Schema** (from source):
```typescript
export interface FileReadInput {
  /** The absolute path to the file to read */
  file_path: string;
  
  /** The line number to start reading from. 
   *  Only provide if the file is too large to read at once */
  offset?: number;
  
  /** The number of lines to read. 
   *  Only provide if the file is too large to read at once. */
  limit?: number;
}
```

**Characteristics**:
- **Default**: First 2000 lines
- **Per-Line Limit**: 2000 characters (truncated silently)
- **PDF Support**: Max 32MB
- **Caching**: File cached after first read
- **Speed**: 1-50ms (cached: <5ms)

**Examples**:
```typescript
// Basic read
FileRead({ file_path: "/workspace/src/app.ts" })

// Paginated read
FileRead({ 
  file_path: "/large-file.txt",
  offset: 1000,
  limit: 500
})

// Read specific section
FileRead({ 
  file_path: "/data.json",
  offset: 0,
  limit: 100
})
```

**Gotchas**:
- Silent per-line truncation at 2000 chars
- Offset is line-based, not byte-based
- PDFs > 32MB are rejected

---

### 2. FileWrite

**Purpose**: Create or overwrite files

**Schema** (from source):
```typescript
export interface FileWriteInput {
  /** The absolute path to the file to write 
   *  (must be absolute, not relative) */
  file_path: string;
  
  /** The content to write to the file */
  content: string;
}
```

**Characteristics**:
- **Read-Before-Write**: REQUIRED (session-scoped)
- **Path**: Must be absolute
- **Atomicity**: Atomic write operation
- **Speed**: 5-20ms

**Examples**:
```typescript
// Create new file
FileWrite({
  file_path: "/workspace/new-file.ts",
  content: "export const hello = 'world';"
})

// Overwrite existing file
FileWrite({
  file_path: "/workspace/config.json",
  content: JSON.stringify(config, null, 2)
})
```

**Gotchas**:
- Must Read file first (same session)
- Overwrites entire file (not append)
- Requires absolute path

---

### 3. FileEdit

**Purpose**: Edit specific sections of files

**Schema** (from source):
```typescript
export interface FileEditInput {
  /** The absolute path to the file to modify */
  file_path: string;
  
  /** The text to replace */
  old_string: string;
  
  /** The text to replace it with 
   *  (must be different from old_string) */
  new_string: string;
  
  /** Replace all occurences of old_string (default false) */
  replace_all?: boolean;
}
```

**Characteristics**:
- **Read-Before-Write**: REQUIRED
- **Uniqueness**: `old_string` must be unique (unless `replace_all`)
- **Exact Match**: Whitespace-sensitive
- **Speed**: 10-30ms

**Examples**:
```typescript
// Replace single occurrence
FileEdit({
  file_path: "/src/app.ts",
  old_string: "const port = 3000;",
  new_string: "const port = 8080;"
})

// Replace all occurrences
FileEdit({
  file_path: "/src/config.ts",
  old_string: "development",
  new_string: "production",
  replace_all: true
})

// Replace with context for uniqueness
FileEdit({
  file_path: "/src/utils.ts",
  old_string: `function calculate() {
  return 42;
}`,
  new_string: `function calculate() {
  return 1337;
}`
})
```

**Gotchas**:
- `old_string` must be unique (or use `replace_all`)
- Exact whitespace matching required
- Fails if `old_string` not found

---

### 4. Glob

**Purpose**: Find files matching pattern

**Schema** (from source):
```typescript
export interface GlobInput {
  /** The glob pattern to match files against */
  pattern: string;
  
  /** The directory to search in. If not specified, 
   *  the current working directory will be used.
   *  IMPORTANT: Omit this field to use the default directory.
   *  DO NOT enter "undefined" or "null" - simply omit it 
   *  for the default behavior. 
   *  Must be a valid directory path if provided. */
  path?: string;
}
```

**Characteristics**:
- **Pattern Syntax**: Standard glob patterns
- **Default Path**: Current working directory
- **Speed**: 50-500ms (pattern dependent)
- **Recursive**: `**` for recursive matching

**Examples**:
```typescript
// Find TypeScript files
Glob({ pattern: "**/*.ts" })

// Find test files
Glob({ pattern: "**/*.test.{ts,tsx,js,jsx}" })

// Find in specific directory
Glob({
  pattern: "*.json",
  path: "/workspace/config"
})

// Find all README files
Glob({ pattern: "**/README.md" })
```

**Pattern Syntax**:
```
*        - Match any characters (except /)
**       - Match any characters (including /)
?        - Match single character
[abc]    - Match a, b, or c
{a,b,c}  - Match a, b, or c (brace expansion)
!pattern - Negate pattern
```

---

### 5. Grep

**Purpose**: Search file contents using regex

**Schema** (from source):
```typescript
export interface GrepInput {
  /** The regular expression pattern to search for in file contents */
  pattern: string;
  
  /** File or directory to search in (rg PATH). 
   *  Defaults to current working directory. */
  path?: string;
  
  /** Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") 
   *  - maps to rg --glob */
  glob?: string;
  
  /** Output mode: "content" shows matching lines (supports -A/-B/-C context, 
   *  -n line numbers, head_limit), "files_with_matches" shows file paths 
   *  (supports head_limit), "count" shows match counts (supports head_limit). 
   *  Defaults to "files_with_matches". */
  output_mode?: "content" | "files_with_matches" | "count";
  
  /** Number of lines to show before each match (rg -B). 
   *  Requires output_mode: "content", ignored otherwise. */
  "-B"?: number;
  
  /** Number of lines to show after each match (rg -A). 
   *  Requires output_mode: "content", ignored otherwise. */
  "-A"?: number;
  
  /** Number of lines to show before and after each match (rg -C). 
   *  Requires output_mode: "content", ignored otherwise. */
  "-C"?: number;
  
  /** Show line numbers in output (rg -n). 
   *  Requires output_mode: "content", ignored otherwise. */
  "-n"?: boolean;
  
  /** Case insensitive search (rg -i) */
  "-i"?: boolean;
  
  /** File type to search (rg --type). 
   *  Common types: js, py, rust, go, java, etc. 
   *  More efficient than include for standard file types. */
  type?: string;
  
  /** Limit output to first N lines/entries, 
   *  equivalent to "| head -N". 
   *  Works across all output modes: content (limits output lines), 
   *  files_with_matches (limits file paths), 
   *  count (limits count entries). 
   *  When unspecified, shows all results from ripgrep. */
  head_limit?: number;
  
  /** Enable multiline mode where . matches newlines 
   *  and patterns can span lines (rg -U --multiline-dotall). 
   *  Default: false. */
  multiline?: boolean;
}
```

**Characteristics**:
- **Engine**: ripgrep (fast!)
- **Default Output**: files_with_matches (filenames only)
- **Regex**: Full regex support
- **Speed**: 100-2000ms (very fast for large codebases)

**Examples**:
```typescript
// Find files containing pattern (default)
Grep({ pattern: "function authenticate" })

// Show matching content
Grep({
  pattern: "TODO|FIXME",
  output_mode: "content",
  "-n": true
})

// Show context around matches
Grep({
  pattern: "error handling",
  output_mode: "content",
  "-C": 3,
  "-n": true
})

// Case-insensitive search
Grep({
  pattern: "api_key",
  "-i": true,
  output_mode: "content"
})

// Search specific file type
Grep({
  pattern: "useState",
  type: "tsx",
  output_mode: "content"
})

// Multiline pattern
Grep({
  pattern: "interface.*\\{[^}]+userId",
  multiline: true,
  output_mode: "content"
})

// Limit results
Grep({
  pattern: "import.*react",
  output_mode: "files_with_matches",
  head_limit: 10
})
```

**Gotchas**:
- Default output is filenames only (not content!)
- Multiline mode disabled by default
- Context flags (-A/-B/-C) require output_mode: "content"

---

### 6. NotebookEdit

**Purpose**: Edit Jupyter notebooks

**Schema** (from source):
```typescript
export interface NotebookEditInput {
  /** The absolute path to the Jupyter notebook file to edit 
   *  (must be absolute, not relative) */
  notebook_path: string;
  
  /** The ID of the cell to edit. When inserting a new cell, 
   *  the new cell will be inserted after the cell with this ID, 
   *  or at the beginning if not specified. */
  cell_id?: string;
  
  /** The new source for the cell */
  new_source: string;
  
  /** The type of the cell (code or markdown). 
   *  If not specified, it defaults to the current cell type. 
   *  If using edit_mode=insert, this is required. */
  cell_type?: "code" | "markdown";
  
  /** The type of edit to make (replace, insert, delete). 
   *  Defaults to replace. */
  edit_mode?: "replace" | "insert" | "delete";
}
```

**Characteristics**:
- **Format**: Jupyter .ipynb files
- **Cell Types**: code, markdown
- **Edit Modes**: replace, insert, delete
- **Speed**: 10-30ms

**Examples**:
```typescript
// Replace cell content
NotebookEdit({
  notebook_path: "/notebooks/analysis.ipynb",
  cell_id: "cell-123",
  new_source: "print('Hello, World!')",
  cell_type: "code"
})

// Insert new cell
NotebookEdit({
  notebook_path: "/notebooks/analysis.ipynb",
  new_source: "# Data Analysis",
  cell_type: "markdown",
  edit_mode: "insert"
})

// Delete cell
NotebookEdit({
  notebook_path: "/notebooks/analysis.ipynb",
  cell_id: "cell-456",
  new_source: "",
  edit_mode: "delete"
})
```

---

### 7. Bash

**Purpose**: Execute shell commands

**Schema** (from source):
```typescript
export interface BashInput {
  /** The command to execute */
  command: string;
  
  /** Optional timeout in milliseconds (max 600000) */
  timeout?: number;
  
  /** Clear, concise description of what this command does 
   *  in 5-10 words, in active voice. 
   *  Examples:
   *  Input: ls
   *  Output: List files in current directory
   *  
   *  Input: git status
   *  Output: Show working tree status
   *  
   *  Input: npm install
   *  Output: Install package dependencies
   *  
   *  Input: mkdir foo
   *  Output: Create directory 'foo' */
  description?: string;
  
  /** Set to true to run this command in the background. 
   *  Use BashOutput to read the output later. */
  run_in_background?: boolean;
}
```

**Characteristics**:
- **Default Timeout**: 120,000ms (2 minutes)
- **Max Timeout**: 600,000ms (10 minutes)
- **Output Truncation**: 30,000 characters (silent!)
- **Background Execution**: Returns immediately with shell ID
- **Speed**: Variable (command-dependent)

**Examples**:
```typescript
// Simple command
Bash({ command: "ls -la" })

// With timeout
Bash({
  command: "npm install",
  timeout: 300000  // 5 minutes
})

// With description
Bash({
  command: "git status",
  description: "Show working tree status"
})

// Background execution
Bash({
  command: "npm test",
  run_in_background: true
})
// Returns: { bash_id: "shell_abc123" }
```

**Output Truncation Example**:
```bash
# Command produces 50,000 characters
Bash({ command: "npm run build --verbose" })

# Only first 30,000 characters returned
# Last 20,000 characters lost (no warning!)

# Workaround:
Bash({ command: "npm run build > output.txt 2>&1" })
FileRead({ file_path: "/workspace/output.txt" })
```

**Gotchas**:
- Output silently truncated at 30K chars
- Default 2-minute timeout
- Background shells persist until killed

---

### 8. BashOutput

**Purpose**: Retrieve output from background shell

**Schema** (from source):
```typescript
export interface BashOutputInput {
  /** The ID of the background shell to retrieve output from */
  bash_id: string;
  
  /** Optional regular expression to filter the output lines. 
   *  Only lines matching this regex will be included in the result. 
   *  Any lines that do not match will no longer be available to read. */
  filter?: string;
}
```

**Characteristics**:
- **Retrieval**: Get output from background shell
- **Filtering**: Regex-based line filtering
- **Consumption**: Filtered lines are consumed (not available again)
- **Speed**: ~5-10ms

**Examples**:
```typescript
// Start background command
const { bash_id } = Bash({
  command: "npm test",
  run_in_background: true
});

// Retrieve all output
BashOutput({ bash_id })

// Filter output
BashOutput({
  bash_id,
  filter: "PASS|FAIL"
})

// Retrieve error lines only
BashOutput({
  bash_id,
  filter: "Error|error|ERROR"
})
```

**Gotchas**:
- Filtered lines are consumed (can't re-read)
- Still subject to 30K char total limit

---

### 9. KillShell

**Purpose**: Terminate background shell

**Schema** (from source):
```typescript
export interface KillShellInput {
  /** The ID of the background shell to kill */
  shell_id: string;
}
```

**Characteristics**:
- **Termination**: Kills background process
- **Grace**: SIGTERM then SIGKILL if needed
- **Speed**: ~10-50ms

**Examples**:
```typescript
// Start background shell
const { bash_id } = Bash({
  command: "npm run dev",
  run_in_background: true
});

// Kill it later
KillShell({ shell_id: bash_id })
```

---

### 10. Agent (Task)

**Purpose**: Invoke subagents for specialized tasks

**Schema** (from source):
```typescript
export interface AgentInput {
  /** A short (3-5 word) description of the task */
  description: string;
  
  /** The task for the agent to perform */
  prompt: string;
  
  /** The type of specialized agent to use for this task */
  subagent_type: string;
}
```

**Characteristics**:
- **Agent Types**: Explore, general-purpose, custom
- **Context**: Forked or isolated (agent-specific)
- **Speed**: 5-120s (agent-dependent)
- **Token Efficiency**: Up to 70-84% savings (Explore agent)

**Examples**:
```typescript
// Use Explore agent
Agent({
  description: "Find authentication code",
  prompt: "Find all authentication-related files and functions",
  subagent_type: "Explore"
})

// Use general-purpose agent
Agent({
  description: "Refactor auth system",
  prompt: "Refactor authentication to use JWT tokens",
  subagent_type: "general-purpose"
})

// Use custom agent
Agent({
  description: "Review code quality",
  prompt: "Review code for best practices and suggest improvements",
  subagent_type: "code-reviewer"
})
```

---

### 11. TodoWrite

**Purpose**: Manage task lists

**Schema** (from source):
```typescript
export interface TodoWriteInput {
  /** The updated todo list */
  todos: {
    content: string;
    status: "pending" | "in_progress" | "completed";
    activeForm: string;
  }[];
}
```

**Characteristics**:
- **Constraint**: Exactly ONE task must be "in_progress"
- **Status**: pending, in_progress, completed
- **Real-time**: UI updates immediately
- **Speed**: ~5ms

**Examples**:
```typescript
// Create todo list
TodoWrite({
  todos: [
    {
      content: "Set up project structure",
      status: "in_progress",
      activeForm: "Setting up project structure"
    },
    {
      content: "Install dependencies",
      status: "pending",
      activeForm: "Installing dependencies"
    },
    {
      content: "Write tests",
      status: "pending",
      activeForm: "Writing tests"
    }
  ]
})

// Update status
TodoWrite({
  todos: [
    {
      content: "Set up project structure",
      status: "completed",
      activeForm: "Setting up project structure"
    },
    {
      content: "Install dependencies",
      status: "in_progress",  // Now in progress
      activeForm: "Installing dependencies"
    },
    {
      content: "Write tests",
      status: "pending",
      activeForm: "Writing tests"
    }
  ]
})
```

**Gotchas**:
- Exactly ONE task must be "in_progress" (strictly enforced)
- Tool call fails if constraint violated

---

### 12. ExitPlanMode

**Purpose**: Exit planning mode and present plan

**Schema** (from source):
```typescript
export interface ExitPlanModeInput {
  /** The plan you came up with, that you want to run by 
   *  the user for approval. Supports markdown. 
   *  The plan should be pretty concise. */
  plan: string;
}
```

**Characteristics**:
- **Mode**: Only available in plan mode
- **Format**: Markdown supported
- **Transition**: Exits plan mode to execution mode
- **Speed**: ~10ms

**Examples**:
```typescript
// Present plan for approval
ExitPlanMode({
  plan: `
# Refactoring Plan

## Phase 1: Update Auth
- Replace JWT library
- Update token generation

## Phase 2: Update Tests
- Add new test cases
- Update existing tests

## Phase 3: Documentation
- Update API docs
- Add migration guide

Ready to proceed?
  `
})
```

---

### 13. WebFetch

**Purpose**: Fetch and process web content

**Schema** (from source):
```typescript
export interface WebFetchInput {
  /** The URL to fetch content from */
  url: string;
  
  /** The prompt to run on the fetched content */
  prompt: string;
}
```

**Characteristics**:
- **HTML→Markdown**: Automatic conversion
- **Cache**: 15-minute cache duration
- **Processing**: LLM processes content with prompt
- **Speed**: ~500-2000ms (network + processing)

**Examples**:
```typescript
// Fetch and summarize
WebFetch({
  url: "https://docs.example.com/api",
  prompt: "Summarize the authentication section"
})

// Extract specific information
WebFetch({
  url: "https://blog.example.com/post",
  prompt: "Extract code examples and explain them"
})

// Compare documentation
WebFetch({
  url: "https://competitor.com/docs",
  prompt: "Compare their API design with our approach"
})
```

**Gotchas**:
- Requires network permission
- 15-minute cache (can't force refresh)
- HTML complexity affects conversion quality

---

### 14. WebSearch

**Purpose**: Perform web searches

**Schema** (from source):
```typescript
export interface WebSearchInput {
  /** The search query to use */
  query: string;
  
  /** Only include search results from these domains */
  allowed_domains?: string[];
  
  /** Never include search results from these domains */
  blocked_domains?: string[];
}
```

**Characteristics**:
- **Billing**: Separate request (counts against API usage)
- **Filtering**: Domain allow/block lists
- **Results**: Top search results with snippets
- **Speed**: ~1000-3000ms

**Examples**:
```typescript
// Basic search
WebSearch({ query: "TypeScript best practices 2024" })

// Restrict to specific domains
WebSearch({
  query: "React hooks tutorial",
  allowed_domains: ["reactjs.org", "react.dev"]
})

// Exclude domains
WebSearch({
  query: "JavaScript frameworks",
  blocked_domains: ["stackoverflow.com", "reddit.com"]
})
```

**Gotchas**:
- Counts as separate API request (billing)
- Results quality varies
- Requires web search permission

---

### 15. ListMcpResources

**Purpose**: List available MCP resources

**Schema** (from source):
```typescript
export interface ListMcpResourcesInput {
  /** Optional server name to filter resources by */
  server?: string;
}
```

**Examples**:
```typescript
// List all resources
ListMcpResources({})

// List from specific server
ListMcpResources({ server: "filesystem" })
```

---

### 16. ReadMcpResource

**Purpose**: Read specific MCP resource

**Schema** (from source):
```typescript
export interface ReadMcpResourceInput {
  /** The MCP server name */
  server: string;
  
  /** The resource URI to read */
  uri: string;
}
```

**Examples**:
```typescript
// Read GitHub issue
ReadMcpResource({
  server: "github",
  uri: "github://repo/owner/name/issues/123"
})

// Read file resource
ReadMcpResource({
  server: "filesystem",
  uri: "file:///workspace/data.json"
})
```

---

### 17. McpInput

**Purpose**: Generic MCP tool invocation

**Schema** (from source):
```typescript
export interface McpInput {
  [k: string]: unknown;
}
```

**Characteristics**:
- **Dynamic**: Any valid JSON object
- **MCP-Specific**: Tool schemas defined by MCP server
- **Flexibility**: Supports all MCP tool types

---

## Tool Input Schemas

All tool schemas are generated from JSON Schema using `json-schema-to-typescript`:

```typescript
/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */
```

### Schema Validation

Tools use **Zod** for runtime validation:

```typescript
import { z } from 'zod';

// Tool input validated against schema
const input = validateInput(toolInput, toolSchema);
```

---

## Tool Execution Patterns

### Sequential Execution

```typescript
// Tools execute sequentially within a turn
FileRead({ file_path: "app.ts" })      // 1st
FileEdit({ file_path: "app.ts", ... }) // 2nd (after FileRead)
FileWrite({ file_path: "config.json", ...}) // 3rd
```

### Parallel Execution (Same Turn)

```typescript
// Agent can request multiple independent tools
Glob({ pattern: "*.ts" })     // Parallel
Grep({ pattern: "TODO" })     // Parallel
// Both execute simultaneously
```

### Tool Chaining

```typescript
// Find files → Read → Edit
const files = Glob({ pattern: "*.ts" });
for (const file of files) {
  const content = FileRead({ file_path: file });
  // Analyze content...
  FileEdit({ file_path: file, ... });
}
```

---

## Tool Restrictions

### Agent-Specific Tool Access

From agent definitions:

```typescript
{
  "Explore": ["Glob", "Grep", "Read", "Bash"],
  "general-purpose": ["*"],  // All tools
  "security-review": ["Bash(git*)", "Read", "Grep", "LS", "Task"]
}
```

### Permission-Based Restrictions

```json
{
  "allowedTools": ["Read", "Write", "Grep"],
  "disallowedTools": ["Delete", "WebSearch"]
}
```

---

## Permission System

The SDK implements a sophisticated permission system to control tool usage and ensure user safety.

### Permission Modes

```typescript
export type PermissionMode =
  | 'default'              // Standard prompting
  | 'acceptEdits'          // Auto-approve edits
  | 'bypassPermissions'    // No prompts
  | 'plan';                // Planning mode
```

### Permission Behaviors

```typescript
export type PermissionBehavior =
  | 'allow'   // Execute without prompting
  | 'deny'    // Block execution
  | 'ask';    // Prompt user for approval
```

### CanUseTool Callback

Custom permission logic via callback:

```typescript
export type CanUseTool = (
  toolName: string,
  input: Record<string, unknown>,
  options: {
    /** Signaled if the operation should be aborted */
    signal: AbortSignal;

    /**
     * Suggestions for updating permissions so that the user will not be
     * prompted again for this tool during this session.
     * Typically used for 'always allow' functionality.
     */
    suggestions?: PermissionUpdate[];
  }
) => Promise<PermissionResult>;
```

### Permission Results

```typescript
export type PermissionResult =
  | {
      behavior: 'allow';
      /** Updated tool input to use, if any changes needed */
      updatedInput: Record<string, unknown>;
      /** Permission updates to apply (e.g., 'always allow') */
      updatedPermissions?: PermissionUpdate[];
    }
  | {
      behavior: 'deny';
      /** Reason for denial or guidance for the model */
      message: string;
      /** If true, interrupt execution completely */
      interrupt?: boolean;
    };
```

### Permission Updates

```typescript
export type PermissionUpdate =
  | { type: 'addRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination }
  | { type: 'replaceRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination }
  | { type: 'removeRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination }
  | { type: 'setMode'; mode: PermissionMode; destination: PermissionUpdateDestination }
  | { type: 'addDirectories'; directories: string[]; destination: PermissionUpdateDestination }
  | { type: 'removeDirectories'; directories: string[]; destination: PermissionUpdateDestination };

export type PermissionUpdateDestination =
  | 'userSettings'      // Global user config
  | 'projectSettings'   // Project-specific config
  | 'localSettings'     // Local workspace config
  | 'session';          // Current session only
```

### Permission Rules

```typescript
export type PermissionRuleValue = {
  toolName: string;
  ruleContent?: string;  // Optional pattern/condition
};
```

### Tool-Specific Permission Requirements

| Tool | Permission Type | Notes |
|------|----------------|-------|
| **FileRead** | Read | Checks file access |
| **FileWrite** | Write | Checks directory access |
| **FileEdit** | Write | Requires prior read |
| **NotebookEdit** | Write | Notebook-specific |
| **Bash** | Execute | Command-dependent |
| **WebFetch** | Network | URL validation |
| **WebSearch** | Network | US-only restriction |
| **Agent** | None | Inherited from parent |
| **Glob** | Read | Directory access |
| **Grep** | Read | Search path access |
| **TodoWrite** | None | In-memory only |
| **BashOutput** | None | Read-only |
| **KillShell** | Execute | Process termination |
| **MCP Tools** | Varies | Server-dependent |

---

## MCP Tool Integration

The SDK supports custom tools via the Model Context Protocol (MCP).

### MCP Server Configuration

```typescript
export type McpServerConfig =
  | McpStdioServerConfig      // External process
  | McpSSEServerConfig        // Server-Sent Events
  | McpHttpServerConfig       // HTTP transport
  | McpSdkServerConfigWithInstance;  // In-process SDK

// Stdio transport (most common)
export type McpStdioServerConfig = {
  type?: 'stdio';
  command: string;
  args?: string[];
  env?: Record<string, string>;
};

// SSE transport
export type McpSSEServerConfig = {
  type: 'sse';
  url: string;
  headers?: Record<string, string>;
};

// HTTP transport
export type McpHttpServerConfig = {
  type: 'http';
  url: string;
  headers?: Record<string, string>;
};

// SDK transport (in-process)
export type McpSdkServerConfig = {
  type: 'sdk';
  name: string;
};

export type McpSdkServerConfigWithInstance = McpSdkServerConfig & {
  instance: McpServer;
};
```

### Configuring MCP Servers

Add MCP servers to SDK options:

```typescript
import { query } from '@anthropic-ai/claude-agent-sdk';

const agent = query({
  prompt: "Your task here",
  options: {
    mcpServers: {
      // External stdio server
      'my-external-tool': {
        type: 'stdio',
        command: 'node',
        args: ['./mcp-server.js'],
        env: { API_KEY: process.env.API_KEY }
      },

      // SSE server
      'remote-service': {
        type: 'sse',
        url: 'https://api.example.com/mcp',
        headers: { 'Authorization': 'Bearer token' }
      },

      // HTTP server
      'http-service': {
        type: 'http',
        url: 'https://api.example.com/mcp',
        headers: { 'X-API-Key': 'secret' }
      },

      // SDK server (in-process)
      'custom-tools': createSdkMcpServer({
        name: 'custom-tools',
        version: '1.0.0',
        tools: [/* ... */]
      })
    }
  }
});
```

### MCP Server Status

Check server connection status:

```typescript
export type McpServerStatus = {
  name: string;
  status: 'connected' | 'failed' | 'needs-auth' | 'pending';
  serverInfo?: {
    name: string;
    version: string;
  };
};

// Query server status
const status = await agent.mcpServerStatus();
```

---

## Custom Tool Creation

Create custom tools that run in-process using the SDK.

### Tool Definition

```typescript
type SdkMcpToolDefinition<Schema extends ZodRawShape = ZodRawShape> = {
  name: string;
  description: string;
  inputSchema: Schema;
  handler: (
    args: z.infer<ZodObject<Schema>>,
    extra: unknown
  ) => Promise<CallToolResult>;
};
```

### Creating a Tool

Use the `tool()` helper function:

```typescript
import { tool, createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk';
import { z } from 'zod';

// Define the tool
const greetTool = tool(
  'greet',
  'Greets a person by name',
  {
    name: z.string().describe('The name of the person to greet'),
    formal: z.boolean().optional().describe('Use formal greeting')
  },
  async (args, extra) => {
    const greeting = args.formal
      ? `Good day, ${args.name}!`
      : `Hey ${args.name}!`;

    return {
      content: [{
        type: 'text',
        text: greeting
      }]
    };
  }
);
```

### Creating an MCP Server

Bundle tools into an MCP server:

```typescript
import { createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk';

const customServer = createSdkMcpServer({
  name: 'my-custom-tools',
  version: '1.0.0',
  tools: [
    greetTool,
    // ... more tools
  ]
});
```

### Complete Example

```typescript
import {
  query,
  tool,
  createSdkMcpServer
} from '@anthropic-ai/claude-agent-sdk';
import { z } from 'zod';

// 1. Define custom tools
const calculateTool = tool(
  'calculate',
  'Performs basic arithmetic calculations',
  {
    operation: z.enum(['add', 'subtract', 'multiply', 'divide'])
      .describe('The arithmetic operation to perform'),
    a: z.number().describe('First operand'),
    b: z.number().describe('Second operand')
  },
  async (args) => {
    let result: number;
    switch (args.operation) {
      case 'add': result = args.a + args.b; break;
      case 'subtract': result = args.a - args.b; break;
      case 'multiply': result = args.a * args.b; break;
      case 'divide':
        if (args.b === 0) {
          return {
            content: [{ type: 'text', text: 'Error: Division by zero' }],
            isError: true
          };
        }
        result = args.a / args.b;
        break;
    }

    return {
      content: [{
        type: 'text',
        text: `Result: ${result}`
      }]
    };
  }
);

const weatherTool = tool(
  'get_weather',
  'Gets weather information for a city',
  {
    city: z.string().describe('City name'),
    units: z.enum(['celsius', 'fahrenheit']).optional()
      .describe('Temperature units')
  },
  async (args) => {
    // In real implementation, call weather API
    return {
      content: [{
        type: 'text',
        text: `Weather in ${args.city}: Sunny, 72°${args.units === 'celsius' ? 'C' : 'F'}`
      }]
    };
  }
);

// 2. Create MCP server with tools
const customTools = createSdkMcpServer({
  name: 'my-custom-tools',
  version: '1.0.0',
  tools: [calculateTool, weatherTool]
});

// 3. Use in agent
const agent = query({
  prompt: "What's 42 + 58? Also check the weather in San Francisco.",
  options: {
    mcpServers: {
      'custom': customTools
    }
  }
});

// 4. Process results
for await (const message of agent) {
  console.log(message);
}
```

### Tool Handler Return Type

```typescript
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';

// Return type for tool handlers
type CallToolResult = {
  content: Array<{
    type: 'text' | 'image' | 'resource';
    text?: string;
    data?: string;
    mimeType?: string;
  }>;
  isError?: boolean;
};
```

### Best Practices for Custom Tools

1. **Schema Design**:
   - Use descriptive field names
   - Include `.describe()` for all fields
   - Mark optional fields with `.optional()`
   - Validate inputs thoroughly

2. **Error Handling**:
   - Return `{ isError: true }` for errors
   - Provide helpful error messages
   - Handle edge cases gracefully

3. **Performance**:
   - Keep tools focused and single-purpose
   - Use async/await for I/O operations
   - Consider timeout constraints

4. **Documentation**:
   - Write clear tool descriptions
   - Document expected behavior
   - Include usage examples

5. **Testing**:
   - Test with various inputs
   - Handle invalid data gracefully
   - Verify error conditions

---

## Performance Characteristics

### Tool Execution Times

| Tool | Typical Time | Notes |
|------|-------------|-------|
| FileRead (cached) | 1-5ms | Very fast |
| FileRead (first) | 10-50ms | File I/O |
| FileWrite | 5-20ms | Atomic |
| FileEdit | 10-30ms | Read + validate + write |
| Glob | 50-500ms | Pattern complexity |
| Grep | 100-2000ms | Very fast (ripgrep) |
| Bash | Variable | Command-dependent |
| BashOutput | 5-10ms | Fast |
| Agent (Explore) | 5-15s | Haiku, isolated |
| Agent (general) | 30-120s | Sonnet, forked |
| TodoWrite | ~5ms | Very fast |
| WebFetch | 500-2000ms | Network + processing |
| WebSearch | 1000-3000ms | Search API |
| Notebook | 10-30ms | JSON parsing |

---

## Real-World Usage Patterns

### Pattern 1: File Discovery → Analysis

```typescript
// 1. Find files
const files = Glob({ pattern: "src/**/*.ts" });

// 2. Search for pattern
const matches = Grep({
  pattern: "TODO|FIXME",
  path: "src",
  output_mode: "content",
  "-n": true
});

// 3. Read and analyze
for (const file of matchedFiles) {
  const content = FileRead({ file_path: file });
  // Analyze...
}
```

### Pattern 2: Edit Workflow

```typescript
// 1. Read file (required!)
FileRead({ file_path: "/src/app.ts" });

// 2. Edit file
FileEdit({
  file_path: "/src/app.ts",
  old_string: "const port = 3000;",
  new_string: "const port = 8080;"
});

// 3. Verify changes
FileRead({ file_path: "/src/app.ts" });
```

### Pattern 3: Background Command Monitoring

```typescript
// 1. Start background command
const { bash_id } = Bash({
  command: "npm run build:watch",
  run_in_background: true
});

// 2. Check output periodically
const output = BashOutput({ bash_id });

// 3. Filter for errors
const errors = BashOutput({
  bash_id,
  filter: "Error|error"
});

// 4. Kill when done
KillShell({ shell_id: bash_id });
```

---

## Gotchas & Best Practices

### Critical Gotchas

1. **Read-Before-Write Enforcement**
   - FileEdit and FileWrite REQUIRE prior FileRead
   - Session-scoped (not persisted)
   - No bypass mechanism

2. **Bash Output Truncation**
   - Silent truncation at 30,000 characters
   - Workaround: Redirect to file, then Read

3. **FileEdit Uniqueness**
   - `old_string` must be unique in file
   - Or use `replace_all: true`

4. **Grep Default Output**
   - Default: "files_with_matches" (filenames only)
   - Must explicitly set `output_mode: "content"` for content

5. **TodoWrite Constraint**
   - Exactly ONE task must be "in_progress"
   - Strictly enforced

### Best Practices

**1. Always Read Before Edit/Write**:
```typescript
// ✅ Correct
FileRead({ file_path: "app.ts" });
FileEdit({ file_path: "app.ts", ... });

// ❌ Wrong - will fail
FileEdit({ file_path: "app.ts", ... });
```

**2. Use Absolute Paths**:
```typescript
// ✅ Correct
FileWrite({ file_path: "/workspace/src/app.ts", ... })

// ❌ Wrong - relative path
FileWrite({ file_path: "./src/app.ts", ... })
```

**3. Set Explicit Bash Timeouts**:
```typescript
// ✅ Good
Bash({
  command: "npm install",
  timeout: 300000  // 5 minutes
})
```

**4. Use Grep with output_mode**:
```typescript
// ✅ Show content
Grep({
  pattern: "function",
  output_mode: "content"
})
```

**5. Handle Bash Output Truncation**:
```typescript
// ✅ Workaround
Bash({ command: "npm test > output.txt 2>&1" })
FileRead({ file_path: "output.txt" })
```

---

## Summary

### Tool Count by Category

- **File Operations**: 6 tools
- **Execution**: 3 tools
- **Agent Management**: 2 tools
- **Planning**: 1 tool
- **Web**: 2 tools
- **MCP**: 3 tools
- **Total**: 17 tools

### Most Used Tools

1. **FileRead** - File content access
2. **Grep** - Fast code search
3. **Bash** - Command execution
4. **FileEdit** - Targeted edits
5. **Agent** - Subagent delegation

### Key Takeaways

- ✅ **17 built-in tools** for comprehensive functionality
- ✅ **Type-safe schemas** generated from JSON Schema
- ✅ **Zod validation** for runtime safety
- ⚠️ **Read-before-write** strictly enforced
- ⚠️ **Bash output truncation** at 30K chars (silent!)
- ⚠️ **Grep default** is filenames only (not content)
- ⚠️ **TodoWrite** requires exactly one in-progress task

---
