Skip to main content
Glama
AllRates-Today

AllRatesToday MCP Server

AllRatesToday MCP Server — @allratestoday/mcp-server

Website: https://allratestoday.com · Hosted endpoint (no install): https://allratestoday.com/api/mcp · Docs: https://allratestoday.com/mcp/

npm version npm downloads license MCP TypeScript

English | 简体中文

Give your AI assistant a live window into the foreign-exchange market. A Model Context Protocol server that lets Claude Code, Cursor, Claude Desktop, Windsurf, and any MCP-compatible client fetch real-time currency rates, historical series, and multi-currency lookups from the AllRatesToday API.

After installation, your assistant can answer questions like:

  • "What's the current USD to EUR rate?"

  • "Show me how GBP/JPY moved over the last 30 days."

  • "Convert 250 USD into CAD at a real rate."

  • "Compare USD against EUR, GBP, and JPY simultaneously."

🚀 Why this server?

  • 📡 Live mid-market rates — 160+ ISO 4217 currencies, refreshed every ~60 seconds

  • 📈 Historical series built in — 1d / 7d / 30d / 1y windows with sensible granularity per period

  • 🧰 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

  • 🔌 Works everywhere MCP does — stdio transport, MCP 1.x; Claude Code, Cursor, Claude Desktop, Windsurf, or any generic host

  • 🔓 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

  • 🛡️ 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

  • 🔒 Nothing leaks — only the request parameters and your API key ever reach allratestoday.com; never conversation context

Related MCP server: xe-mcp

⚖️ Mid-market vs official central-bank rates

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 122 central banks and 4 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, and time on get_rates_authenticated) is paid-plan too — free and trial keys get 403. See the central bank REST API and per-bank npm SDKs. The two can diverge by several percent, so pick by use case, not convenience.

🔑 Get your API key (free)

A key unlocks real-time mid-market rates across 160+ currencies and multi-target lookups. The free tier is enough for development and trying it out — no credit card required. Historical series, point-in-time lookups and dated official and reference-rate tables need a paid plan from €4.99/month.

  1. Register at allratestoday.com/register — 30 seconds

  2. Verify your email

  3. Copy your key from the dashboard (format: art_live_xxxxx)

  4. Use it as ALLRATES_API_KEY in the configs below

Without one the server prints a short summary of keyless mode (below) on stderr and keeps running — it never exits, because an MCP server that exits breaks the host client's whole configuration.

🔓 Keyless mode — what works with no setup

Install it with no configuration at all and it starts, connects, and answers:

Tool

Keyless

What you get

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.

list_currencies

✅

All 160+ supported ISO 4217 codes.

list_central_banks

✅

Codes, names and latest publication date of all 122 central banks and 4 tax authorities.

get_official_rates

✅

Latest official table (or one pair) published by any of them. A dated table needs a paid-plan key.

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.

request_trial_key

✅

Self-issues a 100-call, 7-day key with no account and adopts it for the session.

get_historical_rates

🔑

Returns one sentence explaining how to get a key. Needs a paid plan.

get_rates_authenticated

🔑

Same.

The keyless path reads the open, edge-cached /api/open/central-bank/{bank} endpoints — no upstream cost, no rate limit to trip over, nothing to sign up for.

Attribution. Keyless use requires a visible, followable link to AllRatesToday wherever the rates are shown (a footer, an about page, a README). With an API key it is appreciated but not required.

<a href="https://allratestoday.com">Exchange rates by AllRatesToday</a>

Markdown: Exchange rates by [AllRatesToday](https://allratestoday.com). Full wording: https://allratestoday.com/terms/#attribution.

🧩 Easiest install: the Claude Code plugin

If you use Claude Code, install the plugin instead of configuring this server by hand — it bundles both AllRatesToday MCP servers, two skills, and five slash commands (/rate, /convert, /official-rate, /fx-history, /add-currency-support):

/plugin marketplace add AllRates-Today/claude-code-plugin
/plugin install allratestoday@allratestoday

Everything below still applies for other MCP clients.

☁️ Hosted endpoint — nothing to install

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:

https://allratestoday.com/api/mcp
claude mcp add --transport http allratestoday https://allratestoday.com/api/mcp

Works keyless. With a key, send Authorization: Bearer art_live_… or, where the client only takes a URL, connect to https://allratestoday.com/api/mcp?api_key=art_live_…. That puts the key in the URL, where client configs, logs and screenshots can expose it: prefer the header when your client supports it, never share or commit that URL, and rotate the key at https://allratestoday.com/profile if it leaks. Registry name: com.allratestoday/mcp. One-click Cursor / VS Code buttons: https://allratestoday.com/mcp/#hosted

📦 Installation

The simplest install is zero-install via npx, which is what every config below uses:

# Run without installing (recommended)
npx -y @allratestoday/mcp-server
# Or install globally
npm install -g @allratestoday/mcp-server
allratestoday-mcp

Both commands launch the stdio MCP server and wait for a client to connect — they're not meant to be run interactively from your shell; your MCP client launches them as a subprocess.

🏁 Quick setup per client

Each client reads MCP servers from a different config file. Pick yours below.

Claude Code

The fastest path uses the built-in CLI:

claude mcp add allratestoday -- npx -y @allratestoday/mcp-server
claude mcp env allratestoday ALLRATES_API_KEY=art_live_xxxxx

Restart Claude Code. Verify by asking it: "What's the current USD to EUR rate?"

Cursor

Edit ~/.cursor/mcp.json (or .cursor/mcp.json inside your project for project-scoped servers):

{
  "mcpServers": {
    "allratestoday": {
      "command": "npx",
      "args": ["-y", "@allratestoday/mcp-server"],
      "env": {
        "ALLRATES_API_KEY": "art_live_xxxxx"
      }
    }
  }
}

Restart Cursor. The eight tools should appear in the MCP tool picker.

Claude Desktop

Edit the config file (path depends on OS):

OS

Path

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "allratestoday": {
      "command": "npx",
      "args": ["-y", "@allratestoday/mcp-server"],
      "env": {
        "ALLRATES_API_KEY": "art_live_xxxxx"
      }
    }
  }
}

Fully quit and reopen Claude Desktop (Cmd+Q on macOS, right-click tray icon → Exit on Windows). Closing the window alone keeps the old config loaded.

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json with the same mcpServers block as above, then restart Windsurf.

Generic stdio MCP client

Any MCP host that supports stdio transport works. The launch command is:

npx -y @allratestoday/mcp-server

…with the environment variable ALLRATES_API_KEY set. The protocol version is MCP 1.x.

✅ Verify it works

After configuring your client, test in this order:

  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.

  2. Tools are listed — most clients have a "tools" or "MCP" panel showing the eight tools.

  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.

More prompts that exercise the other tools:

  • "What was the ECB's official USD rate on the latest published table?" → get_official_rates

  • "Give me today's 16:00 London reference rate for EUR, GBP and JPY." → get_reference_rate

  • "Which central banks can you get official rates from?" → list_central_banks

  • "Convert 250 USD to CAD." → get_exchange_rate

🧪 Test with MCP Inspector

To check the server on its own, without any AI client in the way, run it under the official MCP Inspector:

npx @modelcontextprotocol/inspector npx -y @allratestoday/mcp-server
  1. Open the URL it prints and click Connect. The Tools tab should list the eight tools.

  2. Call get_exchange_rate with source: USD, target: EUR — it answers keyless with an official rate.

  3. Set ALLRATES_API_KEY in the Inspector's environment panel, reconnect, and call it again — now it returns the live mid-market rate.

If this works but your client doesn't, the problem is the client's config (path to npx, Node version, JSON syntax), not the server.

📚 Tools reference

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.


get_exchange_rate

Current mid-market rate between two currencies.

Input

Field

Type

Required

Description

source

string

yes

3-letter ISO 4217 code, e.g. USD

target

string

yes

3-letter ISO 4217 code, e.g. EUR

Example call

{ "source": "USD", "target": "EUR" }

Response (with a key):

{ "rate": 0.888889, "source": "mid-market" }

Response (keyless — USD → GBP, not in the ECB table, so the Bank of England table answers):

{
  "rate": 0.7598784195,
  "source": "Bank of England official rate (keyless mode)",
  "bank": "boe",
  "rate_date": "2026-10-14",
  "derived": true,
  "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."
}

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.

get_historical_rates

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).

Input

Field

Type

Required

Description

source

string

yes

Source currency code

target

string

yes

Target currency code

period

string

no (default 7d)

One of 1d, 7d, 30d, 1y

Granularity by period

period

Data points

1d

Hourly (24 points)

7d

Daily (7 points)

30d

Daily (30 points)

1y

Weekly (52 points)

Example call

{ "source": "USD", "target": "INR", "period": "30d" }

Response (truncated):

{
  "source": "USD",
  "target": "INR",
  "period": "30d",
  "data": [
    { "date": "2026-09-17", "rate": 96.1006, "timestamp": 1789603200000 },
    { "date": "2026-09-18", "rate": 95.8142, "timestamp": 1789689600000 },
    "...",
    { "date": "2026-10-16", "rate": 94.9643, "timestamp": 1792108800000 }
  ]
}

get_rates_authenticated

Multiple targets in one call, with optional historical timestamp or grouping window.

Input

Field

Type

Required

Description

source

string

yes

Source currency code

target

string

yes

One or more codes, comma-separated (EUR,GBP,JPY)

time

string (ISO 8601)

no

Historical point in time (paid plans)

group

string

no

One of hour, day, week, month

Example call

{ "source": "USD", "target": "EUR,GBP,JPY" }

Response:

{
  "rates": [
    { "rate": 0.888889, "source": "USD", "target": "EUR", "time": "2026-10-16T12:16:01+0000" },
    { "rate": 0.749766, "source": "USD", "target": "GBP", "time": "2026-10-16T12:16:01+0000" },
    { "rate": 157.985, "source": "USD", "target": "JPY", "time": "2026-10-16T12:16:01+0000" }
  ]
}

list_currencies

All supported currencies with codes, names, and symbols. Cached upstream for 24 hours — cheap to call for validating user input before the other tools.

Input — none.

Response (truncated):

{
  "currencies": [
    { "code": "USD", "name": "US Dollar", "symbol": "$" },
    { "code": "EUR", "name": "Euro", "symbol": "€" },
    { "code": "GBP", "name": "British Pound", "symbol": "£" },
    "..."
  ],
  "count": 163
}

list_central_banks

Every official source the server can quote — 122 central banks plus HMRC, the US Treasury, Swiss BAZG and India's CBIC — 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.

Input — none.

Response (truncated):

{
  "sources": [
    { "code": "ecb", "name": "European Central Bank", "latest": "2026-10-15", "age_days": 1, "stale": false, "cadence": "daily" },
    { "code": "fed", "name": "US Federal Reserve (H.10)", "latest": "2026-10-09", "age_days": 7, "stale": false, "cadence": "weekly" },
    "..."
  ],
  "stale_count": 3,
  "checked_at": "2026-10-16T12:16:46.232Z"
}

get_official_rates

The fixed, citable rate an institution published — for invoices, VAT and tax returns, customs, transfer pricing and audit. Not a live market rate.

Input:

Field

Type

Required

Description

bank

string

yes

Source code from list_central_banks, e.g. ecb, fed, boe, rbi, hmrc

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.

source

string

no

With target, narrows to one pair

target

string

no

With source, narrows to one pair

Response (one pair):

{
  "bank": "ecb",
  "rate_date": "2026-10-15",
  "source": "EUR",
  "target": "USD",
  "rate": 1.1208,
  "rate_type": "reference",
  "derived": false,
  "method": "published",
  "age_days": 1,
  "stale": false,
  "cadence": "daily",
  "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" }
}

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.


get_reference_rate

AllRatesToday's Daily Reference Rate: the per-currency median of samples taken in a five-minute window centred on 16:00 London, published once per business day and never revised. Use it when a report, index or research series needs one reproducible rate per day. It is not the WM/Refinitiv fix and not a registered benchmark; every response carries a disclaimer and the rate_date.

Input

Field

Type

Required

Description

source

string

no

With target, narrows to one pair (crossed via USD, flagged derived)

target

string

no

See above

date

string

no

Past business day YYYY-MM-DD (API key on a paid plan). Omit for the latest table

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/


request_trial_key

Self-issues an API key with 100 lifetime calls, valid 7 days, with no account and no email, and switches this server to it for the rest of the session. The reply tells the user to copy the key into the MCP config as ALLRATES_API_KEY to keep it across restarts. Capped at 3 keys per IP per day.

Input — agent (string, optional), purpose (string, optional).

Output — { key, calls, expires_at, adopted, note }.


⚙️ Environment variables

Variable

Default

Required

Purpose

ALLRATES_API_KEY

—

no

Your API key, sent as Authorization: Bearer. Unset ⇒ keyless mode (see above); set ⇒ real-time rates and multi-target lookups (the historical tools need a paid-plan key).

ALLRATES_BASE_URL

https://allratestoday.com/api

no

Override for self-hosted or staging deployments.

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.

💳 Plans

A free tier and paid plans are available — see allratestoday.com/pricing for current quotas. The free tier covers real-time rates and multi-target lookups. All history and dated rates — mid-market history, point-in-time lookups, dated official and reference-rate tables — need a paid plan (free and trial keys get 403 historical_requires_paid_plan). The Official Rates plan covers official central-bank and tax-authority rates only (no market rates).

🛠️ Troubleshooting

Symptom

Likely cause

Fix

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

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

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)

HTTP 403 — Historical rates require a paid plan

get_historical_rates, or time on get_rates_authenticated, on a free or trial key

Upgrade at /pricing — history is paid-only

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

Every call returns "Invalid AllRatesToday API key"

Key is malformed (missing prefix, truncated, or revoked)

Copy a fresh key from the dashboard

Tools return "AllRatesToday API quota exceeded"

Quota used up — the free tier does not reset; paid plans are monthly

Upgrade at /pricing

Historical tool returns "Bad request"

Invalid period or unknown currency code

Period must be 1d/7d/30d/1y; codes must be 3 letters

Server starts but tools never appear

Client didn't reload after config change

Fully quit (not just close) and reopen the client

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

To inspect what the server is doing, run it manually with the key set:

ALLRATES_API_KEY=art_live_xxxxx npx -y @allratestoday/mcp-server

No output means healthy (stdio is reserved for the MCP protocol); errors print to stderr.

🛡️ Error reference

The server maps API errors to clear, actionable messages the assistant can relay to the user:

HTTP status

Meaning

Tool error message

200

Success

(rate returned)

400

Bad request — usually unknown currency code

Bad request — possibly an unknown currency code

401

Invalid API key (a missing key does not cause this — the server runs keyless)

Invalid AllRatesToday API key

403

Plan does not include it (e.g. a dated official table on a free key)

HTTP 403 — <upstream message>

404 (keyless)

No keyless official source covers the pair

No keyless official source covers X/Y. …

429

Quota exceeded

AllRatesToday API quota exceeded

5xx

Server-side issue at allratestoday.com

HTTP 5xx — <upstream message>

❓ FAQ

Is the free plan really enough for normal use? For trying it out and light dev use. It does not reset monthly; regular use or production needs a paid tier. Keyless mode costs nothing and has no quota.

Do you store my conversation or query data? No. Only your API key and the request parameters (source, target, period, time) are sent to allratestoday.com — never the LLM's conversation context.

What happens to my API key? It's only sent as a Bearer token in the Authorization header on requests to the AllRatesToday API. It's never logged or transmitted elsewhere.

Why is my first call slow? Cold-start of npx (first run downloads the package) plus the initial cache miss. Subsequent calls are typically <200ms.

Can I run this without npm/Node? Not currently — Node ≥18 is required. If a standalone binary matters to you, open an issue.

Is there a self-hosted option? Set ALLRATES_BASE_URL to your own AllRatesToday instance. Contact support@allratestoday.com for self-hosted licensing.

Does this work with ChatGPT? Yes, through the hosted endpoint: add https://allratestoday.com/api/mcp as a connector (custom MCP / remote server) in ChatGPT. This npm package is the local stdio server, for clients that launch a command — Claude Code, Cursor, Claude Desktop, Windsurf.

👩‍💻 Development

git clone https://github.com/AllRates-Today/mcp-server.git
cd mcp-server
npm install
npm run build
ALLRATES_API_KEY=art_live_xxxxx node dist/index.js

The server runs on stdio and waits for an MCP client to connect; Ctrl+C to exit. npm run dev watches and rebuilds. To test against a local AllRatesToday instance:

ALLRATES_BASE_URL=http://localhost:8080/api ALLRATES_API_KEY=test_key node dist/index.js

Project structure

src/
├── index.ts      # MCP server, tool registration, request handlers
├── client.ts     # HTTP client for AllRatesToday API + error mapping
└── home-banks.ts # currency → issuing central bank, for the keyless get_exchange_rate fallback
dist/             # Compiled JS (gitignored)
server.json       # MCP registry manifest

Contributing — issues and PRs welcome at github.com/AllRates-Today/mcp-server. Before opening a PR: npm run build must succeed, test against a real API key, and update the tool descriptions in src/index.ts plus this README's tools reference if you change tool behavior.

📝 Changelog

Recent changes. Full history: GitHub Releases.

  • 0.7.9 — README: changelog trimmed to the 0.7.x line

  • 0.7.8 — README: MCP Inspector test guide, example prompts for every tool, hosted ?api_key= security note, ChatGPT FAQ and 401 row corrected, history consistently paid-plan

  • 0.7.6 — Keyless get_rates_authenticated with time now says a paid plan is needed; README: free tier no longer listed as covering history, source example is mid-market

  • 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, lifetime free tier

  • 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)

📜 License

MIT — see LICENSE.

Available Tools

8 tools
get_exchange_rateGet live exchange rateA
Read-only
Inspect

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.

NameRequiredDescriptionDefault
sourceYesISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported.
targetYesISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported.

Output Schema

NameRequiredDescription
bankNo
noteNo
rateYesHow much 1 unit of source is worth in target
sourceYesUpstream data provider the rate came from
derivedNo
rate_dateNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only readOnlyHint/openWorldHint provided, the description carries real behavioral weight: it explains the no-API-key fallback (ECB first, else the issuing central bank), that this is surfaced in a `note` field, that `rate_date` should be relayed, that some pairs or inverted pairs require a key, and that the returned rate is a mid-market rate. That is well beyond what the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the when-to-use triggers, then return shape, then fallback behavior, then exclusions and alternatives. Every sentence carries distinct information; nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers invocation conditions, output shape, degraded-mode behavior, limitations, and sibling routing. With an output schema present it need not explain return values, yet the extra detail it does give (note, rate_date) is directly actionable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters already document the ISO 4217 format, case-insensitivity, fiat-only restriction, pair direction, and the list_currencies fallback. The description restates the same direction semantics ('1 source = 0.9234 target') rather than adding new parameter-level detail, so the baseline 3 for schema-driven params is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('live exchange rate') and explicitly scopes it to single fiat-to-fiat pair conversion. It distinguishes itself from siblings in the same breath ('For multiple targets in one call use get_rates_authenticated; for a past date ... use get_historical_rates'), so an agent can route without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete trigger phrases ('what is X in Y?', 'convert X to Y', 'current rate of EUR/USD'), states the exclusions (no crypto, no commodities, no arithmetic on amounts), and names both the multi-target alternative and the historical alternative with the condition that selects each.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historical_ratesGet historical rate time-seriesA
Read-only
Inspect

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.

NameRequiredDescriptionDefault
periodNoLookback window ending NOW. '1d' returns ~24 hourly points, '7d' returns 7 daily points, '30d' returns 30 daily points, '1y' returns ~52 weekly points. Defaults to '7d' if omitted.7d
sourceYesISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported.
targetYesISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported.

Output Schema

NameRequiredDescription
dataYes
periodYes
sourceYes
targetYes
source_apiNoUpstream data provider

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond readOnlyHint/openWorldHint by disclosing the paid-plan API key requirement and the 403 failure mode for free/trial keys, the fixed sampling cadence per period, and the fact the window always ends NOW. These are non-obvious operational constraints an agent cannot derive from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with example phrasings that map directly to user utterances, then return shape, then sampling, then auth, then alternatives. Every sentence carries a distinct piece of information with no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not restate the return structure in depth, yet it does summarize it and still covers sampling resolution, window semantics, and auth gating. Nothing needed for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the period enum, its point counts and the ISO 4217 pattern are already documented. The description mostly restates the sampling mapping and the source/target direction semantics already present in the schema, adding little beyond the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource (fetch a fixed-window historical rate time-series) and anchors it with concrete example queries. It distinguishes itself from siblings by explicitly naming get_rates_authenticated for past datetimes and get_exchange_rate for a single live rate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('fixed-window time-series questions') plus two named alternatives with the exact condition that selects each (a specific past datetime, a single live rate). The agent never has to infer routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_official_ratesGet a bank's official published ratesA
Read-only
Inspect

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.

NameRequiredDescriptionDefault
bankYesSource code from list_central_banks, e.g. 'ecb', 'fed', 'boe', 'rbi', 'hmrc'. Case-insensitive.
dateNoOptional YYYY-MM-DD. Omit for the latest table.
sourceNoOptional. With target, narrows to one pair.
targetNoOptional. With source, narrows to one pair.

Output Schema

NameRequiredDescription
bankYes
rateNo
ratesNo
staleNoTrue when the institution is behind its publication schedule
sourceNo
targetNo
derivedNoTrue when cross-computed inside the bank table
rate_dateYesPublication date of the table — cite this, not today
rate_typeNo
attributionNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnlyHint and openWorldHint, so the description usefully adds the parts they cannot: the API-key/paid-plan requirement for `date`, weekend/holiday rollback to the last published date, the `derived` flag for cross-computed pairs, and the instruction to cite `rate_date`. It stops short of discussing rate limits, caching, or table size limits, so it is strong but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the definition and the get_exchange_rate distinction, then handles each parameter mode in order. It is dense — semicolons carry several distinct constraints per sentence — but nearly every clause carries a decision-relevant fact rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter read tool with an output schema present, the description covers everything an agent needs to choose the right call: source-tool dependency (list_central_banks for bank codes), auth implications, date fallback behavior, and pair narrowing. Return-value details are appropriately deferred to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds genuine semantics the schema lacks: `date` shifts to the last published table on weekends/holidays, omitting `date` yields the newest table without a key, and omitting both source and target returns the full table with cross-computed pairs flagged `derived`.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the resource precisely ('OFFICIAL rates a named institution published') with three real user-phrasing examples, and explicitly names the sibling it is not (get_exchange_rate). An agent can distinguish it from get_exchange_rate and get_historical_rates without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use routing ('NOT live market rates — use get_exchange_rate for those'), plus conditions for each invocation mode: omit `date` for the newest table (no API key), supply `date` for the table in force that day (API key, paid plan), omit source/target for the full table vs both for one pair.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_rates_authenticatedGet multi-target or point-in-time ratesA
Read-only
Inspect

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.

NameRequiredDescriptionDefault
timeNoSingle point-in-time ISO 8601 UTC timestamp (e.g. '2025-03-14T12:00:00Z'). Omit for the latest rate.
groupNoAggregation bucket: 'hour', 'day', 'week', or 'month'. Useful when time is omitted to return rolling averages. Omit for raw single-point output.
sourceYesISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported.
targetYesOne or more ISO 4217 codes, comma-separated, no spaces, case-insensitive. Examples: 'EUR' (single) or 'EUR,GBP,JPY' (multi). Each target becomes a separate row in the response.

Output Schema

NameRequiredDescription
ratesYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint; the description adds a real access constraint ('a past datetime needs a paid plan') that annotations cannot express, plus the row-per-target x bucket response semantics. It stops short of discussing rate limits, pagination, or the cost/behavior of large multi-target requests, so it is strong but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the two primary use cases, the return shape, then the caveat and alternatives - a sensible ordering. It is dense and some inline examples duplicate what the schema already shows, which keeps it just under fully economical.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not restate the response shape but does briefly clarify the row semantics anyway, and it covers auth/plan gating, all four parameters' intent, and sibling routing. Nothing required to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3; the description still adds meaning by spelling out the return direction ('1 unit of source is worth in target'), the no-spaces comma-separated target syntax, and the interaction between omitting `time` and using `group` for rolling averages.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource and enumerates the two exact modes it serves: multi-target latest rates in one call, and point-in-time rate at a past datetime. It also names the sibling tools it is NOT (get_exchange_rate, get_historical_rates), so an agent can disambiguate without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use for both modes ('a' multi-target, 'b' past datetime with optional bucketing) plus exclusions routed to alternatives: single live pair -> get_exchange_rate, fixed lookback windows -> get_historical_rates. It even flags the plan constraint that gates the `time` path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_reference_rateGet the Daily Reference Rate (16:00 London)A
Read-only
Inspect

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.

NameRequiredDescriptionDefault
dateNoOptional past business day, YYYY-MM-DD (API key, paid plan). Omit for the latest table.
sourceNoOptional. With target, narrows to one pair.
targetNoOptional. With source, narrows to one pair.

Output Schema

NameRequiredDescription
baseNo
rateNo
timeNoFixing time, e.g. 16:00 Europe/London
ratesNoFull table keyed by currency code
methodNo
sourceNo
targetNo
derivedNo
rate_dateYesBusiness day the table was fixed on — cite this
disclaimerNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint, and the description adds substantial context beyond them: the rate is never revised, the cross is computed via USD and flagged `derived`, the latest table needs no key while a past date requires an API key on a paid plan, and it warns this is not the WM/Refinitiv fix nor a registered benchmark with a disclaimer to relay. This is exactly the auth/caveat/derivation detail the annotations do not carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core definition, then usage, then parameter behavior, then caveats – a logical progression. It is dense with parentheticals and slightly long, but nearly every clause carries non-redundant information; little is pure padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description still covers usage, sibling routing, parameter interaction, auth/plan requirements, and benchmark caveats. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (baseline 3), but the description adds genuine semantics beyond the schema: omit source/target for the whole table vs. supply both for one pair crossed via USD and flagged `derived`, and omit date for the latest (no key) vs. supply it for a past day (API key, paid plan). This clarifies interaction and side effects the parameter docs alone do not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('once-a-day, never-revised mid-market rate') and defines the exact methodology (per-currency median of samples in a five-minute window at 16:00 London). It actively distinguishes this from the live-quote sibling (get_exchange_rate) and the official-rate sibling (get_official_rates), so an agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use is given with concrete scenarios ('index levels, return series, research datasets, month-end reports') plus explicit when-not-to-use via named alternatives ('rather than a live quote (get_exchange_rate) or an institution's official rate (get_official_rates)'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_central_banksList covered central banks & tax authoritiesA
Read-only
Inspect

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
sourcesYes
checked_atYes
stale_countYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the read-only and open-world hints, and the description goes beyond them with auth context ('No API key needed') — a real distinction from the sibling get_rates_authenticated — plus freshness/health metadata ('whether it is behind schedule'). That is exactly the kind of operational context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The call-first instruction is front-loaded, and every subsequent clause carries distinct payload: use cases, inventory size, return fields, and auth requirement. No filler or restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list tool with an output schema and read-only annotations, this description covers trigger conditions, inventory scope, field contents, cross-tool linkage, and auth needs. Nothing an agent needs to select or invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4 and there is no parameter semantics to clarify. The description's field-level explanation (code, name, publication date, schedule status) is informative but describes the response rather than inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a precise verb+resource ('Returns every covered source — 121 central banks plus 3 tax authorities') and enumerates the exact returned fields (code, name, latest publication date, schedule status). It distinguishes itself from siblings by explicitly linking its `code` output to `get_official_rates`'s `bank` input.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It opens with an explicit trigger ('Call this FIRST when you need a bank code') and supplies sample user questions ('which central banks do you cover?' / 'do you have rates from X?'), which map intent to this tool. It also names the downstream tool that consumes the result, so the when-to-use path is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_currenciesList supported currenciesA
Read-only
Inspect

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
countYes
currenciesYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, and the description adds real context beyond them: upstream caching for 24h, low call cost, the validation-purpose rationale, and the crypto exclusion. These are operational traits an agent needs for budgeting calls and setting expectations that annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The directive that matters most — call this before other tools — is front-loaded, followed by concrete trigger phrases, then the return shape, scope limits, and cost. Every sentence carries a distinct piece of information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not detail return values, yet it still sketches the shape ({currencies: [{code,name,symbol}], count}). Given the zero-parameter simplicity and existing annotations, nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the rubric the baseline is 4. There is no parameter semantics to add, and the description correctly says nothing about inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List supported currencies') and pins down scope precisely: 160+ ISO 4217 fiat currencies, explicitly excluding cryptocurrencies. An agent can distinguish this reference/enumeration tool from the rate-fetching siblings (get_exchange_rate, get_historical_rates) without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit temporal instruction ('Call this BEFORE other tools'), enumerates the exact user phrasings that should trigger it, and names the downstream tools it protects (get_exchange_rate / get_rates_authenticated / get_historical_rates). The when-not case (cryptocurrencies) is also stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

request_trial_keyRequest a trial API keyAInspect

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.

NameRequiredDescriptionDefault
agentNoOptional: the agent or product requesting the key.
purposeNoOptional: one line on what the rates are for.

Output Schema

NameRequiredDescription
keyNo
noteYes
callsNo
adoptedYesTrue when this server switched to the new key
expires_atNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say it is a non-read-only, open-world, non-idempotent call; the description goes well beyond that by disclosing the 3-keys-per-IP-per-day rate cap, that the key is adopted by the server for the rest of the session, and that it is returned exactly once and must be persisted by the user in MCP config. That is exactly the operational context an agent cannot infer from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and limits, then the trigger condition, then the session/return behavior, then the durable alternative. Every sentence carries distinct information with no restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and the description still covers limits, session adoption, persistence instructions, and escalation paths. Nothing an agent needs to call this correctly or explain the result to a user is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for both optional parameters (agent, purpose), so the schema already carries their meaning. The description adds no extra syntax, format, or example guidance for either field, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (self-issue an AllRatesToday API key) plus the exact scope: 100 lifetime calls, 7-day validity, no account or email. This is unmistakably distinct from the read-only rate siblings, which none of them create credentials.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('when another tool answered "needs an API key" and the user wants real-time rates or history right now') and names the alternative for the opposite case ('For a lasting key, register at ... or see pricing'). Both the when and the when-not are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv0.7.9
    • Changedget_exchange_rate11 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / source / description
        Previous value: -"ISO 4217 currency code (e.g. USD, EUR, GBP)."New value: +"ISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported."
      • removedInput schema / properties / source / maxLength
        Removed value: -3
      • removedInput schema / properties / source / minLength
        Removed value: -3
      • addedInput schema / properties / source / pattern
        Added value: +"^[A-Za-z]{3}$"
      • changedInput schema / properties / target / description
        Previous value: -"ISO 4217 currency code (e.g. USD, EUR, GBP)."New value: +"ISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported."
      • removedInput schema / properties / target / maxLength
        Removed value: -3
      • removedInput schema / properties / target / minLength
        Removed value: -3
      • addedInput schema / properties / target / pattern
        Added value: +"^[A-Za-z]{3}$"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "bank": {
        +      "type": "string"
        +    },
        +    "derived": {
        +      "type": "boolean"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "rate": {
        +      "description": "How much 1 unit of source is worth in target",
        +      "type": "number"
        +    },
        +    "rate_date": {
        +      "type": "string"
        +    },
        +    "source": {
        +      "description": "Upstream data provider the rate came from",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "rate",
        +    "source"
        +  ],
        +  "type": "object"
        +}
    • Changedget_historical_rates12 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / period / description
        Previous value: -"Time period to fetch history for."New value: +"Lookback window ending NOW. '1d' returns ~24 hourly points, '7d' returns 7 daily points, '30d' returns 30 daily points, '1y' returns ~52 weekly points. Defaults to '7d' if omitted."
      • changedInput schema / properties / source / description
        Previous value: -"ISO 4217 currency code (e.g. USD, EUR, GBP)."New value: +"ISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported."
      • removedInput schema / properties / source / maxLength
        Removed value: -3
      • removedInput schema / properties / source / minLength
        Removed value: -3
      • addedInput schema / properties / source / pattern
        Added value: +"^[A-Za-z]{3}$"
      • changedInput schema / properties / target / description
        Previous value: -"ISO 4217 currency code (e.g. USD, EUR, GBP)."New value: +"ISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported."
      • removedInput schema / properties / target / maxLength
        Removed value: -3
      • removedInput schema / properties / target / minLength
        Removed value: -3
      • addedInput schema / properties / target / pattern
        Added value: +"^[A-Za-z]{3}$"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "data": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "date": {
        +            "type": "string"
        +          },
        +          "rate": {
        +            "type": "number"
        +          },
        +          "timestamp": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "date",
        +          "rate",
        +          "timestamp"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "period": {
        +      "type": "string"
        +    },
        +    "source": {
        +      "type": "string"
        +    },
        +    "source_api": {
        +      "description": "Upstream data provider",
        +      "type": "string"
        +    },
        +    "target": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "source",
        +    "target",
        +    "period",
        +    "data"
        +  ],
        +  "type": "object"
        +}
    • Addedget_official_rates
    • Changedget_rates_authenticated12 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / group / description
        Previous value: -"Optional grouping window."New value: +"Aggregation bucket: 'hour', 'day', 'week', or 'month'. Useful when time is omitted to return rolling averages. Omit for raw single-point output."
      • changedInput schema / properties / source / description
        Previous value: -"ISO 4217 currency code (e.g. USD, EUR, GBP)."New value: +"ISO 4217 currency code, 3 letters, case-insensitive (e.g. 'USD', 'EUR', 'GBP', 'JPY'). For a source/target pair, the returned rate is how much 1 unit of source is worth in target. Fiat only — no crypto, no commodities. Call list_currencies if unsure whether a code is supported."
      • removedInput schema / properties / source / maxLength
        Removed value: -3
      • removedInput schema / properties / source / minLength
        Removed value: -3
      • addedInput schema / properties / source / pattern
        Added value: +"^[A-Za-z]{3}$"
      • changedInput schema / properties / target / description
        Previous value: -"One or more target codes, comma-separated."New value: +"One or more ISO 4217 codes, comma-separated, no spaces, case-insensitive. Examples: 'EUR' (single) or 'EUR,GBP,JPY' (multi). Each target becomes a separate row in the response."
      • addedInput schema / properties / target / pattern
        Added value: +"^[A-Za-z]{3}(,[A-Za-z]{3})*$"
      • changedInput schema / properties / time / description
        Previous value: -"Optional historical ISO 8601 timestamp."New value: +"Single point-in-time ISO 8601 UTC timestamp (e.g. '2025-03-14T12:00:00Z'). Omit for the latest rate."
      • addedInput schema / properties / time / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "rates": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "rate": {
        +            "type": "number"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "target": {
        +            "type": "string"
        +          },
        +          "time": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "rate",
        +          "source",
        +          "target",
        +          "time"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "rates"
        +  ],
        +  "type": "object"
        +}
    • Addedget_reference_rate
    • Addedlist_central_banks
    • Changedlist_currencies3 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "count": {
        +      "type": "number"
        +    },
        +    "currencies": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "code": {
        +            "type": "string"
        +          },
        +          "name": {
        +            "type": "string"
        +          },
        +          "symbol": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "code",
        +          "name",
        +          "symbol"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "currencies",
        +    "count"
        +  ],
        +  "type": "object"
        +}
    • Addedrequest_trial_key
  2. 4 tool updatesv0.2.0
    • First observedget_exchange_rate
    • First observedget_historical_rates
    • First observedget_rates_authenticated
    • First observedlist_currencies

TDQS

A4.6/5.0

Scored across 8 tools

Disambiguation4/5

The five rate-related tools (get_exchange_rate, get_historical_rates, get_rates_authenticated, get_official_rates, get_reference_rate) cover genuinely different use cases, and descriptions cross-reference each other well ('for a single live rate use get_exchange_rate'). However, the boundaries between get_historical_rates and get_rates_authenticated (past datetime vs fixed window) require careful reading and could still trip up an agent.

Naming Consistency4/5

Nearly all tools follow a predictable verb_noun pattern (get_official_rates, list_currencies, list_central_banks, request_trial_key). The one outlier is get_rates_authenticated, whose adjectival suffix breaks the otherwise clean convention, but it remains readable.

Tool Count5/5

Eight tools is well-scoped for a currency-rate API: five rate-retrieval variants, two discovery/lookup tools, and one key-management utility. Each tool earns its place with no obvious redundancy.

Completeness4/5

The surface covers live rates, history, official/institutional rates, a daily reference rate, currency and bank lookup, plus onboarding via a trial key. Gaps are deliberate scope exclusions (crypto, commodities, amount arithmetic) rather than accidental omissions.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Real-time currency exchange rates and crypto prices via MCP. Convert between 60+ fiat currencies and 30+ cryptocurrencies with multi-source failover. No API keys needed for upstream data.
    5 npm
    ISC
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server for the Xe Currency Data API that brings live FX rates, historical analysis, and quant-flavored tools into AI tools, working out of the box with zero credentials via Frankfurter/ECB data.
    12
    4 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Real-time US-equity quotes, company fundamentals, earnings, analyst trends, and financial news via Finnhub. Supports STDIO and Streamable HTTP transports.
    103 npm
    1
    Apache 2.0