Skip to main content
Glama
Seitrace

Seitrace Insights MCP Server

Official
by Seitrace
resolver.ts3.5 kB
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { McpResponse } from '../../../../utils/index.js'; function toText(result: CallToolResult): string { return (result.content && result.content[0] && (result.content[0] as any).text) || ''; } type EarningItem = { id?: string; pool_name?: string; pool_address?: string; pool_image?: string; total_apr?: number; total_apy?: number; tvl?: number; provider?: { provider_name?: string; provider_type: string; provider_key: string }; [k: string]: any; }; function normalizeAddress(addr?: string): string { return typeof addr === 'string' ? addr.toLowerCase() : ''; } function simplifyItem(it: EarningItem) { const address = it?.pool_address || ''; return { name: it?.pool_name, address, url: address ? `https://seitrace.com/earning/${address}` : undefined, image: it?.pool_image, provider: it?.provider?.provider_name, provider_type: it?.provider?.provider_type, provider_key: it?.provider?.provider_key, tvl: it?.tvl, apr: it?.total_apr, apy: it?.total_apy, }; } export function searchEarningsResolver(result: CallToolResult, payload?: any): CallToolResult { const text = toText(result); try { const parsed = JSON.parse(text); if (parsed?.error) return result; const items: EarningItem[] = Array.isArray(parsed?.items) ? parsed.items : []; // Optional local filter by search_terms if executor didn't include it const q = String((payload && payload.search_terms) || '') .trim() .toLowerCase(); const limitRaw = Number((payload && payload.limit) || 20); const limit = isFinite(limitRaw) ? Math.max(1, Math.min(50, limitRaw)) : 20; let filtered = items; if (q) { filtered = items.filter((i) => { const name = String(i?.pool_name || '').toLowerCase(); const provider = String(i?.provider?.provider_name || '').toLowerCase(); const addr = String(i?.pool_address || '').toLowerCase(); return name.includes(q) || provider.includes(q) || addr.includes(q); }); } const simplified = filtered.slice(0, limit).map(simplifyItem); return McpResponse( JSON.stringify({ items: simplified, count: simplified.length, }) ); } catch (error) { return McpResponse( JSON.stringify({ error: 'Failed to parse earnings response', details: error instanceof Error ? error.message : 'Unknown error', }) ); } } export function getEarningDetailsResolver(result: CallToolResult, payload?: any): CallToolResult { const text = toText(result); try { const parsed = JSON.parse(text); if (parsed?.error) return result; const items: EarningItem[] = Array.isArray(parsed?.items) ? parsed.items : []; const qAddr = normalizeAddress((payload && payload.pool_address) || ''); if (!qAddr) return McpResponse(JSON.stringify({ error: 'pool_address not provided to resolver' })); const match = items.find((i) => normalizeAddress(i?.pool_address) === qAddr); if (!match) return McpResponse( JSON.stringify({ error: 'EARNING_NOT_FOUND', pool_address: payload?.pool_address }) ); return McpResponse(JSON.stringify({ item: simplifyItem(match) })); } catch (error) { return McpResponse( JSON.stringify({ error: 'Failed to parse earnings response', details: error instanceof Error ? error.message : 'Unknown error', }) ); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Seitrace/seitrace-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server