@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 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
- - 🛡️ **Fail-fast and honest** — refuses to start without a key, maps API errors to clear actionable messages the assistant can relay
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
- ## 🔑 Get your API key
30
+ ## ⚖️ Mid-market vs official central-bank rates
30
31
 
31
- The server **will not start** without a valid `ALLRATES_API_KEY`. A free key is enough for development and personal use**no credit card required**.
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
- If you forget, the server prints registration instructions on stderr and exits with code 1.
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` | — | **yes** | Your API key. The server exits at startup if unset. |
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 | `ALLRATES_API_KEY` not set or invalid | Verify the key in your client config; check it matches the dashboard |
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': `allratestoday-mcp/${VERSION}`,
46
- 'Authorization': `Bearer ${this.apiKey}`,
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 server requires an API key.',
41
+ ' AllRatesToday MCP running in KEYLESS mode.',
37
42
  '',
38
- ' 1. Sign up free at https://allratestoday.com/register (free tier — no card required)',
39
- ' 2. Copy your API key from the dashboard',
40
- ' 3. Set ALLRATES_API_KEY in your MCP client config:',
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
- ' "allratestoday": {',
43
- ' "command": "npx",',
44
- ' "args": ["-y", "@allratestoday/mcp-server"],',
45
- ' "env": { "ALLRATES_API_KEY": "art_live_..." }',
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.4.2",
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": [