live_risk_overview
Get an exchange-wide market risk snapshot, including open interest, leverage, crowding, and near-liquidation exposure. Identify the most fragile coins to anticipate potential market moves.
Instructions
Get the exchange-wide market risk snapshot. Best for questions like 'what looks fragile right now?' or 'which coins are most crowded?'. Returns total open interest, leverage, crowding concentration, near-liquidation exposure, 7-day liquidation totals, and the top coins where positioning looks most fragile.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| useToonFormat | No | Return data in compact toon format (default: true). Set to false for standard JSON. |
Implementation Reference
- src/index.ts:567-579 (registration)Registration of the 'live_risk_overview' tool on the MCP server. Uses shouldRegister() to check if the tool can be registered (always with an API key, only free-tier tools without).
// ══════════════════════════════════════════════════════════ // TOOL 15: Market Risk Overview // ══════════════════════════════════════════════════════════ if (shouldRegister("live_risk_overview")) server.registerTool( "live_risk_overview", { description: "Get the exchange-wide market risk snapshot. Best for questions like 'what looks fragile right now?' or 'which coins are most crowded?'. Returns total open interest, leverage, crowding concentration, near-liquidation exposure, 7-day liquidation totals, and the top coins where positioning looks most fragile.", inputSchema: { useToonFormat: useToonFormatSchema, }, }, async ({ useToonFormat }) => toolResult(await callAPI(useToonFormat, "/live/risk/overview")) ); - src/index.ts:572-576 (schema)Input schema for live_risk_overview: only accepts the shared useToonFormat boolean parameter (default true) to toggle compact toon vs standard JSON output.
{ description: "Get the exchange-wide market risk snapshot. Best for questions like 'what looks fragile right now?' or 'which coins are most crowded?'. Returns total open interest, leverage, crowding concentration, near-liquidation exposure, 7-day liquidation totals, and the top coins where positioning looks most fragile.", inputSchema: { useToonFormat: useToonFormatSchema, }, - src/index.ts:578-578 (handler)Handler function: async lambda that calls the API helper with the '/live/risk/overview' endpoint, passing the useToonFormat flag. The API call is delegated to callAPI which handles retries, timeouts and error formatting.
async ({ useToonFormat }) => toolResult(await callAPI(useToonFormat, "/live/risk/overview")) - src/index.ts:94-166 (helper)The callAPI helper function that the tool handler delegates to. Makes HTTP fetch requests to the Coinversa API with timeout, retry logic, and error transformation. Appends the tool-specific path ('/live/risk/overview') to the configured BASE URL.
async function callAPI(useToon: boolean, path: string, params?: Record<string, string>): Promise<any> { const url = new URL(`${BASE}${path}`); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== "") { url.searchParams.set(key, value); } }); } let lastError: Error | null = null; for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { try { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); const headers: Record<string, string> = {}; if (API_KEY) headers["X-API-Key"] = API_KEY; const response = await fetch(url.toString(), { headers, signal: controller.signal, }); clearTimeout(timeout); if (response.status === 429) { // Rate limited — retry after delay if (attempt < MAX_RETRIES) { await new Promise((r) => setTimeout(r, RETRY_DELAY_MS * (attempt + 1))); continue; } throw new Error("Rate limit exceeded. Please wait a moment and try again."); } if (response.status === 404) { throw new Error("Not found. The requested resource does not exist — check the address or symbol."); } if (response.status === 401) { throw new Error("Invalid API key. Check your COINVERSAA_API_KEY environment variable."); } if (!response.ok) { const body = await response.json().catch(() => null); const msg = body?.error || response.statusText; throw new Error(`Request failed (${response.status}): ${msg}`); } const data = await response.json(); return useToon ? toonEncode(data) : data; } catch (err: any) { if (err.name === "AbortError") { lastError = new Error("Request timed out after 30 seconds. The server may be under heavy load — try again."); } else if (err.cause?.code === "ECONNREFUSED" || err.cause?.code === "ENOTFOUND") { lastError = new Error("Cannot connect to the Coinversa API. Check your COINVERSAA_API_URL setting and network connection."); } else { lastError = err; } // Retry on transient network errors if (attempt < MAX_RETRIES && (err.name === "AbortError" || err.cause?.code === "ECONNRESET")) { await new Promise((r) => setTimeout(r, RETRY_DELAY_MS * (attempt + 1))); continue; } throw lastError; } } throw lastError || new Error("Request failed after retries"); }