explain_command
Understand what a CLI command does, its parameters, and potential risks before executing it.
Instructions
Explain what a perp CLI command does, its parameters, and any risks. Helps the user understand a command before running it
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | The CLI command to explain, e.g. 'perp trade market BTC buy 0.1' or 'perp arb scan' |
Implementation Reference
- src/mcp-server.ts:694-1050 (handler)The `explain_command` tool is defined in `src/mcp-server.ts` as part of the MCP server's tool registration. It takes a CLI command string, parses it, and provides an explanation of the command, its parameters, risks, and related commands.
server.tool( "explain_command", "Explain what a perp CLI command does, its parameters, and any risks. Helps the user understand a command before running it", { command: z.string().describe("The CLI command to explain, e.g. 'perp trade market BTC buy 0.1' or 'perp arb scan'"), }, async ({ command }) => { try { const parts = command.replace(/^perp\s+/, "").split(/\s+/); const flags: string[] = []; const args: string[] = []; for (const p of parts) { if (p.startsWith("-")) flags.push(p); else args.push(p); } const category = args[0] ?? ""; const sub = args[1] ?? ""; interface Explanation { command: string; description: string; parameters: { name: string; value?: string; description: string }[]; risks: string[]; category: "read" | "write" | "analysis"; relatedCommands: string[]; } let explanation: Explanation; if (category === "trade" && (sub === "market" || sub === "limit")) { const symbol = args[2] || "<symbol>"; const side = args[3] || "<side>"; const sizeOrPrice = args[4] || ""; const isLimit = sub === "limit"; explanation = { command, description: isLimit ? `Places a limit ${side} order for ${symbol}. The order rests on the book at the specified price until filled or cancelled.` : `Places a market ${side} order for ${symbol}. Executes immediately at the best available price.`, parameters: [ { name: "symbol", value: symbol, description: "Trading pair (e.g. BTC, ETH, SOL)" }, { name: "side", value: side, description: "buy = open/increase long, sell = open/increase short" }, ...(isLimit ? [ { name: "price", value: sizeOrPrice, description: "Limit price in USD" }, { name: "size", value: args[5] || "<size>", description: "Order size in base asset units" }, ] : [{ name: "size", value: sizeOrPrice, description: "Order size in base asset units" }]), ], risks: [ "This EXECUTES a real trade and uses real funds", isLimit ? "Limit orders may not fill if price doesn't reach the level" : "Market orders may experience slippage in low liquidity", "Use 'perp trade check' first for pre-flight validation", ], category: "write", relatedCommands: [ `perp trade check ${symbol} ${side} ${sizeOrPrice || "<size>"}`, `perp market book ${symbol}`, `perp account balance`, ], }; } else if (category === "trade" && sub === "close") { explanation = { command, description: `Closes the position for ${args[2] || "the specified symbol"} by placing a market order in the opposite direction.`, parameters: [{ name: "symbol", value: args[2] || "<symbol>", description: "Symbol of the position to close" }], risks: ["Executes a market order — subject to slippage", "Closes the entire position size"], category: "write", relatedCommands: ["perp account positions", "perp trade cancel-all"], }; } else if (category === "trade" && (sub === "cancel" || sub === "cancel-all")) { explanation = { command, description: sub === "cancel-all" ? "Cancels all open orders on the current exchange" : `Cancels a specific order by ID`, parameters: sub === "cancel-all" ? [] : [ { name: "symbol", value: args[2], description: "Trading pair of the order" }, { name: "orderId", value: args[3], description: "Order ID to cancel" }, ], risks: ["Open orders will be removed and won't execute"], category: "write", relatedCommands: ["perp account orders"], }; } else if (category === "trade" && sub === "stop") { explanation = { command, description: "Places a stop order that triggers when the mark price reaches the stop price", parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "side", value: args[3], description: "buy or sell" }, { name: "stopPrice", value: args[4], description: "Trigger price" }, { name: "size", value: args[5], description: "Order size" }, ], risks: ["Stop orders become market orders when triggered — slippage possible", "Stop may not fill in fast markets"], category: "write", relatedCommands: ["perp account positions", "perp trade tpsl"], }; } else if (category === "trade" && sub === "tpsl") { explanation = { command, description: "Sets take-profit and stop-loss bracket orders on a position. Both orders are reduce-only.", parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "side", value: args[3], description: "Position side (buy=long, sell=short)" }, { name: "--tp", description: "Take-profit price" }, { name: "--sl", description: "Stop-loss price" }, ], risks: ["Creates two orders that will execute automatically when price is reached"], category: "write", relatedCommands: ["perp account positions", "perp trade stop", "perp trade scale-tp"], }; } else if (category === "trade" && (sub === "scale-tp" || sub === "scale-in")) { const isTP = sub === "scale-tp"; explanation = { command, description: isTP ? "Places multiple take-profit orders at different price levels to gradually exit a position" : "Places multiple limit orders at different price levels to gradually build a position", parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, ...(!isTP ? [{ name: "side", value: args[3], description: "buy or sell" }] : []), { name: "--levels", description: isTP ? "Price:percent pairs, e.g. '50000:25%,52000:50%,55000:25%'" : "Price:size pairs, e.g. '48000:0.01,47000:0.02'" }, ], risks: isTP ? ["Places multiple reduce-only limit orders", "Total percentage should not exceed 100%"] : ["Places multiple limit orders — total size uses margin", "Review available balance before placing"], category: "write", relatedCommands: isTP ? ["perp account positions", "perp trade tpsl"] : ["perp account balance", "perp market book"], }; } else if (category === "trade" && sub === "twap") { explanation = { command, description: "Executes a large order in small slices over a time period (Time-Weighted Average Price) to minimize market impact", parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "side", value: args[3], description: "buy or sell" }, { name: "size", value: args[4], description: "Total order size" }, { name: "duration", value: args[5], description: "Duration (e.g. 30m, 1h, 2h)" }, ], risks: ["Executes real trades over time — total size will be filled", "Market may move during execution"], category: "write", relatedCommands: ["perp account balance", "perp trade cancel-twap"], }; } else if (category === "trade" && (sub === "trailing-stop" || sub === "pnl-track")) { explanation = { command, description: sub === "trailing-stop" ? "Sets a trailing stop that follows the price by a callback percentage. Triggers a market close when price reverses." : "Starts real-time PnL tracking for open positions with visual updates", parameters: [{ name: "symbol", value: args[2], description: "Trading pair" }], risks: sub === "trailing-stop" ? ["Will close position when trailing stop is triggered"] : [], category: sub === "trailing-stop" ? "write" : "read", relatedCommands: ["perp account positions", "perp trade stop"], }; } else if (category === "trade" && (sub === "reduce" || sub === "flatten" || sub === "close-all")) { explanation = { command, description: { reduce: `Reduces position by a percentage`, flatten: "Cancels all orders AND closes all positions at market", "close-all": "Closes all positions at market price" }[sub]!, parameters: sub === "reduce" ? [{ name: "symbol", value: args[2], description: "Trading pair" }, { name: "percent", value: args[3], description: "Percentage to reduce (1-100)" }] : [], risks: ["Executes market orders — subject to slippage"], category: "write", relatedCommands: ["perp account positions"], }; } else if (category === "trade" && (sub === "check" || sub === "fills" || sub === "status")) { explanation = { command, description: { check: "Pre-flight validation — checks if a trade would succeed without executing", fills: "Shows recent trade fills", status: "Checks the status of a specific order" }[sub]!, parameters: sub === "check" ? [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "side", value: args[3], description: "buy or sell" }, { name: "size", value: args[4], description: "Order size" }, ] : [], risks: [], category: "read", relatedCommands: ["perp trade market", "perp account orders"], }; } else if (category === "trade" && sub === "leverage") { explanation = { command, description: `Sets the leverage multiplier for ${args[2] || "a symbol"}`, parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "leverage", value: args[3], description: "Leverage multiplier (e.g. 5 for 5x)" }, ], risks: ["Higher leverage increases liquidation risk", "Changes apply to new and existing positions"], category: "write", relatedCommands: ["perp risk status", "perp account positions"], }; } else if (category === "trade" && sub === "edit") { explanation = { command, description: "Modifies the price and/or size of an existing open order", parameters: [ { name: "symbol", value: args[2], description: "Trading pair" }, { name: "orderId", value: args[3], description: "Order ID to modify" }, { name: "price", value: args[4], description: "New price" }, { name: "size", value: args[5], description: "New size" }, ], risks: ["Replaces the existing order — old order is cancelled"], category: "write", relatedCommands: ["perp account orders"], }; } else if (category === "market") { explanation = { command, description: { list: "Lists all available markets with price, funding rate, volume, and max leverage", book: `Shows the order book (bids/asks) for ${args[2] || "a symbol"}`, prices: "Shows mark prices across exchanges for comparison", funding: `Shows funding rate history for ${args[2] || "a symbol"}`, trades: `Shows recent trades for ${args[2] || "a symbol"}`, kline: `Shows OHLCV candle data for ${args[2] || "a symbol"}`, mid: `Shows the mid price for ${args[2] || "a symbol"} (fast)`, info: `Shows market details for ${args[2] || "a symbol"}: tick size, min order size, max leverage`, }[sub] || `Market data command: ${sub}`, parameters: args.slice(2).map((a, i) => ({ name: `arg${i}`, value: a, description: "See perp market --help" })), risks: [], category: "read", relatedCommands: ["perp market list", "perp market prices"], }; } else if (category === "account") { explanation = { command, description: { info: "Shows account balance: equity, available margin, margin used, unrealized PnL", balance: "Shows account balance details", positions: "Lists all open positions with size, entry price, mark price, PnL, leverage", orders: "Lists all pending/open orders", history: "Shows order history (filled, cancelled, etc.)", trades: "Shows trade execution history with prices and fees", "funding-history": "Shows funding payments received/paid", funding: "Shows funding payments received/paid (alias for funding-history)", "twap-orders": "Shows active TWAP orders", pnl: "Shows profit & loss summary", margin: `Shows margin info for ${args[2] || "a symbol"}`, settings: "Shows account settings (leverage, margin mode per symbol)", }[sub] || `Account data command: ${sub}`, parameters: [], risks: [], category: "read", relatedCommands: ["perp portfolio", "perp account balance"], }; } else if (category === "arb") { explanation = { command, description: { scan: "Scans for funding rate arbitrage opportunities. Use --rates for funding rates, --gaps for price gaps, --hip3 for cross-dex arb, --positions for funding impact, --basis for basis trading", auto: "Auto-execute funding rate arbitrage (runs as background job)", exec: "Execute an arb trade (enter paired positions on two exchanges)", status: "Shows current arb positions and P&L", close: "Closes an arb position on both exchanges", history: "Shows arb execution history", config: "View/edit arb configuration", rebalance: "Rebalance funds across exchanges for arb positions", }[sub] || `Arbitrage command: ${sub}`, parameters: [], risks: [sub === "auto" || sub === "exec" ? "Executes trades on exchanges" : ""].filter(Boolean), category: sub === "auto" || sub === "close" || sub === "exec" || sub === "rebalance" ? "write" : "analysis", relatedCommands: ["perp arb scan", "perp arb status", "perp arb scan --gaps"], }; } else if (category === "bridge") { explanation = { command, description: { chains: "Lists supported chains for cross-chain USDC bridging", quote: "Gets a bridge quote with estimated fees and time", send: "Executes a cross-chain USDC bridge transfer", exchange: "Bridges USDC between exchange accounts", status: "Checks the status of a bridge transfer", }[sub] || `Bridge command: ${sub}`, parameters: [], risks: sub === "send" || sub === "exchange" ? ["Transfers real funds cross-chain — verify addresses carefully"] : [], category: sub === "send" || sub === "exchange" ? "write" : "read", relatedCommands: ["perp bridge chains", "perp bridge quote"], }; } else if (category === "funds") { const sub = args[1]; // deposit or withdraw explanation = { command, description: sub === "deposit" ? `Deposits USDC into ${args[2] || "an exchange"} account` : sub === "withdraw" ? `Withdraws USDC from ${args[2] || "an exchange"} account` : "Funds management (deposit, withdraw, bridge, transfer)", parameters: [{ name: "amount", value: args[3] || args[2], description: "Amount in USDC" }], risks: ["Moves real funds — verify amount before executing"], category: "write", relatedCommands: ["perp wallet balance", "perp account balance"], }; } else if (category === "risk") { explanation = { command, description: { status: "Portfolio risk overview: margin utilization, exposure, concentration", limits: "Shows current position limits per symbol", check: "Pre-trade risk check for a hypothetical position" }[sub] || `Risk management: ${sub}`, parameters: [], risks: [], category: "read", relatedCommands: ["perp account positions", "perp portfolio"], }; } else if (category === "bot" || category === "run") { explanation = { command, description: `Automated strategy: ${sub}. Runs as a background job.`, parameters: args.slice(2).map((a, i) => ({ name: `arg${i}`, value: a, description: "See --help" })), risks: ["Runs automated trades — monitor with 'perp jobs list'", "Use --dry-run to simulate first"], category: "write", relatedCommands: ["perp jobs list", "perp jobs stop"], }; } else if (category === "history") { explanation = { command, description: { list: "Execution audit trail", stats: "Execution statistics", positions: "Position history", summary: "Trading performance summary", pnl: "P&L breakdown by symbol and time period", funding: "Funding payment history and totals", report: "Detailed performance report", snapshot: "Portfolio snapshot", track: "Track position over time", perf: "Performance breakdown (daily/weekly/summary)", prune: "Prune old execution records" }[sub] || `History: ${sub}`, parameters: [], risks: sub === "prune" ? ["Permanently removes old execution records"] : [], category: "read", relatedCommands: ["perp history summary", "perp history list"], }; } else if (category === "wallet") { explanation = { command, description: { show: "Show configured wallets with public addresses", list: "List configured wallets", balance: "Check on-chain USDC/SOL/ETH balances", generate: "Generate a new wallet keypair", import: "Import an existing private key", set: "Set private key for an exchange", use: "Set active wallet", remove: "Remove a wallet", rename: "Rename a wallet" }[sub] || `Wallet: ${sub}`, parameters: [], risks: sub === "generate" ? ["Store the private key securely — it cannot be recovered"] : sub === "remove" ? ["Wallet will be removed — ensure you have the private key backed up"] : [], category: "read", relatedCommands: ["perp wallet show", "perp wallet balance"], }; } else if (category === "backtest") { explanation = { command, description: { "funding-arb": "Backtest funding rate arbitrage strategy on historical data", grid: "Backtest grid trading strategy on historical data" }[sub] || `Backtest: ${sub}`, parameters: [], risks: [], category: "analysis", relatedCommands: ["perp backtest funding-arb", "perp backtest grid"], }; } else if (category === "settings") { explanation = { command, description: { show: "Display current CLI settings", referrals: "Toggle referral codes on/off (no extra fees, helps track volume)", set: "Set a specific setting value" }[sub] || `Settings: ${sub}`, parameters: [], risks: [], category: "read", relatedCommands: ["perp settings show"], }; } else { const writeCommands = new Set(["trade", "funds", "manage", "rebalance"]); explanation = { command, description: `CLI command: ${command}. Run 'perp ${category} --help' for detailed usage.`, parameters: args.slice(1).map((a, i) => ({ name: `arg${i}`, value: a, description: "See --help for details" })), risks: writeCommands.has(category) ? ["This command may modify account state — review carefully"] : [], category: writeCommands.has(category) ? "write" : "read", relatedCommands: ["perp agent capabilities", "perp schema"], }; } return { content: [{ type: "text", text: ok(explanation) }] }; } catch (e) { return { content: [{ type: "text", text: err(e instanceof Error ? e.message : String(e)) }], isError: true }; } }, );