Skip to main content
Glama

elfa_set_base

Configure the base URL for ELFA's sentiment data API to enable crypto market analysis with combined sentiment and technical indicators.

Instructions

Set ELFA base URL (e.g., https://api.elfa.ai).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
baseYes

Implementation Reference

  • The main handler function for the 'elfa_set_base' tool. It extracts the 'base' parameter from args, validates it as a URL, sets the global ELFA_BASE variable, and returns success or error response.
    "elfa_set_base": async (args) => { const base = args && args.base; try { const u = new URL(base); ELFA_BASE = u.toString().replace(/\/+$/,""); return { content: textContent({ ok:true, base: ELFA_BASE }) }; } catch { return { content: textContent({ ok:false, message:"Invalid URL for 'base'" }), isError:true }; } },
  • The schema definition for the 'elfa_set_base' tool, specifying input schema requiring a 'base' string, description, and annotations.
    { name:"elfa_set_base", description:"Set ELFA base URL (e.g., https://api.elfa.ai).", inputSchema:{ type:"object", properties:{ base:{type:"string"} }, required:["base"] }, annotations:{ title:"ELFA: Set Base URL", readOnlyHint:false, openWorldHint:false } },
  • mcp-server.js:123-262 (registration)
    The toolHandlers object registers the 'elfa_set_base' handler function, which is used in tools/call method.
    const toolHandlers = { // Admin: set auth "elfa_set_auth": async (args) => { const key = args && args.key; const headerName = args && args.headerName; const scheme = args && args.scheme; if (!key || typeof key !== "string") return { content: textContent({ ok:false, message:"Missing 'key' (string)" }), isError:true }; if (headerName && typeof headerName === "string") ELFA_AUTH.headerName = headerName; if (scheme !== undefined && typeof scheme === "string") ELFA_AUTH.scheme = scheme; ELFA_AUTH.key = key; return { content: textContent({ ok:true, headerName: ELFA_AUTH.headerName || "", scheme: ELFA_AUTH.scheme || "", key: maskKey(ELFA_AUTH.key) }) }; }, // Admin: set base URL "elfa_set_base": async (args) => { const base = args && args.base; try { const u = new URL(base); ELFA_BASE = u.toString().replace(/\/+$/,""); return { content: textContent({ ok:true, base: ELFA_BASE }) }; } catch { return { content: textContent({ ok:false, message:"Invalid URL for 'base'" }), isError:true }; } }, // Admin: reload .env (no restart) "elfa_reload_env": async () => { loadEnvMulti(); ELFA_AUTH = buildAuthFromEnv(); ELFA_BASE = (process.env.ELFA_BASE || ELFA_BASE).replace(/\/+$/,""); return { content: textContent({ ok: true, base: ELFA_BASE, loaded: ENV_INFO.loaded, from: ENV_INFO.from, vars: ENV_INFO.vars, auth: { headerName: ELFA_AUTH.headerName || "", scheme: ELFA_AUTH.scheme || "", key: maskKey(ELFA_AUTH.key) } }) }; }, // Admin: status "elfa_status": async () => { return { content: textContent({ base: ELFA_BASE, loaded: ENV_INFO.loaded, from: ENV_INFO.from, vars: ENV_INFO.vars, auth: { headerName: ELFA_AUTH.headerName || "", scheme: ELFA_AUTH.scheme || "", key: maskKey(ELFA_AUTH.key) } }) }; }, // Generic proxy "elfa_query": async (args, meta) => { const path = args && args.path; if (!path || typeof path !== "string") return { content: textContent({ error:true, message:"Missing required 'path' (string)" }), isError:true }; const method = (args.method || "GET").toUpperCase(); const query = args.query || undefined; const body = args.body || undefined; progressNotify(meta && meta.progressToken, 1, 3, "Calling ELFA"); const { ok, status, data } = await elfaFetch(path, { method, query, body }); progressNotify(meta && meta.progressToken, 2, 3, "Formatting result"); if (!ok) return { content: textContent({ error:true, status, data }), isError:true, _meta:{ status } }; progressNotify(meta && meta.progressToken, 3, 3, "Done"); return { content: textContent({ ok:true, status, data }) }; }, // /v2/aggregations/trending-tokens (this replaces the old /v2/data/trending) "elfa_trending": async (args, meta) => { return toolHandlers["elfa_trending_tokens"](args, meta); }, "elfa_trending_tokens": async (args, meta) => { const query = {}; if (args && args.timeframe !== undefined) query.timeframe = args.timeframe; // "24h","7d","30d" if (args && args.chain !== undefined) query.chain = args.chain; if (args && args.limit !== undefined) query.limit = args.limit; if (args && args.cursor !== undefined) query.cursor = args.cursor; return toolHandlers["elfa_query"]({ path: "/v2/aggregations/trending-tokens", method: "GET", query }, meta); }, // /v2/data/token-news "elfa_token_news": async (args, meta) => { const query = {}; if (args && args.symbols !== undefined) query.symbols = args.symbols; // "ETH,BTC" if (args && args.chain !== undefined) query.chain = args.chain; if (args && args.start !== undefined) query.start = args.start; if (args && args.end !== undefined) query.end = args.end; if (args && args.limit !== undefined) query.limit = args.limit; if (args && args.cursor !== undefined) query.cursor = args.cursor; if (args && args.sources !== undefined) query.sources = args.sources; return toolHandlers["elfa_query"]({ path: "/v2/data/token-news", method: "GET", query }, meta); }, // /v2/data/keyword-mentions "elfa_keyword_mentions": async (args, meta) => { const query = {}; if (args && args.keywords !== undefined) query.keywords = Array.isArray(args.keywords) ? args.keywords.join(",") : String(args.keywords); if (args && args.start !== undefined) query.start = args.start; if (args && args.end !== undefined) query.end = args.end; if (args && args.chain !== undefined) query.chain = args.chain; if (args && args.limit !== undefined) query.limit = args.limit; if (args && args.cursor !== undefined) query.cursor = args.cursor; if (args && args.sources !== undefined) query.sources = args.sources; return toolHandlers["elfa_query"]({ path: "/v2/data/keyword-mentions", method: "GET", query }, meta); }, // ----- TA tools ----- // Compute RSI on an array of closes (oldest → newest) "ta_rsi": async (args) => { const values = Array.isArray(args?.values) ? args.values : null; const period = Number.isFinite(Number(args?.period)) ? Number(args.period) : 14; if (!values || values.length === 0) { return { content: textContent({ error:true, message:"'values' must be a non-empty array of numbers (oldest → newest)" }), isError:true }; } const out = taRSI(values, period); return { content: textContent({ ok:true, rsi: out, period }) }; }, // Compute Bollinger Bands on an array of closes (oldest → newest) "ta_bollinger": async (args) => { const values = Array.isArray(args?.values) ? args.values : null; const period = Number.isFinite(Number(args?.period)) ? Number(args.period) : 20; const mult = Number.isFinite(Number(args?.mult)) ? Number(args.mult) : 2; if (!values || values.length === 0) { return { content: textContent({ error:true, message:"'values' must be a non-empty array of numbers (oldest → newest)" }), isError:true }; } const out = taBoll(values, period, mult); return { content: textContent({ ok:true, ...out, period, mult }) }; }, // Convenience: return both indicators in one call "ta_summary": async (args) => { const values = Array.isArray(args?.values) ? args.values : null; const rsiPeriod = Number.isFinite(Number(args?.rsiPeriod)) ? Number(args.rsiPeriod) : 14; const bbPeriod = Number.isFinite(Number(args?.bbPeriod)) ? Number(args.bbPeriod) : 20; const bbMult = Number.isFinite(Number(args?.bbMult)) ? Number(args.bbMult) : 2; if (!values || values.length === 0) { return { content: textContent({ error:true, message:"'values' must be a non-empty array of numbers (oldest → newest)" }), isError:true }; } const rsiVal = taRSI(values, rsiPeriod); const bbVal = taBoll(values, bbPeriod, bbMult); return { content: textContent({ ok:true, rsi: rsiVal, bollinger: bbVal, rsiPeriod, bbPeriod, bbMult }) }; } };

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