search_vaults
Search and filter DeFi vaults by chain, protocol, asset, risk tier, TVL, and other criteria. Get paginated results with risk scores and APR data for due diligence.
Instructions
Search and filter DeFi vaults by chain, protocol, asset, risk tier, TVL, and more. Returns a paginated list with risk scores and APR.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Search by vault name, symbol, asset, protocol, or curator | |
| chain | No | Filter by chain name (e.g. Ethereum, Base, Arbitrum) | |
| protocol | No | Filter by protocol ID (e.g. morpho, aave-v3, yearn-v3) | |
| asset | No | Filter by asset symbol (e.g. USDC, WETH) | |
| riskTier | No | Filter by risk tier: Prime, Core, or Edge | |
| minTvl | No | Minimum TVL in USD | |
| sortBy | No | Sort field: tvl_usd, apr_net, name, last_synced_at | |
| sortOrder | No | Sort order: asc or desc | |
| limit | No | Max results (default 10, max 50) |
Implementation Reference
- src/tools/search-vaults.ts:6-60 (handler)Main implementation of search_vaults tool. Contains the registerSearchVaults function that defines the tool schema (lines 10-26) and the async handler (lines 27-58) which builds query parameters, calls the API, and formats the results for display.export function registerSearchVaults(server: McpServer) { server.tool( 'search_vaults', 'Search and filter DeFi vaults by chain, protocol, asset, risk tier, TVL, and more. Returns a paginated list with risk scores and APR.', { query: z .string() .optional() .describe('Search by vault name, symbol, asset, protocol, or curator'), chain: z.string().optional().describe('Filter by chain name (e.g. Ethereum, Base, Arbitrum)'), protocol: z .string() .optional() .describe('Filter by protocol ID (e.g. morpho, aave-v3, yearn-v3)'), asset: z.string().optional().describe('Filter by asset symbol (e.g. USDC, WETH)'), riskTier: z.string().optional().describe('Filter by risk tier: Prime, Core, or Edge'), minTvl: z.number().optional().describe('Minimum TVL in USD'), sortBy: z.string().optional().describe('Sort field: tvl_usd, apr_net, name, last_synced_at'), sortOrder: z.string().optional().describe('Sort order: asc or desc'), limit: z.number().optional().describe('Max results (default 10, max 50)'), }, async (params) => { const qs = buildQueryString({ search: params.query, chain: params.chain, protocol: params.protocol, asset: params.asset, riskTier: params.riskTier, minTvl: params.minTvl, sortBy: params.sortBy || 'tvl_usd', sortOrder: params.sortOrder || 'desc', limit: Math.min(params.limit || 10, 50), page: 1, }); const result = await apiGet<{ data: any[]; meta: any }>(`/v1/vaults${qs}`); const vaults = result.data; if (!vaults.length) { return { content: [ { type: 'text' as const, text: 'No vaults found matching the given criteria.' }, ], }; } const lines = vaults.map((v) => formatVaultSummary(v)); const summary = `Found ${result.meta.total} vaults (showing ${vaults.length}):\n\n` + lines.join('\n\n---\n\n'); return { content: [{ type: 'text' as const, text: summary }] }; } ); }
- src/server.ts:31-31 (registration)Tool registration - the search_vaults tool is registered with the MCP server by calling registerSearchVaults(server).registerSearchVaults(server);
- src/api-client.ts:21-30 (helper)Helper function buildQueryString that converts an object of parameters into a URL query string, used by search_vaults to construct API request parameters.export function buildQueryString( params: Record<string, string | number | boolean | undefined> ): string { const sp = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== undefined && value !== false) sp.set(key, String(value)); } const str = sp.toString(); return str ? `?${str}` : ''; }
- src/api-client.ts:3-19 (helper)Helper function apiGet that makes HTTP GET requests to the Philidor API endpoint, used by search_vaults to fetch vault data from /v1/vaults.export async function apiGet<T = any>(path: string): Promise<T> { const res = await fetch(`${API_BASE}${path}`, { headers: { Accept: 'application/json' }, }); if (!res.ok) { let message: string; try { const json = (await res.json()) as Record<string, any>; message = json?.error?.message || json?.message || JSON.stringify(json); } catch { message = res.statusText || `HTTP ${res.status}`; } throw new Error(`API ${res.status}: ${message}`); } const json = await res.json(); return json as T; }
- src/lib/formatters.ts:1-22 (helper)Helper function formatVaultSummary that formats a single vault object into a human-readable markdown summary with protocol, chain, asset, TVL, APR, and risk score information.export function formatVaultSummary(vault: any): string { const rs = vault.risk_score; const riskTier = vault.risk_tier || (rs != null && rs >= 8 ? 'Prime' : rs != null && rs >= 5 ? 'Core' : rs != null ? 'Edge' : 'N/A'); const score = vault.total_score ?? vault.risk_score ?? 'N/A'; return [ `## ${vault.name}`, `**Protocol:** ${vault.protocol_name} | **Chain:** ${vault.chain_name} | **Asset:** ${vault.asset_symbol || 'N/A'}`, `**TVL:** $${formatNumber(vault.tvl_usd)} | **APR:** ${formatPercent(vault.apr_net)}`, `**Risk Score:** ${score}/10 (${riskTier})`, vault.curator_name ? `**Curator:** ${vault.curator_name}` : null, ] .filter(Boolean) .join('\n'); }