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 URLasync ({ 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 serverexport 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 setupregisterPancakeRemovePosition(server);
- Core helper function implementing the V3 liquidity removal logic via multicall to PositionManagerexport 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 }