How to Give Your Claude Agent a USDC Wallet in 5 Minutes
Step-by-step tutorial to connect a Claude AI agent to a USDC wallet on Base using Bithaven's MCP SDK. Check balances, send payments, and request human approval — all through Claude's tool_use.
Your Claude agent can reason, plan, and use tools. But it can't spend money — until now. In this tutorial, you'll connect a Claude agent to a USDC wallet on Base, giving it the ability to check balances, send payments, and request your approval for large transactions.
We'll use Bithaven's MCP SDK, which wraps financial operations as standard tool calls that Claude can invoke through tool_use.
Prerequisites
- A Bithaven account (sign up free)
- An agent wallet with an API key (created from the dashboard)
- USDC deposited to your master wallet on Base
- Node.js 20+ and an Anthropic API key
Step 1: Install the SDK
npm install @bithaven/mcp-sdk @anthropic-ai/sdk
Step 2: Initialize the Bithaven client
import { BithavenClient } from '@bithaven/mcp-sdk';
const bithaven = new BithavenClient({
apiKey: process.env.BITHAVEN_API_KEY!,
baseUrl: 'https://api.bithaven.ai',
});
Step 3: Define tools for Claude
Bithaven's SDK exposes four core tools that map directly to Claude's tool_use format:
const tools = [
{
name: 'check_balance',
description: 'Check the agent wallet USDC balance and remaining spend caps.',
input_schema: { type: 'object', properties: {} },
},
{
name: 'send_payment',
description: 'Send USDC to an address. Evaluated against spending policies.',
input_schema: {
type: 'object',
properties: {
to: { type: 'string', description: 'Recipient wallet address' },
amount: { type: 'string', description: 'USDC amount to send' },
memo: { type: 'string', description: 'Payment description' },
},
required: ['to', 'amount'],
},
},
{
name: 'get_tx_history',
description: 'Get recent transaction history for this agent wallet.',
input_schema: {
type: 'object',
properties: {
page: { type: 'number', description: 'Page number' },
limit: { type: 'number', description: 'Results per page' },
},
},
},
{
name: 'request_approval',
description: 'Request human approval for a transaction that exceeds policy.',
input_schema: {
type: 'object',
properties: {
to: { type: 'string', description: 'Recipient address' },
amount: { type: 'string', description: 'USDC amount' },
reason: { type: 'string', description: 'Why this payment is needed' },
},
required: ['to', 'amount', 'reason'],
},
},
];
Step 4: Handle tool calls
When Claude decides to use a financial tool, route the call to Bithaven:
async function handleToolCall(name: string, input: any) {
switch (name) {
case 'check_balance':
return await bithaven.checkBalance();
case 'send_payment':
return await bithaven.sendPayment(input);
case 'get_tx_history':
return await bithaven.getTxHistory(input);
case 'request_approval':
return await bithaven.requestApproval(input);
default:
return { error: `Unknown tool: ${name}` };
}
}
Step 5: Run the agent loop
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
async function runAgent(userMessage: string) {
let messages = [{ role: 'user', content: userMessage }];
while (true) {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
tools,
messages,
});
// If Claude wants to use a tool
if (response.stop_reason === 'tool_use') {
const toolBlock = response.content.find(
(block) => block.type === 'tool_use'
);
if (toolBlock) {
const result = await handleToolCall(toolBlock.name, toolBlock.input);
messages.push({ role: 'assistant', content: response.content });
messages.push({
role: 'user',
content: [{
type: 'tool_result',
tool_use_id: toolBlock.id,
content: JSON.stringify(result),
}],
});
continue;
}
}
// Claude is done — return the final response
const textBlock = response.content.find(
(block) => block.type === 'text'
);
return textBlock?.text || '';
}
}
Step 6: Test it
// Check balance
const balance = await runAgent("What's my current USDC balance?");
console.log(balance);
// Send a payment
const payment = await runAgent(
"Send 5 USDC to 0x1234...abcd for the DataAPI monthly subscription"
);
console.log(payment);
// Request approval for a large transaction
const approval = await runAgent(
"I need to pay 500 USDC to 0xabcd...1234 for GPU compute. This exceeds my daily limit, so please request approval."
);
console.log(approval);
What happens under the hood
When Claude calls send_payment, Bithaven evaluates the transaction against all active policies on the agent wallet:
- Within policy? → Transaction is signed and broadcast on Base. Claude receives a confirmation with the transaction hash.
- Exceeds daily cap? → Transaction is blocked. Claude receives the specific policy violation and can decide to request human approval instead.
- Address not whitelisted? → Transaction is blocked with a clear error explaining which policy was violated.
This means your agent can operate autonomously for routine transactions while automatically escalating anything unusual for your review.
Next steps
- Set up spending policies to control your agent's budget
- Configure approval workflows for human-in-the-loop oversight
- Explore the full MCP tool reference for all available operations
- Try the LangChain integration if you're using LangChain agents
Bithaven gives your AI agents a budget, not a blank check. Create your first agent wallet →
Ready to give your agents a budget?
Create an account and have your first agent transacting in minutes.
Get Started Free