@allratestoday/mcp-server 0.4.2 → 0.5.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 +45 -6
- package/dist/client.d.ts +10 -0
- package/dist/client.js +43 -5
- package/dist/index.js +18 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,19 +23,56 @@ After installation, your assistant can answer questions like:
|
|
|
23
23
|
- 📈 **Historical series built in** — `1d` / `7d` / `30d` / `1y` windows with sensible granularity per period
|
|
24
24
|
- 🧰 **Four focused tools** — `get_exchange_rate`, `get_historical_rates`, `get_rates_authenticated`, `list_currencies`; 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
|
+
- 🛡️ **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
|
|
27
28
|
- 🔒 **Nothing leaks** — only the request parameters and your API key ever reach allratestoday.com; never conversation context
|
|
28
29
|
|
|
29
|
-
##
|
|
30
|
+
## ⚖️ Mid-market vs official central-bank rates
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
Everything this server returns is a **mid-market rate**: the live interbank midpoint, 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, AllRatesToday also serves **published central-bank and tax-authority rates** (100+ sources — ECB, Fed, HMRC, US Treasury, …) that are fixed once published and carry the institution's own publication date — via 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
|
+
|
|
34
|
+
## 🔓 Keyless mode — what works with no setup
|
|
35
|
+
|
|
36
|
+
Install it with no configuration at all and it starts, connects, and answers:
|
|
37
|
+
|
|
38
|
+
| Tool | Keyless | What you get |
|
|
39
|
+
|---|---|---|
|
|
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
|
+
| `list_currencies` | ✅ | All 160+ supported ISO 4217 codes. |
|
|
42
|
+
| `get_historical_rates` | 🔑 | Returns one sentence explaining how to get a free key. |
|
|
43
|
+
| `get_rates_authenticated` | 🔑 | Same. |
|
|
44
|
+
|
|
45
|
+
The keyless path reads the open, edge-cached `/api/open/central-bank/ecb`
|
|
46
|
+
endpoint — no upstream cost, no rate limit to trip over, nothing to sign up for.
|
|
47
|
+
|
|
48
|
+
## 🔑 Get your API key (free)
|
|
49
|
+
|
|
50
|
+
A key unlocks **real-time mid-market rates across 160+ currencies**, historical
|
|
51
|
+
series, and multi-target / point-in-time lookups. The free tier is enough for
|
|
52
|
+
development and personal use — **no credit card required**.
|
|
32
53
|
|
|
33
54
|
1. Register at [allratestoday.com/register](https://allratestoday.com/register) — 30 seconds
|
|
34
55
|
2. Verify your email
|
|
35
56
|
3. Copy your key from the dashboard (format: `art_live_xxxxx`)
|
|
36
57
|
4. Use it as `ALLRATES_API_KEY` in the configs below
|
|
37
58
|
|
|
38
|
-
|
|
59
|
+
Without one the server prints a short summary of keyless mode on stderr and
|
|
60
|
+
keeps running — it never exits, because an MCP server that exits breaks the
|
|
61
|
+
host client's whole configuration.
|
|
62
|
+
|
|
63
|
+
## 🧩 Easiest install: the Claude Code plugin
|
|
64
|
+
|
|
65
|
+
If you use Claude Code, install the plugin instead of configuring this server by
|
|
66
|
+
hand — it bundles both AllRatesToday MCP servers, two skills, and five slash
|
|
67
|
+
commands (`/rate`, `/convert`, `/official-rate`, `/fx-history`,
|
|
68
|
+
`/add-currency-support`):
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
/plugin marketplace add AllRates-Today/claude-code-plugin
|
|
72
|
+
/plugin install allratestoday@allratestoday
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Everything below still applies for other MCP clients.
|
|
39
76
|
|
|
40
77
|
## 📦 Installation
|
|
41
78
|
|
|
@@ -268,7 +305,7 @@ All supported currencies with codes, names, and symbols. Cached upstream for 24
|
|
|
268
305
|
|
|
269
306
|
| Variable | Default | Required | Purpose |
|
|
270
307
|
|---|---|---|---|
|
|
271
|
-
| `ALLRATES_API_KEY` | — |
|
|
308
|
+
| `ALLRATES_API_KEY` | — | no | Your API key. Unset ⇒ keyless mode (see above); set ⇒ real-time rates and the historical tools. |
|
|
272
309
|
| `ALLRATES_BASE_URL` | `https://allratestoday.com/api` | no | Override for self-hosted or staging deployments. |
|
|
273
310
|
|
|
274
311
|
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.
|
|
@@ -281,7 +318,8 @@ A free tier and paid plans are available — see [allratestoday.com/pricing](htt
|
|
|
281
318
|
|
|
282
319
|
| Symptom | Likely cause | Fix |
|
|
283
320
|
|---|---|---|
|
|
284
|
-
| Client shows "MCP server failed to start" or red dot | `
|
|
321
|
+
| 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 |
|
|
322
|
+
| 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 |
|
|
285
323
|
| Every call returns "Invalid AllRatesToday API key" | Key is malformed (missing prefix, truncated, or revoked) | Copy a fresh key from the dashboard |
|
|
286
324
|
| Tools return "AllRatesToday API quota exceeded" | Monthly limit hit | Wait until next month or upgrade plan |
|
|
287
325
|
| Historical tool returns "Bad request" | Invalid period or unknown currency code | Period must be `1d`/`7d`/`30d`/`1y`; codes must be 3 letters |
|
|
@@ -363,6 +401,7 @@ server.json # MCP registry manifest
|
|
|
363
401
|
|
|
364
402
|
See [GitHub Releases](https://github.com/cahthuranag/mcp-server/releases) for the full list. Recent highlights:
|
|
365
403
|
|
|
404
|
+
- **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
|
|
366
405
|
- **0.4.x** — README overhaul; registry metadata updates
|
|
367
406
|
- **0.3.x** — API key required for all tools; fail-fast at startup with clear error
|
|
368
407
|
- **0.2.x** — Removed news tool, required auth on `get_historical_rates`
|
package/dist/client.d.ts
CHANGED
|
@@ -8,12 +8,22 @@ export declare class AllRatesTodayError extends Error {
|
|
|
8
8
|
readonly body?: unknown;
|
|
9
9
|
constructor(message: string, status?: number | undefined, body?: unknown);
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Thrown when a tool needs an endpoint that sits behind the API key. Carries
|
|
13
|
+
* the sign-up instructions so the assistant relays one actionable sentence
|
|
14
|
+
* rather than a bare 401.
|
|
15
|
+
*/
|
|
16
|
+
export declare class NeedsKeyError extends AllRatesTodayError {
|
|
17
|
+
constructor(what: string);
|
|
18
|
+
}
|
|
11
19
|
export declare class AllRatesTodayClient {
|
|
12
20
|
private readonly apiKey?;
|
|
13
21
|
private readonly baseUrl;
|
|
14
22
|
private readonly fetchImpl;
|
|
15
23
|
constructor(options?: ClientOptions);
|
|
16
24
|
private request;
|
|
25
|
+
/** True when no API key is configured: only the open endpoints are reachable. */
|
|
26
|
+
get keyless(): boolean;
|
|
17
27
|
getRate(source: string, target: string): Promise<{
|
|
18
28
|
rate: number;
|
|
19
29
|
source: string;
|
package/dist/client.js
CHANGED
|
@@ -10,6 +10,21 @@ export class AllRatesTodayError extends Error {
|
|
|
10
10
|
this.name = 'AllRatesTodayError';
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Thrown when a tool needs an endpoint that sits behind the API key. Carries
|
|
15
|
+
* the sign-up instructions so the assistant relays one actionable sentence
|
|
16
|
+
* rather than a bare 401.
|
|
17
|
+
*/
|
|
18
|
+
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) and ' +
|
|
24
|
+
'list_currencies.');
|
|
25
|
+
this.name = 'NeedsKeyError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
13
28
|
function errorMessage(status, upstream) {
|
|
14
29
|
switch (status) {
|
|
15
30
|
case 400:
|
|
@@ -37,14 +52,14 @@ export class AllRatesTodayClient {
|
|
|
37
52
|
if (value !== undefined && value !== '')
|
|
38
53
|
url.searchParams.set(key, value);
|
|
39
54
|
}
|
|
40
|
-
if (!this.apiKey) {
|
|
41
|
-
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.');
|
|
42
|
-
}
|
|
43
55
|
const headers = {
|
|
44
56
|
'Accept': 'application/json',
|
|
45
|
-
'User-Agent':
|
|
46
|
-
|
|
57
|
+
'User-Agent': this.apiKey
|
|
58
|
+
? `allratestoday-mcp/${VERSION}`
|
|
59
|
+
: `allratestoday-mcp/${VERSION} (keyless)`,
|
|
47
60
|
};
|
|
61
|
+
if (this.apiKey)
|
|
62
|
+
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
48
63
|
const res = await this.fetchImpl(url.toString(), { method: 'GET', headers });
|
|
49
64
|
const text = await res.text();
|
|
50
65
|
let body;
|
|
@@ -62,13 +77,36 @@ export class AllRatesTodayClient {
|
|
|
62
77
|
}
|
|
63
78
|
return body;
|
|
64
79
|
}
|
|
80
|
+
/** True when no API key is configured: only the open endpoints are reachable. */
|
|
81
|
+
get keyless() {
|
|
82
|
+
return !this.apiKey;
|
|
83
|
+
}
|
|
65
84
|
getRate(source, target) {
|
|
85
|
+
// Keyless: fall back to the open, edge-cached ECB reference table. It is
|
|
86
|
+
// the official daily fixing rather than a live mid-market quote and covers
|
|
87
|
+
// ~30 majors, so the result is labelled for the model to relay honestly.
|
|
88
|
+
if (this.keyless) {
|
|
89
|
+
return this.request('/open/central-bank/ecb', { source, target }).then((r) => ({
|
|
90
|
+
rate: r.rate,
|
|
91
|
+
source: 'ECB official daily reference rate (keyless mode)',
|
|
92
|
+
rate_date: r.rate_date,
|
|
93
|
+
derived: r.derived ?? false,
|
|
94
|
+
note: 'Keyless mode: this is the European Central Bank reference rate published on ' +
|
|
95
|
+
`${r.rate_date}, not a live mid-market quote, and covers ~30 major currencies. ` +
|
|
96
|
+
'For real-time rates across 160+ currencies set ALLRATES_API_KEY — free tier at ' +
|
|
97
|
+
'https://allratestoday.com/register.',
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
66
100
|
return this.request('/rate', { source, target });
|
|
67
101
|
}
|
|
68
102
|
getHistoricalRates(source, target, period = '7d') {
|
|
103
|
+
if (this.keyless)
|
|
104
|
+
return Promise.reject(new NeedsKeyError('Historical time-series'));
|
|
69
105
|
return this.request('/historical-rates', { source, target, period });
|
|
70
106
|
}
|
|
71
107
|
getAuthenticatedRates(params) {
|
|
108
|
+
if (this.keyless)
|
|
109
|
+
return Promise.reject(new NeedsKeyError('Multi-target and point-in-time rates'));
|
|
72
110
|
return this.request('/v1/rates', params);
|
|
73
111
|
}
|
|
74
112
|
listSymbols() {
|
package/dist/index.js
CHANGED
|
@@ -30,23 +30,26 @@ function fail(err) {
|
|
|
30
30
|
}
|
|
31
31
|
async function main() {
|
|
32
32
|
const apiKey = process.env.ALLRATES_API_KEY;
|
|
33
|
+
// No key is NOT a fatal error. get_exchange_rate falls back to the open,
|
|
34
|
+
// edge-cached ECB reference table and list_currencies is already keyless, so
|
|
35
|
+
// the server is useful the moment it is installed; the metered tools explain
|
|
36
|
+
// how to get a free key when they are called. Exiting here instead would
|
|
37
|
+
// break the whole MCP config in the host client.
|
|
33
38
|
if (!apiKey) {
|
|
34
39
|
console.error([
|
|
35
40
|
'',
|
|
36
|
-
' AllRatesToday MCP
|
|
41
|
+
' AllRatesToday MCP — running in KEYLESS mode.',
|
|
37
42
|
'',
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
43
|
+
' Available now, no key needed:',
|
|
44
|
+
' • get_exchange_rate — official ECB daily reference rate, ~30 major currencies',
|
|
45
|
+
' • list_currencies — all supported currency codes',
|
|
41
46
|
'',
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
' }',
|
|
47
|
+
' Needs a free API key (real-time mid-market rates for 160+ currencies,',
|
|
48
|
+
' historical series, multi-target and point-in-time lookups):',
|
|
49
|
+
' 1. https://allratestoday.com/register — free tier, no card, under a minute',
|
|
50
|
+
' 2. Add to this server\'s MCP config: "env": { "ALLRATES_API_KEY": "art_live_..." }',
|
|
47
51
|
'',
|
|
48
52
|
].join('\n'));
|
|
49
|
-
process.exit(1);
|
|
50
53
|
}
|
|
51
54
|
const client = new AllRatesTodayClient({
|
|
52
55
|
apiKey,
|
|
@@ -60,6 +63,11 @@ async function main() {
|
|
|
60
63
|
outputSchema: {
|
|
61
64
|
rate: z.number().describe('How much 1 unit of source is worth in target'),
|
|
62
65
|
source: z.string().describe('Upstream data provider the rate came from'),
|
|
66
|
+
// Keyless mode answers from the open ECB reference table and adds the
|
|
67
|
+
// publication date plus a note the assistant should relay.
|
|
68
|
+
rate_date: z.string().optional(),
|
|
69
|
+
derived: z.boolean().optional(),
|
|
70
|
+
note: z.string().optional(),
|
|
63
71
|
},
|
|
64
72
|
annotations: READ_ONLY,
|
|
65
73
|
}, async ({ source, target }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allratestoday/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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": [
|