pancakeAddLiquidity
Enable liquidity provision on PancakeSwap by specifying token pairs and amounts through the BSC MCP Server for secure and structured Binance Smart Chain transactions.
Instructions
add liquidity to pancake
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| token0 | Yes | ||
| token0Amount | Yes | ||
| token1 | Yes | ||
| token1Amount | Yes |
Implementation Reference
- src/tools/pancakeAddLiquidity.ts:24-72 (handler)MCP tool handler logic for 'Add_PancakeSwap_Liquidity': fetches tokens and account, prepares CurrencyAmounts, calls addLiquidityV3, handles success/error with transaction URL.async ({ token0, token1, token0Amount, token1Amount }) => { let txHash = undefined; try { // Define tokens const tokenA = await getToken(token0); const tokenB = await getToken(token1); // Amounts to add const amountTokenA = CurrencyAmount.fromRawAmount(tokenA, parseUnits(token0Amount, tokenA.decimals).toString()); const amountTokenB = CurrencyAmount.fromRawAmount(tokenB, parseUnits(token1Amount, tokenB.decimals).toString()); const account = await getAccount(); txHash = await addLiquidityV3( tokenA, tokenB, FeeAmount.MEDIUM, // 0.3% amountTokenA, amountTokenB, account, ); const txUrl = await checkTransactionHash(txHash) return { content: [ { type: "text", text: `add liquidity to pancake successfully. ${txUrl}`, url: txUrl, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); const txUrl = buildTxUrl(txHash); return { content: [ { type: "text", text: `transaction failed: ${errorMessage}`, url: txUrl, }, ], isError: true, }; }
- Zod input schema defining the parameters for the pancakeAddLiquidity tool: token addresses and amounts as strings.token0: z.string(), token1: z.string(), token0Amount: z.string(), token1Amount: z.string(), },
- src/tools/pancakeAddLiquidity.ts:16-75 (registration)Registration function for the pancakeAddLiquidity tool, called from main.ts, which sets up the tool name, description, schema, and handler on the McpServer.export function registerPancakeAddLiquidity(server: McpServer) { server.tool("Add_PancakeSwap_Liquidity", "💧Provide liquidity to PancakeSwap trading pairs", { token0: z.string(), token1: z.string(), token0Amount: z.string(), token1Amount: z.string(), }, async ({ token0, token1, token0Amount, token1Amount }) => { let txHash = undefined; try { // Define tokens const tokenA = await getToken(token0); const tokenB = await getToken(token1); // Amounts to add const amountTokenA = CurrencyAmount.fromRawAmount(tokenA, parseUnits(token0Amount, tokenA.decimals).toString()); const amountTokenB = CurrencyAmount.fromRawAmount(tokenB, parseUnits(token1Amount, tokenB.decimals).toString()); const account = await getAccount(); txHash = await addLiquidityV3( tokenA, tokenB, FeeAmount.MEDIUM, // 0.3% amountTokenA, amountTokenB, account, ); const txUrl = await checkTransactionHash(txHash) return { content: [ { type: "text", text: `add liquidity to pancake successfully. ${txUrl}`, url: txUrl, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); const txUrl = buildTxUrl(txHash); return { content: [ { type: "text", text: `transaction failed: ${errorMessage}`, url: txUrl, }, ], isError: true, }; } } ); }
- Core helper function addLiquidityV3 that executes the V3 liquidity provision: approves tokens, checks balances, sorts tokens, retrieves pool, computes ticks and position, mints LP position.export async function addLiquidityV3( tokenA: Currency, tokenB: Currency, fee: FeeAmount, amountA: CurrencyAmount<Currency>, amountB: CurrencyAmount<Currency>, account: PrivateKeyAccount, slippageTolerance: Percent = new Percent('50', '10000'), // default 0.5% deadline: number = Math.floor(Date.now() / 1000) + 20 * 60, // default 20 minutes priceLower: number = 0.8, priceUpper: number = 1.2 ): Promise<Hex> { await Promise.all([ approveTokensIfNeeded(account, tokenA, POSITION_MANAGER_ADDRESS, amountA.quotient.toString()), approveTokensIfNeeded(account, tokenB, POSITION_MANAGER_ADDRESS, amountB.quotient.toString()), ]); await checkBalance(account, tokenA, amountA) await checkBalance(account, tokenB, amountB) const [token0, token1, amount0, amount1] = sortTokens(tokenA, tokenB, amountA, amountB); const poolAddress = await publicClient.readContract({ address: FACTORY_ADDRESS, abi: FACTORY_ABI, functionName: 'getPool', args: [ token0.address as Address, token1.address as Address, fee ] }) as Address; if (!poolAddress || poolAddress === '0x0000000000000000000000000000000000000000') { throw new Error(`Pool for ${tokenA.symbol}/${tokenB.symbol} not found`); } const [liquidity, slot0] = await Promise.all([ publicClient.readContract({ address: poolAddress, abi: POOL_ABI, functionName: 'liquidity' }), publicClient.readContract({ address: poolAddress, abi: POOL_ABI, functionName: 'slot0' }) ]); const pool = new Pool( token0, token1, fee, (slot0 as any)[0].toString(), // sqrtPriceX96 liquidity.toString(), (slot0 as any)[1] // tick ); // Retrieve tickSpacing from the SDK constants const tickSpacing = TICK_SPACINGS[fee]; // fee should correspond to a valid // Convert prices to square root ratio and then to ticks const priceLowerRatio = encodeSqrtRatioX96(priceLower * 1e18, 1e18); const priceUpperRatio = encodeSqrtRatioX96(priceUpper * 1e18, 1e18); const lowerPriceTick = TickMath.getTickAtSqrtRatio(priceLowerRatio); const upperPriceTick = TickMath.getTickAtSqrtRatio(priceUpperRatio); // Round ticks to the nearest valid tick const tickLower = nearestUsableTick(lowerPriceTick, tickSpacing); const tickUpper = nearestUsableTick(upperPriceTick, tickSpacing); const position = Position.fromAmounts({ pool, tickLower, tickUpper, amount0: amount0.quotient.toString(), amount1: amount1.quotient.toString(), useFullPrecision: true }); const { amount0: amount0Min, amount1: amount1Min } = position.mintAmountsWithSlippage(slippageTolerance); const value = tokenA.isNative ? amountA.quotient.toString() : tokenB.isNative ? amountB.quotient.toString() : '0'; const mintParams = { token0: token0.address as Address, token1: token1.address as Address, fee, tickLower, tickUpper, amount0Desired: BigInt(amount0.quotient.toString()), amount1Desired: BigInt(amount1.quotient.toString()), amount0Min: BigInt(amount0Min.toString()), amount1Min: BigInt(amount1Min.toString()), recipient: account.address, deadline: BigInt(deadline) }; const hash = await walletClient(account).writeContract({ address: POSITION_MANAGER_ADDRESS, abi: POSITION_MANAGER_ABI, functionName: 'mint', args: [mintParams], value: BigInt(value), account: account }); return hash; }
- src/main.ts:33-33 (registration)Top-level call to register the pancakeAddLiquidity tool in the main server setup.registerPancakeAddLiquidity(server);
- src/main.ts:13-13 (registration)Import of the registerPancakeAddLiquidity function.import { registerPancakeAddLiquidity } from "./tools/pancakeAddLiquidity.js";