Skip to main content
Glama

BORROW

Borrow tokens from a BAMM position by providing the contract address and amount. Optionally specify the token address and symbol for accuracy.

Instructions

Borrow tokens from a BAMM position

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bammAddressYesThe address of the BAMM contract
amountYesThe amount to borrow
borrowTokenNoThe address of the token to borrow
borrowTokenSymbolNoThe symbol of the token to borrow (e.g., 'IQT')

Implementation Reference

  • Main tool definition for BORROW. Defines the tool name, description, Zod schema (parameters), and the execute handler which instantiates WalletService and BorrowService, calls borrowService.execute(), and returns a formatted success/error message.
    export const borrowTool: Tool<FastMCPSessionAuth, typeof borrowToolParams> = {
    	name: "BORROW",
    	description: "Borrow tokens from a BAMM position",
    	parameters: borrowToolParams,
    	execute: async (params, _context) => {
    		try {
    			if (!params.borrowToken && !params.borrowTokenSymbol) {
    				return "Error: Either borrowToken address or borrowTokenSymbol is required";
    			}
    
    			const privateKey = process.env.WALLET_PRIVATE_KEY;
    			if (!privateKey) {
    				return "Error: WALLET_PRIVATE_KEY environment variable is not set. Please set it with your wallet's private key (without 0x prefix).";
    			}
    
    			const walletService = new WalletService(privateKey);
    			const borrowService = new BorrowService(walletService);
    
    			const result = await borrowService.execute({
    				bammAddress: params.bammAddress as Address,
    				borrowToken: params.borrowToken as Address | undefined,
    				borrowTokenSymbol: params.borrowTokenSymbol,
    				amount: params.amount,
    			});
    
    			return dedent`
            ✅ Borrowing Successful
    
            🌐 BAMM Address: ${params.bammAddress}
            💸 Amount: ${formatNumber(Number(params.amount))}
            🪙 Token: ${params.borrowTokenSymbol ?? params.borrowToken}
            🔗 Transaction: ${result.txHash}
    
            Tokens have been borrowed from your BAMM position.
          `;
    		} catch (error) {
    			if (error instanceof Error) {
    				return dedent`
              ❌ Borrowing Failed
    
              Error: ${error.message}
    
              Please verify your inputs and try again.
            `;
    			}
    			return "An unknown error occurred while borrowing tokens";
    		}
    	},
    };
  • Zod schema for BORROW tool parameters: bammAddress (required, hex address), amount (required string), borrowToken (optional hex address), borrowTokenSymbol (optional string).
    const borrowToolParams = z.object({
    	bammAddress: z
    		.string()
    		.regex(/^0x[a-fA-F0-9]{40}$/)
    		.describe("The address of the BAMM contract"),
    	amount: z.string().min(1).describe("The amount to borrow"),
    	borrowToken: z
    		.string()
    		.regex(/^0x[a-fA-F0-9]{40}$/)
    		.optional()
    		.describe("The address of the token to borrow"),
    	borrowTokenSymbol: z
    		.string()
    		.optional()
    		.describe("The symbol of the token to borrow (e.g., 'IQT')"),
    });
  • src/index.ts:19-20 (registration)
    Registration of the BORROW tool on the FastMCP server via server.addTool(borrowTool).
    server.addTool(addCollateralTool);
    server.addTool(borrowTool);
  • BorrowService class with the execute() method that performs the actual borrowing logic: resolves token address from symbol, validates token against BAMM, checks balance, ensures token approval, calculates rent, builds the action struct, and submits the transaction via the wallet client.
    export interface BorrowParams {
    	bammAddress: Address;
    	borrowToken?: Address;
    	borrowTokenSymbol?: string;
    	amount: string;
    }
    
    export class BorrowService {
    	constructor(private walletService: WalletService) {}
    
    	async execute(params: BorrowParams): Promise<{ txHash: string }> {
    		let { bammAddress, borrowToken, borrowTokenSymbol, amount } = params;
    
    		if (!borrowToken && !borrowTokenSymbol) {
    			throw new Error("Either borrowToken or borrowTokenSymbol is required");
    		}
    		const publicClient = this.walletService.getPublicClient();
    		const walletClient = this.walletService.getWalletClient();
    
    		if (!walletClient || !walletClient.account) {
    			throw new Error("Wallet client is not initialized");
    		}
    
    		const userAddress = walletClient.account.address;
    		const amountInWei = BigInt(Math.floor(Number(amount) * 1e18));
    
    		try {
    			if (borrowTokenSymbol) {
    				borrowToken = await getTokenAddressFromSymbol(borrowTokenSymbol);
    			}
    
    			if (!borrowToken) {
    				throw new Error("Could not resolve borrow token address");
    			}
    
    			const tokenValidation = await validateTokenAgainstBAMM(
    				bammAddress,
    				borrowToken,
    				publicClient,
    			);
    
    			const collateralBalance: bigint = await publicClient.readContract({
    				address: borrowToken,
    				abi: erc20Abi,
    				functionName: "balanceOf",
    				args: [userAddress],
    			});
    			if (collateralBalance < amountInWei) {
    				throw new Error("Insufficient collateral token balance");
    			}
    
    			await checkTokenBalance(
    				borrowToken,
    				userAddress,
    				amountInWei,
    				publicClient,
    			);
    			await ensureTokenApproval(
    				borrowToken,
    				bammAddress,
    				amountInWei,
    				publicClient,
    				walletClient,
    			);
    
    			const rentedMultiplier: bigint = await publicClient.readContract({
    				address: bammAddress,
    				abi: BAMM_ABI,
    				functionName: "rentedMultiplier",
    				args: [],
    			});
    
    			// Calculate rent based on borrowed amount and rentedMultiplier
    			const rent = (amountInWei * rentedMultiplier) / BigInt(1e18);
    
    			const currentTime = Math.floor(Date.now() / 1000);
    			const deadline = BigInt(currentTime + 300);
    
    			const action = {
    				token0Amount: tokenValidation.isToken0 ? -amountInWei : 0n,
    				token1Amount: tokenValidation.isToken1 ? -amountInWei : 0n,
    				rent: rent,
    				to: userAddress,
    				token0AmountMin: 0n,
    				token1AmountMin: 0n,
    				closePosition: false,
    				approveMax: false,
    				v: 0,
    				r: "0x0000000000000000000000000000000000000000000000000000000000000000" as `0x${string}`,
    				s: "0x0000000000000000000000000000000000000000000000000000000000000000" as `0x${string}`,
    				deadline,
    			};
    
    			const { request: executeRequest } = await publicClient.simulateContract({
    				address: bammAddress,
    				abi: BAMM_ABI,
    				functionName: "executeActions",
    				args: [action],
    				account: walletClient.account,
    			});
    			const txHash = await walletClient.writeContract(executeRequest);
    			await publicClient.waitForTransactionReceipt({ hash: txHash });
    
    			return { txHash };
    		} catch (error) {
    			console.error("Error in borrow service", error);
    			throw error;
    		}
    	}
    }
  • BORROW_TEMPLATE - a prompt template for the LLM to extract borrowing parameters, derived from TOKEN_OPERATION_TEMPLATE.
    export const BORROW_TEMPLATE = TOKEN_OPERATION_TEMPLATE.replace(
    	/{{operation}}/g,
    	"borrowing",
    ).replace(/{{tokenType}}/g, "borrowToken");
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It only states 'borrow tokens' without explaining consequences (e.g., debt creation, collateral requirements, or mutability). This is insufficient for a transactional tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence. However, it is possibly too minimal, sacrificing valuable context for brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a borrowing operation and the lack of output schema or annotations, the description fails to provide essential behavioral and contextual details, such as what happens upon execution.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 100% coverage with descriptions for each parameter, so the baseline is 3. The tool description does not add additional semantic context beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (borrow) and target (tokens from a BAMM position), but does not differentiate from sibling tools like LEND. It is specific enough for a general understanding.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like LEND, or any prerequisites. The description lacks context for appropriate usage scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IQAIcom/mcp-bamm'

If you have feedback or need assistance with the MCP directory API, please join our Discord server