Skip to main content
Glama
clumsynonono

Aave Liquidation MCP Server

by clumsynonono

analyze_liquidation

Analyze Aave V3 positions to identify liquidation opportunities by evaluating collateral, debt, risk levels, and potential profit for any Ethereum address.

Instructions

Analyze a user position for liquidation opportunity. Returns detailed information including collateral assets, debt assets, risk level, and potential profit.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
addressYesEthereum address to analyze (must be a valid address)

Implementation Reference

  • src/index.ts:66-80 (registration)
    Registration of the 'analyze_liquidation' tool including its name, description, and input schema in the MCP server's listTools handler.
    { name: 'analyze_liquidation', description: 'Analyze a user position for liquidation opportunity. Returns detailed information including collateral assets, debt assets, risk level, and potential profit.', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Ethereum address to analyze (must be a valid address)', }, }, required: ['address'], }, },
  • Input schema definition for the 'analyze_liquidation' tool, specifying the required 'address' parameter.
    inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Ethereum address to analyze (must be a valid address)', }, }, required: ['address'], }, },
  • MCP CallToolRequest handler for 'analyze_liquidation': validates address, calls AaveClient.analyzeLiquidationOpportunity, and returns JSON-formatted opportunity or healthy message.
    case 'analyze_liquidation': { const address = args?.address as string; if (!address || typeof address !== 'string') { throw new McpError( ErrorCode.InvalidParams, 'address parameter is required and must be a string' ); } if (!aaveClient.isValidAddress(address)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid Ethereum address format' ); } const opportunity = await aaveClient.analyzeLiquidationOpportunity(address); if (!opportunity) { return { content: [ { type: 'text', text: JSON.stringify( { message: 'No liquidation opportunity found. Position is healthy.', address, }, null, 2 ), }, ], }; } return { content: [ { type: 'text', text: JSON.stringify(opportunity, null, 2), }, ], }; }
  • Core implementation in AaveClient: analyzes liquidation opportunity by fetching account data, reserves, prices, calculates risk level and potential profit considering liquidation bonus and close factor.
    async analyzeLiquidationOpportunity( userAddress: string ): Promise<LiquidationOpportunity | null> { const accountData = await this.getUserAccountData(userAddress); // Only return if liquidatable or at risk if (!accountData.isLiquidatable && !accountData.isAtRisk) { return null; } const { collateral, debt } = await this.getUserReserves(userAddress); // Calculate risk level const hf = parseFloat(accountData.healthFactorFormatted); let riskLevel: 'HIGH' | 'MEDIUM' | 'LOW'; if (hf < LIQUIDATION_THRESHOLD) { riskLevel = 'HIGH'; } else if (hf < 1.02) { riskLevel = 'MEDIUM'; } else { // 1.02 <= hf < WARNING_THRESHOLD (1.05) riskLevel = 'LOW'; } // Format values in USD (base is already in USD with 8 decimals from oracle) const totalCollateralUSD = ethers.formatUnits(accountData.totalCollateralBase, 8); const totalDebtUSD = ethers.formatUnits(accountData.totalDebtBase, 8); const availableBorrowsUSD = ethers.formatUnits(accountData.availableBorrowsBase, 8); // Calculate potential profit with actual liquidation bonus let potentialProfit = '0'; if (accountData.isLiquidatable) { const debtValue = parseFloat(totalDebtUSD); // Close factor: can liquidate up to 50% of debt const maxDebtByCloseFactor = debtValue * 0.5; // Fetch prices for collateral assets to avoid overstating profit const priceMap = collateral.length ? await this.getAssetsPrices(collateral.map((c) => c.asset)) : new Map<string, string>(); let bestEstimatedProfit = 0; for (const c of collateral) { const priceStr = priceMap.get(c.asset); const price = priceStr ? parseFloat(priceStr) : 0; if (!price) { continue; } // Convert collateral balance to USD using token decimals and oracle price (8 decimals) const collateralAmount = parseFloat(ethers.formatUnits(c.currentATokenBalance, c.decimals)); const collateralValueUSD = collateralAmount * price; // liquidationBonus is in bps, e.g. 10500 => 5% bonus const bonusPercentage = Math.max(0, Number(c.liquidationBonus) - 10000) / 10000; if (bonusPercentage <= 0) { continue; } // Debt that can be covered by this collateral considering bonus const maxDebtByCollateral = collateralValueUSD / (1 + bonusPercentage); // Actual liquidatable debt for this collateral const liquidatableDebt = Math.min(maxDebtByCloseFactor, maxDebtByCollateral, debtValue); const estimatedProfit = liquidatableDebt * bonusPercentage; if (estimatedProfit > bestEstimatedProfit) { bestEstimatedProfit = estimatedProfit; } } potentialProfit = bestEstimatedProfit.toFixed(2); } return { userAddress, healthFactor: accountData.healthFactorFormatted, totalCollateralUSD, totalDebtUSD, availableBorrowsUSD, liquidationThreshold: parseFloat( ethers.formatUnits(accountData.currentLiquidationThreshold, 4) ), collateralAssets: collateral, debtAssets: debt, potentialProfit, riskLevel, gasWarning: 'Profit calculation does not include Gas costs. Actual profit will be lower.', }; }

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/clumsynonono/aave-liquidation-mcp'

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