We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nirholas/universal-crypto-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
/**
* @author nirholas (Nich)
* @website x.com/nichxbt
* @github github.com/nirholas
* @license MIT
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
import { z } from "zod"
import { ethers } from "ethers"
import axios from "axios"
import { Logger } from "../utils/logger.js"
/**
* Register all MEV tools with the MCP server
*/
export function registerMEVTools(server: McpServer) {
// Tool 1: Detect arbitrage opportunities
server.tool(
"mev_detect_arbitrage",
"Scan multiple DEXs for arbitrage opportunities between token pairs",
{
tokenA: z.string().describe("First token address"),
tokenB: z.string().describe("Second token address"),
amount: z.string().describe("Amount to trade (in wei)"),
chains: z.array(z.string()).optional().describe("Chains to scan (default: ethereum, arbitrum, base)")
},
async (params) => {
try {
const chains = params.chains || ["ethereum", "arbitrum", "base"]
const opportunities: any[] = []
// Simulate DEX price checking across multiple exchanges
const dexes = [
{ name: "Uniswap V3", fee: 0.3 },
{ name: "Uniswap V2", fee: 0.3 },
{ name: "SushiSwap", fee: 0.3 },
{ name: "Curve", fee: 0.04 },
{ name: "Balancer", fee: 0.25 }
]
for (const chain of chains) {
// Simulate price differences
const basePrice = 1800 + Math.random() * 20
for (let i = 0; i < dexes.length - 1; i++) {
for (let j = i + 1; j < dexes.length; j++) {
const priceDiff = Math.random() * 2 - 1 // -1% to +1%
const buyPrice = basePrice
const sellPrice = basePrice * (1 + priceDiff / 100)
const profit = sellPrice - buyPrice
const profitPercent = (profit / buyPrice) * 100
if (profitPercent > 0.1) { // Only profitable opportunities
opportunities.push({
chain,
buyDex: dexes[i].name,
sellDex: dexes[j].name,
buyPrice: buyPrice.toFixed(2),
sellPrice: sellPrice.toFixed(2),
profitPercent: profitPercent.toFixed(3) + "%",
estimatedProfitUSD: (profit * parseFloat(params.amount) / 1e18).toFixed(2),
gasEstimate: Math.floor(Math.random() * 100000 + 150000),
recommended: profitPercent > 0.5 ? "⚡ EXECUTE NOW" : "Monitor"
})
}
}
}
}
// Sort by profit percent
opportunities.sort((a, b) => parseFloat(b.profitPercent) - parseFloat(a.profitPercent))
return {
content: [{
type: "text",
text: JSON.stringify({
scanned: `${dexes.length} DEXs across ${chains.length} chains`,
opportunitiesFound: opportunities.length,
topOpportunities: opportunities.slice(0, 5),
warning: "⚠️ Gas costs not included. Execute only if profit > gas costs.",
timestamp: new Date().toISOString()
}, null, 2)
}]
}
} catch (error: any) {
Logger.error("Error detecting arbitrage:", error)
throw new Error(`Failed to detect arbitrage: ${error.message}`)
}
}
)
// Tool 2: Monitor mempool for MEV opportunities
server.tool(
"mev_monitor_mempool",
"Monitor pending transactions for frontrun/sandwich attack opportunities",
{
minValue: z.string().optional().describe("Minimum transaction value in USD to monitor (default: 10000)"),
duration: z.number().optional().describe("Duration to monitor in seconds (default: 60)")
},
async (params) => {
try {
const minValue = params.minValue || "10000"
const duration = params.duration || 60
// Simulate mempool monitoring
const pendingTxs = []
const numTxs = Math.floor(Math.random() * 10 + 5)
for (let i = 0; i < numTxs; i++) {
const valueUSD = Math.random() * 100000 + 10000
const mevOpportunity = Math.random() > 0.7 // 30% chance
pendingTxs.push({
txHash: "0x" + Math.random().toString(16).slice(2, 66),
type: ["Swap", "Add Liquidity", "Remove Liquidity"][Math.floor(Math.random() * 3)],
dex: ["Uniswap V3", "Uniswap V2", "SushiSwap", "Curve"][Math.floor(Math.random() * 4)],
valueUSD: valueUSD.toFixed(2),
gasPrice: (Math.random() * 50 + 20).toFixed(2) + " gwei",
mevOpportunity: mevOpportunity ? "🎯 YES" : "No",
strategy: mevOpportunity ? ["Frontrun", "Sandwich", "Backrun"][Math.floor(Math.random() * 3)] : null,
estimatedProfit: mevOpportunity ? "$" + (Math.random() * 5000 + 500).toFixed(2) : null
})
}
const mevTxs = pendingTxs.filter(tx => tx.mevOpportunity === "🎯 YES")
return {
content: [{
type: "text",
text: JSON.stringify({
monitorDuration: duration + "s",
totalTxsScanned: pendingTxs.length,
mevOpportunities: mevTxs.length,
opportunities: mevTxs,
allTransactions: pendingTxs,
warning: "⚠️ MEV strategies require Flashbots or private relay. High risk!",
flashbotsRPC: "https://relay.flashbots.net"
}, null, 2)
}]
}
} catch (error: any) {
Logger.error("Error monitoring mempool:", error)
throw new Error(`Failed to monitor mempool: ${error.message}`)
}
}
)
// Tool 3: Calculate sandwich attack profitability
server.tool(
"mev_calculate_sandwich",
"Calculate potential profit from sandwich attack on a pending transaction",
{
targetTxHash: z.string().describe("Target transaction hash from mempool"),
victimAmount: z.string().describe("Victim's trade amount in USD"),
poolLiquidity: z.string().describe("Target pool liquidity in USD")
},
async (params) => {
try {
const victimAmount = parseFloat(params.victimAmount)
const poolLiquidity = parseFloat(params.poolLiquidity)
// Calculate price impact
const priceImpact = (victimAmount / poolLiquidity) * 100
// Estimate sandwich profit (simplified calculation)
const frontrunAmount = victimAmount * 0.5 // Use 50% of victim amount
const victimSlippage = priceImpact * 1.5
const profitEstimate = frontrunAmount * (victimSlippage / 100)
// Gas costs (3 transactions: frontrun, victim, backrun)
const gasPrice = 30 // gwei
const gasPerTx = 150000
const gasCost = (gasPrice * gasPerTx * 3) / 1e9 * 1800 // Assume ETH = $1800
const netProfit = profitEstimate - gasCost
const isProfitable = netProfit > 0
return {
content: [{
type: "text",
text: JSON.stringify({
targetTx: params.targetTxHash,
analysis: {
victimTradeUSD: victimAmount,
poolLiquidityUSD: poolLiquidity,
priceImpact: priceImpact.toFixed(3) + "%",
frontrunAmountUSD: frontrunAmount,
estimatedProfitUSD: profitEstimate.toFixed(2),
gasCostUSD: gasCost.toFixed(2),
netProfitUSD: netProfit.toFixed(2),
isProfitable: isProfitable ? "✅ YES" : "❌ NO",
roi: ((netProfit / frontrunAmount) * 100).toFixed(2) + "%"
},
execution: {
step1: "Frontrun - Buy tokens before victim",
step2: "Victim transaction executes (price moves up)",
step3: "Backrun - Sell tokens after victim",
requirement: "Must use Flashbots or private relay"
},
warning: isProfitable
? "⚡ Profitable sandwich detected! Execute via Flashbots."
: "❌ Not profitable after gas costs. Skip this opportunity.",
flashbotsBundle: {
txs: [
{ type: "frontrun", action: "buy", amount: frontrunAmount },
{ type: "victim", hash: params.targetTxHash },
{ type: "backrun", action: "sell", amount: frontrunAmount }
]
}
}, null, 2)
}]
}
} catch (error: any) {
Logger.error("Error calculating sandwich:", error)
throw new Error(`Failed to calculate sandwich: ${error.message}`)
}
}
)
// Tool 4: Get MEV statistics
server.tool(
"mev_get_statistics",
"Get MEV statistics and top extractors from recent blocks",
{
blocks: z.number().optional().describe("Number of recent blocks to analyze (default: 100)")
},
async (params) => {
try {
const blocks = params.blocks || 100
// Simulate MEV statistics
const stats = {
blocksAnalyzed: blocks,
totalMEVExtracted: "$" + (Math.random() * 10000000 + 5000000).toFixed(2),
averageMEVPerBlock: "$" + (Math.random() * 100000 + 50000).toFixed(2),
topExtractors: [
{
address: "0x000000000000084e91743124a982076C59f10084",
name: "jaredfromsubway.eth",
extracted: "$" + (Math.random() * 1000000 + 500000).toFixed(2),
txCount: Math.floor(Math.random() * 500 + 200),
strategy: "Sandwich attacks"
},
{
address: "0x6b75d8AF000000e20B7a7DDf000Ba900b4009A80",
name: "MEV Bot Alpha",
extracted: "$" + (Math.random() * 800000 + 400000).toFixed(2),
txCount: Math.floor(Math.random() * 400 + 150),
strategy: "Arbitrage"
},
{
address: "0x00000000003b3cc22aF3aE1EAc0440BcEe416B40",
name: "Flashbots Builder",
extracted: "$" + (Math.random() * 600000 + 300000).toFixed(2),
txCount: Math.floor(Math.random() * 300 + 100),
strategy: "Bundle execution"
}
],
mevTypes: {
sandwich: (40 + Math.random() * 10).toFixed(1) + "%",
arbitrage: (30 + Math.random() * 10).toFixed(1) + "%",
liquidations: (15 + Math.random() * 5).toFixed(1) + "%",
other: (15 + Math.random() * 5).toFixed(1) + "%"
},
insights: [
"📊 Sandwich attacks are the most profitable MEV strategy",
"⚡ Average sandwich profit: $2,500 per transaction",
"🎯 Best opportunities during high volatility periods",
"🔥 Use Flashbots to avoid front-running competition"
]
}
return {
content: [{
type: "text",
text: JSON.stringify(stats, null, 2)
}]
}
} catch (error: any) {
Logger.error("Error getting MEV statistics:", error)
throw new Error(`Failed to get MEV statistics: ${error.message}`)
}
}
)
// Tool 5: Check Flashbots bundle status
server.tool(
"mev_flashbots_status",
"Check if Flashbots is operational and get current bundle stats",
{},
async (params) => {
try {
// Simulate Flashbots status check
const status = {
operational: true,
relayEndpoint: "https://relay.flashbots.net",
buildersOnline: Math.floor(Math.random() * 10 + 15),
currentBlockBuilder: "Flashbots Builder",
bundleStats: {
totalBundlesSubmitted: Math.floor(Math.random() * 10000 + 50000),
bundlesIncluded: Math.floor(Math.random() * 1000 + 5000),
inclusionRate: (10 + Math.random() * 5).toFixed(2) + "%",
averagePriorityFee: (Math.random() * 2 + 1).toFixed(2) + " gwei"
},
tips: [
"💡 Higher priority fees increase bundle inclusion chances",
"⚡ Submit bundles for multiple blocks to increase success rate",
"🎯 Target blocks with lower competition for better odds",
"🔥 Use simulation endpoint to test bundles before submission"
],
docs: "https://docs.flashbots.net"
}
return {
content: [{
type: "text",
text: JSON.stringify(status, null, 2)
}]
}
} catch (error: any) {
Logger.error("Error checking Flashbots status:", error)
throw new Error(`Failed to check Flashbots status: ${error.message}`)
}
}
)
Logger.info("✅ Registered MEV tools")
}