@allratestoday/mcp-server 0.5.2 → 0.6.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 +65 -5
- package/dist/client.d.ts +21 -0
- package/dist/client.js +27 -2
- package/dist/index.js +66 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ After installation, your assistant can answer questions like:
|
|
|
21
21
|
|
|
22
22
|
- 📡 **Live mid-market rates** — 150+ ISO 4217 currencies, refreshed every ~60 seconds
|
|
23
23
|
- 📈 **Historical series built in** — `1d` / `7d` / `30d` / `1y` windows with sensible granularity per period
|
|
24
|
-
- 🧰 **
|
|
24
|
+
- 🧰 **Six focused tools** — `get_exchange_rate`, `get_historical_rates`, `get_rates_authenticated`, `list_currencies`, `list_central_banks`, `get_official_rates`; small surface, easy for the model to use correctly
|
|
25
25
|
- 🔌 **Works everywhere MCP does** — stdio transport, MCP 1.x; Claude Code, Cursor, Claude Desktop, Windsurf, or any generic host
|
|
26
26
|
- 🔓 **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
27
|
- 🛡️ **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
|
|
@@ -29,7 +29,7 @@ After installation, your assistant can answer questions like:
|
|
|
29
29
|
|
|
30
30
|
## ⚖️ Mid-market vs official central-bank rates
|
|
31
31
|
|
|
32
|
-
Everything this server returns is a **mid-market rate**, refreshed every ~60 seconds — the right number for price display, conversion, and anything that should track the market. It is *not* the official rate a tax authority or auditor may require. For those,
|
|
32
|
+
Everything this server returns is a **mid-market rate**, refreshed every ~60 seconds — the right number for price display, conversion, and anything that should track the market. It is *not* the official rate a tax authority or auditor may require. For those, call **`get_official_rates`**: the latest table published by any of 121 central banks and 3 tax authorities (ECB, Fed, HMRC, US Treasury, Swiss BAZG, …), fixed once published and carrying the institution's own `rate_date`, no key needed. `list_central_banks` gives the codes. Dated tables and history sit behind the free key — see the [central bank REST API](https://allratestoday.com/docs/#central-bank) and [per-bank npm SDKs](https://allratestoday.com/central-bank-rates-api/). The two can diverge by several percent, so pick by use case, not convenience.
|
|
33
33
|
|
|
34
34
|
## 🔓 Keyless mode — what works with no setup
|
|
35
35
|
|
|
@@ -39,6 +39,8 @@ Install it with no configuration at all and it starts, connects, and answers:
|
|
|
39
39
|
|---|---|---|
|
|
40
40
|
| `get_exchange_rate` | ✅ | Official **ECB daily reference rate**, ~30 major currencies. The response carries `rate_date` and a note saying so, so the assistant never passes it off as a live quote. |
|
|
41
41
|
| `list_currencies` | ✅ | All 160+ supported ISO 4217 codes. |
|
|
42
|
+
| `list_central_banks` | ✅ | Codes, names and latest publication date of all 121 central banks + 3 tax authorities. |
|
|
43
|
+
| `get_official_rates` | ✅ | Latest **official table** (or one pair) published by any of them. A dated table needs the key. |
|
|
42
44
|
| `get_historical_rates` | 🔑 | Returns one sentence explaining how to get a free key. |
|
|
43
45
|
| `get_rates_authenticated` | 🔑 | Same. |
|
|
44
46
|
|
|
@@ -138,7 +140,7 @@ Edit `~/.cursor/mcp.json` (or `.cursor/mcp.json` inside your project for project
|
|
|
138
140
|
}
|
|
139
141
|
```
|
|
140
142
|
|
|
141
|
-
Restart Cursor. The
|
|
143
|
+
Restart Cursor. The six tools should appear in the MCP tool picker.
|
|
142
144
|
|
|
143
145
|
### Claude Desktop
|
|
144
146
|
|
|
@@ -185,7 +187,7 @@ npx -y @allratestoday/mcp-server
|
|
|
185
187
|
After configuring your client, test in this order:
|
|
186
188
|
|
|
187
189
|
1. **Server starts** — open the client. A red dot or "failed to connect" means the API key is missing or wrong (see Troubleshooting below).
|
|
188
|
-
2. **Tools are listed** — most clients have a "tools" or "MCP" panel showing the
|
|
190
|
+
2. **Tools are listed** — most clients have a "tools" or "MCP" panel showing the six tools.
|
|
189
191
|
3. **A live call returns a number** — ask: *"What's the current USD to EUR rate?"* The assistant should call `get_exchange_rate(source: "USD", target: "EUR")` and reply with a real rate. If it fabricates a number without a tool call, the server isn't connected.
|
|
190
192
|
|
|
191
193
|
## 📚 Tools reference
|
|
@@ -194,8 +196,10 @@ After configuring your client, test in this order:
|
|
|
194
196
|
- [`get_historical_rates`](#get_historical_rates) — time series over a preset period
|
|
195
197
|
- [`get_rates_authenticated`](#get_rates_authenticated) — multiple targets in one call, optional point-in-time
|
|
196
198
|
- [`list_currencies`](#list_currencies) — all supported currency codes, names, symbols
|
|
199
|
+
- [`list_central_banks`](#list_central_banks) — every covered central bank / tax authority with its code and latest publication date
|
|
200
|
+
- [`get_official_rates`](#get_official_rates) — the official table (or one pair) a named institution published
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
`get_historical_rates` and `get_rates_authenticated` require `ALLRATES_API_KEY`; the other four work keyless.
|
|
199
203
|
|
|
200
204
|
---
|
|
201
205
|
|
|
@@ -315,6 +319,61 @@ All supported currencies with codes, names, and symbols. Cached upstream for 24
|
|
|
315
319
|
|
|
316
320
|
---
|
|
317
321
|
|
|
322
|
+
### `list_central_banks`
|
|
323
|
+
|
|
324
|
+
Every official source the server can quote — 121 central banks plus HMRC, the US Treasury and Swiss BAZG — with the `code` that `get_official_rates` takes as `bank`, the institution's name, its latest publication date and a `stale` flag when it is behind its own schedule. Keyless.
|
|
325
|
+
|
|
326
|
+
**Input** — none.
|
|
327
|
+
|
|
328
|
+
**Response (truncated):**
|
|
329
|
+
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"sources": [
|
|
333
|
+
{ "code": "ecb", "name": "European Central Bank", "latest": "2026-09-30", "stale": false },
|
|
334
|
+
{ "code": "fed", "name": "Federal Reserve", "latest": "2026-09-29", "stale": false },
|
|
335
|
+
"..."
|
|
336
|
+
],
|
|
337
|
+
"stale_count": 0,
|
|
338
|
+
"checked_at": "2026-10-01T09:00:00Z"
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### `get_official_rates`
|
|
345
|
+
|
|
346
|
+
The fixed, citable rate an institution published — for invoices, VAT and tax returns, customs, transfer pricing and audit. Not a live market rate.
|
|
347
|
+
|
|
348
|
+
**Input:**
|
|
349
|
+
|
|
350
|
+
| Field | Type | Required | Description |
|
|
351
|
+
|---|---|---|---|
|
|
352
|
+
| `bank` | string | yes | Source code from `list_central_banks`, e.g. `ecb`, `fed`, `boe`, `rbi`, `hmrc` |
|
|
353
|
+
| `date` | string | no | `YYYY-MM-DD`. Omit for the latest table (keyless). Needs the API key. Weekends/holidays roll back to the last published date. |
|
|
354
|
+
| `source` | string | no | With `target`, narrows to one pair |
|
|
355
|
+
| `target` | string | no | With `source`, narrows to one pair |
|
|
356
|
+
|
|
357
|
+
**Response (one pair):**
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"bank": "ecb",
|
|
362
|
+
"rate_date": "2026-09-30",
|
|
363
|
+
"source": "EUR",
|
|
364
|
+
"target": "USD",
|
|
365
|
+
"rate": 1.1355,
|
|
366
|
+
"rate_type": "reference",
|
|
367
|
+
"derived": false,
|
|
368
|
+
"method": "published",
|
|
369
|
+
"attribution": { "source": "Official rates published by ECB, served by AllRatesToday", "url": "https://allratestoday.com/central-bank-rates-api/ecb/", "terms": "Free to use with visible attribution linking to allratestoday.com" }
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Omit `source`/`target` for the whole table as `rates: [{ base, quote, type, value }]`. Pairs the bank does not publish directly are cross-computed inside its own table and flagged `derived: true`. Always cite `rate_date`.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
318
377
|
## ⚙️ Environment variables
|
|
319
378
|
|
|
320
379
|
| Variable | Default | Required | Purpose |
|
|
@@ -415,6 +474,7 @@ server.json # MCP registry manifest
|
|
|
415
474
|
|
|
416
475
|
See [GitHub Releases](https://github.com/cahthuranag/mcp-server/releases) for the full list. Recent highlights:
|
|
417
476
|
|
|
477
|
+
- **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)
|
|
418
478
|
- **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
|
|
419
479
|
- **0.4.x** — README overhaul; registry metadata updates
|
|
420
480
|
- **0.3.x** — API key required for all tools; fail-fast at startup with clear error
|
package/dist/client.d.ts
CHANGED
|
@@ -50,6 +50,27 @@ export declare class AllRatesTodayClient {
|
|
|
50
50
|
target: string;
|
|
51
51
|
time: string;
|
|
52
52
|
}[]>;
|
|
53
|
+
/** Every covered official source (121 central banks + 3 tax authorities). Keyless. */
|
|
54
|
+
listCentralBanks(): Promise<{
|
|
55
|
+
sources: {
|
|
56
|
+
code: string;
|
|
57
|
+
name: string;
|
|
58
|
+
latest: string | null;
|
|
59
|
+
stale?: boolean;
|
|
60
|
+
}[];
|
|
61
|
+
stale_count: number;
|
|
62
|
+
checked_at: string;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Latest OFFICIAL table published by a central bank or tax authority, or one
|
|
66
|
+
* pair from it (cross-computed inside the bank's own table when not published
|
|
67
|
+
* directly, flagged `derived`). Keyless; a dated table needs the key.
|
|
68
|
+
*/
|
|
69
|
+
getOfficialRates(bank: string, params?: {
|
|
70
|
+
date?: string;
|
|
71
|
+
source?: string;
|
|
72
|
+
target?: string;
|
|
73
|
+
}): Promise<Record<string, unknown>>;
|
|
53
74
|
listSymbols(): Promise<{
|
|
54
75
|
currencies: {
|
|
55
76
|
code: string;
|
package/dist/client.js
CHANGED
|
@@ -20,8 +20,8 @@ export class NeedsKeyError extends AllRatesTodayError {
|
|
|
20
20
|
super(`${what} needs an AllRatesToday API key. The free tier covers it — sign up at ` +
|
|
21
21
|
'https://allratestoday.com/register (no card, under a minute), then set ALLRATES_API_KEY ' +
|
|
22
22
|
"in this MCP server's config and restart. Without a key the server still answers " +
|
|
23
|
-
'get_exchange_rate for ~30 major currencies (official ECB daily reference rate)
|
|
24
|
-
'list_currencies.');
|
|
23
|
+
'get_exchange_rate for ~30 major currencies (official ECB daily reference rate), ' +
|
|
24
|
+
'list_currencies, list_central_banks and get_official_rates (latest tables).');
|
|
25
25
|
this.name = 'NeedsKeyError';
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -109,6 +109,31 @@ export class AllRatesTodayClient {
|
|
|
109
109
|
return Promise.reject(new NeedsKeyError('Multi-target and point-in-time rates'));
|
|
110
110
|
return this.request('/v1/rates', params);
|
|
111
111
|
}
|
|
112
|
+
/** Every covered official source (121 central banks + 3 tax authorities). Keyless. */
|
|
113
|
+
listCentralBanks() {
|
|
114
|
+
return this.request(this.keyless ? '/open/central-banks' : '/v1/central-banks', {});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Latest OFFICIAL table published by a central bank or tax authority, or one
|
|
118
|
+
* pair from it (cross-computed inside the bank's own table when not published
|
|
119
|
+
* directly, flagged `derived`). Keyless; a dated table needs the key.
|
|
120
|
+
*/
|
|
121
|
+
getOfficialRates(bank, params = {}) {
|
|
122
|
+
const code = bank.trim().toLowerCase();
|
|
123
|
+
if (!/^[a-z0-9_-]{2,20}$/.test(code)) {
|
|
124
|
+
return Promise.reject(new AllRatesTodayError(`Unknown source code "${bank}" — call list_central_banks first.`));
|
|
125
|
+
}
|
|
126
|
+
if (Boolean(params.source) !== Boolean(params.target)) {
|
|
127
|
+
return Promise.reject(new AllRatesTodayError('Provide both source and target, or neither.'));
|
|
128
|
+
}
|
|
129
|
+
const pair = { source: params.source?.toUpperCase(), target: params.target?.toUpperCase() };
|
|
130
|
+
if (this.keyless) {
|
|
131
|
+
if (params.date)
|
|
132
|
+
return Promise.reject(new NeedsKeyError(`The ${code} table for ${params.date}`));
|
|
133
|
+
return this.request(`/open/central-bank/${encodeURIComponent(code)}`, pair);
|
|
134
|
+
}
|
|
135
|
+
return this.request(`/v1/central-bank/${encodeURIComponent(code)}/${params.date ?? 'latest'}`, pair);
|
|
136
|
+
}
|
|
112
137
|
listSymbols() {
|
|
113
138
|
return this.request('/v1/symbols', {});
|
|
114
139
|
}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,8 @@ async function main() {
|
|
|
43
43
|
' Available now, no key needed:',
|
|
44
44
|
' • get_exchange_rate — official ECB daily reference rate, ~30 major currencies',
|
|
45
45
|
' • list_currencies — all supported currency codes',
|
|
46
|
+
' • list_central_banks — 121 central banks + 3 tax authorities we carry',
|
|
47
|
+
' • get_official_rates — latest official table (or one pair) from any of them',
|
|
46
48
|
'',
|
|
47
49
|
' Needs a free API key (real-time mid-market rates for 160+ currencies,',
|
|
48
50
|
' historical series, multi-target and point-in-time lookups):',
|
|
@@ -169,6 +171,70 @@ async function main() {
|
|
|
169
171
|
return fail(err);
|
|
170
172
|
}
|
|
171
173
|
});
|
|
174
|
+
server.registerTool('list_central_banks', {
|
|
175
|
+
title: 'List covered central banks & tax authorities',
|
|
176
|
+
description: "Call this FIRST when you need a bank code, or for 'which central banks do you cover?' / 'do you have rates from X?'. Returns every covered source — 121 central banks plus 3 tax authorities (HMRC, US Treasury, Swiss BAZG) — with `code` (what get_official_rates takes as `bank`), name, latest publication date and whether it is behind schedule. No API key needed.",
|
|
177
|
+
inputSchema: {},
|
|
178
|
+
outputSchema: {
|
|
179
|
+
sources: z.array(z.object({
|
|
180
|
+
code: z.string(),
|
|
181
|
+
name: z.string(),
|
|
182
|
+
latest: z.string().nullable(),
|
|
183
|
+
stale: z.boolean().optional(),
|
|
184
|
+
}).passthrough()),
|
|
185
|
+
stale_count: z.number(),
|
|
186
|
+
checked_at: z.string(),
|
|
187
|
+
},
|
|
188
|
+
annotations: READ_ONLY,
|
|
189
|
+
}, async () => {
|
|
190
|
+
try {
|
|
191
|
+
return ok(await client.listCentralBanks());
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
return fail(err);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
server.registerTool('get_official_rates', {
|
|
198
|
+
title: "Get a bank's official published rates",
|
|
199
|
+
description: "OFFICIAL rates a named institution published — 'what is the ECB rate for USD?', 'Bank of Japan rate today', 'HMRC rate for invoicing'. These are the fixed, citable rates for compliance, tax, customs and accounting — NOT live market rates (use get_exchange_rate for those). Omit `date` for the newest published table (no API key needed); give `date` (API key) for the table in force that day — weekends/holidays roll back to the last published date and the response's `rate_date` says which. Omit source/target for the full table; give both for one pair — cross-computed inside the bank's own table when not directly published, flagged `derived`. Always cite the returned `rate_date`.",
|
|
200
|
+
inputSchema: {
|
|
201
|
+
bank: z
|
|
202
|
+
.string()
|
|
203
|
+
.regex(/^[A-Za-z0-9_-]{2,20}$/)
|
|
204
|
+
.describe("Source code from list_central_banks, e.g. 'ecb', 'fed', 'boe', 'rbi', 'hmrc'. Case-insensitive."),
|
|
205
|
+
date: z
|
|
206
|
+
.string()
|
|
207
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
208
|
+
.optional()
|
|
209
|
+
.describe('Optional YYYY-MM-DD. Omit for the latest table.'),
|
|
210
|
+
source: ccy.optional().describe('Optional. With target, narrows to one pair.'),
|
|
211
|
+
target: ccy.optional().describe('Optional. With source, narrows to one pair.'),
|
|
212
|
+
},
|
|
213
|
+
outputSchema: {
|
|
214
|
+
bank: z.string(),
|
|
215
|
+
rate_date: z.string().describe('Publication date of the table — cite this, not today'),
|
|
216
|
+
// Full table (no pair given)
|
|
217
|
+
rates: z
|
|
218
|
+
.array(z.object({ base: z.string(), quote: z.string(), type: z.string(), value: z.number() }))
|
|
219
|
+
.optional(),
|
|
220
|
+
// One pair (source + target given)
|
|
221
|
+
source: z.string().optional(),
|
|
222
|
+
target: z.string().optional(),
|
|
223
|
+
rate: z.number().optional(),
|
|
224
|
+
rate_type: z.string().optional(),
|
|
225
|
+
derived: z.boolean().optional().describe('True when cross-computed inside the bank table'),
|
|
226
|
+
stale: z.boolean().optional().describe('True when the institution is behind its publication schedule'),
|
|
227
|
+
attribution: z.object({ source: z.string(), url: z.string(), terms: z.string() }).passthrough().optional(),
|
|
228
|
+
},
|
|
229
|
+
annotations: READ_ONLY,
|
|
230
|
+
}, async ({ bank, date, source, target }) => {
|
|
231
|
+
try {
|
|
232
|
+
return ok(await client.getOfficialRates(bank, { date, source, target }));
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
return fail(err);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
172
238
|
const transport = new StdioServerTransport();
|
|
173
239
|
await server.connect(transport);
|
|
174
240
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allratestoday/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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": [
|