Tool use with Claude¶
- URL: https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview.md
- Retrieved: 2026-01-08T05:11:24.847228+00:00
Tool use with Claude¶
Claude is capable of interacting with tools and functions, allowing you to extend Claude's capabilities to perform a wider variety of tasks.
Structured Outputs provides guaranteed schema validation for tool inputs. Add strict: true to your tool definitions to ensure Claude's tool calls always match your schema exactly—no more type mismatches or missing fields.
Perfect for production agents where invalid tool parameters would cause failures. Learn when to use strict tool use →
Here's an example of how to provide tools to Claude using the Messages API:
```bash Shell curl https://api.anthropic.com/v1/messages \ -H "content-type: application/json" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-5", "max_tokens": 1024, "tools": [ { "name": "get_weather", "description": "Get the current weather in a given location", "input_schema": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" } }, "required": ["location"] } } ], "messages": [ { "role": "user", "content": "What is the weather like in San Francisco?" } ] }'
```python Python
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
)
print(response)
```typescript TypeScript import { Anthropic } from '@anthropic-ai/sdk';
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
async function main() { const response = await anthropic.messages.create({ model: "claude-sonnet-4-5", max_tokens: 1024, tools: [{ name: "get_weather", description: "Get the current weather in a given location", input_schema: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. San Francisco, CA" } }, required: ["location"] } }], messages: [{ role: "user", content: "Tell me the weather in San Francisco." }] });
console.log(response); }
main().catch(console.error);
```java Java
import java.util.List;
import java.util.Map;
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.Tool;
import com.anthropic.models.messages.Tool.InputSchema;
public class GetWeatherExample {
public static void main(String args) {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
InputSchema schema = InputSchema.builder()
.properties(JsonValue.from(Map.of(
"location",
Map.of(
"type", "string",
"description", "The city and state, e.g. San Francisco, CA"))))
.putAdditionalProperty("required", JsonValue.from(List.of("location")))
.build();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_0)
.maxTokens(1024)
.addTool(Tool.builder()
.name("get_weather")
.description("Get the current weather in a given location")
.inputSchema(schema)
.build())
.addUserMessage("What's the weather like in San Francisco?")
.build();
Message message = client.messages().create(params);
System.out.println(message);
}
}
How tool use works¶
Claude supports two types of tools:
- Client tools: Tools that execute on your systems, which include:
- User-defined custom tools that you create and implement
-
Anthropic-defined tools like computer use and text editor that require client implementation
-
Server tools: Tools that execute on Anthropic's servers, like the web search and web fetch tools. These tools must be specified in the API request but don't require implementation on your part.
web_search_20250305, text_editor_20250124) to ensure compatibility across model versions.
Client tools¶
Integrate client tools with Claude in these steps:
stop_reason of tool_use, signaling Claude's intent.
user message containing a tool_result content block
Server tools¶
Server tools follow a different workflow:
Using MCP tools with Claude¶
If you're building an application that uses the Model Context Protocol (MCP), you can use tools from MCP servers directly with Claude's Messages API. MCP tool definitions use a schema format that's similar to Claude's tool format. You just need to rename inputSchema to input_schema.
Converting MCP tools to Claude format¶
When you build an MCP client and call list_tools() on an MCP server, you'll receive tool definitions with an inputSchema field. To use these tools with Claude, convert them to Claude's format:
async def get_claude_tools(mcp_session: ClientSession): """Convert MCP tools to Claude's tool format.""" mcp_tools = await mcp_session.list_tools()
claude_tools =
for tool in mcp_tools.tools:
claude_tools.append({
"name": tool.name,
"description": tool.description or "",
"input_schema": tool.inputSchema # Rename inputSchema to input_schema
})
return claude_tools
```typescript TypeScript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
async function getClaudeTools(mcpClient: Client) {
// Convert MCP tools to Claude's tool format
const mcpTools = await mcpClient.listTools();
return mcpTools.tools.map((tool) => ({
name: tool.name,
description: tool.description ?? "",
input_schema: tool.inputSchema, // Rename inputSchema to input_schema
}));
}
Then pass these converted tools to Claude:
client = anthropic.Anthropic() claude_tools = await get_claude_tools(mcp_session)
response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, tools=claude_tools, messages=[{"role": "user", "content": "What tools do you have available?"}] )
```typescript TypeScript
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
const claudeTools = await getClaudeTools(mcpClient);
const response = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
tools: claudeTools,
messages: [{ role: "user", content: "What tools do you have available?" }],
});
When Claude responds with a tool_use block, execute the tool on your MCP server using call_tool() and return the result to Claude in a tool_result block.
For a complete guide to building MCP clients, see Build an MCP client.
Tool use examples¶
Here are a few code examples demonstrating various tool use patterns and techniques. For brevity's sake, the tools are simple tools, and the tool descriptions are shorter than would be ideal to ensure best performance.
You would then need to execute the `get_weather` function with the provided input, and return the result in a new `user` message:
<CodeGroup>
```bash Shell
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "content-type: application/json" \
--data \
'{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
}
},
"required": ["location"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the weather like in San Francisco?"
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll check the current weather in San Francisco for you."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {
"location": "San Francisco, CA",
"unit": "celsius"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "15 degrees"
}
]
}
]
}'
```
```python Python
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The unit of temperature, either 'celsius' or 'fahrenheit'"
}
},
"required": ["location"]
}
}
],
messages=[
{
"role": "user",
"content": "What's the weather like in San Francisco?"
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll check the current weather in San Francisco for you."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {"location": "San Francisco, CA", "unit": "celsius"}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9", # from the API response
"content": "65 degrees" # from running your tool
}
]
}
]
)
print(response)
```
```java Java
import java.util.List;
import java.util.Map;
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.*;
import com.anthropic.models.messages.Tool.InputSchema;
public class ToolConversationExample {
public static void main(String args) {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
InputSchema schema = InputSchema.builder()
.properties(JsonValue.from(Map.of(
"location", Map.of(
"type", "string",
"description", "The city and state, e.g. San Francisco, CA"
),
"unit", Map.of(
"type", "string",
"enum", List.of("celsius", "fahrenheit"),
"description", "The unit of temperature, either \"celsius\" or \"fahrenheit\""
)
)))
.putAdditionalProperty("required", JsonValue.from(List.of("location")))
.build();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_0)
.maxTokens(1024)
.addTool(Tool.builder()
.name("get_weather")
.description("Get the current weather in a given location")
.inputSchema(schema)
.build())
.addUserMessage("What is the weather like in San Francisco?")
.addAssistantMessageOfBlockParams(
List.of(
ContentBlockParam.ofText(
TextBlockParam.builder()
.text("I'll check the current weather in San Francisco for you.")
.build()
),
ContentBlockParam.ofToolUse(
ToolUseBlockParam.builder()
.id("toolu_01A09q90qw90lq917835lq9")
.name("get_weather")
.input(JsonValue.from(Map.of(
"location", "San Francisco, CA",
"unit", "celsius"
)))
.build()
)
)
)
.addUserMessageOfBlockParams(List.of(
ContentBlockParam.ofToolResult(
ToolResultBlockParam.builder()
.toolUseId("toolu_01A09q90qw90lq917835lq9")
.content("15 degrees")
.build()
)
))
.build();
Message message = client.messages().create(params);
System.out.println(message);
}
}
```
</CodeGroup>
This will print Claude's final response, incorporating the weather data:
```json JSON
{
"id": "msg_01Aq9w938a90dw8q",
"model": "claude-sonnet-4-5",
"stop_reason": "stop_sequence",
"role": "assistant",
"content": [
{
"type": "text",
"text": "The current weather in San Francisco is 15 degrees Celsius (59 degrees Fahrenheit). It's a cool day in the city by the bay!"
}
]
}
Pricing¶
Tool use requests are priced based on:
1. The total number of input tokens sent to the model (including in the tools parameter)
2. The number of output tokens generated
3. For server-side tools, additional usage-based pricing (e.g., web search charges per search performed)
Client-side tools are priced the same as any other Claude API request, while server-side tools may incur additional charges based on their specific usage.
The additional tokens from tool use come from:
- The
toolsparameter in API requests (tool names, descriptions, and schemas) tool_usecontent blocks in API requests and responsestool_resultcontent blocks in API requests
When you use tools, we also automatically include a special system prompt for the model which enables tool use. The number of tool use tokens required for each model are listed below (excluding the additional tokens listed above). Note that the table assumes at least 1 tool is provided. If no tools are provided, then a tool choice of none uses 0 additional system prompt tokens.
| Model | Tool choice | Tool use system prompt token count |
|---|---|---|
| Claude Opus 4.5 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Opus 4.1 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Opus 4 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Sonnet 4.5 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Sonnet 4 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Sonnet 3.7 (deprecated) | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Haiku 4.5 | auto, noneany, tool |
346 tokens 313 tokens |
| Claude Haiku 3.5 | auto, noneany, tool |
264 tokens 340 tokens |
| Claude Opus 3 (deprecated) | auto, noneany, tool |
530 tokens 281 tokens |
| Claude Sonnet 3 | auto, noneany, tool |
159 tokens 235 tokens |
| Claude Haiku 3 | auto, noneany, tool |
264 tokens 340 tokens |
These token counts are added to your normal input and output tokens to calculate the total cost of a request.
Refer to our models overview table for current per-model prices.
When you send a tool use prompt, just like any other API request, the response will output both input and output token counts as part of the reported usage metrics.
Next Steps¶
Explore our repository of ready-to-implement tool use code examples in our cookbooks:
Learn how to integrate a simple calculator tool with Claude for precise numerical computations.
{" "} <Card title="Customer Service Agent" icon="headset" href="https://platform.claude.com/cookbook/tool-use-customer-service-agent"
Build a responsive customer service bot that leverages client tools to enhance support.
<Card title="JSON Extractor" icon="code-brackets" href="https://platform.claude.com/cookbook/tool-use-extracting-structured-json"
See how Claude and tool use can extract structured data from unstructured text.