madeonsol_kol_leaderboard
Retrieve KOL performance rankings sorted by PnL or win rate. PRO+ users can sort by ROI, profit factor, or early entry.
Instructions
Get KOL performance rankings by PnL and win rate. PRO+ can sort by alternative axes (winrate/roi/profit_factor/early_entry).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Time period (trade retention is 180d) | 7d |
| limit | No | Number of KOLs to return in ranking | |
| sort | No | PRO+: sort axis (default 'pnl') | |
| strategy | No | PRO+: filter by strategy tag | |
| min_winrate | No | PRO+: minimum winrate cutoff (0-100) |
Implementation Reference
- src/index.ts:139-157 (registration)Tool registration via server.tool() — registers the 'madeonsol_kol_leaderboard' tool with its name, description, schema, annotations, and handler callback.
server.tool( "madeonsol_kol_leaderboard", "Get KOL performance rankings by PnL and win rate. PRO+ can sort by alternative axes (winrate/roi/profit_factor/early_entry).", { period: z.enum(["today", "7d", "30d", "90d", "180d"]).default("7d").describe("Time period (trade retention is 180d)"), limit: z.number().min(1).max(50).default(20).describe("Number of KOLs to return in ranking"), sort: z.enum(["pnl", "winrate", "profit_factor", "roi", "early_entry"]).optional().describe("PRO+: sort axis (default 'pnl')"), strategy: z.enum(["sniper", "flipper", "swinger", "holder", "mixed"]).optional().describe("PRO+: filter by strategy tag"), min_winrate: z.number().optional().describe("PRO+: minimum winrate cutoff (0-100)"), }, readOnlyAnnotations, async ({ period, limit, sort, strategy, min_winrate }) => { const params: Record<string, string | number> = { period, limit }; if (sort) params.sort = sort; if (strategy) params.strategy = strategy; if (min_winrate !== undefined) params.min_winrate = min_winrate; return { content: [{ type: "text" as const, text: await query("/api/x402/kol/leaderboard", params) }] }; } ); - src/index.ts:142-148 (schema)Zod-based input schema for the tool — defines period (today/7d/30d/90d/180d), limit (1-50, default 20), sort (pnl/winrate/profit_factor/roi/early_entry), strategy (sniper/flipper/swinger/holder/mixed), and min_winrate (0-100). The sort, strategy, and min_winrate parameters are marked PRO+ features.
{ period: z.enum(["today", "7d", "30d", "90d", "180d"]).default("7d").describe("Time period (trade retention is 180d)"), limit: z.number().min(1).max(50).default(20).describe("Number of KOLs to return in ranking"), sort: z.enum(["pnl", "winrate", "profit_factor", "roi", "early_entry"]).optional().describe("PRO+: sort axis (default 'pnl')"), strategy: z.enum(["sniper", "flipper", "swinger", "holder", "mixed"]).optional().describe("PRO+: filter by strategy tag"), min_winrate: z.number().optional().describe("PRO+: minimum winrate cutoff (0-100)"), }, - src/index.ts:150-156 (handler)Handler function that executes the tool logic — builds query params from provided input, delegates to the generic 'query()' helper to make an HTTP call to the external API at /api/x402/kol/leaderboard, and returns the response as formatted JSON text.
async ({ period, limit, sort, strategy, min_winrate }) => { const params: Record<string, string | number> = { period, limit }; if (sort) params.sort = sort; if (strategy) params.strategy = strategy; if (min_winrate !== undefined) params.min_winrate = min_winrate; return { content: [{ type: "text" as const, text: await query("/api/x402/kol/leaderboard", params) }] }; } - src/index.ts:60-80 (helper)The generic 'query()' helper function used by the leaderboard handler to make authenticated HTTP requests to the external MadeOnSol API. It handles both x402 (micropayment) and API-key-based auth modes, builds URLs with query params, and returns formatted JSON or error text.
async function query(path: string, params?: Record<string, string | number>) { // API key uses /api/v1/ endpoints; x402 uses /api/x402/ const apiPath = authMode === "x402" || authMode === "none" ? path : path.replace("/api/x402/", "/api/v1/"); const url = new URL(apiPath, BASE_URL); if (params) { for (const [k, v] of Object.entries(params)) { if (v !== undefined) url.searchParams.set(k, String(v)); } } const headers = apiKeyHeaders(); const res = authMode === "x402" ? await paidFetch(url.toString()) : await fetch(url.toString(), { headers }); if (!res.ok) { const body = await res.text().catch(() => ""); return `Error ${res.status}: ${body}`; } return JSON.stringify(await res.json(), null, 2); }