# Frankfurter Forex MCP
MCP server in Python for currency rates, conversion, and exchange-rate history using the Frankfurter API.
## Features
- `base_quote`: latest rates from a base currency to one or many targets
- `convert_currency`: converts an amount between two currencies
- `exchange_history`: returns the time series for a currency pair in a date range
- Structured error payloads with `error_code`, `tool`, and `trace_id`
- Retry with exponential backoff for transient upstream failures
## Tech stack
- Python 3.11+
- MCP Python SDK (`mcp`)
- `httpx` async client
- Pydantic v2
- `pytest`, `pytest-asyncio`, `ruff`
## Project structure
```text
src/frankfurter_forex_mcp/
client/frankfurter.py
models/schemas.py
tools/
base_quote.py
convert_currency.py
exchange_history.py
server.py
tests/
```
## Setup
1. Install dependencies:
```bash
uv sync --all-extras
```
2. Copy environment file:
```bash
cp .env.example .env
```
## Run MCP server (stdio)
```bash
uv run python -m frankfurter_forex_mcp.server
```
## Use with MCP Inspector on localhost
The easiest way to expose this server in the local Inspector is using:
```bash
uv run mcp dev src/frankfurter_forex_mcp/server.py
```
This command starts the local Inspector bridge and shows a localhost URL in the terminal.
For a manual Inspector stdio connection flow, see [`.docs/mcp-inspector-guide.md`](.docs/mcp-inspector-guide.md).
## Advanced MCP practices implemented
- Strict request validation with Pydantic before external calls
- Strict external payload validation before response serialization
- Stable JSON error contracts for machine clients
- `stdio`-safe runtime behavior (no stdout logging side effects)
- CI pipeline for linting, testing, and package smoke checks
## Run quality checks
```bash
uv run ruff check .
uv run pytest
```
## CI
GitHub Actions workflow is available at `.github/workflows/ci.yaml`.