Artificial intelligence technology

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:

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

  1. Sign up for a free API key at exchange-rateapi.com. The free tier includes 1,500 requests per month.
  2. Choose your approach based on the comparison table above.
  3. Install the SDK if you prefer a higher-level interface:
  4. JavaScript: npm install @exchangerateapi/sdk
  5. Python: pip install exchangerateapi
  6. MCP: npx -y @allratestoday/mcp-server
  7. Start with a single tool (get_exchange_rate) and expand as needed.
  8. 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

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 →

Related Articles