Skip to main content
Glama
elfa.js3.15 kB
// services/elfa.js — ELFA v2 client (data + aggregations) import axios from 'axios'; const ELFA_BASE = (process.env.ELFA_BASE || 'https://api.elfa.ai').replace(/\/+$/, ''); const ELFA_KEY = (process.env.ELFA_API_KEY ?? process.env.ELFA_KEY ?? '').trim(); export const elfa = axios.create({ baseURL: ELFA_BASE, timeout: 30_000, headers: { Accept: 'application/json', 'User-Agent': 'cg-alpha-mcp/1.0', // harmless, helps some gateways ...(ELFA_KEY ? { 'x-elfa-api-key': ELFA_KEY } : {}) } }); elfa.interceptors.request.use((cfg) => { cfg.headers = cfg.headers || {}; cfg.headers['Accept'] = 'application/json'; cfg.headers['User-Agent'] = cfg.headers['User-Agent'] || 'cg-alpha-mcp/1.0'; if (ELFA_KEY) cfg.headers['x-elfa-api-key'] = ELFA_KEY; return cfg; }); const safeGet = async (path, params) => { try { const r = await elfa.get(path, { params }); return r.data; } catch (e) { const status = e?.response?.status; const data = e?.response?.data; const msg = data?.error || data?.message || e?.message || 'request failed'; console.warn(`[ELFA] ${status || '?'} ${path}`, { params, msg }); return { ok: false, status: status || 500, error: msg, sent: { path, params } }; } }; // ✅ Include timeWindow so aggregations does not 400 export const elfaKeyStatus = async () => { if (!ELFA_KEY) return { ok:false, status:401, error:'Missing ELFA_API_KEY' }; // cheap ping to a real v2 endpoint (use an always-available, lightweight call) const ping = await safeGet('/v2/aggregations/trending-tokens', { page: 1, pageSize: 1, timeWindow: '24h' }); if (ping?.ok === false) return ping; return { ok:true, base: ELFA_BASE, keyLen: ELFA_KEY.length }; }; export const elfaTrendingTokens = async ({ timeWindow='7d', page=1, pageSize=50, minMentions=5, from=null, to=null }) => { const params = { page, pageSize, minMentions }; if (from != null && to != null) { params.from = from; params.to = to; } else { params.timeWindow = timeWindow; } return safeGet('/v2/aggregations/trending-tokens', params); }; export const elfaTokenNews = async (opts) => { const { coinIds, page = 1, pageSize = 20, reposts = false } = opts; const params = { coinIds, page, pageSize, reposts }; if ('from' in opts && 'to' in opts && opts.from != null && opts.to != null) { params.from = opts.from; params.to = opts.to; } else { params.timeWindow = opts.timeWindow || '7d'; } return safeGet('/v2/data/token-news', params); }; export const elfaKeywordMentions = async (opts) => { const { keywords, accountName, timeWindow = '7d', limit = 20, searchType = 'or', cursor = null, reposts = false } = opts; const params = { limit, searchType, reposts }; if (keywords) params.keywords = keywords; if (accountName) params.accountName = accountName; if ('from' in opts && 'to' in opts && opts.from != null && opts.to != null) { params.from = opts.from; params.to = opts.to; } else { params.timeWindow = timeWindow; } if (cursor) params.cursor = cursor; return safeGet('/v2/data/keyword-mentions', params); };

Implementation Reference

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/JCF0/cg-alpha-mcp'

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