Uniswap/PancakeSwap/Aerodrome LP pools and price ranges ranked by net APR after impermanent loss
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Optional if your client signs in with OAuth (it will open lpsignal.app for you); otherwise 'Bearer lps_…' (an LPSignal API key).
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Backtest a symmetric range of ±rangePct% around the price at the window's start (0 = full range) on a pool over the last `days` days: fee APR, impermanent loss, net APR, time in range, the ticks.
pool contract address (0x + 40 hex), or a Uniswap v4 pool id (0x + 64 hex)
half-width in percent; 0 = full range
default 7
Backtest a symmetric range of ±rangePct% around the price at the window's start (0 = full range) on a pool over the last `days` days: fee APR, impermanent loss, net APR, time in range, the ticks.
| Argument | Type | Description |
|---|---|---|
| days | integer | default 7 |
| chain* | string | |
| address* | string | pool contract address (0x + 40 hex), or a Uniswap v4 pool id (0x + 64 hex) |
| rangePct* | number | half-width in percent; 0 = full range |
{
"type": "object",
"required": [
"chain",
"address",
"rangePct"
],
"properties": {
"days": {
"type": "integer",
"maximum": 30,
"minimum": 1,
"description": "default 7"
},
"chain": {
"enum": [
"ethereum",
"bsc",
"base",
"arbitrum",
"optimism",
"polygon",
"robinhood"
],
"type": "string"
},
"address": {
"type": "string",
"description": "pool contract address (0x + 40 hex), or a Uniswap v4 pool id (0x + 64 hex)"
},
"rangePct": {
"type": "number",
"maximum": 50,
"minimum": 0,
"description": "half-width in percent; 0 = full range"
}
},
"additionalProperties": false
}Every listed pool of a token pair across chains, DEXes and fee tiers (TVL ≥ $10k), each with its best range by 7-day net APR, best first — a small pool can rank first, so weigh tvlUsd. Symbols are matched case-insensitively, in either order.
| Argument | Type | Description |
|---|---|---|
| chain | string | |
| tokenA* | string | e.g. USDC |
| tokenB* | string | e.g. WETH |
{
"type": "object",
"required": [
"tokenA",
"tokenB"
],
"properties": {
"chain": {
"enum": [
"ethereum",
"bsc",
"base",
"arbitrum",
"optimism",
"polygon",
"robinhood"
],
"type": "string"
},
"tokenA": {
"type": "string",
"description": "e.g. USDC"
},
"tokenB": {
"type": "string",
"description": "e.g. WETH"
}
},
"additionalProperties": false
}A pool's details and its backtest of every range it is evaluated on (fee APR, impermanent loss, net APR, time in range, the exact ticks) over 1 hour, 24 hours, 7 days and 30 days.
| Argument | Type | Description |
|---|---|---|
| chain* | string | |
| address* | string | pool contract address (0x + 40 hex), or a Uniswap v4 pool id (0x + 64 hex) |
{
"type": "object",
"required": [
"chain",
"address"
],
"properties": {
"chain": {
"enum": [
"ethereum",
"bsc",
"base",
"arbitrum",
"optimism",
"polygon",
"robinhood"
],
"type": "string"
},
"address": {
"type": "string",
"description": "pool contract address (0x + 40 hex), or a Uniswap v4 pool id (0x + 64 hex)"
}
},
"additionalProperties": false
}Active pools ranked by the net APR (fees − impermanent loss) of their best price range over a window (default 7 days), with that range's ticks, TVL, 24h volume and the pool-level fee APR DEX sites show. Filter by chain and pool class.
| Argument | Type | Description |
|---|---|---|
| sort | string | default netApr |
| chain | string | |
| class | string | stable = stablecoin pairs, correlated = e.g. ETH/stETH, volatile = everything else |
| limit | integer | default 10 |
| order | string | |
| offset | integer | |
| window | integer | backtest window in hours (default 168 = 7 days) |
| minTvlUsd | number | default 10000 |
{
"type": "object",
"required": [],
"properties": {
"sort": {
"enum": [
"netApr",
"feeApr",
"ilApr",
"inRange",
"tvl",
"volume24h",
"fees24h",
"poolApr"
],
"type": "string",
"description": "default netApr"
},
"chain": {
"enum": [
"ethereum",
"bsc",
"base",
"arbitrum",
"optimism",
"polygon",
"robinhood"
],
"type": "string"
},
"class": {
"enum": [
"stable",
"correlated",
"volatile"
],
"type": "string",
"description": "stable = stablecoin pairs, correlated = e.g. ETH/stETH, volatile = everything else"
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "default 10"
},
"order": {
"enum": [
"asc",
"desc"
],
"type": "string"
},
"offset": {
"type": "integer",
"minimum": 0
},
"window": {
"enum": [
1,
24,
168,
720
],
"type": "integer",
"description": "backtest window in hours (default 168 = 7 days)"
},
"minTvlUsd": {
"type": "number",
"description": "default 10000"
}
},
"additionalProperties": false
}The newest signals: opportunities (net_apr: a range paying a high net APR over 7 days and still today; burst: the last hour; hot_pool: a big pool's fee APR jumping; launch: a new pool outside the whitelist with a 15-minute fee APR spike — high risk, data not advice) and risk alerts (depeg, tvl_outflow), with the exact ticks and, once scored, the realised outcome. Each says access: live, or delayed_24h (opportunities on a free plan or without sign-in appear 24 hours after they fired). Page back with before.
| Argument | Type | Description |
|---|---|---|
| kinds | array | |
| limit | integer | default 10 |
| before | string | page: signals with an id below this |
| source | string | with a key: rules = your custom-rule matches, subscribed = what your push channels deliver |
{
"type": "object",
"required": [],
"properties": {
"kinds": {
"type": "array",
"items": {
"enum": [
"net_apr",
"burst",
"hot_pool",
"launch",
"tvl_outflow",
"depeg",
"smart_lp"
],
"type": "string"
}
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "default 10"
},
"before": {
"type": "string",
"description": "page: signals with an id below this"
},
"source": {
"enum": [
"default",
"rules",
"subscribed"
],
"type": "string",
"description": "with a key: rules = your custom-rule matches, subscribed = what your push channels deliver"
}
},
"additionalProperties": false
}How past opportunity signals really did: each is backtested again on its exact ticks after the fact (7 days for net_apr, 24 hours for burst). Counts, share positive, median APR at the signal vs realised, the worst.
| Argument | Type | Description |
|---|---|---|
| days | integer | signals fired in the last N days (default 30) |
| kind | string | default net_apr |
{
"type": "object",
"required": [],
"properties": {
"days": {
"type": "integer",
"maximum": 365,
"minimum": 7,
"description": "signals fired in the last N days (default 30)"
},
"kind": {
"enum": [
"net_apr",
"burst"
],
"type": "string",
"description": "default net_apr"
}
},
"additionalProperties": false
}Wallets ranked by what their closed LP positions made versus simply holding the tokens. Without a Pro key: the top 10, addresses masked.
| Argument | Type | Description |
|---|---|---|
| chain | string | |
| limit | integer | default 10 |
| windowDays | integer |
{
"type": "object",
"required": [],
"properties": {
"chain": {
"enum": [
"ethereum",
"bsc",
"base",
"arbitrum",
"optimism",
"polygon",
"robinhood"
],
"type": "string"
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "default 10"
},
"windowDays": {
"enum": [
30,
90
],
"type": "integer"
}
},
"additionalProperties": false
}