Skip to main content
Tools extend the agent’s capabilities. This guide shows how to create custom tools.

Tool Structure

Each tool has:
  • Name: Unique identifier
  • Description: For Claude to understand when to use it
  • Parameters: JSON Schema for inputs
  • Handler: Function that executes the tool

Basic Example

import { defineTool } from '../tools/registry'

defineTool({
  name: 'get_weather',
  description: 'Get current weather for a location',
  parameters: {
    type: 'object',
    properties: {
      location: {
        type: 'string',
        description: 'City name or coordinates',
      },
    },
    required: ['location'],
  },
  handler: async ({ location }) => {
    const response = await fetch(
      `https://api.weather.com/v1/${location}`
    )
    return response.json()
  },
})

Permission Levels

Tools are categorized by risk:
LevelExamplesBehavior
readread_file, globAlways allowed
modifywrite_file, editRequires confirmation in “ask” mode
dangerousbash, deleteRequires confirmation
Set the level in your tool definition:
defineTool({
  name: 'run_tests',
  level: 'dangerous',
  // ...
})

MCP Integration

Tools can come from MCP servers:
await mcpManager.registerServer({
  name: 'my-tools',
  transport: 'stdio',
  command: 'npx',
  args: ['-y', 'my-mcp-server'],
})

Best Practices

Clear descriptions

Help Claude know when to use the tool

Validate inputs

Check parameters before execution

Handle errors

Return helpful error messages

Minimize side effects

Make tools predictable
Document your tools well with examples and edge cases. The description is what Claude uses to decide when to invoke your tool.