How to Use Exchange Rate APIs with AI Agents, LLMs, and Chatbots
Large language models are increasingly embedded in products that require accurate, real-time data. When a user asks a chatbot "How much is 500 EUR in Japanese yen right now?" the model cannot answer from its training data alone. Training corpora are months or years out of date, and exchange rates change every few seconds during market hours. The model needs a live data source.
An exchange rate API solves this problem. It gives AI agents, LLMs, and chatbots a structured way to fetch current and historical currency data on demand, turning a hallucination-prone guess into a precise, timestamped answer.
This guide covers three integration approaches -- MCP servers, function calling (tool use), and direct API injection -- with working code examples for each. All examples use the Exchange Rate API, which returns JSON, supports 160+ currencies, and provides a free tier with 1,500 requests per month.
Why AI Agents Need Real-Time Exchange Rates
LLMs have a fundamental limitation when it comes to financial data: their training data is static. A model trained in early 2025 has no idea what the USD/EUR rate is today, and even if it memorizes a rate from its training set, that number is almost certainly wrong by now.
This matters for several reasons:
- Accuracy expectations are high. Users asking about money expect precise answers. A chatbot that says "1 USD is approximately 0.85 EUR" when the actual rate is 0.92 will lose trust immediately.
- Exchange rates are volatile. Major currency pairs can move 1-2% in a single day during periods of economic uncertainty. Emerging market currencies can swing much more.
- Financial decisions depend on correct data. Whether a user is sending a remittance, pricing a product for international customers, or analyzing a portfolio, stale rates lead to real financial consequences.
- Compliance and audit trails. Applications in fintech, e-commerce, and accounting often need to record the exact rate used for a transaction, along with its timestamp and source.
An exchange rate API provides the missing link between the LLM's reasoning capabilities and the live data it needs to answer currency questions correctly.
Three Integration Approaches
| Approach | Best For | Complexity |
|---|---|---|
| MCP Servers | Claude Code, Cursor, AI IDEs | Low |
| Function Calling / Tool Use | OpenAI, Anthropic, custom agents | Medium |
| RAG / Direct API Calls | Custom chatbots, pipelines | Medium |
Approach 1: MCP Servers (Model Context Protocol)
What Is MCP?
The Model Context Protocol (MCP) is an open standard that lets AI applications connect to external data sources and tools through a unified interface. Think of MCP as a USB port for AI tools. Once a data source exposes an MCP server, any MCP-compatible client -- Claude Code, Cursor, Windsurf, or a custom application -- can connect to it without custom integration code.
An MCP server exposes tools (functions the AI can call), resources (data the AI can read), and prompts (reusable templates). For exchange rates, the tools are the important part: they let the AI fetch live rates, convert amounts, and look up historical data by calling the API on behalf of the user.
The Exchange Rate API MCP Server
The Exchange Rate API provides an official MCP server as an npm package: @allratestoday/mcp-server. It exposes tools for fetching latest rates, converting currencies, retrieving historical rates, and querying time-series data. Authentication, request formatting, and response parsing are all handled internally.
Setting Up in Claude Code
Add the MCP server to your project's .mcp.json configuration file:
{
"mcpServers": {
"exchange-rates": {
"command": "npx",
"args": ["-y", "@allratestoday/mcp-server"],
"env": {
"EXCHANGE_RATE_API_KEY": "era_live_your_api_key_here"
}
}
}
}
Once configured, Claude Code can directly answer questions like "What is the current USD to EUR rate?", "Convert 1000 GBP to INR", or "Show me how the EUR/JPY rate changed over the last 30 days." The AI automatically selects the right tool, calls the MCP server, and formats the response. No additional code is required.
Setting Up in Cursor
For Cursor, create a .cursor/mcp.json file in your project root with the same configuration:
{
"mcpServers": {
"exchange-rates": {
"command": "npx",
"args": ["-y", "@allratestoday/mcp-server"],
"env": {
"EXCHANGE_RATE_API_KEY": "era_live_your_api_key_here"
}
}
}
}
The setup is identical because both tools follow the MCP standard. Write one server, use it everywhere.
Setting Up in Claude Desktop
Edit the configuration file at ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows) with the same mcpServers block shown above. After restarting Claude Desktop, the exchange rate tools will appear in the tools menu automatically.
Approach 2: Function Calling / Tool Use
Function calling (also called tool use) is the most common way to integrate external APIs with LLMs programmatically. You define a set of tools with their parameters and descriptions, the model decides when to call them, and your application executes the actual API request and feeds the result back.
OpenAI Function Calling Example
import json
import requests
from openai import OpenAI
EXCHANGE_RATE_API_KEY = "era_live_your_api_key_here"
EXCHANGE_RATE_BASE_URL = "https://api.allratestoday.com/v1"
client = OpenAI()
tools = [
{
"type": "function",
"function": {
"name": "get_exchange_rate",
"description": "Get the current exchange rate between two currencies and optionally convert an amount.",
"parameters": {
"type": "object",
"properties": {
"base": {"type": "string", "description": "The source currency code (e.g., USD, EUR, GBP)"},
"target": {"type": "string", "description": "The target currency code (e.g., JPY, CAD, INR)"},
"amount": {"type": "number", "description": "The amount to convert. Defaults to 1."}
},
"required": ["base", "target"]
}
}
}
]
def call_exchange_rate_api(base: str, target: str, amount: float = 1.0) -> dict:
"""Call the Exchange Rate API and return the result."""
response = requests.get(
f"{EXCHANGE_RATE_BASE_URL}/latest",
params={"base": base, "symbols": target},
headers={"Authorization": f"Bearer {EXCHANGE_RATE_API_KEY}"}
)
response.raise_for_status()
data = response.json()
rate = data["rates"][target]
return {
"base": base,
"target": target,
"rate": rate,
"converted_amount": round(rate * amount, 4),
"amount": amount,
"date": data["date"]
}
def chat_with_exchange_rates(user_message: str) -> str:
"""Send a message to the model with exchange rate tool access."""
messages = [
{"role": "system", "content": "You are a helpful financial assistant. Use the get_exchange_rate tool to answer currency questions with live data. Always cite the date of the rate."},
{"role": "user", "content": user_message}
]
response = client.chat.completions.create(
model="gpt-4o", messages=messages, tools=tools, tool_choice="auto"
)
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
args = json.loads(tool_call.function.arguments)
result = call_exchange_rate_api(**args)
messages.append(message)
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)})
final_response = client.chat.completions.create(model="gpt-4o", messages=messages)
return final_response.choices[0].message.content
return message.content
print(chat_with_exchange_rates("How much is 500 euros in Japanese yen?"))
Anthropic Claude Tool Use Example
The Anthropic Messages API uses a similar pattern with a slightly different schema format:
import json
import requests
import anthropic
EXCHANGE_RATE_API_KEY = "era_live_your_api_key_here"
EXCHANGE_RATE_BASE_URL = "https://api.allratestoday.com/v1"
client = anthropic.Anthropic()
tools = [
{
"name": "get_exchange_rate",
"description": "Get the current exchange rate between two currencies and optionally convert an amount.",
"input_schema": {
"type": "object",
"properties": {
"base": {"type": "string", "description": "The source currency code (e.g., USD, EUR, GBP)"},
"target": {"type": "string", "description": "The target currency code (e.g., JPY, CAD, INR)"},
"amount": {"type": "number", "description": "The amount to convert. Defaults to 1."}
},
"required": ["base", "target"]
}
}
]
def call_exchange_rate_api(base: str, target: str, amount: float = 1.0) -> dict:
response = requests.get(
f"{EXCHANGE_RATE_BASE_URL}/latest",
params={"base": base, "symbols": target},
headers={"Authorization": f"Bearer {EXCHANGE_RATE_API_KEY}"}
)
response.raise_for_status()
data = response.json()
rate = data["rates"][target]
return {"base": base, "target": target, "rate": rate, "converted_amount": round(rate * amount, 4), "date": data["date"]}
def chat_with_exchange_rates(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
system = "You are a helpful financial assistant. Use the get_exchange_rate tool to answer currency questions with live data. Always cite the date of the rate."
response = client.messages.create(
model="claude-sonnet-4-20250514", max_tokens=1024, system=system, tools=tools, messages=messages
)
if response.stop_reason == "tool_use":
tool_use_block = next(b for b in response.content if b.type == "tool_use")
result = call_exchange_rate_api(**tool_use_block.input)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": [{"type": "tool_result", "tool_use_id": tool_use_block.id, "content": json.dumps(result)}]})
final_response = client.messages.create(
model="claude-sonnet-4-20250514", max_tokens=1024, system=system, tools=tools, messages=messages
)
return final_response.content[0].text
return response.content[0].text
print(chat_with_exchange_rates("Convert 250 GBP to Indian rupees"))
Expanding to Multiple Tools
For more capable agents, define separate tools for different API endpoints:
tools = [
{"name": "get_latest_rate", "description": "Get the current exchange rate between two currencies.", ...},
{"name": "convert_currency", "description": "Convert a specific amount from one currency to another.", ...},
{"name": "get_historical_rate", "description": "Get the exchange rate on a specific past date.", ...}
]
This lets the model route "What was the USD to EUR rate on January 1st?" to get_historical_rate, while "Convert 100 dollars to pounds" triggers convert_currency.
Approach 3: RAG / Direct API Calls
For custom chatbots or pipelines where you control the prompt, you can fetch exchange rate data before calling the LLM and inject it directly. This works with any model, including those without function calling support.
Python Chatbot with Exchange Rate Lookup
import requests
EXCHANGE_RATE_API_KEY = "era_live_your_api_key_here"
BASE_URL = "https://api.allratestoday.com/v1"
CURRENCY_CODES = ["USD", "EUR", "GBP", "JPY", "CAD", "AUD", "CHF", "CNY", "INR", "MXN", "BRL", "KRW"]
def detect_currencies(text: str) -> list:
text_upper = text.upper()
return [code for code in CURRENCY_CODES if code in text_upper]
def fetch_rates(base: str, targets: list) -> dict:
response = requests.get(
f"{BASE_URL}/latest",
params={"base": base, "symbols": ",".join(targets)},
headers={"Authorization": f"Bearer {EXCHANGE_RATE_API_KEY}"}
)
response.raise_for_status()
return response.json()
def build_prompt_with_rates(user_message: str) -> str:
currencies = detect_currencies(user_message)
rate_context = ""
if len(currencies) >= 2:
base, targets = currencies[0], currencies[1:]
rate_data = fetch_rates(base, targets)
rate_context = f"\n\nCurrent exchange rates as of {rate_data['date']}:\n"
for currency, rate in rate_data["rates"].items():
rate_context += f" 1 {base} = {rate} {currency}\n"
rate_context += "Source: Exchange Rate API (exchange-rateapi.com)\n"
system = "You are a helpful financial assistant. Answer currency questions using the provided exchange rate data. Always mention the date and cite the source."
return f"{system}{rate_context}\n\nUser question: {user_message}"
# Build the prompt, then send to any LLM
prompt = build_prompt_with_rates("How much is 500 EUR in JPY?")
# response = client.chat.completions.create(model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}])
Using the Official SDKs
For cleaner code, use the official SDKs instead of raw HTTP calls:
Python:
from exchangerateapi import ExchangeRateApi
api = ExchangeRateApi(api_key="era_live_your_api_key_here")
rates = api.latest(base="USD", symbols=["EUR", "GBP", "JPY"])
result = api.convert(from_currency="EUR", to_currency="USD", amount=1000)
JavaScript:
import { ExchangeRateApi } from "@exchangerateapi/sdk";
const api = new ExchangeRateApi({ apiKey: "era_live_your_api_key_here" });
const rates = await api.latest({ base: "USD", symbols: ["EUR", "GBP", "JPY"] });
const result = await api.convert({ from: "EUR", to: "USD", amount: 1000 });
Use Cases
Customer Support Bots with Live Pricing
E-commerce companies serving international customers can embed exchange rate lookups into their support chatbots. When a customer asks "How much does this cost in my currency?", the bot fetches the live rate, calculates the localized price, and presents it alongside the original price.
Financial Analysis Assistants
AI-powered financial analysis tools can use historical exchange rate data to generate reports on currency trends, calculate cross-border investment returns adjusted for FX movements, or flag unusual rate movements.
Travel Planning Agents
Travel chatbots can answer questions like "What's a good budget for a week in Tokyo in US dollars?" by combining general knowledge with live JPY/USD rates. They can also track rate changes and notify users when a favorable rate appears.
E-Commerce Price Localization
Online stores can use AI agents to dynamically localize prices during checkout. The agent fetches the latest rate, applies a markup or rounding strategy, and presents the price in the customer's local currency -- all without hard-coding rates into the application.
Multi-Currency Accounting
Accounting teams dealing with multiple currencies can use AI agents to reconcile transactions, calculate realized gains and losses from FX movements, and generate reports that pull historical rates for each transaction date.
Best Practices
Cache Exchange Rates
Exchange rates do not change every second for most use cases. Caching rates for 5-15 minutes reduces API calls significantly without affecting accuracy. This is especially important for AI agents, where a single conversation might trigger multiple lookups.
from functools import lru_cache
from datetime import datetime
@lru_cache(maxsize=128)
def get_cached_rate(base: str, target: str, cache_key: str) -> dict:
response = requests.get(
f"{BASE_URL}/latest", params={"base": base, "symbols": target},
headers={"Authorization": f"Bearer {EXCHANGE_RATE_API_KEY}"}
)
response.raise_for_status()
return response.json()
def get_rate(base: str, target: str) -> dict:
now = datetime.utcnow()
cache_key = now.strftime("%Y-%m-%d-%H") + f"-{now.minute // 10}"
return get_cached_rate(base, target, cache_key)
Handle Rate Limits Gracefully
The free tier provides 1,500 requests per month. For production agents, handle 429 responses with a fallback message rather than crashing:
def call_api_with_fallback(base: str, target: str) -> dict:
try:
response = requests.get(
f"{BASE_URL}/latest", params={"base": base, "symbols": target},
headers={"Authorization": f"Bearer {EXCHANGE_RATE_API_KEY}"}, timeout=10
)
if response.status_code == 429:
return {"error": "rate_limited", "message": "Exchange rate data is temporarily unavailable."}
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return {"error": "request_failed", "message": str(e)}
Request Only the Currencies You Need
Always use the symbols parameter instead of fetching all 160+ rates. This reduces payload size and response times, which matters when the API call is happening inside a tool-call loop that blocks the conversation.
Write Clear Tool Descriptions
The quality of your tool descriptions directly affects how well the model uses them:
# Weak -- the model may not know when to use this
"description": "Get exchange rates"
# Strong -- the model knows exactly when and why to call this tool
"description": "Get the current exchange rate between two currencies. Use this whenever the user asks about currency conversion, exchange rates, how much something costs in another currency, or foreign exchange prices. Returns the live mid-market rate with a timestamp."
Include Rate Metadata in Responses
Always include the date and source of the rate in the AI's response. This builds user trust and creates an audit trail. Add instructions in your system prompt:
When providing exchange rate information:
1. Always state the date the rate was retrieved
2. Mention that rates are mid-market rates from Exchange Rate API
3. Note that actual bank or payment provider rates may differ
4. For financial decisions, suggest verifying the rate at transaction time
Choosing the Right Approach
| Factor | MCP Server | Function Calling | Direct API / RAG |
|---|---|---|---|
| Setup effort | Minimal (JSON config) | Moderate (code required) | Moderate (code required) |
| Model support | Claude, Cursor, MCP clients | OpenAI, Anthropic, most LLMs | Any LLM |
| User control | Low (AI decides when to call) | Medium (you define tools) | High (you control everything) |
| Best for | Developer tools, AI IDEs | Production chatbots, agents | Custom pipelines, batch jobs |
For most production applications, function calling provides the best balance of control and ease of use. For developer-facing tools and AI-assisted coding, MCP servers are the fastest path to integration. For legacy systems or models without tool support, direct API injection works reliably.
Getting Started
- Sign up for a free API key at exchange-rateapi.com. The free tier includes 1,500 requests per month.
- Choose your approach based on the comparison table above.
- Install the SDK if you prefer a higher-level interface:
- JavaScript:
npm install @exchangerateapi/sdk - Python:
pip install exchangerateapi - MCP:
npx -y @allratestoday/mcp-server - Start with a single tool (
get_exchange_rate) and expand as needed. - Add caching before going to production to stay within rate limits and reduce latency.
Conclusion
AI agents are only as useful as the data they can access. For any application that touches international commerce, travel, or finance, real-time exchange rates are a core requirement -- not a nice-to-have. By integrating the Exchange Rate API through MCP servers, function calling, or direct API injection, you give your AI system the ability to answer currency questions accurately, with live data and proper citations.
The three approaches covered in this guide serve different needs. MCP servers offer zero-code setup for tools like Claude Code and Cursor. Function calling provides fine-grained control for production chatbots built on OpenAI or Anthropic APIs. Direct API calls work with any LLM, including open-source models running locally.
Whichever approach you choose, the principles are the same: fetch live data instead of relying on training knowledge, cache aggressively to manage costs and latency, handle errors gracefully, and always tell the user when the rate was last updated.
Further Resources
- Exchange Rate API Documentation
- MCP Server on npm
- JavaScript SDK on npm
- Python SDK on PyPI
- GitHub Organization
- Model Context Protocol Specification
Get Started for Free
Real-time mid-market rates, historical data, 160+ currencies. Official SDKs for JavaScript, Python, PHP, and React.
Get Your Free API Key →