@allratestoday/mcp-server 0.7.3 β†’ 0.7.5

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 CHANGED
@@ -21,17 +21,17 @@ After installation, your assistant can answer questions like:
21
21
 
22
22
  ## πŸš€ Why this server?
23
23
 
24
- - πŸ“‘ **Live mid-market rates** β€” 150+ ISO 4217 currencies, refreshed every ~60 seconds
24
+ - πŸ“‘ **Live mid-market rates** β€” 160+ ISO 4217 currencies, refreshed every ~60 seconds
25
25
  - πŸ“ˆ **Historical series built in** β€” `1d` / `7d` / `30d` / `1y` windows with sensible granularity per period
26
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
27
27
  - πŸ”Œ **Works everywhere MCP does** β€” stdio transport, MCP 1.x; Claude Code, Cursor, Claude Desktop, Windsurf, or any generic host
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
28
+ - πŸ”“ **Works with no API key** β€” installs and answers out of the box from open official central-bank tables (ECB first, else the bank that issues one of the two currencies); a free key unlocks real-time rates for 160+ currencies
29
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
30
30
  - πŸ”’ **Nothing leaks** β€” only the request parameters and your API key ever reach allratestoday.com; never conversation context
31
31
 
32
32
  ## βš–οΈ Mid-market vs official central-bank rates
33
33
 
34
- 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.
34
+ With a key, `get_exchange_rate`, `get_historical_rates` and `get_rates_authenticated` return 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 official tables (a past `date`) need an API key on a **paid plan** β€” a free key gets `403 Historical central bank rates require a paid plan`; mid-market history (`get_historical_rates`) works on 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.
35
35
 
36
36
  ## πŸ”“ Keyless mode β€” what works with no setup
37
37
 
@@ -39,23 +39,25 @@ Install it with no configuration at all and it starts, connects, and answers:
39
39
 
40
40
  | Tool | Keyless | What you get |
41
41
  |---|---|---|
42
- | `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. |
42
+ | `get_exchange_rate` | βœ… | An **official central-bank rate**: the ECB reference table first, else the central bank that issues the target or source currency (USD/GBP β†’ Bank of England, USD/INR β†’ Reserve Bank of India). The response carries `bank`, `rate_date`, `derived` and a note saying so, so the assistant never passes it off as a live quote. Only pairs one bank publishes, or their inverses (flagged `derived: true`), work keyless; other crosses are refused with a pointer to the key. |
43
43
  | `list_currencies` | βœ… | All 160+ supported ISO 4217 codes. |
44
44
  | `list_central_banks` | βœ… | Codes, names and latest publication date of all 121 central banks + 3 tax authorities. |
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. |
45
+ | `get_official_rates` | βœ… | Latest **official table** (or one pair) published by any of them. A dated table needs a paid-plan 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 a paid-plan key. |
47
47
  | `request_trial_key` | βœ… | Self-issues a 100-call, 7-day key with no account and adopts it for the session. |
48
- | `get_historical_rates` | πŸ”‘ | Returns one sentence explaining how to get a free key. |
48
+ | `get_historical_rates` | πŸ”‘ | Returns one sentence explaining how to get a key. Needs a paid plan. |
49
49
  | `get_rates_authenticated` | πŸ”‘ | Same. |
50
50
 
51
- The keyless path reads the open, edge-cached `/api/open/central-bank/ecb`
52
- endpoint β€” no upstream cost, no rate limit to trip over, nothing to sign up for.
51
+ The keyless path reads the open, edge-cached `/api/open/central-bank/{bank}`
52
+ endpoints β€” no upstream cost, no rate limit to trip over, nothing to sign up for.
53
53
 
54
54
  ## πŸ”‘ Get your API key (free)
55
55
 
56
- A key unlocks **real-time mid-market rates across 160+ currencies**, historical
57
- series, and multi-target / point-in-time lookups. The free tier is enough for
58
- development and personal use β€” **no credit card required**.
56
+ A key unlocks **real-time mid-market rates across 160+ currencies** and
57
+ multi-target lookups. The free tier (300 requests, lifetime β€” it does not reset
58
+ monthly) is enough for development and trying it out β€” **no credit card required**.
59
+ Historical series, point-in-time lookups and dated official and reference-rate
60
+ tables need a paid plan from €4.99/month.
59
61
 
60
62
  1. Register at [allratestoday.com/register](https://allratestoday.com/register) β€” 30 seconds
61
63
  2. Verify your email
@@ -82,7 +84,7 @@ Everything below still applies for other MCP clients.
82
84
 
83
85
  ## ☁️ Hosted endpoint β€” nothing to install
84
86
 
85
- The same tools also run as a hosted **Streamable HTTP** MCP server (together with the tools of the sibling AllRatesToday server, nine in total). Paste the URL into any client that supports remote MCP β€” Claude.ai and Claude Desktop connectors, ChatGPT, Cursor, VS Code, Codex, Gemini CLI:
87
+ The same tools also run as a hosted **Streamable HTTP** MCP server, which lists **11 tools**: the 8 of this stdio package plus `get_official_rate_history`, `compare_official_rates` and `get_publication_calendar` from the sibling central-bank server. Paste the URL into any client that supports remote MCP β€” Claude.ai and Claude Desktop connectors, ChatGPT, Cursor, VS Code, Codex, Gemini CLI:
86
88
 
87
89
  ```
88
90
  https://allratestoday.com/api/mcp
@@ -144,7 +146,7 @@ Edit `~/.cursor/mcp.json` (or `.cursor/mcp.json` inside your project for project
144
146
  }
145
147
  ```
146
148
 
147
- Restart Cursor. The six tools should appear in the MCP tool picker.
149
+ Restart Cursor. The eight tools should appear in the MCP tool picker.
148
150
 
149
151
  ### Claude Desktop
150
152
 
@@ -190,8 +192,8 @@ npx -y @allratestoday/mcp-server
190
192
 
191
193
  After configuring your client, test in this order:
192
194
 
193
- 1. **Server starts** β€” open the client. A red dot or "failed to connect" means the API key is missing or wrong (see Troubleshooting below).
194
- 2. **Tools are listed** β€” most clients have a "tools" or "MCP" panel showing the six tools.
195
+ 1. **Server starts** β€” open the client. The server starts with or without a key (no key β‡’ keyless mode), so a red dot or "failed to connect" means the client could not launch it β€” usually `npx` or Node β‰₯18 (see Troubleshooting below). A wrong key does not stop it starting; calls then return `Invalid AllRatesToday API key`.
196
+ 2. **Tools are listed** β€” most clients have a "tools" or "MCP" panel showing the eight tools.
195
197
  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.
196
198
 
197
199
  ## πŸ“š Tools reference
@@ -205,7 +207,7 @@ After configuring your client, test in this order:
205
207
  - [`get_reference_rate`](#get_reference_rate) β€” the Daily Reference Rate, one fixed mid-market table per business day (16:00 London)
206
208
  - [`request_trial_key`](#request_trial_key) β€” self-issue a 100-call, 7-day trial key, no account needed
207
209
 
208
- `get_historical_rates` and `get_rates_authenticated` require `ALLRATES_API_KEY`; the other six work keyless.
210
+ `get_historical_rates` and `get_rates_authenticated` require `ALLRATES_API_KEY`; the other six of the eight work keyless. History (`get_historical_rates`, and `time` on `get_rates_authenticated`) needs a paid plan.
209
211
 
210
212
  ---
211
213
 
@@ -226,15 +228,30 @@ Current mid-market rate between two currencies.
226
228
  { "source": "USD", "target": "EUR" }
227
229
  ```
228
230
 
229
- **Response:**
231
+ **Response (with a key):**
232
+
233
+ ```json
234
+ { "rate": 0.888889, "source": "interbank" }
235
+ ```
236
+
237
+ **Response (keyless β€” `USD` β†’ `GBP`, not in the ECB table, so the Bank of England table answers):**
230
238
 
231
239
  ```json
232
- { "rate": 0.92145, "source": "wise" }
240
+ {
241
+ "rate": 0.7598784195,
242
+ "source": "Bank of England official rate (keyless mode)",
243
+ "bank": "boe",
244
+ "rate_date": "2026-10-14",
245
+ "derived": true,
246
+ "note": "Keyless mode: this is the Bank of England official rate published on 2026-10-14, not a live mid-market quote. For real-time rates across 160+ currencies set ALLRATES_API_KEY β€” free tier at https://allratestoday.com/register."
247
+ }
233
248
  ```
234
249
 
250
+ `derived: true` means the bank publishes the inverse (GBPβ†’USD) and the rate was inverted. A pair no single bank publishes is refused keyless with `No keyless official source covers …` and a pointer to the key.
251
+
235
252
  ### `get_historical_rates`
236
253
 
237
- Time-series data points for a currency pair over a fixed period.
254
+ Time-series data points for a currency pair over a fixed period. Needs an API key on a paid plan (free and trial keys get a 403).
238
255
 
239
256
  **Input**
240
257
 
@@ -267,9 +284,10 @@ Time-series data points for a currency pair over a fixed period.
267
284
  "target": "INR",
268
285
  "period": "30d",
269
286
  "data": [
270
- { "date": "2026-03-27T00:00:00Z", "rate": 83.42, "timestamp": 1743033600000 },
271
- { "date": "2026-03-28T00:00:00Z", "rate": 83.51, "timestamp": 1743120000000 },
272
- "..."
287
+ { "date": "2026-09-17", "rate": 96.1006, "timestamp": 1789603200000 },
288
+ { "date": "2026-09-18", "rate": 95.8142, "timestamp": 1789689600000 },
289
+ "...",
290
+ { "date": "2026-10-16", "rate": 94.9643, "timestamp": 1792108800000 }
273
291
  ]
274
292
  }
275
293
  ```
@@ -284,7 +302,7 @@ Multiple targets in one call, with optional historical timestamp or grouping win
284
302
  |---|---|---|---|
285
303
  | `source` | string | yes | Source currency code |
286
304
  | `target` | string | yes | One or more codes, comma-separated (`EUR,GBP,JPY`) |
287
- | `time` | string (ISO 8601) | no | Historical point in time |
305
+ | `time` | string (ISO 8601) | no | Historical point in time (paid plans) |
288
306
  | `group` | string | no | One of `hour`, `day`, `week`, `month` |
289
307
 
290
308
  **Example call**
@@ -296,11 +314,13 @@ Multiple targets in one call, with optional historical timestamp or grouping win
296
314
  **Response:**
297
315
 
298
316
  ```json
299
- [
300
- { "rate": 0.9214, "source": "USD", "target": "EUR", "time": "2026-04-26T11:00:00Z" },
301
- { "rate": 0.7891, "source": "USD", "target": "GBP", "time": "2026-04-26T11:00:00Z" },
302
- { "rate": 151.34, "source": "USD", "target": "JPY", "time": "2026-04-26T11:00:00Z" }
303
- ]
317
+ {
318
+ "rates": [
319
+ { "rate": 0.888889, "source": "USD", "target": "EUR", "time": "2026-10-16T12:16:01+0000" },
320
+ { "rate": 0.749766, "source": "USD", "target": "GBP", "time": "2026-10-16T12:16:01+0000" },
321
+ { "rate": 157.985, "source": "USD", "target": "JPY", "time": "2026-10-16T12:16:01+0000" }
322
+ ]
323
+ }
304
324
  ```
305
325
 
306
326
  ### `list_currencies`
@@ -319,7 +339,7 @@ All supported currencies with codes, names, and symbols. Cached upstream for 24
319
339
  { "code": "GBP", "name": "British Pound", "symbol": "Β£" },
320
340
  "..."
321
341
  ],
322
- "count": 162
342
+ "count": 163
323
343
  }
324
344
  ```
325
345
 
@@ -327,7 +347,7 @@ All supported currencies with codes, names, and symbols. Cached upstream for 24
327
347
 
328
348
  ### `list_central_banks`
329
349
 
330
- 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.
350
+ 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, `age_days`, its publication `cadence` and a `stale` flag when it is behind its own schedule. Keyless.
331
351
 
332
352
  **Input** β€” none.
333
353
 
@@ -336,12 +356,12 @@ Every official source the server can quote β€” 121 central banks plus HMRC, the
336
356
  ```json
337
357
  {
338
358
  "sources": [
339
- { "code": "ecb", "name": "European Central Bank", "latest": "2026-09-30", "stale": false },
340
- { "code": "fed", "name": "Federal Reserve", "latest": "2026-09-29", "stale": false },
359
+ { "code": "ecb", "name": "European Central Bank", "latest": "2026-10-15", "age_days": 1, "stale": false, "cadence": "daily" },
360
+ { "code": "fed", "name": "US Federal Reserve (H.10)", "latest": "2026-10-09", "age_days": 7, "stale": false, "cadence": "weekly" },
341
361
  "..."
342
362
  ],
343
- "stale_count": 0,
344
- "checked_at": "2026-10-01T09:00:00Z"
363
+ "stale_count": 3,
364
+ "checked_at": "2026-10-16T12:16:46.232Z"
345
365
  }
346
366
  ```
347
367
 
@@ -356,7 +376,7 @@ The fixed, citable rate an institution published β€” for invoices, VAT and tax r
356
376
  | Field | Type | Required | Description |
357
377
  |---|---|---|---|
358
378
  | `bank` | string | yes | Source code from `list_central_banks`, e.g. `ecb`, `fed`, `boe`, `rbi`, `hmrc` |
359
- | `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. |
379
+ | `date` | string | no | `YYYY-MM-DD`. Omit for the latest table (keyless). Needs an API key on a **paid plan** β€” a free key gets `403 Historical central bank rates require a paid plan`. Weekends/holidays roll back to the last published date. |
360
380
  | `source` | string | no | With `target`, narrows to one pair |
361
381
  | `target` | string | no | With `source`, narrows to one pair |
362
382
 
@@ -365,18 +385,21 @@ The fixed, citable rate an institution published β€” for invoices, VAT and tax r
365
385
  ```json
366
386
  {
367
387
  "bank": "ecb",
368
- "rate_date": "2026-09-30",
388
+ "rate_date": "2026-10-15",
369
389
  "source": "EUR",
370
390
  "target": "USD",
371
- "rate": 1.1355,
391
+ "rate": 1.1208,
372
392
  "rate_type": "reference",
373
393
  "derived": false,
374
394
  "method": "published",
395
+ "age_days": 1,
396
+ "stale": false,
397
+ "cadence": "daily",
375
398
  "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" }
376
399
  }
377
400
  ```
378
401
 
379
- 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`.
402
+ Omit `source`/`target` for the whole table as `rates: [{ base, quote, type, value }]`. Keyless, only pairs the bank publishes and their inverses (flagged `derived: true`) are served; other crosses are refused. With a key, pairs the bank does not publish directly are cross-computed inside its own table and flagged `derived: true`. Always cite `rate_date`.
380
403
 
381
404
  ---
382
405
 
@@ -390,7 +413,7 @@ AllRatesToday's **Daily Reference Rate**: the per-currency median of samples tak
390
413
  |---|---|---|---|
391
414
  | `source` | string | no | With `target`, narrows to one pair (crossed via USD, flagged `derived`) |
392
415
  | `target` | string | no | See above |
393
- | `date` | string | no | Past business day `YYYY-MM-DD` (API key). Omit for the latest table |
416
+ | `date` | string | no | Past business day `YYYY-MM-DD` (API key on a paid plan). Omit for the latest table |
394
417
 
395
418
  **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
419
 
@@ -410,23 +433,25 @@ Self-issues an API key with 100 lifetime calls, valid 7 days, with no account an
410
433
 
411
434
  | Variable | Default | Required | Purpose |
412
435
  |---|---|---|---|
413
- | `ALLRATES_API_KEY` | β€” | no | Your API key. Unset β‡’ keyless mode (see above); set β‡’ real-time rates and the historical tools. |
436
+ | `ALLRATES_API_KEY` | β€” | no | Your API key, sent as `Authorization: Bearer`. Unset β‡’ keyless mode (see above); set β‡’ real-time rates and the historical tools. |
414
437
  | `ALLRATES_BASE_URL` | `https://allratestoday.com/api` | no | Override for self-hosted or staging deployments. |
415
438
 
416
439
  Set these in your MCP client's config (in the `env` block) β€” not in your shell β€” because MCP servers are launched as subprocesses with isolated environments.
417
440
 
418
441
  ## πŸ’³ Plans
419
442
 
420
- A free tier and paid plans are available β€” see [allratestoday.com/pricing](https://allratestoday.com/pricing) for current quotas. All plans include the same currency coverage and historical depth; only the request quotas differ.
443
+ A free tier and paid plans are available β€” see [allratestoday.com/pricing](https://allratestoday.com/pricing) for current quotas. The free tier is 300 requests, lifetime (it never resets), and covers real-time rates, mid-market history and multi-target lookups. Dated official and reference-rate tables need a paid plan. The Official Rates plan covers official central-bank and tax-authority rates only (no market rates).
421
444
 
422
445
  ## πŸ› οΈ Troubleshooting
423
446
 
424
447
  | Symptom | Likely cause | Fix |
425
448
  |---|---|---|
426
449
  | Client shows "MCP server failed to start" or red dot | Not a missing key β€” 0.5.0+ starts fine without one. Usually `npx` cannot reach the registry, or Node is older than 18 | Run `npx -y @allratestoday/mcp-server` in a shell and read stderr |
427
- | Rates look like yesterday's, response mentions "keyless mode" | No key set, so answers come from the ECB daily reference table | Set `ALLRATES_API_KEY` for real-time mid-market rates |
450
+ | Rates look like yesterday's, response mentions "keyless mode" | No key set, so answers come from an official central-bank table (see `bank` and `rate_date`) | Set `ALLRATES_API_KEY` for real-time mid-market rates |
451
+ | `No keyless official source covers X/Y` | Keyless mode, and no single central bank publishes that pair or its inverse | Set `ALLRATES_API_KEY` (free) |
452
+ | `HTTP 403 β€” Historical central bank rates require a paid plan` | `date` given to `get_official_rates` / `get_reference_rate` on a free key | Omit `date` for the latest table, or upgrade at /pricing |
428
453
  | Every call returns "Invalid AllRatesToday API key" | Key is malformed (missing prefix, truncated, or revoked) | Copy a fresh key from the dashboard |
429
- | Tools return "AllRatesToday API quota exceeded" | Monthly limit hit | Wait until next month or upgrade plan |
454
+ | Tools return "AllRatesToday API quota exceeded" | Quota used up β€” the free tier is 300 requests lifetime and never resets; paid plans are monthly | Upgrade at [/pricing](https://allratestoday.com/pricing) |
430
455
  | Historical tool returns "Bad request" | Invalid period or unknown currency code | Period must be `1d`/`7d`/`30d`/`1y`; codes must be 3 letters |
431
456
  | Server starts but tools never appear | Client didn't reload after config change | Fully quit (not just close) and reopen the client |
432
457
  | `npx` runs but hangs forever | The server is waiting for an MCP client to connect β€” normal when run from a shell | Let your MCP client launch it |
@@ -448,13 +473,15 @@ The server maps API errors to clear, actionable messages the assistant can relay
448
473
  | 200 | Success | (rate returned) |
449
474
  | 400 | Bad request β€” usually unknown currency code | `Bad request β€” possibly an unknown currency code` |
450
475
  | 401 | Invalid or missing API key | `Invalid AllRatesToday API key` |
476
+ | 403 | Plan does not include it (e.g. a dated official table on a free key) | `HTTP 403 β€” <upstream message>` |
477
+ | 404 (keyless) | No keyless official source covers the pair | `No keyless official source covers X/Y. …` |
451
478
  | 429 | Quota exceeded | `AllRatesToday API quota exceeded` |
452
479
  | 5xx | Server-side issue at allratestoday.com | `HTTP 5xx β€” <upstream message>` |
453
480
 
454
481
  ## ❓ FAQ
455
482
 
456
483
  **Is the free plan really enough for normal use?**
457
- Yes for personal/dev use. Heavy interactive use, multiple chat sessions per day, or production should consider the paid tiers.
484
+ For trying it out and light dev use. It is 300 requests in total (lifetime, no monthly reset); regular use or production needs a paid tier. Keyless mode costs nothing and has no quota.
458
485
 
459
486
  **Do you store my conversation or query data?**
460
487
  No. Only your API key and the request parameters (source, target, period, time) are sent to allratestoday.com β€” never the LLM's conversation context.
@@ -495,7 +522,8 @@ ALLRATES_BASE_URL=http://localhost:8080/api ALLRATES_API_KEY=test_key node dist/
495
522
  ```
496
523
  src/
497
524
  β”œβ”€β”€ index.ts # MCP server, tool registration, request handlers
498
- └── client.ts # HTTP client for AllRatesToday API + error mapping
525
+ β”œβ”€β”€ client.ts # HTTP client for AllRatesToday API + error mapping
526
+ └── home-banks.ts # currency β†’ issuing central bank, for the keyless get_exchange_rate fallback
499
527
  dist/ # Compiled JS (gitignored)
500
528
  server.json # MCP registry manifest
501
529
  ```
@@ -506,6 +534,7 @@ server.json # MCP registry manifest
506
534
 
507
535
  See [GitHub Releases](https://github.com/AllRates-Today/mcp-server/releases) for the full list. Recent highlights:
508
536
 
537
+ - **0.7.4** β€” Keyless `get_exchange_rate` falls back from the ECB table to the central bank that issues the target or source currency (USD/GBP, GBP/JPY, USD/INR now answer keyless), same as the hosted endpoint; response adds `bank`. Dated-table errors say a paid plan is needed. README: real response shapes, tool counts, 300-lifetime free tier
509
538
  - **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)
510
539
  - **0.6.1** β€” README: Claude Code plugin and hosted `/api/mcp` endpoint cross-links; coverage wording refreshed
511
540
  - **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)
package/dist/client.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare class AllRatesTodayError extends Error {
14
14
  * rather than a bare 401.
15
15
  */
16
16
  export declare class NeedsKeyError extends AllRatesTodayError {
17
- constructor(what: string);
17
+ constructor(what: string, paid?: boolean);
18
18
  }
19
19
  export declare class AllRatesTodayClient {
20
20
  private apiKey?;
@@ -29,7 +29,7 @@ export declare class AllRatesTodayClient {
29
29
  /**
30
30
  * Daily Reference Rate: one never-revised mid-market table per business day,
31
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.
32
+ * table and single pairs are keyless; a dated table needs a paid-plan key.
33
33
  */
34
34
  getReferenceRate(params?: {
35
35
  source?: string;
@@ -48,6 +48,13 @@ export declare class AllRatesTodayClient {
48
48
  getRate(source: string, target: string): Promise<{
49
49
  rate: number;
50
50
  source: string;
51
+ bank: string;
52
+ rate_date: string;
53
+ derived: boolean;
54
+ note: string;
55
+ } | {
56
+ rate: number;
57
+ source: string;
51
58
  }>;
52
59
  getHistoricalRates(source: string, target: string, period?: '1d' | '7d' | '30d' | '1y'): Promise<{
53
60
  source: string;
@@ -85,7 +92,7 @@ export declare class AllRatesTodayClient {
85
92
  /**
86
93
  * Latest OFFICIAL table published by a central bank or tax authority, or one
87
94
  * pair from it (cross-computed inside the bank's own table when not published
88
- * directly, flagged `derived`). Keyless; a dated table needs the key.
95
+ * directly, flagged `derived`). Keyless; a dated table needs a paid-plan key.
89
96
  */
90
97
  getOfficialRates(bank: string, params?: {
91
98
  date?: string;
package/dist/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { VERSION } from './version.js';
2
+ import { HOME_BANKS } from './home-banks.js';
2
3
  const DEFAULT_BASE_URL = 'https://allratestoday.com/api';
3
4
  export class AllRatesTodayError extends Error {
4
5
  status;
@@ -16,12 +17,17 @@ export class AllRatesTodayError extends Error {
16
17
  * rather than a bare 401.
17
18
  */
18
19
  export class NeedsKeyError extends AllRatesTodayError {
19
- constructor(what) {
20
- super(`${what} needs an AllRatesToday API key. The free tier covers it β€” sign up at ` +
21
- 'https://allratestoday.com/register (no card, under a minute), then set ALLRATES_API_KEY ' +
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, list_central_banks and get_official_rates (latest tables).');
20
+ constructor(what, paid = false) {
21
+ super(paid
22
+ ? `${what} needs an AllRatesToday API key on a paid plan (from €4.99/month; free and trial ` +
23
+ 'keys get 403 for historical rates and dated tables) β€” see https://allratestoday.com/pricing, ' +
24
+ "then set ALLRATES_API_KEY in this MCP server's config and restart. Latest rates and the latest " +
25
+ 'official tables need no paid plan.'
26
+ : `${what} needs an AllRatesToday API key. The free tier covers it β€” sign up at ` +
27
+ 'https://allratestoday.com/register (no card, under a minute), then set ALLRATES_API_KEY ' +
28
+ "in this MCP server's config and restart. Without a key the server still answers " +
29
+ 'get_exchange_rate from official central-bank tables (ECB first, then the issuing bank), ' +
30
+ 'list_currencies, list_central_banks and get_official_rates (latest tables).');
25
31
  this.name = 'NeedsKeyError';
26
32
  }
27
33
  }
@@ -88,7 +94,7 @@ export class AllRatesTodayClient {
88
94
  /**
89
95
  * Daily Reference Rate: one never-revised mid-market table per business day,
90
96
  * 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.
97
+ * table and single pairs are keyless; a dated table needs a paid-plan key.
92
98
  */
93
99
  getReferenceRate(params = {}) {
94
100
  if (Boolean(params.source) !== Boolean(params.target)) {
@@ -97,7 +103,7 @@ export class AllRatesTodayClient {
97
103
  const pair = { source: params.source?.toUpperCase(), target: params.target?.toUpperCase() };
98
104
  if (params.date) {
99
105
  if (this.keyless)
100
- return Promise.reject(new NeedsKeyError(`The reference-rate table for ${params.date}`));
106
+ return Promise.reject(new NeedsKeyError(`The reference-rate table for ${params.date}`, true));
101
107
  return this.request(`/v1/reference-rate/${encodeURIComponent(params.date)}`, pair);
102
108
  }
103
109
  return this.request('/open/reference-rate', pair);
@@ -140,27 +146,51 @@ export class AllRatesTodayClient {
140
146
  'at https://allratestoday.com/register (300 calls) or see https://allratestoday.com/pricing.',
141
147
  };
142
148
  }
143
- getRate(source, target) {
144
- // Keyless: fall back to the open, edge-cached ECB reference table. It is
145
- // the official daily fixing rather than a live mid-market quote and covers
146
- // ~30 majors, so the result is labelled for the model to relay honestly.
149
+ async getRate(source, target) {
150
+ // Keyless: answer from the open, edge-cached official tables. The ECB
151
+ // reference table goes first; when it does not cover the pair, the central
152
+ // bank that issues one of the two currencies almost always does (same
153
+ // order as the hosted /api/mcp server). Each answer is an official print
154
+ // with a publication date, not a live quote, so it is labelled for the
155
+ // model to relay honestly; `derived` is passed through from the API (true
156
+ // for an inverse or a cross inside that bank's own table).
147
157
  if (this.keyless) {
148
- return this.request('/open/central-bank/ecb', { source, target }).then((r) => ({
149
- rate: r.rate,
150
- source: 'ECB official daily reference rate (keyless mode)',
151
- rate_date: r.rate_date,
152
- derived: r.derived ?? false,
153
- note: 'Keyless mode: this is the European Central Bank reference rate published on ' +
154
- `${r.rate_date}, not a live mid-market quote, and covers ~30 major currencies. ` +
155
- 'For real-time rates across 160+ currencies set ALLRATES_API_KEY β€” free tier at ' +
156
- 'https://allratestoday.com/register.',
157
- }));
158
+ const candidates = [{ code: 'ecb', name: 'European Central Bank' }];
159
+ for (const c of [target, source]) {
160
+ const home = HOME_BANKS[c];
161
+ if (home && !candidates.some((x) => x.code === home.code))
162
+ candidates.push(home);
163
+ }
164
+ let lastErr;
165
+ for (const bank of candidates) {
166
+ try {
167
+ const r = await this.request(`/open/central-bank/${bank.code}`, { source, target });
168
+ return {
169
+ rate: r.rate,
170
+ source: `${bank.name} official rate (keyless mode)`,
171
+ bank: bank.code,
172
+ rate_date: r.rate_date,
173
+ derived: r.derived ?? false,
174
+ note: `Keyless mode: this is the ${bank.name} official rate published on ${r.rate_date}, ` +
175
+ 'not a live mid-market quote. For real-time rates across 160+ currencies set ' +
176
+ 'ALLRATES_API_KEY β€” free tier at https://allratestoday.com/register.',
177
+ };
178
+ }
179
+ catch (err) {
180
+ lastErr = err;
181
+ if (!(err instanceof AllRatesTodayError && err.status === 404))
182
+ throw err;
183
+ }
184
+ }
185
+ throw new AllRatesTodayError(`No keyless official source covers ${source}/${target}. Real-time rates for 160+ currencies ` +
186
+ 'need an API key β€” set ALLRATES_API_KEY (free tier at https://allratestoday.com/register).' +
187
+ (lastErr instanceof AllRatesTodayError ? ` Last upstream error: ${lastErr.message}` : ''), 404);
158
188
  }
159
189
  return this.request('/rate', { source, target });
160
190
  }
161
191
  getHistoricalRates(source, target, period = '7d') {
162
192
  if (this.keyless)
163
- return Promise.reject(new NeedsKeyError('Historical time-series'));
193
+ return Promise.reject(new NeedsKeyError('Historical time-series', true));
164
194
  return this.request('/historical-rates', { source, target, period });
165
195
  }
166
196
  getAuthenticatedRates(params) {
@@ -175,7 +205,7 @@ export class AllRatesTodayClient {
175
205
  /**
176
206
  * Latest OFFICIAL table published by a central bank or tax authority, or one
177
207
  * pair from it (cross-computed inside the bank's own table when not published
178
- * directly, flagged `derived`). Keyless; a dated table needs the key.
208
+ * directly, flagged `derived`). Keyless; a dated table needs a paid-plan key.
179
209
  */
180
210
  getOfficialRates(bank, params = {}) {
181
211
  const code = bank.trim().toLowerCase();
@@ -188,7 +218,7 @@ export class AllRatesTodayClient {
188
218
  const pair = { source: params.source?.toUpperCase(), target: params.target?.toUpperCase() };
189
219
  if (this.keyless) {
190
220
  if (params.date)
191
- return Promise.reject(new NeedsKeyError(`The ${code} table for ${params.date}`));
221
+ return Promise.reject(new NeedsKeyError(`The ${code} table for ${params.date}`, true));
192
222
  return this.request(`/open/central-bank/${encodeURIComponent(code)}`, pair);
193
223
  }
194
224
  return this.request(`/v1/central-bank/${encodeURIComponent(code)}/${params.date ?? 'latest'}`, pair);
@@ -0,0 +1,4 @@
1
+ export declare const HOME_BANKS: Readonly<Record<string, {
2
+ code: string;
3
+ name: string;
4
+ }>>;
@@ -0,0 +1,123 @@
1
+ // Home currency β†’ the central bank that issues it, for the keyless
2
+ // get_exchange_rate fallback (mirrors the hosted /api/mcp server). Generated
3
+ // from the site's central-banks list: first non-ECB central bank per home
4
+ // currency, tax authorities and composites excluded.
5
+ export const HOME_BANKS = {
6
+ USD: { code: "fed", name: "US Federal Reserve (H.10)" },
7
+ GBP: { code: "boe", name: "Bank of England" },
8
+ CNY: { code: "pboc", name: "People's Bank of China (CFETS)" },
9
+ AUD: { code: "rba", name: "Reserve Bank of Australia" },
10
+ RUB: { code: "cbr", name: "Bank of Russia" },
11
+ TRY: { code: "tcmb", name: "Central Bank of TΓΌrkiye" },
12
+ BRL: { code: "bcb", name: "Banco Central do Brasil (PTAX)" },
13
+ IDR: { code: "bi", name: "Bank Indonesia" },
14
+ INR: { code: "rbi", name: "Reserve Bank of India" },
15
+ CAD: { code: "boc", name: "Bank of Canada" },
16
+ MYR: { code: "bnm", name: "Bank Negara Malaysia" },
17
+ LKR: { code: "cbsl", name: "Central Bank of Sri Lanka" },
18
+ CZK: { code: "cnb", name: "Czech National Bank" },
19
+ PLN: { code: "nbp", name: "Narodowy Bank Polski" },
20
+ NOK: { code: "norges", name: "Norges Bank" },
21
+ SEK: { code: "riksbank", name: "Sveriges Riksbank" },
22
+ NGN: { code: "cbn", name: "Central Bank of Nigeria" },
23
+ KWD: { code: "cbk", name: "Central Bank of Kuwait" },
24
+ BHD: { code: "cbb", name: "Central Bank of Bahrain" },
25
+ AZN: { code: "cbar", name: "Central Bank of Azerbaijan" },
26
+ BAM: { code: "cbbh", name: "Central Bank of Bosnia and Herzegovina" },
27
+ EUR: { code: "bnb", name: "Bulgarian National Bank" },
28
+ PEN: { code: "bcrp", name: "Central Reserve Bank of Peru" },
29
+ JPY: { code: "boj", name: "Bank of Japan" },
30
+ HKD: { code: "hkma", name: "Hong Kong Monetary Authority" },
31
+ ILS: { code: "boi", name: "Bank of Israel" },
32
+ ARS: { code: "bcra", name: "Central Bank of Argentina" },
33
+ ZAR: { code: "sarb", name: "South African Reserve Bank" },
34
+ CHF: { code: "snb", name: "Swiss National Bank" },
35
+ NZD: { code: "rbnz", name: "Reserve Bank of New Zealand" },
36
+ KRW: { code: "bok", name: "Bank of Korea" },
37
+ RON: { code: "bnr", name: "National Bank of Romania" },
38
+ UAH: { code: "nbu", name: "National Bank of Ukraine" },
39
+ MXN: { code: "banxico", name: "Banco de MΓ©xico" },
40
+ PHP: { code: "bsp", name: "Bangko Sentral ng Pilipinas" },
41
+ DOP: { code: "bcrd", name: "Banco Central de la RepΓΊblica Dominicana" },
42
+ PYG: { code: "bcp", name: "Banco Central del Paraguay" },
43
+ KHR: { code: "nbc", name: "National Bank of Cambodia" },
44
+ GHS: { code: "bog", name: "Bank of Ghana" },
45
+ EGP: { code: "cbe", name: "Central Bank of Egypt" },
46
+ ALL: { code: "boa", name: "Bank of Albania" },
47
+ GTQ: { code: "banguat", name: "Banco de Guatemala" },
48
+ MNT: { code: "bom", name: "Bank of Mongolia" },
49
+ SGD: { code: "mas", name: "Monetary Authority of Singapore" },
50
+ DKK: { code: "dnb", name: "Danmarks Nationalbank" },
51
+ COP: { code: "sfc", name: "Superintendencia Financiera de Colombia (TRM)" },
52
+ KZT: { code: "nbk", name: "National Bank of Kazakhstan" },
53
+ GEL: { code: "nbg", name: "National Bank of Georgia" },
54
+ UZS: { code: "cbu", name: "Central Bank of Uzbekistan" },
55
+ HUF: { code: "mnb", name: "Magyar Nemzeti Bank" },
56
+ ISK: { code: "cbi", name: "Central Bank of Iceland" },
57
+ AED: { code: "cbuae", name: "Central Bank of the UAE" },
58
+ PKR: { code: "sbp", name: "State Bank of Pakistan" },
59
+ NPR: { code: "nrb", name: "Nepal Rastra Bank" },
60
+ JOD: { code: "cbj", name: "Central Bank of Jordan" },
61
+ BDT: { code: "bb", name: "Bangladesh Bank" },
62
+ OMR: { code: "cbo", name: "Central Bank of Oman" },
63
+ MMK: { code: "cbm", name: "Central Bank of Myanmar" },
64
+ TWD: { code: "cbc", name: "Central Bank of the Republic of China (Taiwan)" },
65
+ THB: { code: "bot", name: "Bank of Thailand" },
66
+ MOP: { code: "amcm", name: "Monetary Authority of Macao" },
67
+ VND: { code: "sbv", name: "State Bank of Vietnam" },
68
+ LAK: { code: "bol", name: "Bank of the Lao PDR" },
69
+ VES: { code: "bcv", name: "Central Bank of Venezuela" },
70
+ CLP: { code: "bcch", name: "Central Bank of Chile" },
71
+ UYU: { code: "bcu", name: "Central Bank of Uruguay" },
72
+ BOB: { code: "bcbol", name: "Banco Central de Bolivia" },
73
+ SRD: { code: "cbvs", name: "Central Bank of Suriname" },
74
+ GYD: { code: "bogy", name: "Bank of Guyana" },
75
+ SAR: { code: "sama", name: "Saudi Central Bank (SAMA)" },
76
+ MAD: { code: "bam", name: "Bank Al-Maghrib" },
77
+ RSD: { code: "nbs", name: "National Bank of Serbia" },
78
+ BYN: { code: "nbrb", name: "National Bank of the Republic of Belarus" },
79
+ QAR: { code: "qcb", name: "Qatar Central Bank" },
80
+ IQD: { code: "cbiq", name: "Central Bank of Iraq" },
81
+ DZD: { code: "bda", name: "Bank of Algeria" },
82
+ CRC: { code: "bccr", name: "Banco Central de Costa Rica" },
83
+ XOF: { code: "bceao", name: "Central Bank of West African States (BCEAO)" },
84
+ ETB: { code: "nbe", name: "National Bank of Ethiopia" },
85
+ KES: { code: "cbke", name: "Central Bank of Kenya" },
86
+ MDL: { code: "nbm", name: "National Bank of Moldova" },
87
+ MKD: { code: "nbrm", name: "National Bank of North Macedonia" },
88
+ AMD: { code: "cba", name: "Central Bank of Armenia" },
89
+ XAF: { code: "beac", name: "Bank of Central African States (BEAC)" },
90
+ TND: { code: "bct", name: "Central Bank of Tunisia" },
91
+ RWF: { code: "bnrw", name: "National Bank of Rwanda" },
92
+ AOA: { code: "bna", name: "National Bank of Angola" },
93
+ TZS: { code: "botz", name: "Bank of Tanzania" },
94
+ UGX: { code: "bou", name: "Bank of Uganda" },
95
+ JMD: { code: "bojm", name: "Bank of Jamaica" },
96
+ NIO: { code: "bcn", name: "Banco Central de Nicaragua" },
97
+ HNL: { code: "bch", name: "Banco Central de Honduras" },
98
+ TTD: { code: "cbtt", name: "Central Bank of Trinidad and Tobago" },
99
+ MUR: { code: "bmu", name: "Bank of Mauritius" },
100
+ MZN: { code: "bdm", name: "Banco de MoΓ§ambique" },
101
+ BWP: { code: "bob", name: "Bank of Botswana" },
102
+ ZMW: { code: "boz", name: "Bank of Zambia" },
103
+ MWK: { code: "rbm", name: "Reserve Bank of Malawi" },
104
+ KGS: { code: "nbkr", name: "National Bank of the Kyrgyz Republic" },
105
+ CDF: { code: "bcc", name: "Banque Centrale du Congo" },
106
+ BBD: { code: "cbbd", name: "Central Bank of Barbados" },
107
+ LYD: { code: "cbl", name: "Central Bank of Libya" },
108
+ GMD: { code: "cbg", name: "Central Bank of The Gambia" },
109
+ HTG: { code: "brh", name: "Banque de la RΓ©publique d'HaΓ―ti" },
110
+ BTN: { code: "rma", name: "Royal Monetary Authority of Bhutan" },
111
+ TJS: { code: "nbt", name: "National Bank of Tajikistan" },
112
+ BZD: { code: "cbbz", name: "Central Bank of Belize" },
113
+ FJD: { code: "rbf", name: "Reserve Bank of Fiji" },
114
+ MVR: { code: "mma", name: "Maldives Monetary Authority" },
115
+ MRU: { code: "bcm", name: "Banque Centrale de Mauritanie" },
116
+ ZWG: { code: "rbz", name: "Reserve Bank of Zimbabwe" },
117
+ NAD: { code: "bon", name: "Bank of Namibia" },
118
+ MGA: { code: "bfm", name: "Central Bank of Madagascar (BFM)" },
119
+ TMT: { code: "cbt", name: "Central Bank of Turkmenistan" },
120
+ CUP: { code: "bccu", name: "Banco Central de Cuba" },
121
+ SLE: { code: "bsl", name: "Bank of Sierra Leone" },
122
+ STN: { code: "bcstp", name: "Banco Central de SΓ£o TomΓ© e PrΓ­ncipe" },
123
+ };
package/dist/index.js CHANGED
@@ -41,15 +41,15 @@ async function main() {
41
41
  ' AllRatesToday MCP β€” running in KEYLESS mode.',
42
42
  '',
43
43
  ' Available now, no key needed:',
44
- ' β€’ get_exchange_rate β€” official ECB daily reference rate, ~30 major currencies',
44
+ ' β€’ get_exchange_rate β€” official central-bank rate (ECB, else the issuing bank)',
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
48
  ' β€’ get_reference_rate β€” Daily Reference Rate, one fixed table per business day (16:00 London)',
49
49
  ' β€’ request_trial_key β€” self-issue a 100-call, 7-day key without an account',
50
50
  '',
51
- ' Needs a free API key (real-time mid-market rates for 160+ currencies,',
52
- ' historical series, multi-target and point-in-time lookups):',
51
+ ' Needs a free API key (real-time mid-market rates for 160+ currencies and',
52
+ ' multi-target lookups). Historical series and point-in-time lookups need a paid plan:',
53
53
  ' 1. https://allratestoday.com/register β€” free tier, no card, under a minute',
54
54
  ' 2. Add to this server\'s MCP config: "env": { "ALLRATES_API_KEY": "art_live_..." }',
55
55
  '',
@@ -62,13 +62,14 @@ async function main() {
62
62
  const server = new McpServer({ name: 'allratestoday-mcp', version: VERSION });
63
63
  server.registerTool('get_exchange_rate', {
64
64
  title: 'Get live exchange rate',
65
- description: "Use this when the user asks 'what is X in Y?', 'convert X to Y', 'current rate of EUR/USD', or any single fiat-to-fiat live exchange rate question. Returns the latest mid-market rate as a JSON object like { rate: 0.9234, source } meaning 1 source = 0.9234 target. Does NOT support cryptocurrencies, commodities, or arithmetic on amounts. For multiple targets in one call use get_rates_authenticated; for a past date or fixed lookback (7d/30d/1y) use get_historical_rates.",
65
+ description: "Use this when the user asks 'what is X in Y?', 'convert X to Y', 'current rate of EUR/USD', or any single fiat-to-fiat live exchange rate question. Returns the latest mid-market rate as a JSON object like { rate: 0.9234, source } meaning 1 source = 0.9234 target. Without an API key it answers from an official central-bank table instead (ECB first, else the bank that issues one of the two currencies) and says so in `note` β€” relay the `rate_date`; pairs no single bank publishes (or inverts) need a key. Does NOT support cryptocurrencies, commodities, or arithmetic on amounts. For multiple targets in one call use get_rates_authenticated; for a past date or fixed lookback (7d/30d/1y) use get_historical_rates.",
66
66
  inputSchema: { source: ccy, target: ccy },
67
67
  outputSchema: {
68
68
  rate: z.number().describe('How much 1 unit of source is worth in target'),
69
69
  source: z.string().describe('Upstream data provider the rate came from'),
70
- // Keyless mode answers from the open ECB reference table and adds the
71
- // publication date plus a note the assistant should relay.
70
+ // Keyless mode answers from an open central-bank table and adds the
71
+ // bank, publication date plus a note the assistant should relay.
72
+ bank: z.string().optional(),
72
73
  rate_date: z.string().optional(),
73
74
  derived: z.boolean().optional(),
74
75
  note: z.string().optional(),
@@ -84,7 +85,7 @@ async function main() {
84
85
  });
85
86
  server.registerTool('get_historical_rates', {
86
87
  title: 'Get historical rate time-series',
87
- description: "Use this for fixed-window time-series questions like 'how has EUR/USD moved this week', 'show me the last month of GBP/JPY', or 'chart 1-year history of AUD/USD'. Returns { source, target, period, data: [{ date, rate, timestamp }, ...] } β€” sampling is fixed per period (1d=hourly, 7d/30d=daily, 1y=weekly) and the window always ends NOW. For a specific past datetime use get_rates_authenticated with `time`. For a single live rate use get_exchange_rate.",
88
+ description: "Use this for fixed-window time-series questions like 'how has EUR/USD moved this week', 'show me the last month of GBP/JPY', or 'chart 1-year history of AUD/USD'. Returns { source, target, period, data: [{ date, rate, timestamp }, ...] } β€” sampling is fixed per period (1d=hourly, 7d/30d=daily, 1y=weekly) and the window always ends NOW. Needs an API key on a paid plan; free and trial keys get a 403. For a specific past datetime use get_rates_authenticated with `time`. For a single live rate use get_exchange_rate.",
88
89
  inputSchema: {
89
90
  source: ccy,
90
91
  target: ccy,
@@ -115,7 +116,7 @@ async function main() {
115
116
  });
116
117
  server.registerTool('get_rates_authenticated', {
117
118
  title: 'Get multi-target or point-in-time rates',
118
- description: "Use this for (a) one source against multiple targets in a single call ('USD vs EUR, GBP, JPY'), or (b) the rate at a specific past datetime ('EUR/USD at 2025-03-14T12:00Z'), optionally bucketed by hour/day/week/month. Returns { rates: [{ rate, source, target, time }, ...] } β€” one row per target Γ— time bucket. For a single live pair use get_exchange_rate. For fixed lookback windows (1d/7d/30d/1y ending now) use get_historical_rates.",
119
+ description: "Use this for (a) one source against multiple targets in a single call ('USD vs EUR, GBP, JPY'), or (b) the rate at a specific past datetime ('EUR/USD at 2025-03-14T12:00Z'), optionally bucketed by hour/day/week/month. Returns { rates: [{ rate, source, target, time }, ...] } β€” one row per target Γ— time bucket. Multi-target latest rates work on any key; a past datetime (`time`) needs a paid plan. For a single live pair use get_exchange_rate. For fixed lookback windows (1d/7d/30d/1y ending now) use get_historical_rates.",
119
120
  inputSchema: {
120
121
  source: ccy,
121
122
  target: ccyList,
@@ -154,7 +155,7 @@ async function main() {
154
155
  });
155
156
  server.registerTool('list_currencies', {
156
157
  title: 'List supported currencies',
157
- description: "Call this BEFORE other tools when you are unsure whether a currency code is supported, or when the user asks 'what currencies do you support?', 'is X a valid currency?', or 'what is the symbol for X?'. Returns { currencies: [{ code: 'USD', name: 'US Dollar', symbol: '$' }, ...], count } covering 150+ ISO 4217 fiat currencies. Does NOT include cryptocurrencies. Cheap to call (cached 24h upstream) β€” use it to validate user input and prevent downstream errors in get_exchange_rate / get_rates_authenticated / get_historical_rates.",
158
+ description: "Call this BEFORE other tools when you are unsure whether a currency code is supported, or when the user asks 'what currencies do you support?', 'is X a valid currency?', or 'what is the symbol for X?'. Returns { currencies: [{ code: 'USD', name: 'US Dollar', symbol: '$' }, ...], count } covering 160+ ISO 4217 fiat currencies. Does NOT include cryptocurrencies. Cheap to call (cached 24h upstream) β€” use it to validate user input and prevent downstream errors in get_exchange_rate / get_rates_authenticated / get_historical_rates.",
158
159
  inputSchema: {},
159
160
  outputSchema: {
160
161
  currencies: z.array(z.object({
@@ -198,7 +199,7 @@ async function main() {
198
199
  });
199
200
  server.registerTool('get_official_rates', {
200
201
  title: "Get a bank's official published rates",
201
- 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`.",
202
+ 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, paid plan) 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`.",
202
203
  inputSchema: {
203
204
  bank: z
204
205
  .string()
@@ -239,7 +240,7 @@ async function main() {
239
240
  });
240
241
  server.registerTool('get_reference_rate', {
241
242
  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
+ 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, paid plan) for a past business day. Not the WM/Refinitiv fix and not a registered benchmark β€” relay the disclaimer and the `rate_date`.",
243
244
  inputSchema: {
244
245
  source: ccy.optional().describe('Optional. With target, narrows to one pair.'),
245
246
  target: ccy.optional().describe('Optional. With source, narrows to one pair.'),
@@ -247,7 +248,7 @@ async function main() {
247
248
  .string()
248
249
  .regex(/^\d{4}-\d{2}-\d{2}$/)
249
250
  .optional()
250
- .describe('Optional past business day, YYYY-MM-DD (API key). Omit for the latest table.'),
251
+ .describe('Optional past business day, YYYY-MM-DD (API key, paid plan). Omit for the latest table.'),
251
252
  },
252
253
  outputSchema: {
253
254
  rate_date: z.string().describe('Business day the table was fixed on β€” cite this'),
@@ -272,7 +273,7 @@ async function main() {
272
273
  });
273
274
  server.registerTool('request_trial_key', {
274
275
  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
+ 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 or history 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
277
  inputSchema: {
277
278
  agent: z.string().max(80).optional().describe('Optional: the agent or product requesting the key.'),
278
279
  purpose: z.string().max(200).optional().describe('Optional: one line on what the rates are for.'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allratestoday/mcp-server",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
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": [