Skip to main content
Glama
lcfranca

Frankfurter Forex MCP

by lcfranca

base_quote

Retrieve current exchange rates from a base currency to multiple target currencies using the Frankfurter Forex MCP server.

Instructions

Get latest exchange rates from one base currency to multiple target currencies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
baseYes
targetsYes

Implementation Reference

  • Core handler function that executes the base_quote tool. Calls Frankfurter API's latest endpoint, validates response payload, extracts rates for target currencies, and returns structured output.
    async def execute(input_data: BaseQuoteInput, client: FrankfurterClient) -> BaseQuoteOutput:
        payload = await client.latest(base=input_data.base, targets=input_data.targets)
        payload_rates = payload.get("rates", {})
        payload_date = payload.get("date")
    
        if not isinstance(payload_rates, dict):
            raise FrankfurterClientError("Frankfurter API returned malformed rates payload")
        if not isinstance(payload_date, str):
            raise FrankfurterClientError("Frankfurter API returned malformed date payload")
    
        rates: dict[str, float] = {}
        for currency in input_data.targets:
            value = payload_rates.get(currency)
            if value is not None:
                try:
                    rates[currency] = float(value)
                except (TypeError, ValueError) as exc:
                    raise FrankfurterClientError("Frankfurter API returned non-numeric rate") from exc
    
        if not rates:
            raise FrankfurterClientError("Frankfurter API returned no rates for requested targets")
    
        return BaseQuoteOutput(
            base=str(payload.get("base", input_data.base)),
            date=date.fromisoformat(payload_date),
            rates=rates,
        )
  • MCP tool registration with @mcp.tool decorator. Wraps the execute function, creates FrankfurterClient, handles validation errors and upstream errors, returns JSON response.
    @mcp.tool(name="base_quote")
    async def base_quote_tool(base: str, targets: list[str]) -> dict:
        """Get latest exchange rates from one base currency to multiple target currencies."""
        try:
            input_data = BaseQuoteInput(base=base, targets=targets)
            async with FrankfurterClient.from_env() as client:
                output = await base_quote.execute(input_data, client)
            return output.model_dump(mode="json")
        except ValidationError as exc:
            return _to_error(str(exc), tool="base_quote", error_code="validation_error")
        except FrankfurterClientError as exc:
            return _to_error(str(exc), tool="base_quote", error_code="upstream_error")
        except Exception:
            return _to_error(
                "Unexpected internal error",
                tool="base_quote",
                error_code="internal_error",
            )
  • Input validation schema (BaseQuoteInput) with field validators for normalizing currency codes, validating 3-letter ISO 4217 format, deduplicating targets, and ensuring base currency is not in targets.
    class BaseQuoteInput(BaseModel):
        model_config = ConfigDict(str_strip_whitespace=True)
    
        base: str = Field(min_length=3, max_length=3, default="EUR")
        targets: list[str] = Field(min_length=1)
    
        @field_validator("base")
        @classmethod
        def normalize_base(cls, value: str) -> str:
            value = _normalize_currency(value)
            if len(value) != 3 or not value.isalpha():
                raise ValueError("base must be a 3-letter ISO 4217 currency code")
            return value
    
        @field_validator("targets")
        @classmethod
        def normalize_targets(cls, values: list[str]) -> list[str]:
            normalized: list[str] = []
            for value in values:
                currency = _normalize_currency(value)
                if len(currency) != 3 or not currency.isalpha():
                    raise ValueError("targets must contain valid 3-letter ISO 4217 codes")
                normalized.append(currency)
    
            deduplicated = list(dict.fromkeys(normalized))
            if not deduplicated:
                raise ValueError("targets cannot be empty")
            return deduplicated
    
        @model_validator(mode="after")
        def validate_base_not_in_targets(self) -> BaseQuoteInput:
            if self.base in self.targets:
                raise ValueError("base currency must not be included in targets")
            return self
  • Output schema (BaseQuoteOutput) defining the structure of the response with base currency, date, and dictionary of exchange rates.
    class BaseQuoteOutput(BaseModel):
        base: str
        date: date
        rates: dict[str, float]
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lcfranca/frankfurter-forex-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server