@allratestoday/mcp-server 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -2
- package/dist/client.d.ts +22 -1
- package/dist/client.js +59 -0
- package/dist/index.js +58 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# AllRatesToday MCP Server — @allratestoday/mcp-server
|
|
2
2
|
|
|
3
|
+
Website: https://allratestoday.com · Hosted endpoint (no install): https://allratestoday.com/api/mcp · Docs: https://allratestoday.com/mcp/
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/@allratestoday/mcp-server)
|
|
4
6
|
[](https://www.npmjs.com/package/@allratestoday/mcp-server)
|
|
5
7
|
[](./LICENSE)
|
|
@@ -21,7 +23,7 @@ After installation, your assistant can answer questions like:
|
|
|
21
23
|
|
|
22
24
|
- 📡 **Live mid-market rates** — 150+ ISO 4217 currencies, refreshed every ~60 seconds
|
|
23
25
|
- 📈 **Historical series built in** — `1d` / `7d` / `30d` / `1y` windows with sensible granularity per period
|
|
24
|
-
- 🧰 **
|
|
26
|
+
- 🧰 **Eight focused tools** — `get_exchange_rate`, `get_historical_rates`, `get_rates_authenticated`, `list_currencies`, `list_central_banks`, `get_official_rates`, `get_reference_rate`, `request_trial_key`; small surface, easy for the model to use correctly
|
|
25
27
|
- 🔌 **Works everywhere MCP does** — stdio transport, MCP 1.x; Claude Code, Cursor, Claude Desktop, Windsurf, or any generic host
|
|
26
28
|
- 🔓 **Works with no API key** — installs and answers out of the box from the open ECB reference table; a free key unlocks real-time rates for 160+ currencies
|
|
27
29
|
- 🛡️ **Honest about what it returned** — every keyless answer says which rate it is and when it was published; API errors map to clear, actionable messages
|
|
@@ -41,6 +43,8 @@ Install it with no configuration at all and it starts, connects, and answers:
|
|
|
41
43
|
| `list_currencies` | ✅ | All 160+ supported ISO 4217 codes. |
|
|
42
44
|
| `list_central_banks` | ✅ | Codes, names and latest publication date of all 121 central banks + 3 tax authorities. |
|
|
43
45
|
| `get_official_rates` | ✅ | Latest **official table** (or one pair) published by any of them. A dated table needs the key. |
|
|
46
|
+
| `get_reference_rate` | ✅ | The **Daily Reference Rate**: one never-revised table per business day, fixed at 16:00 London. A past date needs the key. |
|
|
47
|
+
| `request_trial_key` | ✅ | Self-issues a 100-call, 7-day key with no account and adopts it for the session. |
|
|
44
48
|
| `get_historical_rates` | 🔑 | Returns one sentence explaining how to get a free key. |
|
|
45
49
|
| `get_rates_authenticated` | 🔑 | Same. |
|
|
46
50
|
|
|
@@ -198,8 +202,10 @@ After configuring your client, test in this order:
|
|
|
198
202
|
- [`list_currencies`](#list_currencies) — all supported currency codes, names, symbols
|
|
199
203
|
- [`list_central_banks`](#list_central_banks) — every covered central bank / tax authority with its code and latest publication date
|
|
200
204
|
- [`get_official_rates`](#get_official_rates) — the official table (or one pair) a named institution published
|
|
205
|
+
- [`get_reference_rate`](#get_reference_rate) — the Daily Reference Rate, one fixed mid-market table per business day (16:00 London)
|
|
206
|
+
- [`request_trial_key`](#request_trial_key) — self-issue a 100-call, 7-day trial key, no account needed
|
|
201
207
|
|
|
202
|
-
`get_historical_rates` and `get_rates_authenticated` require `ALLRATES_API_KEY`; the other
|
|
208
|
+
`get_historical_rates` and `get_rates_authenticated` require `ALLRATES_API_KEY`; the other six work keyless.
|
|
203
209
|
|
|
204
210
|
---
|
|
205
211
|
|
|
@@ -374,6 +380,32 @@ Omit `source`/`target` for the whole table as `rates: [{ base, quote, type, valu
|
|
|
374
380
|
|
|
375
381
|
---
|
|
376
382
|
|
|
383
|
+
### `get_reference_rate`
|
|
384
|
+
|
|
385
|
+
AllRatesToday's **Daily Reference Rate**: the per-currency median of samples taken in a five-minute window centred on 16:00 London, published once per business day and never revised. Use it when a report, index or research series needs *one* reproducible rate per day. It is not the WM/Refinitiv fix and not a registered benchmark; every response carries a disclaimer and the `rate_date`.
|
|
386
|
+
|
|
387
|
+
**Input**
|
|
388
|
+
|
|
389
|
+
| Field | Type | Required | Description |
|
|
390
|
+
|---|---|---|---|
|
|
391
|
+
| `source` | string | no | With `target`, narrows to one pair (crossed via USD, flagged `derived`) |
|
|
392
|
+
| `target` | string | no | See above |
|
|
393
|
+
| `date` | string | no | Past business day `YYYY-MM-DD` (API key). Omit for the latest table |
|
|
394
|
+
|
|
395
|
+
**Output** — `{ rate_date, base, time, rates }` for the table, or `{ rate_date, source, target, rate, derived }` for a pair, plus `method` and `disclaimer`. Keyless for the latest table. Docs: https://allratestoday.com/reference-rate/
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
### `request_trial_key`
|
|
400
|
+
|
|
401
|
+
Self-issues an API key with 100 lifetime calls, valid 7 days, with no account and no email, and switches this server to it for the rest of the session. The reply tells the user to copy the key into the MCP config as `ALLRATES_API_KEY` to keep it across restarts. Capped at 3 keys per IP per day.
|
|
402
|
+
|
|
403
|
+
**Input** — `agent` (string, optional), `purpose` (string, optional).
|
|
404
|
+
|
|
405
|
+
**Output** — `{ key, calls, expires_at, adopted, note }`.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
377
409
|
## ⚙️ Environment variables
|
|
378
410
|
|
|
379
411
|
| Variable | Default | Required | Purpose |
|
|
@@ -474,6 +506,7 @@ server.json # MCP registry manifest
|
|
|
474
506
|
|
|
475
507
|
See [GitHub Releases](https://github.com/cahthuranag/mcp-server/releases) for the full list. Recent highlights:
|
|
476
508
|
|
|
509
|
+
- **0.7.0** — `get_reference_rate` (Daily Reference Rate, 16:00 London, keyless latest table) and `request_trial_key` (self-issued 100-call trial key adopted for the session)
|
|
477
510
|
- **0.6.1** — README: Claude Code plugin and hosted `/api/mcp` endpoint cross-links; coverage wording refreshed
|
|
478
511
|
- **0.6.0** — Official rates: new keyless `list_central_banks` and `get_official_rates` tools expose the latest table from 121 central banks + 3 tax authorities (dated tables need the key)
|
|
479
512
|
- **0.5.0** — Keyless mode: the server starts and answers without an API key (`get_exchange_rate` via the open ECB reference table, `list_currencies` unchanged); metered tools return actionable sign-up guidance instead of the process exiting
|
package/dist/client.d.ts
CHANGED
|
@@ -17,13 +17,34 @@ export declare class NeedsKeyError extends AllRatesTodayError {
|
|
|
17
17
|
constructor(what: string);
|
|
18
18
|
}
|
|
19
19
|
export declare class AllRatesTodayClient {
|
|
20
|
-
private
|
|
20
|
+
private apiKey?;
|
|
21
21
|
private readonly baseUrl;
|
|
22
22
|
private readonly fetchImpl;
|
|
23
23
|
constructor(options?: ClientOptions);
|
|
24
24
|
private request;
|
|
25
25
|
/** True when no API key is configured: only the open endpoints are reachable. */
|
|
26
26
|
get keyless(): boolean;
|
|
27
|
+
/** Adopt a key at runtime (used after request_trial_key) so the rest of the session is keyed. */
|
|
28
|
+
setApiKey(key: string | undefined): void;
|
|
29
|
+
/**
|
|
30
|
+
* Daily Reference Rate: one never-revised mid-market table per business day,
|
|
31
|
+
* fixed at 16:00 London (median of samples in a 5-minute window). Latest
|
|
32
|
+
* table and single pairs are keyless; a dated table needs the key.
|
|
33
|
+
*/
|
|
34
|
+
getReferenceRate(params?: {
|
|
35
|
+
source?: string;
|
|
36
|
+
target?: string;
|
|
37
|
+
date?: string;
|
|
38
|
+
}): Promise<Record<string, unknown>>;
|
|
39
|
+
/**
|
|
40
|
+
* Self-issue a trial key (100 calls, 7 days, no account) and adopt it for the
|
|
41
|
+
* rest of this process. POST with a JSON body: the site rejects bodiless
|
|
42
|
+
* POSTs as cross-site form submissions.
|
|
43
|
+
*/
|
|
44
|
+
requestTrialKey(params?: {
|
|
45
|
+
agent?: string;
|
|
46
|
+
purpose?: string;
|
|
47
|
+
}): Promise<any>;
|
|
27
48
|
getRate(source: string, target: string): Promise<{
|
|
28
49
|
rate: number;
|
|
29
50
|
source: string;
|
package/dist/client.js
CHANGED
|
@@ -81,6 +81,65 @@ export class AllRatesTodayClient {
|
|
|
81
81
|
get keyless() {
|
|
82
82
|
return !this.apiKey;
|
|
83
83
|
}
|
|
84
|
+
/** Adopt a key at runtime (used after request_trial_key) so the rest of the session is keyed. */
|
|
85
|
+
setApiKey(key) {
|
|
86
|
+
this.apiKey = key || undefined;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Daily Reference Rate: one never-revised mid-market table per business day,
|
|
90
|
+
* fixed at 16:00 London (median of samples in a 5-minute window). Latest
|
|
91
|
+
* table and single pairs are keyless; a dated table needs the key.
|
|
92
|
+
*/
|
|
93
|
+
getReferenceRate(params = {}) {
|
|
94
|
+
if (Boolean(params.source) !== Boolean(params.target)) {
|
|
95
|
+
return Promise.reject(new AllRatesTodayError('Provide both source and target, or neither.'));
|
|
96
|
+
}
|
|
97
|
+
const pair = { source: params.source?.toUpperCase(), target: params.target?.toUpperCase() };
|
|
98
|
+
if (params.date) {
|
|
99
|
+
if (this.keyless)
|
|
100
|
+
return Promise.reject(new NeedsKeyError(`The reference-rate table for ${params.date}`));
|
|
101
|
+
return this.request(`/v1/reference-rate/${encodeURIComponent(params.date)}`, pair);
|
|
102
|
+
}
|
|
103
|
+
return this.request('/open/reference-rate', pair);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Self-issue a trial key (100 calls, 7 days, no account) and adopt it for the
|
|
107
|
+
* rest of this process. POST with a JSON body: the site rejects bodiless
|
|
108
|
+
* POSTs as cross-site form submissions.
|
|
109
|
+
*/
|
|
110
|
+
async requestTrialKey(params = {}) {
|
|
111
|
+
const res = await this.fetchImpl(`${this.baseUrl}/agent/keys`, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: {
|
|
114
|
+
'Accept': 'application/json',
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
'User-Agent': `allratestoday-mcp/${VERSION}`,
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({ agent: params.agent, purpose: params.purpose }),
|
|
119
|
+
});
|
|
120
|
+
const text = await res.text();
|
|
121
|
+
let body;
|
|
122
|
+
try {
|
|
123
|
+
body = text ? JSON.parse(text) : null;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
body = text;
|
|
127
|
+
}
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
const upstream = body && typeof body === 'object' && typeof body.error === 'string' ? body.error : undefined;
|
|
130
|
+
throw new AllRatesTodayError(upstream ?? `HTTP ${res.status}`, res.status, body);
|
|
131
|
+
}
|
|
132
|
+
const key = body && typeof body === 'object' && typeof body.key === 'string' ? body.key : undefined;
|
|
133
|
+
if (key)
|
|
134
|
+
this.setApiKey(key);
|
|
135
|
+
return {
|
|
136
|
+
...(body ?? {}),
|
|
137
|
+
adopted: Boolean(key),
|
|
138
|
+
note: 'This server now uses the trial key for the rest of this session. To keep it after a restart, ' +
|
|
139
|
+
'put it in the MCP config: "env": { "ALLRATES_API_KEY": "<key>" }. For a lasting key register free ' +
|
|
140
|
+
'at https://allratestoday.com/register (300 calls) or see https://allratestoday.com/pricing.',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
84
143
|
getRate(source, target) {
|
|
85
144
|
// Keyless: fall back to the open, edge-cached ECB reference table. It is
|
|
86
145
|
// the official daily fixing rather than a live mid-market quote and covers
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,8 @@ async function main() {
|
|
|
45
45
|
' • list_currencies — all supported currency codes',
|
|
46
46
|
' • list_central_banks — 121 central banks + 3 tax authorities we carry',
|
|
47
47
|
' • get_official_rates — latest official table (or one pair) from any of them',
|
|
48
|
+
' • get_reference_rate — Daily Reference Rate, one fixed table per business day (16:00 London)',
|
|
49
|
+
' • request_trial_key — self-issue a 100-call, 7-day key without an account',
|
|
48
50
|
'',
|
|
49
51
|
' Needs a free API key (real-time mid-market rates for 160+ currencies,',
|
|
50
52
|
' historical series, multi-target and point-in-time lookups):',
|
|
@@ -235,6 +237,62 @@ async function main() {
|
|
|
235
237
|
return fail(err);
|
|
236
238
|
}
|
|
237
239
|
});
|
|
240
|
+
server.registerTool('get_reference_rate', {
|
|
241
|
+
title: 'Get the Daily Reference Rate (16:00 London)',
|
|
242
|
+
description: "AllRatesToday's once-a-day, never-revised mid-market rate: the per-currency median of samples in a five-minute window centred on 16:00 London, published each business day. Use it when the user needs ONE reproducible rate per day — index levels, return series, research datasets, month-end reports — rather than a live quote (get_exchange_rate) or an institution's official rate (get_official_rates). Omit source/target for the whole table; give both for one pair (crossed via USD, flagged `derived`). Omit `date` for the latest table (no key needed); give `date` (API key) for a past business day. Not the WM/Refinitiv fix and not a registered benchmark — relay the disclaimer and the `rate_date`.",
|
|
243
|
+
inputSchema: {
|
|
244
|
+
source: ccy.optional().describe('Optional. With target, narrows to one pair.'),
|
|
245
|
+
target: ccy.optional().describe('Optional. With source, narrows to one pair.'),
|
|
246
|
+
date: z
|
|
247
|
+
.string()
|
|
248
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
249
|
+
.optional()
|
|
250
|
+
.describe('Optional past business day, YYYY-MM-DD (API key). Omit for the latest table.'),
|
|
251
|
+
},
|
|
252
|
+
outputSchema: {
|
|
253
|
+
rate_date: z.string().describe('Business day the table was fixed on — cite this'),
|
|
254
|
+
base: z.string().optional(),
|
|
255
|
+
time: z.string().optional().describe('Fixing time, e.g. 16:00 Europe/London'),
|
|
256
|
+
rates: z.record(z.string(), z.unknown()).optional().describe('Full table keyed by currency code'),
|
|
257
|
+
source: z.string().optional(),
|
|
258
|
+
target: z.string().optional(),
|
|
259
|
+
rate: z.number().optional(),
|
|
260
|
+
derived: z.boolean().optional(),
|
|
261
|
+
method: z.string().optional(),
|
|
262
|
+
disclaimer: z.string().optional(),
|
|
263
|
+
},
|
|
264
|
+
annotations: READ_ONLY,
|
|
265
|
+
}, async ({ source, target, date }) => {
|
|
266
|
+
try {
|
|
267
|
+
return ok(await client.getReferenceRate({ source, target, date }));
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
return fail(err);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
server.registerTool('request_trial_key', {
|
|
274
|
+
title: 'Request a trial API key',
|
|
275
|
+
description: 'Self-issue an AllRatesToday API key with 100 lifetime calls, valid 7 days, with no account and no email. Use it when another tool answered "needs an API key" and the user wants real-time rates, history or dated tables right now. The key is adopted by this server for the rest of the session and returned once — tell the user to put it in the MCP config as ALLRATES_API_KEY to keep it. Capped at 3 keys per IP per day. For a lasting key, register at https://allratestoday.com/register (free, 300 calls) or see https://allratestoday.com/pricing.',
|
|
276
|
+
inputSchema: {
|
|
277
|
+
agent: z.string().max(80).optional().describe('Optional: the agent or product requesting the key.'),
|
|
278
|
+
purpose: z.string().max(200).optional().describe('Optional: one line on what the rates are for.'),
|
|
279
|
+
},
|
|
280
|
+
outputSchema: {
|
|
281
|
+
key: z.string().optional(),
|
|
282
|
+
calls: z.number().optional(),
|
|
283
|
+
expires_at: z.string().optional(),
|
|
284
|
+
adopted: z.boolean().describe('True when this server switched to the new key'),
|
|
285
|
+
note: z.string(),
|
|
286
|
+
},
|
|
287
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
288
|
+
}, async ({ agent, purpose }) => {
|
|
289
|
+
try {
|
|
290
|
+
return ok(await client.requestTrialKey({ agent, purpose }));
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
return fail(err);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
238
296
|
const transport = new StdioServerTransport();
|
|
239
297
|
await server.connect(transport);
|
|
240
298
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allratestoday/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"mcpName": "io.github.cahthuranag/mcp-server",
|
|
5
5
|
"description": "MCP server for AllRatesToday — let AI coding tools (Claude Code, Cursor, Claude Desktop) fetch real-time and historical currency exchange rates.",
|
|
6
6
|
"keywords": [
|