pancakeRemovePosition
Withdraw liquidity from PancakeSwap positions using the BSC MCP Server. Specify the position ID and percentage to remove, ensuring precise control over your DeFi transactions on Binance Smart Chain.
Instructions
remove liquidity position on panceke
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| percent | Yes | ||
| positionId | Yes |
Implementation Reference
- src/tools/pancakeRemovePosition.ts:14-47 (handler)MCP tool handler: executes remove liquidity by calling removeLiquidityV3, handles success/error with transaction URL
async ({ positionId, percent }) => { let txHash = undefined; try { const account = await getAccount(); txHash = await removeLiquidityV3(account, BigInt(positionId), percent); const txUrl = await checkTransactionHash(txHash) return { content: [ { type: "text", text: `remove liquidity position on panceke 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, }; } } - Input schema for the tool: positionId (string), percent (number between 1 and 100)
positionId: z.string(), percent: z.number().max(100).min(1), }, - src/tools/pancakeRemovePosition.ts:8-49 (registration)Registration function that defines and registers the 'Remove_PancakeSwap_Liquidity' tool on the MCP server
export function registerPancakeRemovePosition(server: McpServer) { server.tool("Remove_PancakeSwap_Liquidity", "🔄Withdraw your liquidity from PancakeSwap pools", { positionId: z.string(), percent: z.number().max(100).min(1), }, async ({ positionId, percent }) => { let txHash = undefined; try { const account = await getAccount(); txHash = await removeLiquidityV3(account, BigInt(positionId), percent); const txUrl = await checkTransactionHash(txHash) return { content: [ { type: "text", text: `remove liquidity position on panceke 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, }; } } ); } - src/main.ts:35-35 (registration)Site-wide registration of the pancakeRemovePosition tool in the main server setup
registerPancakeRemovePosition(server); - Core helper function implementing the V3 liquidity removal logic via multicall to PositionManager
export const removeLiquidityV3 = async (account: PrivateKeyAccount, tokenId: BigInt, percent: number) => { const calldatas: Hex[] = [] const client = walletClient(account).extend(publicActions) const positionInfo = await publicClient.readContract({ address: POSITION_MANAGER_ADDRESS, abi: positionManagerABI, functionName: 'positions', args: [tokenId] }) as any[] const bnb = Native.onChain(ChainId.BSC) const liquidity: bigint = new Percent(percent!, 100).multiply(positionInfo[7]).quotient // remove liquidity calldatas.push(encodeFunctionData({ abi: positionManagerABI, functionName: 'decreaseLiquidity', args: [ { tokenId, liquidity, amount0Min: BigInt(1), amount1Min: BigInt(1), deadline: Math.floor(Date.now() / 1000) + 1200, }, ], })) const involvesETH = getAddress(bnb.wrapped.address) === getAddress(positionInfo[2]) || getAddress(bnb.wrapped.address) === getAddress(positionInfo[3]) calldatas.push(encodeFunctionData({ abi: positionManagerABI, functionName: 'collect', args: [ { tokenId, recipient: involvesETH ? zeroAddress : account.address, amount0Max: maxUint128, amount1Max: maxUint128, }, ], })) if (involvesETH) { const poolAddrs = await client.readContract({ address: FACTORY_ADDRESS, abi: FACTORY_ABI, functionName: 'getPool', args: [ positionInfo[2] as Address, positionInfo[3] as Address, positionInfo[4] ] }) const slot0 = await client.readContract({ address: poolAddrs as Address, abi: POOL_ABI, functionName: 'slot0', }) const token0Amount = PositionMath.getToken0Amount( slot0[1], positionInfo[5], positionInfo[6], slot0[0], positionInfo[7], ) const discountedAmount0 = new Percent(percent!, 100).multiply(token0Amount).quotient const token1Amount = PositionMath.getToken1Amount( slot0[1], positionInfo[5], positionInfo[6], slot0[0], positionInfo[7], ) const discountedAmount1 = new Percent(percent!, 100).multiply(token1Amount).quotient const ethAmount = getAddress(bnb.wrapped.address) === getAddress(positionInfo[2]) ? discountedAmount0 : discountedAmount1 const token = getAddress(bnb.wrapped.address) === getAddress(positionInfo[2]) ? positionInfo[3] : positionInfo[2] const tokenAmount = getAddress(bnb.wrapped.address) === getAddress(positionInfo[2]) ? discountedAmount1 : discountedAmount0 calldatas.push(encodeFunctionData({ abi: Payments_ABI, functionName: 'unwrapWETH9', args: [ethAmount, account.address], })) calldatas.push(encodeFunctionData({ abi: Payments_ABI, functionName: 'sweepToken', args: [token, tokenAmount, account.address], })) } const data = Multicall.encodeMulticall(calldatas) const tx = await client.sendTransaction({ to: POSITION_MANAGER_ADDRESS, data: data, value: BigInt(0), account: account, chain: client.chain as any, }) return tx }