MCP server for the Xe Currency Data API — real-time rates, historical data, and volatility analysis in Claude Code
xe-mcp defines 12 tools with complete JSON schemas and descriptions. All tools are READ_ONLY and follow verb_noun naming (get_rate, convert, list_currencies, etc.). Descriptions are substantive (100-250 chars) and explain WHAT the tool does and WHEN to use it. However, parameter descriptions lack actionable constraints (e.g., 'days' accepts 1 - 90 but description says 'Number of days of history' without bounds). Output schemas are not documented, LLMs cannot predict response structure. Error handling returns plain text errors without recovery guidance. No tool annotations (readOnlyHint, idempotentHint) despite all tools being read-only. Tool composition is sound: each tool has one responsibility, and outputs contain IDs for chaining (e.g., pair_summary returns rate, volatility, send_window verdict).
Convert an amount from one currency to another at the current mid-market rate.
Compute the Pearson correlation of daily log-returns between two currency pairs over N days. Useful for understanding co-movement: NZD/USD vs AUD/USD typically correlate highly (~0.85). Range: -1 (inverse) to +1 (perfect).
Fetch daily mid-market rates for a currency pair over the past N days. Uses Xe when credentials are set; falls back to Frankfurter (ECB) for free use.
Get the current mid-market exchange rate between two currencies. Uses Xe when credentials are set; falls back to Frankfurter (ECB) for free use.
List currency codes. Returns common currencies without credentials; the full Xe list (~170 currencies) requires Xe credentials.
Calculate simple moving averages (SMA) for a currency pair. Returns 20, 50, and 200-day SMAs (or custom period), current rate, and distance from each MA — useful for trend assessment.
Output schemas not documented. LLMs cannot predict response structure (e.g., does volatility_analysis return {volatility: number, annualized: number} or {daily_std_dev, annualized_volatility}?). Forces agents to guess field names and risks parsing errors.
Parameter constraints not stated in descriptions. 'days' parameter accepts 1 - 90 (or 7 - 90 for volatility) but descriptions omit bounds. LLMs may pass invalid values (e.g., days=365) causing silent API failures.
No tool annotations despite all tools being read-only. Adding readOnlyHint=true to all tools would signal to agents that these calls are safe to retry and have no side effects.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
Snapshot of NZD against all major trading pairs simultaneously (USD, AUD, EUR, GBP, JPY, SGD, CNY). Useful for a quick NZD strength overview.
Tells you where today's rate sits in the N-day distribution and whether now is statistically favourable to convert. Useful for FX timing decisions.
One-call morning briefing for a currency pair: current rate, N-day range, annualised volatility, send window verdict, and correlation context.
Check whether a currency pair's current rate has crossed a threshold. Returns a boolean verdict and the current rate — designed for use in polling loops or CI checks that trigger alerts.
Render an ASCII line chart of a currency pair's rate history over N days. Shows trend visually in the terminal.
Calculate annualised volatility of a currency pair over the past N days. Returns daily std-dev of log-returns and annualised figure — same methodology used in FX options pricing.
Error handling returns plain text without recovery guidance. E.g., 'Error: Invalid currency code' does not tell the agent to call list_currencies() first. Errors should be actionable per pattern:recovery-guide.
Fallback behavior (Xe vs Frankfurter) not exposed to LLM. Descriptions mention 'Uses Xe when credentials are set; falls back to Frankfurter' but LLM cannot control or predict which backend is used. Consider exposing as a parameter or documenting expected behavior differences.