t2000_invest
Manage investment assets by buying, selling, or earning yield through lending. Automatically handles insufficient balances by withdrawing from savings.
Instructions
Buy, sell, earn yield, or stop earning on investment assets. Actions: buy (invest USD), sell (convert to USDC), earn (deposit into best-rate lending for yield), unearn (withdraw from lending, keep in portfolio). Amount required for buy/sell only. If checking balance is insufficient for a buy, the SDK will auto-withdraw from savings — no manual withdraw needed.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | 'buy' to invest, 'sell' to liquidate, 'earn' to deposit into lending for yield, 'unearn' to withdraw from lending | |
| asset | Yes | Asset to invest in | |
| amount | No | USD amount (required for buy/sell, ignored for earn/unearn) | |
| slippage | No | Max slippage percent (default: 3, for buy/sell only) | |
| dryRun | No | Preview without signing (default: false) |
Implementation Reference
- packages/mcp/src/tools/write.ts:278-329 (handler)The handler function for t2000_invest, which processes actions: buy, sell, earn, and unearn. It interacts with the agent to perform these actions and optionally supports a dry run.
async ({ action, asset, amount, slippage, dryRun }) => { try { if (dryRun) { agent.enforcer.assertNotLocked(); const balance = await agent.balance(); const portfolio = await agent.getPortfolio(); const position = portfolio.positions.find(p => p.asset === asset); if (action === 'sell' && amount === 'all' && !position) { return { content: [{ type: 'text', text: JSON.stringify({ preview: true, error: `No ${asset} position to sell` }) }], }; } return { content: [{ type: 'text', text: JSON.stringify({ preview: true, action, asset, amount: amount === 'all' ? position?.currentValue ?? 0 : amount ?? position?.totalAmount ?? 0, currentBalance: balance.available, currentPosition: position ?? null, earning: position?.earning ?? false, earningProtocol: position?.earningProtocol ?? null, earningApy: position?.earningApy ?? null, }), }], }; } const maxSlippage = slippage ? slippage / 100 : undefined; if (action === 'buy') { if (typeof amount !== 'number') throw new Error('Buy amount must be a number'); const result = await mutex.run(() => agent.investBuy({ asset: asset as InvestmentAsset, usdAmount: amount, maxSlippage })); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } else if (action === 'sell') { const usdAmount = amount === 'all' ? 'all' as const : amount as number; const result = await mutex.run(() => agent.investSell({ asset: asset as InvestmentAsset, usdAmount, maxSlippage })); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } else if (action === 'earn') { const result = await mutex.run(() => agent.investEarn({ asset: asset as InvestmentAsset })); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } else { const result = await mutex.run(() => agent.investUnearn({ asset: asset as InvestmentAsset })); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } } catch (err) { return errorResult(err); } }, - packages/mcp/src/tools/write.ts:268-277 (registration)Registration of the t2000_invest tool with the MCP server, defining its schema and tool description.
server.tool( 't2000_invest', 'Buy, sell, earn yield, or stop earning on investment assets. Actions: buy (invest USD), sell (convert to USDC), earn (deposit into best-rate lending for yield), unearn (withdraw from lending, keep in portfolio). Amount required for buy/sell only. If checking balance is insufficient for a buy, the SDK will auto-withdraw from savings — no manual withdraw needed.', { action: z.enum(['buy', 'sell', 'earn', 'unearn']).describe("'buy' to invest, 'sell' to liquidate, 'earn' to deposit into lending for yield, 'unearn' to withdraw from lending"), asset: z.enum(investAssets).describe('Asset to invest in'), amount: z.union([z.number(), z.literal('all')]).optional().describe('USD amount (required for buy/sell, ignored for earn/unearn)'), slippage: z.number().optional().describe('Max slippage percent (default: 3, for buy/sell only)'), dryRun: z.boolean().optional().describe('Preview without signing (default: false)'), },