Hydrex Plugin
[!IMPORTANT] Run Base MCP onboarding first (see SKILL.md). Obtain the user’s wallet address viaget_wallets— it is required asfromorrecipientin every prepare call. The Hydrex prepare server must be running locally before any write operations.
Overview
Hydrex is an Omni-Liquidity MetaDEX on Base — concentrated-liquidity swaps aggregated across 0x, OpenOcean, OKX, and KyberSwap, plus liquidity positions that earn fees and rewards automatically. Adding liquidity creates an active earning position immediately; there is no separate staking step. The plugin calls a local prepare server (https://hydrex-agent.com) to fetch unsigned calldata, then submits via send_calls on Base mainnet (chainId: 8453).
Surface Routing
The prepare server (
https://hydrex-agent.com) is not on the Base MCP web_request allowlist. On chat-only surfaces, construct the full GET URL with all query parameters and ask the user to open it in a browser, paste the JSON response into chat, then continue with send_calls.
Endpoints
Server URL:https://hydrex-agent.com
GET /health
Response:{ "ok": true, "service": "hydrex-base-skill-server", "chainId": 8453 }
GET /state/quote
Response:
amountOut (human-readable) and priceImpact to the user before executing. Warn and require confirmation if priceImpact > 5%.
GET /state/portfolio
GET /state/positions
positionId with /prepare/remove-liquidity.
GET /state/trade-history
GET /state/pools
Discovers Hydrex pools — including each pool’s contract address, token addresses, and decimals — from the Hydrex stats API. This is how the agent resolves apool address (and token0/token1/decimals0/decimals1) for /prepare/add-liquidity and /prepare/remove-liquidity when the user only gives a token pair.
Pass
tokenA + tokenB to find pools for a specific pair regardless of token order. With no token filters it returns every pool. Results are sorted by TVL (USD) descending, so pools[0] is the deepest pool for the pair.
Response:
pool address plus token0/token1 addresses and decimals — exactly the inputs /prepare/add-liquidity needs (use them directly, preserving the returned token0/token1 order). Handling:
count = 0— no pool exists for that pair; tell the user and do not call a prepare endpoint.count > 1— multiple pools/fee tiers; show the options (tvlUsd,fee,liquidityType) and let the user choose before proceeding.count = 1— use it; confirm with the user before any write.
GET /prepare/swap
Example:
transactions[] array length is not fixed. For an ERC-20 tokenIn, an approve-tokenIn step is prepended only when the wallet’s current allowance is too low — if allowance is already sufficient, just the swap step is returned. Native ETH swaps never include an approve step. Always pass every returned transaction to send_calls in order, rather than assuming a single call.
GET /prepare/add-liquidity
The range is set in exactly one of these mutually exclusive ways —
rangePreset, a custom priceLower+priceUpper, or fullRange. Sending more than one returns 400 (“Choose only one range option…”); sending only one of priceLower/priceUpper returns 400 (“A custom range requires both…”). If you send none, the server uses the common preset (±12.5%).
Response — three transactions, always in this order:
Price range selection
Choose one of three mutually exclusive ways to set the range (the server does the percentage→price math on-chain, so the agent only passes the choice):
If the user gives no preference, the server applies the
common preset (±12.5%). Always tell the user which range was used, e.g. “I’m using the common ±12.5% range around the current price — say the word for a tighter (narrow/tight), wider (wide), full, or custom range.”
GET /prepare/remove-liquidity
Response:
{ "ok": false, "error": "..." } on failure — surface the error field to the user and do not call send_calls.
Orchestration
Swap
Add liquidity (enter a position)
Remove liquidity (exit a position)
Submission
Target tool:send_calls
Map every transactions[] array from a prepare endpoint into send_calls:
calls array — Base MCP executes them atomically in one user approval. After send_calls returns, immediately call get_request_status(requestId) and poll until the status is success or failed. Do not ask the user to type or paste anything during polling. See approval-mode.md.
Example Prompts
“Swap 5 USDC for ETH on Hydrex”get_wallets→ wallet addressGET /state/quote?tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&tokenOut=0x4200000000000000000000000000000000000006&amount=5000000&recipient=<address>→ show amountOut, priceImpactGET /prepare/swap?tokenIn=0x833589...&tokenOut=0x420000...&amount=5&decimals=6&recipient=<address>&slippage=50send_calls(chain="base", calls=[swap tx])- Poll
get_request_status→ report outcome
get_wallets→ wallet addressGET /state/positions?address=<address>→ display each positionId, token pair, tick range, and liquidity
get_wallets→ wallet addressGET /state/positions?address=<address>→ existing position context (count may be 0 — fine for a first position)GET /state/pools?tokenA=USDC&tokenB=WETH→ pick the pool (if count > 1, let the user choose); read its pool/token0/token1/decimals. Range defaults to thecommonpreset (±12.5%) unless the user picks another; inform the user of the range usedGET /prepare/add-liquidity?from=<address>&pool=<pool>&token0=<USDC>&token1=<WETH>&decimals0=6&decimals1=18&amount0=100&amount1=0.04- Show returned
position(tickLower, tickUpper, amounts) to user send_calls(chain="base", calls=[approve-token0, approve-token1, mint])- Poll
get_request_status→ report outcome
get_wallets→ wallet addressweb_requestcannot reachhttps://hydrex-agent.com→ construct the full URL and ask the user to open it in a browser and paste the JSON response into chat- On receiving JSON,
send_calls(chain="base", calls from transactions[]) - Poll
get_request_status→ report outcome
Risks & Warnings
- Slippage — swap and liquidity operations fill at market price; actual output can differ from the quote. Default tolerance is 50 bps (0.5%). Always check
priceImpactbefore executing; ifpriceImpact > 5%, warn the user and wait for explicit confirmation. Never auto-raise slippage. - Irreversible — onchain transactions cannot be undone once approved. Always show the user the full operation details (amounts, price range for LP positions, positionId for removals) and confirm before calling
send_calls.
Notes
Well-known token addresses (Base mainnet)
For other tokens, look up the address (and decimals) via
GET /state/pools (returns token0/token1 with address, symbol, and decimals), or ask the user to supply the contract address.
Error handling
Liquidity notes
- Adding liquidity creates a concentrated liquidity position that earns fees and rewards automatically — no separate staking step is required.
- Removing liquidity fully exits the position and returns both tokens to the wallet.
- The
positionIdis the NFT tokenId from the NonfungiblePositionManager; always fetch current positions via/state/positionsbefore a remove.