read.strategy.list
Retrieve a paginated list of Arcadia liquidity pool strategies with 7-day average APY for each default range. Use featured_only for curated top strategies and pagination parameters to control results.
Instructions
Get Arcadia LP strategies. Use featured_only=true for curated top strategies (recommended first call). Returns a paginated list with 7d avg APY for each strategy's default range. Increase limit or use offset for pagination. All APY values are decimal fractions (1.0 = 100%, 0.05 = 5%). For full detail on a specific strategy (APY per range width), use read.strategy.info.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| featured_only | No | Return only featured/curated strategies (recommended) | |
| limit | No | Max strategies to return (default 25) | |
| offset | No | Skip first N strategies for pagination | |
| chain_id | No | Chain ID: 8453 (Base), 130 (Unichain), or 10 (Optimism) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| total | Yes | ||
| offset | Yes | ||
| limit | Yes | ||
| strategies | Yes | ||
| context_notes | No |
Implementation Reference
- src/tools/read/strategy.ts:11-34 (registration)The tool 'read.strategy.list' is registered via `server.registerTool()` inside `registerStrategyTools()` with annotations, inputSchema, and outputSchema.
export function registerStrategyTools(server: McpServer, api: ArcadiaApiClient) { server.registerTool( "read.strategy.list", { annotations: { title: "Get Strategies", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, description: "Get Arcadia LP strategies. Use featured_only=true for curated top strategies (recommended first call). Returns a paginated list with 7d avg APY for each strategy's default range. Increase limit or use offset for pagination. All APY values are decimal fractions (1.0 = 100%, 0.05 = 5%). For full detail on a specific strategy (APY per range width), use read.strategy.info.", inputSchema: { featured_only: z .boolean() .default(false) .describe("Return only featured/curated strategies (recommended)"), limit: z.number().default(25).describe("Max strategies to return (default 25)"), offset: z.number().default(0).describe("Skip first N strategies for pagination"), chain_id: z.number().default(8453).describe(CHAIN_ID_DESCRIPTION), }, outputSchema: StrategyListOutput, }, - src/tools/read/strategy.ts:35-121 (handler)The handler function for 'read.strategy.list'. When `featured_only` is true, calls `api.getFeatured(chain_id)` and filters by chain; otherwise calls `api.getStrategies(chain_id)` and returns a paginated list with strategy_id, name, strategy_apy_7d, tvl, underlyings, max_leverage.
async ({ featured_only, limit, offset, chain_id }) => { try { let strategies: Record<string, unknown>[]; let total: number; if (featured_only) { const raw = await api.getFeatured(chain_id); const all = Array.isArray(raw) ? (raw as Record<string, unknown>[]) : []; // The /featured endpoint currently returns curated Base strategies regardless of // chain_id. Filter by the chain baked into each strategy's url (`/farm/<chainId>/…`) // so we never hand back strategies that belong to a different chain. const urlChainRe = /\/farm\/(\d+)\//; strategies = all.filter((s) => { const url = s.url as string | undefined; if (!url) return true; const match = url.match(urlChainRe); if (!match) return true; return Number(match[1]) === chain_id; }); total = strategies.length; const result: Record<string, unknown> = { total, offset: 0, limit: total, strategies, }; if (total === 0 && all.length > 0) { result.context_notes = [ `Featured strategies are not curated for chain ${chain_id} yet. Backend returned ${all.length} Base strategies; filtered out. Use featured_only=false to list all strategies on this chain.`, ]; } return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], structuredContent: result, }; } const all = await api.getStrategies(chain_id); const list = Array.isArray(all) ? all : (all as Record<string, unknown>).data; if (Array.isArray(list)) { total = list.length; const effectiveOffset = offset ?? 0; const effectiveLimit = limit ?? 25; const page = (list as Record<string, unknown>[]).slice( effectiveOffset, effectiveOffset + effectiveLimit, ); strategies = page.map((s) => ({ strategy_id: s.strategy_id, name: s.strategy_name, strategy_apy_7d: s.strategy_apy, tvl: s.tvl, underlyings: (s.underlyings as Record<string, unknown>[] | undefined)?.map((u) => ({ address: u.underlying_address, symbol: u.underlying_symbol, })), max_leverage: s.max_leverage, })); const result = { total, offset: effectiveOffset, limit: effectiveLimit, strategies, }; return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], structuredContent: result, }; } const fallback = { total: 0, offset: 0, limit, strategies: [] }; return { content: [{ type: "text" as const, text: JSON.stringify(fallback, null, 2) }], structuredContent: fallback, }; } catch (err) { return { content: [ { type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, ); - src/tools/output-schemas.ts:137-143 (schema)StrategyListOutput Zod schema defining the output shape: total, offset, limit, strategies (array of unknown records), and optional context_notes.
export const StrategyListOutput = z.object({ total: z.number(), offset: z.number(), limit: z.number(), strategies: z.array(z.record(z.unknown())), context_notes: z.array(z.string()).optional(), }); - src/tools/index.ts:34-79 (registration)`registerStrategyTools(server, api)` is called from `registerAllTools()` at line 43, which is the entry point where the tool registration is wired in.
export function registerAllTools( server: McpServer, api: ArcadiaApiClient, chains: Record<ChainId, ChainConfig>, ) { // Read tools registerAccountTools(server, api, chains); registerPoolTools(server, api); registerAssetTools(server, api); registerStrategyTools(server, api); registerPointsTools(server, api); registerGuideTools(server); registerWalletTools(server, chains, api); registerAssetManagerTools(server); // Write tools — account registerCreateTool(server, chains); registerDepositTool(server, chains); registerWithdrawTool(server, chains); registerBorrowTool(server, chains, api); registerRepayTool(server, chains); registerAddLiquidityTool(server, api, chains); registerRemoveLiquidityTool(server, api); registerSwapTool(server, api); registerDeleverageTool(server, api); registerStakeTool(server, api); registerCloseTool(server, api, chains); // Write tools — wallet registerApproveTool(server, chains); // Write tools — pool (lending tranches, ERC-4626) registerPoolDepositTool(server, chains); registerPoolRedeemTool(server, chains); // Write tools — asset managers registerRebalancerTool(server, chains); registerCompounderTools(server, chains); registerYieldClaimerTools(server, chains); registerCowSwapperTool(server, chains); registerMerklOperatorTool(server, chains); registerSetAssetManagersTool(server, chains); // Dev tools registerSendTool(server, chains); } - src/clients/api.ts:168-180 (helper)The `api.getFeatured()` and `api.getStrategies()` methods on the ArcadiaApiClient that the handler calls to fetch data from the backend.
// ── Strategies ─────────────────────────────────────────────────── async getStrategies(chainId: number) { return this.get<ApiListResponse>("/strategies", { chain_id: chainId }); } async getStrategyInfo(chainId: number, strategyId: number) { return this.get(`/strategies/${strategyId}/info`, { chain_id: chainId }); } async getFeatured(chainId: number) { return this.get<ApiListResponse>("/featured", { chain_id: chainId }); }