io.github.cyanheads/exchange-rates-mcp-server
REMOTE · EXCHANGE-RATES.CASEYJHAND.COM · 2 COMPONENTS
Convert currencies, get FX rates, and query historical Frankfurter v1 exchange rate data.
Available components
Last scanned (8 hours ago)
Scores higher than 98% of remote servers
Reachable. Last reached 5 Nov 2026.
Category Finance and Payments
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security83
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- No authorisation is required to call this server. Every tool declares its destructiveHint and none is destructive, so open access doesn't expose one. See how to fix → View diagnostics → Partial
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC is configured correctly; the domain's records validate against the full chain to the root. View diagnostics → Pass
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability81
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 2132 tokens (~164/item across 13 items; 7 tools + 6 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 7 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 9 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 3 Nov 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “fx_list_currencies” rewrote its description, which is the text the model reads security
- Tool “fx_get_timeseries” rewrote its description, which is the text the model reads security
- Schema quality: 1896 → 2132 ▼ functional
- New resource “exchange-rates-guide” functional
- Server version: 0.5.1 → 0.6.0 functional
- “fx_list_currencies” added an optional parameter “include_retired” cosmetic
- “fx_get_timeseries” added an optional parameter “limit” cosmetic
- 24 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “fx_get_rate” rewrote its description, which is the text the model reads security
- Tool “fx_get_timeseries” rewrote its description, which is the text the model reads security
- Tool “fx_list_currencies” rewrote its description, which is the text the model reads security
- Server version: 0.5.0 → 0.5.1 functional
- “fx_get_timeseries” reworded the description of “start_date” cosmetic
- “fx_get_rates” reworded the description of “date” cosmetic
- “fx_get_rate” reworded the description of “date” cosmetic
- “fx_dataframe_query” reworded the description of “row_limit” cosmetic
- “fx_dataframe_query” reworded the description of “query” cosmetic
- “fx_convert_currency” reworded the description of “date” cosmetic
- “fx_get_timeseries” reworded the description of “canvas_id” cosmetic
- 20 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “fx_dataframe_describe” rewrote its description, which is the text the model reads security
- Tool “fx_dataframe_query” rewrote its description, which is the text the model reads security
- Tool “fx_get_timeseries” rewrote its description, which is the text the model reads security
- Server version: 0.4.2 → 0.5.0 functional
- 4 Oct 26 0
- Server version: 0.4.1 → 0.4.2 functional
- 28 Sept 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 25 Sept 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 19 Sept 26 0
- Server version: 0.4.0 → 0.4.1 functional
- 12 Sept 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “fx_get_rates” rewrote its description, which is the text the model reads security
- Tool “fx_get_timeseries” rewrote its description, which is the text the model reads security
- Schema quality: 136 → 152 ▼ functional
- Server version: 0.3.1 → 0.4.0 functional
- “fx_dataframe_query” added an optional parameter “row_limit” cosmetic
- “fx_convert_currency” reworded the description of “quote_currency” cosmetic
- “fx_get_rate” reworded the description of “quote_currency” cosmetic
- “fx_get_rates” reworded the description of “symbols” cosmetic
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Probed https://exchange-rates.caseyjhand.com/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=caseyjhand.com | CN=WE1,O=Google Trust Services,C=US | 2 Nov 2026 | 31 Jan 2027 | ECDSA 256 | ECDSA-SHA256 | 995a30681ab772540e934241ca1d576c |
| SANs: caseyjhand.com, *.caseyjhand.com | ||||||
| CN=WE1,O=Google Trust Services,C=US (CA) | CN=GTS Root R4,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | ECDSA 256 | ECDSA-SHA384 | 7ff31977972c224a76155d13b6d685e3 |
| CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 15 Nov 2023 | 28 Jan 2028 | ECDSA 384 | SHA256-RSA | 7fe530bf331343bedd821610493d8a1b |
Background: What to check on a remote MCP endpoint →
DNSSEC secure
Validation of exchange-rates.caseyjhand.com. — Secure
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| com. | present | 19718 | 13 | Verified |
| caseyjhand.com. | present | 2371 | 13 | Verified |
| exchange-rates.caseyjhand.com. | Verified address RRset verified with the apex keys |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| strict-transport-security | max-age=63072000; includeSubDomains; preload |
| x-content-type-options | nosniff |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://exchange-rates.caseyjhand.com/mcp | Verified | 200 | |
| http (plaintext) | http://exchange-rates.caseyjhand.com/mcp | HTTPS enforced | 301 | https://exchange-rates.caseyjhand.com/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
fx_convert_currency Fx Convert Currency ~203
Convert an amount between any two currencies at the latest or a historical rate. Returns the converted amount, the rate used, the actual rate date, and whether the date was snapped from a weekend/holiday to the prior business day. Cross-rates are triangulated through EUR automatically.
| Name | Type | Req | Description |
|---|---|---|---|
| amount | number | yes | Amount in the base currency to convert. Must be greater than zero. |
| base_currency | string | yes | ISO 4217 source currency code (e.g. USD). Call fx_list_currencies to get valid codes. |
| date | string | – | ISO 8601 date (YYYY-MM-DD) for a historical rate. Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported. |
| quote_currency | string | yes | ISO 4217 target currency code (e.g. EUR). The amount will be expressed in this currency. Call fx_list_currencies to get valid codes. |
| Name | Type | Req | Description |
|---|---|---|---|
| base_amount | number | – | The input amount in the base currency. |
| base_currency | string | – | Source currency code. |
| date_snapped | boolean | – | True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day. |
| error | object | – | Present when the call failed. Absent on success. |
| quote_amount | number | – | The unrounded amount × rate product in the quote currency, using JavaScript floating-point precision; no currency minor-unit rounding policy is applied. |
| quote_currency | string | – | Target currency code. |
| rate | number | – | Exchange rate used: units of quote currency per 1 unit of base currency. |
| rate_date | string | – | Actual date of the rate used for conversion. |
| rate_type | string | – | Always "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask. |
| source | string | – | Always "Frankfurter v1" — the upstream data provider. |
No examples provided.
fx_dataframe_describe Fx Dataframe Describe ~115
List tables and columns staged on a DataCanvas from a prior fx_get_timeseries call. Required first step before fx_dataframe_query — use it to discover table names and column schemas. Requires DataCanvas, which is on by default — a deployment that turns it off does not list this tool at all, and fx_get_timeseries returns every range inline there.
| Name | Type | Req | Description |
|---|---|---|---|
| canvas_id | string | yes | Canvas ID returned by fx_get_timeseries. Re-run fx_get_timeseries to obtain a fresh canvas_id if this one has expired. |
| Name | Type | Req | Description |
|---|---|---|---|
| canvas_id | string | – | The canvas ID echoed back — use this in fx_dataframe_query. |
| error | object | – | Present when the call failed. Absent on success. |
| expires_at | string | – | ISO 8601 timestamp when this canvas will be evicted. |
| tables | array | – | All tables and views currently staged on this canvas. |
No examples provided.
fx_dataframe_query Fx Dataframe Query ~275
Run a read-only SQL SELECT against DataCanvas tables staged by fx_get_timeseries. Supports aggregations, GROUP BY, window functions, and JOINs across multiple registered tables. Run fx_dataframe_describe first to discover table names and column schemas. Requires DataCanvas, which is on by default — a deployment that turns it off does not list this tool at all, and fx_get_timeseries returns every range inline there.
| Name | Type | Req | Description |
|---|---|---|---|
| canvas_id | string | yes | Canvas ID returned by fx_get_timeseries. Re-run fx_get_timeseries to obtain a fresh canvas_id if this one has expired. |
| query | string | yes | Read-only SQL SELECT statement. Reference tables by the names returned by fx_dataframe_describe or the table_name field from fx_get_timeseries. Example: SELECT date, rate FROM <table_name> WHERE date… |
| row_limit | integer | – | Most rows to return (positive integer, default 150; values above 10000 clamp to 10000 with a notice). When the query produces more, truncated is true — page with ORDER BY <column> LIMIT <n> OFFSET <m… |
| Name | Type | Req | Description |
|---|---|---|---|
| canvas_id | string | – | The canvas ID used — pass to a subsequent fx_dataframe_query or fx_dataframe_describe call. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Reports requested and effective row limits when clamped, and the ORDER BY … LIMIT … OFFSET query shape when the result is truncated. |
| row_count | number | – | Rows returned — always the length of rows. When truncated is true this equals row_limit, not the full result size. |
| rows | array | – | Result rows, at most row_limit (default 150). Each key is a column name from the query. |
| truncated | boolean | – | True when the query produced more rows than row_limit and rows holds only the first row_limit of them. Fetch the rest with ORDER BY <column> LIMIT <n> OFFSET <m> — ORDER BY is required for determinis… |
No examples provided.
fx_get_rate Fx Get Rate ~240
Get the exchange rate for a currency pair on a given date (default: latest). Returns the rate, the actual rate date (which may differ from the requested date on weekends/holidays — daily observations may skip non-publication days), and source provenance. Cross-rates are triangulated through EUR automatically. A same-currency pair returns a rate of 1, dated to the same publication day any other pair would report for that date. Use fx_convert_currency when you want the converted amount; use this tool when you only need the rate number.
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | yes | ISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes. |
| date | string | – | ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported. |
| quote_currency | string | yes | ISO 4217 quote currency code (e.g. EUR). The rate is expressed as "how many quote units per 1 base unit". Call fx_list_currencies to get valid codes. |
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | – | The base currency code. |
| date_snapped | boolean | – | True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day. |
| error | object | – | Present when the call failed. Absent on success. |
| quote_currency | string | – | The quote currency code. |
| rate | number | – | Exchange rate: units of quote currency per 1 unit of base currency. |
| rate_date | string | – | Actual date of the rate returned. |
| rate_type | string | – | Always "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask. |
| source | string | – | Always "Frankfurter v1" — the upstream data provider. |
No examples provided.
fx_get_rates Fx Get Rates ~240
Get all available exchange rates for one base currency in a single snapshot. Useful for bulk comparison and seeding downstream tools. Returns a map of quote currency → rate, the actual snapshot date, and whether a historical date was snapped from a weekend/holiday to the prior business day. Optionally filter to a subset of quote currencies via symbols. Listing the base currency itself in symbols is accepted and returns a rate of 1 for it.
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | yes | ISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes. |
| date | string | – | ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported. |
| symbols | array | – | Optional list of quote currency codes to filter the response. When provided, must contain at least one currency code — omit the field entirely, not an empty array, to return all ~30 supported currenc… |
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | – | The base currency code. |
| date_snapped | boolean | – | True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day. Always false when date is omitted. |
| error | object | – | Present when the call failed. Absent on success. |
| rate_date | string | – | Actual date of the rates. May differ from requested date on weekends/holidays — daily observations may skip non-publication days; the API silently snaps to the prior business day. |
| rate_type | string | – | Always "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask. |
| rates | object | – | Map of quote currency code → exchange rate (units of quote per 1 base). |
| source | string | – | Always "Frankfurter v1" — the upstream data provider. |
No examples provided.
fx_get_timeseries Fx Get Timeseries ~449
Get historical daily Frankfurter v1 rates over an inclusive date range. Same-date EUR legs are divided without intermediate rounding; only days with both currencies appear, including observed self-pairs at 1 and historical retired currencies. Missing-leg served days produce coverage notices; weekends and holidays are not counted as missing. summary covers all observed days before delivery: arithmetic mean, earliest tied extrema, endpoints and percentage change, without accounting policy. limit bounds returned rows (default/max 500); 0 returns summary only. Continue inline with next_start_date, the same end_date and a positive limit. Long ranges (>90 days by default) stage beyond the 40,000-character preview budget, independently of limit. Explicit canvas_id always stages the complete series, including short/empty results, and fails if unavailable or unknown. Each registration preserves earlier tables with a unique table_name. spilled=true returns canvas_id and table_name; use fx_dataframe_describe then fx_dataframe_query for SQL. Without DataCanvas, omit canvas_id to page inline.
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | yes | ISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes. |
| canvas_id | string | – | Existing canvas ID from a prior call explicitly requesting staging even for short or empty results. Every call creates a uniquely named table. Omit for automatic staging or inline paging. |
| end_date | string | yes | ISO 8601 end date (YYYY-MM-DD). Must be >= start_date. Future dates are not supported. |
| limit | integer | – | Maximum observations returned in rates, default 500, clamped to 500. Use 0 for summary only; continue inline with a positive limit. Does not affect summary, counts, bounds, staging eligibility or the… |
| quote_currency | string | yes | ISO 4217 quote currency code (e.g. EUR). Call fx_list_currencies to get valid codes. |
| start_date | string | yes | ISO 8601 start date (YYYY-MM-DD). Frankfurter v1 data starts 1999-01-04. The actual first data point may be later if start_date falls on a weekend/holiday. |
| Name | Type | Req | Description |
|---|---|---|---|
| base_currency | string | – | Base currency code. |
| canvas_id | string | – | Canvas ID — present when spilled is true. Pass to fx_dataframe_describe to inspect the staged table, then to fx_dataframe_query to run SQL. |
| end_date | string | – | Last publication date in the requested range. Always inside the requested range — earlier than the requested end when that day had no Frankfurter v1 fix, and equal to it when the series is empty. Lat… |
| error | object | – | Present when the call failed. Absent on success. |
| next_start_date | string | – | Present only when an inline page was cut short: the first publication date not in rates. Pass it as start_date with the same end_date and a positive limit to get the next page. For limit 0 it is the… |
| notice | string | – | Explains a result that would otherwise look broken or incomplete: an empty series (no publication day in the range); an inline page cut short (the start_date to continue from, plus why a long range w… |
| quote_currency | string | – | Quote currency code. |
| rate_count | number | – | Total observed publication days in the requested range (the start_date through end_date passed on this call) — not the number of entries in rates, which is smaller when truncated is true. On a contin… |
| rate_type | string | – | Always "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask. |
| rates | object | – | Date → rate map in date order, observed days inside the requested range only. Bounded by limit (default/max 500), and by the character budget for automatically staged previews. Empty for limit 0 or n… |
| source | string | – | Always "Frankfurter v1" — the upstream data provider. |
| spilled | boolean | – | True when the complete result was staged on DataCanvas, either explicitly through canvas_id or automatically after exceeding the threshold and preview budget. |
| start_date | string | – | First observed publication date in the requested range, including when limit is 0. Always inside the requested range — later than the requested start when that day had no Frankfurter v1 fix, and equa… |
| summary | object | – | Statistics over all observed days in the full clipped requested range before limit, paging or staging; omitted for empty ranges. Missing-leg coverage notices describe excluded served days. Continuati… |
| table_name | string | – | Canvas table name — present when spilled is true. Use it as the FROM target in fx_dataframe_query SQL; fx_dataframe_describe lists its columns. |
| truncated | boolean | – | True when rates holds only part of the series: an inline page (next_start_date continues it) or a spilled preview (spilled is true). False when rates holds every publication day in the requested rang… |
No examples provided.
fx_list_currencies Fx List Currencies ~135
List current Frankfurter v1 currency codes and names with as_of, the latest served rate date. include_retired=true adds historical codes absent from the current set. Optional official ECB start_date/end_date are outer coverage bounds, not uninterrupted availability; a dated end_date does not imply retirement. Metadata outages are disclosed without failing current discovery. Historical availability remains validated from requested v1 data. Use this to disambiguate dollars (USD vs AUD vs CAD).
| Name | Type | Req | Description |
|---|---|---|---|
| include_retired | boolean | – | Include historical codes absent from current v1 discovery, default false. Optional official ECB coverage dates are outer bounds and may contain gaps. |
| Name | Type | Req | Description |
|---|---|---|---|
| as_of | string | – | Latest served daily rate date for this current-discovery list; historical availability is checked against historical data. |
| count | number | – | Total number of supported currencies. |
| currencies | array | – | All supported currencies, sorted alphabetically by code. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Discloses unavailable optional coverage metadata or incomplete coverage dates. |
| source | string | – | Always "Frankfurter v1" — the upstream data provider. |
No examples provided.
How do I install the io.github.cyanheads/exchange-rates-mcp-server server?
io.github.cyanheads/exchange-rates-mcp-server is a hosted endpoint at https://exchange-rates.caseyjhand.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · exchange-rates.caseyjhand.com
claude mcp add --transport http cyanheads-exchange-rates-mcp-server 'https://exchange-rates.caseyjhand.com/mcp'
What is the io.github.cyanheads/exchange-rates-mcp-server server?
io.github.cyanheads/exchange-rates-mcp-server is listed in the public MCP registry as io.github.cyanheads/exchange-rates-mcp-server. Convert currencies, get FX rates, and query historical Frankfurter v1 exchange rate data. This page covers its hosted endpoint (https://exchange-rates.caseyjhand.com/mcp).
Is the io.github.cyanheads/exchange-rates-mcp-server server safe to use?
io.github.cyanheads/exchange-rates-mcp-server scores 90 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the io.github.cyanheads/exchange-rates-mcp-server server expose?
io.github.cyanheads/exchange-rates-mcp-server exposes 7 tools: fx_list_currencies, fx_get_rates, fx_get_rate, fx_convert_currency, fx_get_timeseries, and 2 more. Their descriptions and schemas cost roughly 1,657 tokens of context every time the server is loaded.
Does the io.github.cyanheads/exchange-rates-mcp-server server require authentication?
No. We connected to io.github.cyanheads/exchange-rates-mcp-server without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the io.github.cyanheads/exchange-rates-mcp-server server still maintained?
io.github.cyanheads/exchange-rates-mcp-server is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.