asset-price-mcp
Version:
An MCP-compatible service that provides real-time asset prices including precious metals, cryptocurrencies, and more
49 lines (48 loc) • 1.77 kB
JavaScript
import { fetchJson } from "../utils.js";
import { apiCache } from "../cache.js";
const RATE_API_PRIMARY = 'https://open.er-api.com/v6/latest/USD';
const RATE_API_BACKUP = 'https://api.exchangerate-api.com/v4/latest/USD';
export class ExchangeRateService {
async getRate(from, to) {
const fromUpper = from.toUpperCase();
const toUpper = to.toUpperCase();
if (fromUpper === toUpper)
return 1;
// Currently our APIs are USD based
// If from is USD, we just look up the rate
// If from is not USD, we might need cross rate (not implemented fully for efficiency, assuming base is USD)
// Check cache for USD rates
const cacheKey = "EXCHANGE_RATES_USD";
let rates = apiCache.get(cacheKey);
if (!rates) {
rates = await this.fetchRates();
if (rates) {
apiCache.set(cacheKey, rates); // Cache default TTL
}
}
if (!rates)
return null;
// If source is USD
if (fromUpper === 'USD') {
return rates[toUpper] || null;
}
// If source is not USD, convert to USD then to Target
// e.g. EUR -> CNY = (USD -> CNY) / (USD -> EUR)
const usdToFrom = rates[fromUpper];
const usdToTo = rates[toUpper];
if (usdToFrom && usdToTo) {
return usdToTo / usdToFrom;
}
return null;
}
async fetchRates() {
// Try primary
let data = await fetchJson(RATE_API_PRIMARY);
if (!data) {
// Try backup
console.warn("Primary exchange rate API failed, trying backup...");
data = await fetchJson(RATE_API_BACKUP);
}
return data?.rates || null;
}
}