FX Rates MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@FX Rates MCP ServerHow much is 100 USD in EUR right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
FX Rates MCP Server
A production-shaped Model Context Protocol server that gives AI agents (Claude, ChatGPT, Cursor, and any MCP client) live and historical foreign-exchange rates. Built by 7Block Labs as a public reference for how we ship MCP servers for companies that sell data and APIs.
It runs on the free Frankfurter API (European Central Bank reference rates, no key required), so you can clone it and have a working MCP server in under a minute.
Why this repo exists
Most "MCP servers" are an OpenAPI spec auto-converted into one tool per endpoint — which agents use badly. This one is deliberately built the way a data/API company should ship theirs:
Task-shaped tools, not endpoint dumps. Five tools that answer real questions (
convert_amount,latest_rates,historical_rate,timeseries,list_currencies) instead of a raw mirror of the HTTP API.Precise tool descriptions + read-only annotations (
readOnlyHint) so the model knows when and which tool to call — the difference between a demo and something agents use reliably.Streamable HTTP transport (MCP spec 2025-06-18 and later), ready to deploy as a remote server.
A clean seam for auth + plan entitlements. For a paid data API this is where per-user OAuth 2.1, plan → scope mapping, rate limits, and usage metering attach. See
docs/PRODUCTION.md.
Related MCP server: Realtime Exchange Rate MCP Server
Quickstart
python -m venv .venv && source .venv/bin/activate
pip install -e .
# Local (stdio) — for Claude Desktop / Cursor:
python -m fx_mcp.server
# Remote (Streamable HTTP) — for hosting:
TRANSPORT=http PORT=8000 python -m fx_mcp.serverUse it in Claude Code
claude mcp add --transport http fx-rates http://localhost:8000/mcpUse it in Claude Desktop / Cursor (stdio)
{
"mcpServers": {
"fx-rates": { "command": "python", "args": ["-m", "fx_mcp.server"] }
}
}Tools
Tool | What it answers |
| "How much is 100 USD in EUR?" (latest or on a date) |
| Today's ECB rates for a base against some/all currencies |
| Rates on a specific past date |
| A daily series over a range (for trends / charts) |
| All supported currency codes + names |
From reference to your production server
This is the free-data version. For a company selling a paid data API, the same architecture extends to: account linking (OAuth 2.1 into your existing logins), plan-aware entitlements and rate limits, usage metering into your billing, an in-chat UI, and listing in the Claude and ChatGPT directories.
That's what we do. 7Block Labs builds and launches MCP servers for data and API companies — get in touch.
License
MIT — see LICENSE.
Available Tools
5 toolsconvert_amountConvert an amount between currenciesARead-only
Convert a money amount from one currency to another using the latest ECB rate (or a specific date). Returns the converted amount and the rate used. Example: convert_amount(amount=100, base='USD', quote='EUR').
| Name | Required | Description | Default |
|---|---|---|---|
| on | No | ||
| base | Yes | ||
| quote | Yes | ||
| amount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly and openWorld safety, so the bar is low; the description goes beyond them by disclosing the data source (ECB) and the return payload (converted amount plus the rate used). That is genuinely useful context, though it omits rate freshness/latency caveats.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three front-loaded sentences: purpose, return, example. No filler, and the most important information leads. The inline example is marginally redundant but cheap and clarifying.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description helpfully states what is returned (converted amount and rate used). Combined with the ECB source and a concrete call example, an agent has enough to invoke it correctly; the only real gap is the format of the optional 'on' date.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load. It effectively explains amount, base, and quote through the example and phrasing, and maps 'or a specific date' to the optional 'on' parameter, but never specifies the accepted date format for 'on'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource (convert a money amount between currencies) and even names the data source (latest ECB rate). It is clearly distinct from rate-listing siblings like latest_rates or historical_rate, though it never names an alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It mentions 'the latest ECB rate (or a specific date)', which implies the two usage modes, but there is no explicit when-to-use guidance, no prerequisites, and no routing to sibling tools like latest_rates or historical_rate. Usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historical_rateHistorical rate on a dateARead-only
Get ECB reference rates for a specific past date (YYYY-MM-DD). Weekends/holidays return the most recent prior business day. Example: historical_rate('2020-01-02', base='USD').
| Name | Required | Description | Default |
|---|---|---|---|
| on | Yes | ||
| base | No | EUR | |
| symbols | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, and the description adds real value on top by disclosing the weekend/holiday fallback semantics, which an agent could not infer. It omits the response shape and any date-range limits (e.g. ECB data start date), but the key surprising behavior is covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly packed sentences: purpose first, then the edge-case rule, then a concrete invocation example. No filler; the example doubles as parameter documentation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only lookup the description is close to complete, but with no output schema the agent gains no picture of the returned rate structure or error behavior for out-of-range dates. The undocumented 'symbols' parameter is also left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the burden: it documents the 'on' format (YYYY-MM-DD) and demonstrates 'base' with a default of EUR via the example. The 'symbols' parameter is never mentioned, leaving one of three parameters undocumented in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource, and source ('Get ECB reference rates for a specific past date'), which separates it from latest_rates and timeseries by temporal scope. It does not name those siblings explicitly, so the differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for when to call it (a specific historical date) and a non-obvious usage rule: weekends/holidays resolve to the most recent prior business day. No alternatives or prerequisite conditions are named, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
latest_ratesLatest exchange ratesARead-only
Get today's ECB reference rates for one base currency against some or all currencies. Example: latest_rates(base='EUR', symbols=['USD','GBP']).
| Name | Required | Description | Default |
|---|---|---|---|
| base | No | EUR | |
| symbols | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety and external-source behavior are covered. The description adds the ECB provenance and same-day freshness, which is useful context, but says nothing about rate availability timing, weekend/holiday behavior, or fallback when a symbol is unknown.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the capability and scope first, then a compact call example. Every element earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool with read-only and open-world annotations, the description covers invocation adequately. But with no output schema, the return shape (a mapping of currency to rate, date stamp, source) is never described, so an agent can't anticipate the response structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate; the inline example clarifies that base is a single currency and symbols is a list, and hints at the default behavior. It still doesn't explain what a null/omitted symbols means (all currencies) or the expected symbol format, leaving part of the gap unfilled.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Get today's ECB reference rates' — with the data source named, which separates it from generic rate lookups. It does not explicitly name how it differs from siblings like historical_rate or timeseries, but the 'today's' scope does most of that work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'today's' framing implicitly tells the agent to use historical_rate/timeseries for other time ranges, and a concrete call example is provided. However, there is no explicit when-to-use or when-not clause, and no mention that a companion call (list_currencies) exists for discovering valid symbols.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_currenciesList supported currenciesARead-only
List all currency codes the service supports, with their full names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety and scope are covered structurally. The description adds only that results include full names alongside codes; it says nothing about ordering, completeness, or caching, so it adds modest value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that states the resource and the payload contents with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, no output schema, and annotations covering the safety profile, the description is nearly self-sufficient; it tells the agent what comes back. Only minor details like ordering or whether codes are ISO-4217 are absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so per the rubric the baseline is 4. Schema coverage is 100% and there is nothing further the description could clarify about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (list) and resource (currency codes the service supports) plus the returned detail (full names). It is clearly distinct from the sibling rate/convert tools, though it does not explicitly say so.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or when-not-to-use guidance is given; usage is only implied by the tool's nature as a reference/enumeration endpoint. For a zero-parameter lookup tool this is adequate but leaves routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timeseriesRate time series over a rangeBRead-only
Get a daily time series of rates between two dates for a base/quote pair. Useful for trends or charts. Example: timeseries('2024-01-01','2024-01-31', base='USD', quote='INR').
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| base | Yes | ||
| quote | Yes | ||
| start | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds that granularity is daily and that the range is bounded by two dates, but says nothing about rate limits, data source, pagination, or whether end is inclusive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core behavior and finished with a concrete example. Nothing is padded, though the example repeats information the leading sentence already supplies.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description partly compensates by describing the result as a daily series of rates. Still missing boundary semantics for the date range and confirmation that the identifiers are ISO currency codes, which the four required params make important.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across four required params, so the description carries real weight. The example conveys date string format and that base/quote are currency identifiers, but it never says whether end is inclusive or whether codes must come from list_currencies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Get) and resource (daily time series of rates) scoped to a date range and base/quote pair. The 'daily time series' framing distinguishes it from latest_rates and historical_rate, though it never names those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Useful for trends or charts' implies the use case but gives no when-not guidance and does not point to siblings like historical_rate for a single date or latest_rates for a current snapshot. Usage is inferable but not routed.
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.
5 tool updates
v1.0.0- First observed
convert_amount - First observed
historical_rate - First observed
latest_rates - First observed
list_currencies - First observed
timeseries
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: convert_amount converts an amount, latest_rates retrieves current rates, historical_rate fetches rates for a specific date, timeseries returns a date-range series, and list_currencies enumerates supported currencies. Although convert_amount mentions using a specific date, it remains the only conversion tool, so boundaries stay unambiguous.
All names use snake_case, but the pattern mixes verb_noun (convert_amount, list_currencies) with adjective/noun phrases (latest_rates, historical_rate) and a bare noun (timeseries). This inconsistency is noticeable, though names remain readable and predictable in casing.
5 tools is well-scoped for an FX rates service, covering conversion, current rates, historical rates, time series, and currency enumeration without redundancy or missing core functionality.
The surface covers the full lifecycle of exchange-rate needs: current and historical retrieval, time series, conversion, and supported-currency listing. No obvious gaps for the stated ECB-based domain.
Maintenance
Related MCP Connectors
Live & historical FX rates and currency conversion for AI agents. No API keys.
Live & historical FX rates and currency conversion for AI agents. No API keys.
Convert currencies, get FX rates, and query historical ECB exchange rate data.
ExchangeRate MCP — wraps open.er-api.com (free, no auth)
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides access to currency exchange rates and conversion tools using the Frankfurter API, including latest rates, historical data, and time series from sources like the European Central Bank.5MIT
- AlicenseAqualityBmaintenanceProvides real-time foreign-exchange rates, historical data, and multi-currency lookups to MCP-compatible AI coding assistants like Claude Code and Cursor.4130 npmMIT
- AlicenseNot gradedqualityAmaintenanceConvert currencies, get FX rates, and query historical ECB exchange rate data via MCP.278 npm1Apache 2.0
- AlicenseNot gradedqualityBmaintenanceMCP server for currency conversion with real-time exchange rates via the Frankfurter API. Enables agents to retrieve latest currency data and perform conversions.Apache 2.0