@allratestoday/mcp-server
Version:
MCP server for AllRatesToday — let AI coding tools (Claude Code, Cursor, Claude Desktop) fetch real-time and historical currency exchange rates.
66 lines (65 loc) • 2.27 kB
JavaScript
const DEFAULT_BASE_URL = 'https://allratestoday.com/api';
const USER_AGENT = `allratestoday-mcp/0.3.1`;
export class AllRatesTodayError extends Error {
status;
body;
constructor(message, status, body) {
super(message);
this.status = status;
this.body = body;
this.name = 'AllRatesTodayError';
}
}
export class AllRatesTodayClient {
apiKey;
baseUrl;
fetchImpl;
constructor(options = {}) {
this.apiKey = options.apiKey;
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
this.fetchImpl = options.fetchImpl ?? fetch;
}
async request(path, query) {
const url = new URL(this.baseUrl + path);
for (const [key, value] of Object.entries(query)) {
if (value !== undefined && value !== '')
url.searchParams.set(key, value);
}
const headers = {
'Accept': 'application/json',
'User-Agent': USER_AGENT,
};
if (!this.apiKey) {
throw new AllRatesTodayError('AllRatesToday API key is required. Sign up free at https://allratestoday.com/register to get a key, then set ALLRATES_API_KEY in your MCP config.');
}
headers['Authorization'] = `Bearer ${this.apiKey}`;
const res = await this.fetchImpl(url.toString(), { method: 'GET', headers });
const text = await res.text();
let body;
try {
body = text ? JSON.parse(text) : null;
}
catch {
body = text;
}
if (!res.ok) {
const msg = (body && typeof body === 'object' && 'error' in body && typeof body.error === 'string'
? body.error
: `HTTP ${res.status}`);
throw new AllRatesTodayError(msg, res.status, body);
}
return body;
}
getRate(source, target) {
return this.request('/rate', { source, target });
}
getHistoricalRates(source, target, period = '7d') {
return this.request('/historical-rates', { source, target, period });
}
getAuthenticatedRates(params) {
return this.request('/v1/rates', params);
}
listSymbols() {
return this.request('/v1/symbols', {});
}
}