Loading...
    • Developer Guide
    • API Reference
    • MCP
    • Resources
    • Release Notes
    Search...
    ⌘K

    First steps

    Intro to ClaudeQuickstart

    Models & pricing

    Models overviewChoosing a modelWhat's new in Claude 4.5Migrating to Claude 4.5Model deprecationsPricing

    Build with Claude

    Features overviewUsing the Messages APIContext windowsPrompting best practices

    Capabilities

    Prompt cachingContext editingExtended thinkingStreaming MessagesBatch processingCitationsMultilingual supportToken countingEmbeddingsVisionPDF supportFiles APISearch resultsGoogle Sheets add-on

    Tools

    OverviewHow to implement tool useToken-efficient tool useFine-grained tool streamingBash toolCode execution toolComputer use toolText editor toolWeb fetch toolWeb search toolMemory tool

    Agent Skills

    OverviewQuickstartBest practicesUsing Skills with the API

    Agent SDK

    OverviewTypeScript SDKPython SDK

    Guides

    Streaming InputHandling PermissionsSession ManagementHosting the Agent SDKModifying system promptsMCP in the SDKCustom ToolsSubagents in the SDKSlash Commands in the SDKAgent Skills in the SDKTracking Costs and UsageTodo ListsPlugins in the SDK

    MCP in the API

    MCP connectorRemote MCP servers

    Claude on 3rd-party platforms

    Amazon BedrockVertex AI

    Prompt engineering

    OverviewPrompt generatorUse prompt templatesPrompt improverBe clear and directUse examples (multishot prompting)Let Claude think (CoT)Use XML tagsGive Claude a role (system prompts)Prefill Claude's responseChain complex promptsLong context tipsExtended thinking tips

    Test & evaluate

    Define success criteriaDevelop test casesUsing the Evaluation ToolReducing latency

    Strengthen guardrails

    Reduce hallucinationsIncrease output consistencyMitigate jailbreaksStreaming refusalsReduce prompt leakKeep Claude in character

    Administration and monitoring

    Admin API overviewUsage and Cost APIClaude Code Analytics API
    Console
    Guides

    Custom Tools

    Build and integrate custom tools to extend Claude Agent SDK functionality

    Custom tools allow you to extend Claude Code's capabilities with your own functionality through in-process MCP servers, enabling Claude to interact with external services, APIs, or perform specialized operations.

    Creating Custom Tools

    Use the createSdkMcpServer and tool helper functions to define type-safe custom tools:

    TypeScript
    import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
    import { z } from "zod";
    
    // Create an SDK MCP server with custom tools
    const customServer = createSdkMcpServer({
      name: "my-custom-tools",
      version: "1.0.0",
      tools: [
        tool(
          "get_weather",
          "Get current temperature for a location using coordinates",
          {
            latitude: z.number().describe("Latitude coordinate"),
            longitude: z.number().describe("Longitude coordinate")
          },
          async (args) => {
            const response = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${args.latitude}&longitude=${args.longitude}&current=temperature_2m&temperature_unit=fahrenheit`);
            const data = await response.json();
    
            return {
              content: [{
                type: "text",
                text: `Temperature: ${data.current.temperature_2m}°F`
              }]
            };
          }
        )
      ]
    });
    Python
    from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeSDKClient, ClaudeAgentOptions
    from typing import Any
    import aiohttp
    
    # Define a custom tool using the @tool decorator
    @tool("get_weather", "Get current temperature for a location using coordinates", {"latitude": float, "longitude": float})
    async def get_weather(args: dict[str, Any]) -> dict[str, Any]:
        # Call weather API
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f"https://api.open-meteo.com/v1/forecast?latitude={args['latitude']}&longitude={args['longitude']}&current=temperature_2m&temperature_unit=fahrenheit"
            ) as response:
                data = await response.json()
    
        return {
            "content": [{
                "type": "text",
                "text": f"Temperature: {data['current']['temperature_2m']}°F"
            }]
        }
    
    # Create an SDK MCP server with the custom tool
    custom_server = create_sdk_mcp_server(
        name="my-custom-tools",
        version="1.0.0",
        tools=[get_weather]  # Pass the decorated function
    )

    Using Custom Tools

    Pass the custom server to the query function via the mcpServers option as a dictionary/object.

    Important: Custom MCP tools require streaming input mode. You must use an async generator/iterable for the prompt parameter - a simple string will not work with MCP servers.

    Tool Name Format

    When MCP tools are exposed to Claude, their names follow a specific format:

    • Pattern: mcp__{server_name}__{tool_name}
    • Example: A tool named get_weather in server my-custom-tools becomes mcp__my-custom-tools__get_weather

    Configuring Allowed Tools

    You can control which tools Claude can use via the allowedTools option:

    import { query } from "@anthropic-ai/claude-agent-sdk";
    
    // Use the custom tools in your query with streaming input
    async function* generateMessages() {
      yield {
        type: "user" as const,
        message: {
          role: "user" as const,
          content: "What's the weather in San Francisco?"
        }
      };
    }
    
    for await (const message of query({
      prompt: generateMessages(),  // Use async generator for streaming input
      options: {
        mcpServers: {
          "my-custom-tools": customServer  // Pass as object/dictionary, not array
        },
        // Optionally specify which tools Claude can use
        allowedTools: [
          "mcp__my-custom-tools__get_weather",  // Allow the weather tool
          // Add other tools as needed
        ],
        maxTurns: 3
      }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(message.result);
      }
    }

    Multiple Tools Example

    When your MCP server has multiple tools, you can selectively allow them:

    const multiToolServer = createSdkMcpServer({
      name: "utilities",
      version: "1.0.0",
      tools: [
        tool("calculate", "Perform calculations", { /* ... */ }, async (args) => { /* ... */ }),
        tool("translate", "Translate text", { /* ... */ }, async (args) => { /* ... */ }),
        tool("search_web", "Search the web", { /* ... */ }, async (args) => { /* ... */ })
      ]
    });
    
    // Allow only specific tools with streaming input
    async function* generateMessages() {
      yield {
        type: "user" as const,
        message: {
          role: "user" as const,
          content: "Calculate 5 + 3 and translate 'hello' to Spanish"
        }
      };
    }
    
    for await (const message of query({
      prompt: generateMessages(),  // Use async generator for streaming input
      options: {
        mcpServers: {
          utilities: multiToolServer
        },
        allowedTools: [
          "mcp__utilities__calculate",   // Allow calculator
          "mcp__utilities__translate",   // Allow translator
          // "mcp__utilities__search_web" is NOT allowed
        ]
      }
    })) {
      // Process messages
    }

    Type Safety with Python

    The @tool decorator supports various schema definition approaches for type safety:

    import { z } from "zod";
    
    tool(
      "process_data",
      "Process structured data with type safety",
      {
        // Zod schema defines both runtime validation and TypeScript types
        data: z.object({
          name: z.string(),
          age: z.number().min(0).max(150),
          email: z.string().email(),
          preferences: z.array(z.string()).optional()
        }),
        format: z.enum(["json", "csv", "xml"]).default("json")
      },
      async (args) => {
        // args is fully typed based on the schema
        // TypeScript knows: args.data.name is string, args.data.age is number, etc.
        console.log(`Processing ${args.data.name}'s data as ${args.format}`);
        
        // Your processing logic here
        return {
          content: [{
            type: "text",
            text: `Processed data for ${args.data.name}`
          }]
        };
      }
    )

    Error Handling

    Handle errors gracefully to provide meaningful feedback:

    tool(
      "fetch_data",
      "Fetch data from an API",
      {
        endpoint: z.string().url().describe("API endpoint URL")
      },
      async (args) => {
        try {
          const response = await fetch(args.endpoint);
          
          if (!response.ok) {
            return {
              content: [{
                type: "text",
                text: `API error: ${response.status} ${response.statusText}`
              }]
            };
          }
          
          const data = await response.json();
          return {
            content: [{
              type: "text",
              text: JSON.stringify(data, null, 2)
            }]
          };
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: `Failed to fetch data: ${error.message}`
            }]
          };
        }
      }
    )

    Example Tools

    Database Query Tool

    const databaseServer = createSdkMcpServer({
      name: "database-tools",
      version: "1.0.0",
      tools: [
        tool(
          "query_database",
          "Execute a database query",
          {
            query: z.string().describe("SQL query to execute"),
            params: z.array(z.any()).optional().describe("Query parameters")
          },
          async (args) => {
            const results = await db.query(args.query, args.params || []);
            return {
              content: [{
                type: "text",
                text: `Found ${results.length} rows:\n${JSON.stringify(results, null, 2)}`
              }]
            };
          }
        )
      ]
    });

    API Gateway Tool

    const apiGatewayServer = createSdkMcpServer({
      name: "api-gateway",
      version: "1.0.0",
      tools: [
        tool(
          "api_request",
          "Make authenticated API requests to external services",
          {
            service: z.enum(["stripe", "github", "openai", "slack"]).describe("Service to call"),
            endpoint: z.string().describe("API endpoint path"),
            method: z.enum(["GET", "POST", "PUT", "DELETE"]).describe("HTTP method"),
            body: z.record(z.any()).optional().describe("Request body"),
            query: z.record(z.string()).optional().describe("Query parameters")
          },
          async (args) => {
            const config = {
              stripe: { baseUrl: "https://api.stripe.com/v1", key: process.env.STRIPE_KEY },
              github: { baseUrl: "https://api.github.com", key: process.env.GITHUB_TOKEN },
              openai: { baseUrl: "https://api.openai.com/v1", key: process.env.OPENAI_KEY },
              slack: { baseUrl: "https://slack.com/api", key: process.env.SLACK_TOKEN }
            };
            
            const { baseUrl, key } = config[args.service];
            const url = new URL(`${baseUrl}${args.endpoint}`);
            
            if (args.query) {
              Object.entries(args.query).forEach(([k, v]) => url.searchParams.set(k, v));
            }
            
            const response = await fetch(url, {
              method: args.method,
              headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
              body: args.body ? JSON.stringify(args.body) : undefined
            });
            
            const data = await response.json();
            return {
              content: [{
                type: "text",
                text: JSON.stringify(data, null, 2)
              }]
            };
          }
        )
      ]
    });

    Calculator Tool

    const calculatorServer = createSdkMcpServer({
      name: "calculator",
      version: "1.0.0",
      tools: [
        tool(
          "calculate",
          "Perform mathematical calculations",
          {
            expression: z.string().describe("Mathematical expression to evaluate"),
            precision: z.number().optional().default(2).describe("Decimal precision")
          },
          async (args) => {
            try {
              // Use a safe math evaluation library in production
              const result = eval(args.expression); // Example only!
              const formatted = Number(result).toFixed(args.precision);
              
              return {
                content: [{
                  type: "text",
                  text: `${args.expression} = ${formatted}`
                }]
              };
            } catch (error) {
              return {
                content: [{
                  type: "text",
                  text: `Error: Invalid expression - ${error.message}`
                }]
              };
            }
          }
        ),
        tool(
          "compound_interest",
          "Calculate compound interest for an investment",
          {
            principal: z.number().positive().describe("Initial investment amount"),
            rate: z.number().describe("Annual interest rate (as decimal, e.g., 0.05 for 5%)"),
            time: z.number().positive().describe("Investment period in years"),
            n: z.number().positive().default(12).describe("Compounding frequency per year")
          },
          async (args) => {
            const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time);
            const interest = amount - args.principal;
            
            return {
              content: [{
                type: "text",
                text: `Investment Analysis:\n` +
                      `Principal: $${args.principal.toFixed(2)}\n` +
                      `Rate: ${(args.rate * 100).toFixed(2)}%\n` +
                      `Time: ${args.time} years\n` +
                      `Compounding: ${args.n} times per year\n\n` +
                      `Final Amount: $${amount.toFixed(2)}\n` +
                      `Interest Earned: $${interest.toFixed(2)}\n` +
                      `Return: ${((interest / args.principal) * 100).toFixed(2)}%`
              }]
            };
          }
        )
      ]
    });

    Related Documentation

    • TypeScript SDK Reference
    • Python SDK Reference
    • MCP Documentation
    • SDK Overview
    • Creating Custom Tools
    • Using Custom Tools
    • Tool Name Format
    • Configuring Allowed Tools
    • Multiple Tools Example
    • Type Safety with Python
    • Error Handling
    • Example Tools
    • Database Query Tool
    • API Gateway Tool
    • Calculator Tool
    • Related Documentation
    © 2025 ANTHROPIC PBC

    Products

    • Claude
    • Claude Code
    • Max plan
    • Team plan
    • Enterprise plan
    • Download app
    • Pricing
    • Log in

    Features

    • Claude and Slack
    • Claude in Excel

    Models

    • Opus
    • Sonnet
    • Haiku

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Claude Developer Platform

    • Overview
    • Developer docs
    • Pricing
    • Amazon Bedrock
    • Google Cloud’s Vertex AI
    • Console login

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Help and security

    • Availability
    • Status
    • Support center

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy

    Products

    • Claude
    • Claude Code
    • Max plan
    • Team plan
    • Enterprise plan
    • Download app
    • Pricing
    • Log in

    Features

    • Claude and Slack
    • Claude in Excel

    Models

    • Opus
    • Sonnet
    • Haiku

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Claude Developer Platform

    • Overview
    • Developer docs
    • Pricing
    • Amazon Bedrock
    • Google Cloud’s Vertex AI
    • Console login

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Help and security

    • Availability
    • Status
    • Support center

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    © 2025 ANTHROPIC PBC