Skip to main content
Mastra 1.0 is available 🎉 Read announcement

createTool()

The createTool() function is used to define custom tools that your Mastra agents can execute. Tools extend an agent's capabilities by allowing it to interact with external systems, perform calculations, or access specific data.

Usage example
Direct link to Usage example

src/mastra/tools/reverse-tool.ts
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const tool = createTool({
id: "test-tool",
description: "Reverse the input string",
inputSchema: z.object({
input: z.string(),
}),
outputSchema: z.object({
output: z.string(),
}),
execute: async (inputData) => {
const reversed = inputData.input.split("").reverse().join("");

return {
output: reversed,
};
},
});

Example with MCP Annotations
Direct link to Example with MCP Annotations

When exposing tools via MCP (Model Context Protocol), you can add annotations to describe tool behavior and customize how clients display the tool. These MCP-specific properties are grouped under the mcp property:

src/mastra/tools/weather-tool.ts
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const weatherTool = createTool({
id: "get-weather",
description: "Get current weather for a location",
inputSchema: z.object({
location: z.string().describe("City name or coordinates"),
}),
// MCP-specific properties
mcp: {
// Annotations for client behavior hints
annotations: {
title: "Weather Lookup", // Human-readable display name
readOnlyHint: true, // Tool doesn't modify environment
destructiveHint: false, // Tool doesn't perform destructive updates
idempotentHint: true, // Same args = same result
openWorldHint: true, // Interacts with external API
},
// Custom metadata for client-specific functionality
_meta: {
version: "1.0.0",
category: "weather",
},
},
execute: async (inputData) => {
const weather = await fetchWeather(inputData.location);
return { weather };
},
});

Parameters
Direct link to Parameters

id:

string
A unique identifier for the tool.

description:

string
A description of what the tool does. This is used by the agent to decide when to use the tool.

inputSchema?:

Zod schema
A Zod schema defining the expected input parameters for the tool's `execute` function.

outputSchema?:

Zod schema
A Zod schema defining the expected output structure of the tool's `execute` function.

suspendSchema?:

Zod schema
A Zod schema defining the structure of the payload passed to `suspend()`. This payload is returned to the client when the tool suspends execution.

resumeSchema?:

Zod schema
A Zod schema defining the expected structure of `resumeData` when the tool is resumed. Used by the agent to extract data from user messages when `autoResumeSuspendedTools` is enabled.

requireApproval?:

boolean
When true, the tool requires explicit approval before execution. The agent will emit a `tool-call-approval` chunk and pause until approved or declined.

mcp?:

MCPToolProperties
MCP-specific properties for tools exposed via Model Context Protocol. Includes `annotations` (tool behavior hints like `title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) and `_meta` (arbitrary metadata passed through to MCP clients).

execute:

function
The function that contains the tool's logic. It receives two parameters: the validated input data (first parameter) and an optional execution context object (second parameter) containing `requestContext`, `tracingContext`, `abortSignal`, and other execution metadata.

input:

z.infer<TInput>
The validated input data based on inputSchema

context?:

ToolExecutionContext
Optional execution context containing metadata

onInputStart?:

function
Optional callback invoked when the tool call input streaming begins. Receives `toolCallId`, `messages`, and `abortSignal`.

onInputDelta?:

function
Optional callback invoked for each incremental chunk of input text as it streams in. Receives `inputTextDelta`, `toolCallId`, `messages`, and `abortSignal`.

onInputAvailable?:

function
Optional callback invoked when the complete tool input is available and parsed. Receives the validated `input` object, `toolCallId`, `messages`, and `abortSignal`.

onOutput?:

function
Optional callback invoked after the tool has successfully executed and returned output. Receives the tool's `output`, `toolCallId`, `messages`, and `abortSignal`.

Returns
Direct link to Returns

The createTool() function returns a Tool object.

Tool:

object
An object representing the defined tool, ready to be added to an agent.

Tool Lifecycle Hooks
Direct link to Tool Lifecycle Hooks

Tools support lifecycle hooks that allow you to monitor and react to different stages of tool execution. These hooks are particularly useful for logging, analytics, validation, and real-time updates during streaming.

Available Hooks
Direct link to Available Hooks

onInputStart
Direct link to onInputStart

Called when tool call input streaming begins, before any input data is received.

export const tool = createTool({
id: "example-tool",
description: "Example tool with hooks",
onInputStart: ({ toolCallId, messages, abortSignal }) => {
console.log(`Tool ${toolCallId} input streaming started`);
},
});

onInputDelta
Direct link to onInputDelta

Called for each incremental chunk of input text as it streams in. Useful for showing real-time progress or parsing partial JSON.

export const tool = createTool({
id: "example-tool",
description: "Example tool with hooks",
onInputDelta: ({ inputTextDelta, toolCallId, messages, abortSignal }) => {
console.log(`Received input chunk: ${inputTextDelta}`);
},
});

onInputAvailable
Direct link to onInputAvailable

Called when the complete tool input is available and has been parsed and validated against the inputSchema.

export const tool = createTool({
id: "example-tool",
description: "Example tool with hooks",
inputSchema: z.object({
city: z.string(),
}),
onInputAvailable: ({ input, toolCallId, messages, abortSignal }) => {
console.log(`Tool received complete input:`, input);
// input is fully typed based on inputSchema
},
});

onOutput
Direct link to onOutput

Called after the tool has successfully executed and returned output. Useful for logging results, triggering follow-up actions, or analytics.

export const tool = createTool({
id: "example-tool",
description: "Example tool with hooks",
outputSchema: z.object({
result: z.string(),
}),
execute: async (input) => {
return { result: "Success" };
},
onOutput: ({ output, toolCallId, toolName, abortSignal }) => {
console.log(`${toolName} execution completed:`, output);
// output is fully typed based on outputSchema
},
});

Hook Execution Order
Direct link to Hook Execution Order

For a typical streaming tool call, the hooks are invoked in this order:

  1. onInputStart - Input streaming begins
  2. onInputDelta - Called multiple times as chunks arrive
  3. onInputAvailable - Complete input is parsed and validated
  4. Tool's execute function runs
  5. onOutput - Tool has completed successfully

Hook Parameters
Direct link to Hook Parameters

All hooks receive a parameter object with these common properties:

  • toolCallId (string): Unique identifier for this specific tool call
  • abortSignal (AbortSignal): Signal for detecting if the operation should be cancelled

Additionally:

  • onInputStart, onInputDelta, and onInputAvailable receive messages (array): The conversation messages at the time of the tool call
  • onInputDelta receives inputTextDelta (string): The incremental text chunk
  • onInputAvailable receives input: The validated input data (typed according to inputSchema)
  • onOutput receives output: The tool's return value (typed according to outputSchema) and toolName (string): The name of the tool

Error Handling
Direct link to Error Handling

Hook errors are caught and logged automatically, but do not prevent tool execution from continuing. If a hook throws an error, it will be logged to the console but will not fail the tool call.

MCP Tool Annotations
Direct link to MCP Tool Annotations

When exposing tools via the Model Context Protocol (MCP), you can provide annotations that describe tool behavior. These annotations help MCP clients like OpenAI Apps SDK understand how to present and handle your tools.

MCP-specific properties are grouped under the mcp property, which includes annotations and _meta:

mcp: {
annotations: { /* behavior hints */ },
_meta: { /* custom metadata */ },
}

ToolAnnotations Properties
Direct link to ToolAnnotations Properties

title?:

string
A human-readable title for the tool. Used for display purposes in UI components.

readOnlyHint?:

boolean
If true, the tool does not modify its environment. This hint indicates the tool only reads data and has no side effects. Defaults to false.

destructiveHint?:

boolean
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates. This hint helps clients determine if confirmation should be required. Defaults to true.

idempotentHint?:

boolean
If true, calling the tool repeatedly with the same arguments will have no additional effect on its environment. This hint indicates idempotent behavior. Defaults to false.

openWorldHint?:

boolean
If true, this tool may interact with an 'open world' of external entities (e.g., web search, external APIs). If false, the tool's domain is closed and fully defined. Defaults to true.

These annotations follow the MCP specification and are passed through when tools are listed via MCP.