Skip to main content
Glama

exchange-rates-mcp-server

Server Details

Convert currencies, get FX rates, and query historical Frankfurter v1 exchange rate data.

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
100.0% over 74 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
cyanheads/exchange-rates-mcp-server
GitHub Stars
1
Server Listing
@cyanheads/exchange-rates-mcp-server

TDQS

A4.3/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a distinct role: single-rate lookup, bulk snapshot, conversion, timeseries retrieval, currency discovery, and DataCanvas schema/query. The descriptions explicitly clarify the boundary between fx_get_rate and fx_convert_currency, and between singular and plural rate retrieval. No two tools appear to do the same thing.

Naming Consistency5/5

All tools use a consistent fx_ snake_case prefix with clear verb_noun or verb_resource patterns. The convention is predictable across retrieval, conversion, listing, and DataCanvas operations. There are no mixed casing or naming styles.

Tool Count5/5

Seven tools is a well-scoped set for an exchange-rates server, covering the core read-only workflows without bloat. The two DataCanvas tools are appropriately specialized and conditional. Each tool earns its place.

Completeness5/5

The surface covers currency discovery, single and bulk rate retrieval, conversion, historical timeseries, and SQL-based analysis of staged data. For a read-only exchange-rate domain, this is complete and avoids dead ends. No obvious missing operation remains for the stated purpose.

Available Tools

7 tools
fx_convert_currencyFx Convert CurrencyA
Read-onlyIdempotent
Inspect

Convert an amount between any two currencies at the latest or a historical rate. Returns the converted amount, the rate used, the actual rate date, and whether the date was snapped from a weekend/holiday to the prior business day. Cross-rates are triangulated through EUR automatically.

NameRequiredDescriptionDefault
dateNoISO 8601 date (YYYY-MM-DD) for a historical rate. Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported.
amountYesAmount in the base currency to convert. Must be greater than zero.
base_currencyYesISO 4217 source currency code (e.g. USD). Call fx_list_currencies to get valid codes.
quote_currencyYesISO 4217 target currency code (e.g. EUR). The amount will be expressed in this currency. Call fx_list_currencies to get valid codes.

Output Schema

NameRequiredDescription
rateNoExchange rate used: units of quote currency per 1 unit of base currency.
errorNoPresent when the call failed. Absent on success.
sourceNoAlways "Frankfurter v1" — the upstream data provider.
rate_dateNoActual date of the rate used for conversion.
rate_typeNoAlways "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask.
base_amountNoThe input amount in the base currency.
date_snappedNoTrue when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day.
quote_amountNoThe converted amount in the quote currency, rounded to 6 decimal places.
base_currencyNoSource currency code.
quote_currencyNoTarget currency code.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/openWorld, yet the description still adds real behavior: weekend/holiday date snapping to the prior business day and automatic EUR triangulation for cross-rates. These are traits an agent could not infer from the schema, though it stops short of stating error behavior or precision/rounding rules.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero filler: purpose first, then return values, then the triangulation caveat. Front-loaded and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and full annotations, the description only needs to convey non-obvious semantics, and it does via date snapping and EUR triangulation. Minor gap: no mention of behavior for unsupported dates or rate precision, though the schema covers the former.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents date format, the 'latest' sentinel, amount constraints, and ISO 4217 codes with a pointer to fx_list_currencies. The description adds no new parameter-level meaning beyond reiterating latest vs. historical, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Convert an amount between any two currencies.' It implicitly separates itself from fx_get_rate/fx_get_rates by converting an amount rather than returning a bare rate, but it never names those siblings outright, so the differentiation is inferential rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'At the latest or a historical rate' implies when the date parameter applies, but the description gives no explicit when-to-use vs. fx_get_rate or fx_get_timeseries, and no exclusions. Usage is implied rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_dataframe_describeFx Dataframe DescribeA
Read-onlyIdempotent
Inspect

List tables and columns staged on a DataCanvas from a prior fx_get_timeseries call. Required first step before fx_dataframe_query — use it to discover table names and column schemas. Requires DataCanvas, which is on by default — a deployment that turns it off does not list this tool at all, and fx_get_timeseries returns every range inline there.

NameRequiredDescriptionDefault
canvas_idYesCanvas ID returned by fx_get_timeseries. Re-run fx_get_timeseries to obtain a fresh canvas_id if this one has expired.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
tablesNoAll tables and views currently staged on this canvas.
canvas_idNoThe canvas ID echoed back — use this in fx_dataframe_query.
expires_atNoISO 8601 timestamp when this canvas will be evicted.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-open-world, so the safety profile is covered. The description adds genuine context beyond that: the DataCanvas dependency, its default-on status, and the fact that deployments without it omit the tool entirely and return ranges inline via fx_get_timeseries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the action and resource, followed by the ordering constraint and the deployment caveat. No filler or repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value documentation is unnecessary. Between the description, the fully documented single parameter, and the annotations, an agent has everything needed to decide when and how to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema itself documents canvas_id, its format pattern, and the expiry/re-run guidance. The description only implies the canvas provenance already stated in the schema, so it adds little parameter-level meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (list) plus resource (tables and columns staged on a DataCanvas) and the provenance of that data (a prior fx_get_timeseries call). It clearly separates itself from fx_dataframe_query, the sibling that consumes what this tool exposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states it is the required first step before fx_dataframe_query and that its purpose is to discover table names and column schemas. It also explains the deployment condition (DataCanvas disabled) under which this tool is absent and the alternative behavior of fx_get_timeseries.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_dataframe_queryFx Dataframe QueryA
Read-onlyIdempotent
Inspect

Run a read-only SQL SELECT against DataCanvas tables staged by fx_get_timeseries. Supports aggregations, GROUP BY, window functions, and JOINs across multiple registered tables. Run fx_dataframe_describe first to discover table names and column schemas. Requires DataCanvas, which is on by default — a deployment that turns it off does not list this tool at all, and fx_get_timeseries returns every range inline there.

NameRequiredDescriptionDefault
queryYesRead-only SQL SELECT statement. Reference tables by the names returned by fx_dataframe_describe or the table_name field from fx_get_timeseries. Example: SELECT date, rate FROM <table_name> WHERE date > '2024-01-01' ORDER BY date; replace <table_name> with the returned name, including its unique suffix.
canvas_idYesCanvas ID returned by fx_get_timeseries. Re-run fx_get_timeseries to obtain a fresh canvas_id if this one has expired.
row_limitNoMost rows to return (positive integer, default 150; values above 10000 clamp to 10000 with a notice). When the query produces more, truncated is true — page with ORDER BY <column> LIMIT <n> OFFSET <m> in the SQL, or aggregate, rather than raising this toward the maximum.

Output Schema

NameRequiredDescription
rowsNoResult rows, at most row_limit (default 150). Each key is a column name from the query.
errorNoPresent when the call failed. Absent on success.
noticeNoReports requested and effective row limits when clamped, and the ORDER BY … LIMIT … OFFSET query shape when the result is truncated.
canvas_idNoThe canvas ID used — pass to a subsequent fx_dataframe_query or fx_dataframe_describe call.
row_countNoRows returned — always the length of rows. When truncated is true this equals row_limit, not the full result size.
truncatedNoTrue when the query produced more rows than row_limit and rows holds only the first row_limit of them. Fetch the rest with ORDER BY <column> LIMIT <n> OFFSET <m> — ORDER BY is required for deterministic paging — or aggregate to shrink the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so the safety profile is covered; the description reinforces this with 'read-only SQL SELECT'. It adds genuinely useful deployment behavior that annotations cannot express: when DataCanvas is off, the tool is absent from the listing entirely. It does not mention query cost, timeouts, or how errors surface, which keeps it below top marks.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the action and capability set, then prerequisites, then the deployment caveat. Nothing is repeated from the schema and every sentence carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full parameter documentation, the description only needs to cover the workflow and preconditions, which it does: staging source, prerequisite describe step, and the DataCanvas gating fallback. Minor gap: it doesn't say whether staged tables persist across calls or expire, though canvas_id expiry is hinted at in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter already carries a detailed description, including the canvas_id pattern, expiry handling, row_limit truncation, and the <table_name> substitution example. The description adds only light framing (which sibling supplies table names) and no new syntax or format details, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Run a read-only SQL SELECT against DataCanvas tables staged by fx_get_timeseries') and names the exact capability envelope (aggregations, GROUP BY, window functions, JOINs). A reader can immediately distinguish it from fx_get_timeseries, which produces the data, and fx_dataframe_describe, which provides schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit prerequisite order ('Run fx_dataframe_describe first to discover table names and column schemas') and names the ordinal alternative path ('fx_get_timeseries returns every range inline there') when DataCanvas is disabled. Both when-to-use and what-to-do-instead are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_get_rateFx Get RateA
Read-onlyIdempotent
Inspect

Get the exchange rate for a currency pair on a given date (default: latest). Returns the rate, the actual rate date (which may differ from the requested date on weekends/holidays — daily observations may skip non-publication days), and source provenance. Cross-rates are triangulated through EUR automatically. A same-currency pair returns a rate of 1, dated to the same publication day any other pair would report for that date. Use fx_convert_currency when you want the converted amount; use this tool when you only need the rate number.

NameRequiredDescriptionDefault
dateNoISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported.
base_currencyYesISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes.
quote_currencyYesISO 4217 quote currency code (e.g. EUR). The rate is expressed as "how many quote units per 1 base unit". Call fx_list_currencies to get valid codes.

Output Schema

NameRequiredDescription
rateNoExchange rate: units of quote currency per 1 unit of base currency.
errorNoPresent when the call failed. Absent on success.
sourceNoAlways "Frankfurter v1" — the upstream data provider.
rate_dateNoActual date of the rate returned.
rate_typeNoAlways "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask.
date_snappedNoTrue when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day.
base_currencyNoThe base currency code.
quote_currencyNoThe quote currency code.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent/openWorld annotations: it discloses that the returned rate date may differ from the requested date on weekends/holidays because non-publication days are skipped, that cross-rates are triangulated through EUR, and that a same-currency pair returns 1 dated to the normal publication day. These are non-obvious behaviors an agent could otherwise misreport to a user.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and default, then progressive behavioral detail, then the sibling routing sentence. Slight redundancy in enumerating the return fields (rate, rate date, provenance) when an output schema already exists, but every sentence still carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter read-only lookup with an output schema and full annotation coverage, the description is complete: it covers the default, the date-mismatch behavior, cross-rate derivation, and the identity-pair edge case. Nothing needed to call it correctly or interpret the result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is effectively 100%, so date format, default-latest behavior, and base/quote directionality are already documented in the schema. The description adds the cross-rate triangulation and identity-pair semantics, but does not extend parameter meaning much past the baseline where the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: exchange rate for a currency pair on a given date, defaulting to latest. The final sentence explicitly contrasts it with fx_convert_currency, so an agent can distinguish rate-only lookup from conversion without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear routing rule: 'Use fx_convert_currency when you want the converted amount; use this tool when you only need the rate number.' No guidance is given against fx_get_rates (plural) or fx_get_timeseries, which are the other plausible alternatives for rate retrieval, so the when-not coverage is partial.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_get_ratesFx Get RatesA
Read-onlyIdempotent
Inspect

Get all available exchange rates for one base currency in a single snapshot. Useful for bulk comparison and seeding downstream tools. Returns a map of quote currency → rate, the actual snapshot date, and whether a historical date was snapped from a weekend/holiday to the prior business day. Optionally filter to a subset of quote currencies via symbols. Listing the base currency itself in symbols is accepted and returns a rate of 1 for it.

NameRequiredDescriptionDefault
dateNoISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported.
symbolsNoOptional list of quote currency codes to filter the response. When provided, must contain at least one currency code — omit the field entirely, not an empty array, to return all ~30 supported currencies (the base is not among them). Including base_currency here is valid — it comes back with a rate of 1.
base_currencyYesISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
ratesNoMap of quote currency code → exchange rate (units of quote per 1 base).
sourceNoAlways "Frankfurter v1" — the upstream data provider.
rate_dateNoActual date of the rates. May differ from requested date on weekends/holidays — daily observations may skip non-publication days; the API silently snaps to the prior business day.
rate_typeNoAlways "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask.
date_snappedNoTrue when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day. Always false when date is omitted.
base_currencyNoThe base currency code.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and open-world, so the description adds value by disclosing the weekend/holiday snap-to-prior-business-day behavior and the actual snapshot date returned — a non-obvious trait not visible in annotations. It does not cover auth or rate-limit behavior, but the key semantic surprise is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences, front-loaded with purpose, followed by usage, return shape, and the one non-obvious parameter nuance. No filler, though the return-shape sentence overlaps with the existing output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema plus annotations cover return structure and safety profile, and the description adds the snapshot/snap-date nuance. What remains uncovered is error behavior for invalid currency codes and the data source, which are minor given 100% schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and independently documents date, symbols (including the empty-array restriction and base-inclusion behavior), and base_currency. The description restates the symbols behavior rather than extending it, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource plus scope ('all available exchange rates for one base currency in a single snapshot'), which implicitly but effectively separates it from fx_get_rate (single pair) and fx_get_timeseries (series over time). An agent can tell what this returns without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Useful for bulk comparison and seeding downstream tools' gives a use context, but there is no explicit when-to-use-this-vs-sibling guidance (e.g. use fx_get_rate for a single pair, fx_get_timeseries for history). Usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_get_timeseriesFx Get TimeseriesA
Read-onlyIdempotent
Inspect

Get historical daily Frankfurter v1 rates for a currency pair over an inclusive date range. Rates use same-date EUR legs without intermediate rounding; only days with both currencies appear, and a self-pair is 1 on actual observation dates. Historical membership includes retired currencies. Empty non-publication windows succeed with a notice. summary covers every observation in the requested interval before paging or staging: unweighted arithmetic mean, extrema with earliest-date ties, endpoints and percentage change, without prescribing accounting policy. Inline rates page at 500 observations; continue with next_start_date and the same end_date. Long ranges (>90 days by default) stage when they exceed the 40,000-character preview budget. An explicit canvas_id always stages, including short or empty ranges, and fails if unavailable or unknown. Each registration returns a unique table_name and preserves older tables. spilled=true returns canvas_id and table_name; call fx_dataframe_describe then fx_dataframe_query for SQL. Without DataCanvas, omit canvas_id to page inline.

NameRequiredDescriptionDefault
end_dateYesISO 8601 end date (YYYY-MM-DD). Must be >= start_date. Future dates are not supported.
canvas_idNoExisting canvas ID from a prior call explicitly requesting staging even for short or empty results. Every call creates a uniquely named table. Omit for automatic staging or inline paging.
start_dateYesISO 8601 start date (YYYY-MM-DD). Frankfurter v1 data starts 1999-01-04. The actual first data point may be later if start_date falls on a weekend/holiday.
base_currencyYesISO 4217 base currency code (e.g. USD). Call fx_list_currencies to get valid codes.
quote_currencyYesISO 4217 quote currency code (e.g. EUR). Call fx_list_currencies to get valid codes.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
ratesNoDate → rate map in date order, publication days inside the requested range only. Holds every publication day when truncated is false; otherwise the first 500 of an inline page (continue with next_start_date) or the preview of a spilled series (the full series is on the canvas). Empty when the range contains no publication day at all.
noticeNoExplains a result that would otherwise look broken or incomplete: an empty series (no publication day in the range); an inline page cut short (the start_date to continue from, plus why a long range was not staged when DataCanvas is turned off); or a spilled series (the canvas and table it was staged to, and the tools that read it).
sourceNoAlways "Frankfurter v1" — the upstream data provider.
spilledNoTrue when the complete result was staged on DataCanvas, either explicitly through canvas_id or automatically after exceeding the threshold and preview budget.
summaryNoStatistics over the full clipped requested range before paging or staging; omitted for empty ranges. Continuations summarize their own requested interval.
end_dateNoLast publication date in the requested range. Always inside the requested range — earlier than the requested end when that day had no Frankfurter v1 fix, and equal to it when the series is empty. Later than the last key in rates when truncated is true.
canvas_idNoCanvas ID — present when spilled is true. Pass to fx_dataframe_describe to inspect the staged table, then to fx_dataframe_query to run SQL.
rate_typeNoAlways "Daily rate (Frankfurter v1)" — these are reference rates, not tradeable bid/ask.
truncatedNoTrue when rates holds only part of the series: an inline page (next_start_date continues it) or a spilled preview (spilled is true). False when rates holds every publication day in the requested range.
rate_countNoTotal publication days in the requested range (the start_date through end_date passed on this call) — not the number of entries in rates, which is smaller when truncated is true. On a continuation call it counts the days from that start_date onward.
start_dateNoFirst publication date in the requested range, and the first key in rates. Always inside the requested range — later than the requested start when that day had no Frankfurter v1 fix, and equal to it when the series is empty.
table_nameNoCanvas table name — present when spilled is true. Use it as the FROM target in fx_dataframe_query SQL; fx_dataframe_describe lists its columns.
base_currencyNoBase currency code.
quote_currencyNoQuote currency code.
next_start_dateNoPresent only when an inline page was cut short: the first publication date not in rates. Pass it as start_date with the same end_date to get the next page. Absent on the final page.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations with substantive semantics: same-date EUR legs without intermediate rounding, only days with both currencies returned, self-pair equals 1, retired currencies included, empty non-publication windows succeed with a notice, and the 40,000-character preview budget triggering staging. It also discloses failure behavior for an unknown canvas_id and that each registration creates a unique, preserved table_name.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The essential scoping and paging facts are front-loaded in the first two sentences, which is good. However, the remainder is a dense wall of run-on clauses mixing edge cases, staging rules, and follow-up tool names, and lines like 'without prescribing accounting policy' are noise that slows an agent scanning for the call decision.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a published output schema and full annotation coverage, this description covers the remaining burden: paging continuation, staging thresholds, spilled=true payload shape, and the required fx_dataframe_describe/fx_dataframe_query follow-up. An agent has everything needed to call it correctly in either mode.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning on top: canvas_id always forces staging even for empty ranges and fails if unavailable, and end_date is reused unchanged when continuing with next_start_date. The summary and paging semantics further clarify what the parameters produce.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb, resource, and scope: historical daily Frankfurter v1 rates for a currency pair over an inclusive date range. That scope is concrete enough to distinguish it from fx_get_rate/fx_convert_currency by inference, but no sibling is named explicitly, so the agent has to reason about which tool is the right one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operating context: page inline at 500 observations with next_start_date, let long ranges stage automatically, pass canvas_id only when staging is desired, and omit it entirely if no DataCanvas is available. It does not mention when to prefer fx_get_rate or fx_convert_currency instead, so the basic tool-selection decision is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fx_list_currenciesFx List CurrenciesA
Read-onlyIdempotent
Inspect

List currently supported ISO 4217 currency codes with full names and as_of, the latest served rate date. Use this to disambiguate dollars (USD vs AUD vs CAD). Historical availability is checked against the requested historical snapshot or range and can include retired currencies absent from current discovery.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
as_ofNoLatest served daily rate date for this current-discovery list; historical availability is checked against historical data.
countNoTotal number of supported currencies.
errorNoPresent when the call failed. Absent on success.
sourceNoAlways "Frankfurter v1" — the upstream data provider.
currenciesNoAll supported currencies, sorted alphabetically by code.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotency and open-world behavior, and the description adds non-obvious context: results are scoped to the 'latest served rate date' (as_of) and historical lookups can surface retired currencies absent from current discovery. That caveat is genuinely useful. It stops short of describing snapshot/range staleness behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and return shape, then the disambiguation guidance in the second sentence. The third sentence about historical availability is a slight topic shift and is wordier than necessary, but it carries real caveat value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-shape detail is not required, and the description still names the key fields (code, full name, as_of). Combined with the historical-scope caveat, an agent has what it needs to call this correctly; only the snapshot/range scoping mechanics remain implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4; there is no parameter surface to document and the description does not waste space inventing one.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('currently supported ISO 4217 currency codes') plus the returned fields (full names, as_of). It is clearly distinguishable from the rate/conversion siblings, which all operate on specific pairs rather than discovery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ('use this to disambiguate dollars (USD vs AUD vs CAD)'), which tells an agent when to prefer this over fx_get_rate or fx_convert_currency. No when-not-to-use or prerequisite conditions are stated, keeping it below a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updates
    • Changedfx_convert_currency6 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"ISO 8601 date (YYYY-MM-DD) for a historical rate. Omit for the latest available rate. ECB data starts 1999-01-04. Future dates are not supported."New value: +"ISO 8601 date (YYYY-MM-DD) for a historical rate. Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported."
      • addedInput schema / properties / date / pattern
        Added value: +"^(?:\\d{4}-\\d{2}-\\d{2}|latest)$"
      • changedOutput schema / properties / date_snapped / description
        Previous value: -"True when the API returned a different date than requested — ECB silently snaps weekend/holiday requests to the prior business day."New value: +"True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the ECB published no rate for this date. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not available in the current discovery or served historical data. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the Frankfurter v1 published no rate for this date. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / rate_type / description
        Previous value: -"Always \"ECB reference (mid-market)\" — these are reference rates, not tradeable bid/ask."New value: +"Always \"Daily rate (Frankfurter v1)\" — these are reference rates, not tradeable bid/ask."
      • changedOutput schema / properties / source / description
        Previous value: -"Always \"ECB via Frankfurter\" — the upstream data provider."New value: +"Always \"Frankfurter v1\" — the upstream data provider."
    • Changedfx_dataframe_query4 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"Read-only SQL SELECT statement. Reference tables by the names returned by fx_dataframe_describe or the table_name field from fx_get_timeseries. Example: SELECT date, rate FROM fx_usd_eur WHERE date > '2024-01-01' ORDER BY date"New value: +"Read-only SQL SELECT statement. Reference tables by the names returned by fx_dataframe_describe or the table_name field from fx_get_timeseries. Example: SELECT date, rate FROM <table_name> WHERE date > '2024-01-01' ORDER BY date; replace <table_name> with the returned name, including its unique suffix."
      • changedInput schema / properties / row_limit / description
        Previous value: -"Most rows to return (1–10000, default 150). When the query produces more, truncated is true — page with ORDER BY <column> LIMIT <n> OFFSET <m> in the SQL, or aggregate, rather than raising this toward the maximum."New value: +"Most rows to return (positive integer, default 150; values above 10000 clamp to 10000 with a notice). When the query produces more, truncated is true — page with ORDER BY <column> LIMIT <n> OFFSET <m> in the SQL, or aggregate, rather than raising this toward the maximum."
      • changedInput schema / properties / row_limit / maximum
        Previous value: -10000New value: +9007199254740991
      • changedOutput schema / properties / notice / description
        Previous value: -"Present when truncated is true: how many rows came back and the ORDER BY … LIMIT … OFFSET query shape that fetches the next page."New value: +"Reports requested and effective row limits when clamped, and the ORDER BY … LIMIT … OFFSET query shape when the result is truncated."
    • Changedfx_get_rate6 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. ECB data starts 1999-01-04. Future dates are not supported."New value: +"ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported."
      • addedInput schema / properties / date / pattern
        Added value: +"^(?:\\d{4}-\\d{2}-\\d{2}|latest)$"
      • changedOutput schema / properties / date_snapped / description
        Previous value: -"True when the API returned a different date than requested — ECB silently snaps weekend/holiday requests to the prior business day."New value: +"True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the ECB published no rate for this date. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not available in the current discovery or served historical data. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the Frankfurter v1 published no rate for this date. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / rate_type / description
        Previous value: -"Always \"ECB reference (mid-market)\" — these are reference rates, not tradeable bid/ask."New value: +"Always \"Daily rate (Frankfurter v1)\" — these are reference rates, not tradeable bid/ask."
      • changedOutput schema / properties / source / description
        Previous value: -"Always \"ECB via Frankfurter\" — the upstream data provider."New value: +"Always \"Frankfurter v1\" — the upstream data provider."
    • Changedfx_get_rates7 fields changed
      • changedInput schema / properties / date / description
        Previous value: -"ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. ECB data starts 1999-01-04. Future dates are not supported."New value: +"ISO 8601 date (YYYY-MM-DD). Omit for the latest available rate. Frankfurter v1 data starts 1999-01-04. Future dates are not supported."
      • addedInput schema / properties / date / pattern
        Added value: +"^(?:\\d{4}-\\d{2}-\\d{2}|latest)$"
      • changedOutput schema / properties / date_snapped / description
        Previous value: -"True when the API returned a different date than requested — ECB silently snaps weekend/holiday requests to the prior business day. Always false when date is omitted."New value: +"True when the API returned a different date than requested — Frankfurter v1 snaps weekend/holiday requests to the prior business day. Always false when date is omitted."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or an entry in symbols is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Every requested currency is supported but the ECB published no rates for this date. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or an entry in symbols is not available in the current discovery or served historical data. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Every requested currency is supported but the Frankfurter v1 published no rates for this date. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / rate_date / description
        Previous value: -"Actual date of the rates. May differ from requested date on weekends/holidays — ECB publishes business days only; the API silently snaps to the prior business day."New value: +"Actual date of the rates. May differ from requested date on weekends/holidays — daily observations may skip non-publication days; the API silently snaps to the prior business day."
      • changedOutput schema / properties / rate_type / description
        Previous value: -"Always \"ECB reference (mid-market)\" — these are reference rates, not tradeable bid/ask."New value: +"Always \"Daily rate (Frankfurter v1)\" — these are reference rates, not tradeable bid/ask."
      • changedOutput schema / properties / source / description
        Previous value: -"Always \"ECB via Frankfurter\" — the upstream data provider."New value: +"Always \"Frankfurter v1\" — the upstream data provider."
    • Changedfx_get_timeseries12 fields changed
      • changedInput schema / properties / canvas_id / description
        Previous value: -"Optional canvas ID from a prior call. Omit on the first call to start a fresh canvas; pass the returned canvas_id to append tables to an existing canvas."New value: +"Existing canvas ID from a prior call explicitly requesting staging even for short or empty results. Every call creates a uniquely named table. Omit for automatic staging or inline paging."
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedInput schema / properties / start_date / description
        Previous value: -"ISO 8601 start date (YYYY-MM-DD). ECB data starts 1999-01-04. The actual first data point may be later if start_date falls on a weekend/holiday."New value: +"ISO 8601 start date (YYYY-MM-DD). Frankfurter v1 data starts 1999-01-04. The actual first data point may be later if start_date falls on a weekend/holiday."
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • changedOutput schema / properties / end_date / description
        Previous value: -"Last publication date in the requested range. Always inside the requested range — earlier than the requested end when that day had no ECB fix, and equal to it when the series is empty. Later than the last key in rates when truncated is true."New value: +"Last publication date in the requested range. Always inside the requested range — earlier than the requested end when that day had no Frankfurter v1 fix, and equal to it when the series is empty. Later than the last key in rates when truncated is true."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: start_date or end_date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: start_date is before 1999-01-04 or end_date is in the future. `invalid_range`: start_date is after end_date. `upstream_no_data`: Both currencies are supported but the ECB published no rates across this range. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_date_format`: start_date or end_date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not available in the current discovery or served historical data. `date_out_of_range`: start_date is before 1999-01-04 or end_date is in the future. `invalid_range`: start_date is after end_date. `upstream_no_data`: Both currencies are supported but the Frankfurter v1 published no rates across this range. `canvas_not_found`: An explicitly supplied canvas_id does not exist or has expired. `canvas_unavailable`: canvas_id requests staging on a deployment with DataCanvas disabled. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "invalid_date_format",
        -  "unsupported_currency",
        -  "date_out_of_range",
        -  "invalid_range",
        -  "upstream_no_data"
        -]New value: +[
        +  "invalid_date_format",
        +  "unsupported_currency",
        +  "date_out_of_range",
        +  "invalid_range",
        +  "upstream_no_data",
        +  "canvas_not_found",
        +  "canvas_unavailable"
        +]
      • changedOutput schema / properties / rate_type / description
        Previous value: -"Always \"ECB reference (mid-market)\" — these are reference rates, not tradeable bid/ask."New value: +"Always \"Daily rate (Frankfurter v1)\" — these are reference rates, not tradeable bid/ask."
      • changedOutput schema / properties / source / description
        Previous value: -"Always \"ECB via Frankfurter\" — the upstream data provider."New value: +"Always \"Frankfurter v1\" — the upstream data provider."
      • changedOutput schema / properties / spilled / description
        Previous value: -"True when the range exceeded the staging threshold and the series exceeded the inline preview budget, so the full result was staged on DataCanvas."New value: +"True when the complete result was staged on DataCanvas, either explicitly through canvas_id or automatically after exceeding the threshold and preview budget."
      • changedOutput schema / properties / start_date / description
        Previous value: -"First publication date in the requested range, and the first key in rates. Always inside the requested range — later than the requested start when that day had no ECB fix, and equal to it when the series is empty."New value: +"First publication date in the requested range, and the first key in rates. Always inside the requested range — later than the requested start when that day had no Frankfurter v1 fix, and equal to it when the series is empty."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Statistics over the full clipped requested range before paging or staging; omitted for empty ranges. Continuations summarize their own requested interval.",
        +  "properties": {
        +    "change_pct": {
        +      "description": "Percentage change from first to last observation.",
        +      "type": "number"
        +    },
        +    "first": {
        +      "additionalProperties": false,
        +      "description": "Chronologically first observation.",
        +      "properties": {
        +        "date": {
        +          "description": "First publication date.",
        +          "type": "string"
        +        },
        +        "rate": {
        +          "description": "First rate.",
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "rate",
        +        "date"
        +      ],
        +      "type": "object"
        +    },
        +    "last": {
        +      "additionalProperties": false,
        +      "description": "Chronologically last observation.",
        +      "properties": {
        +        "date": {
        +          "description": "Last publication date.",
        +          "type": "string"
        +        },
        +        "rate": {
        +          "description": "Last rate.",
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "rate",
        +        "date"
        +      ],
        +      "type": "object"
        +    },
        +    "max": {
        +      "additionalProperties": false,
        +      "description": "Maximum observation.",
        +      "properties": {
        +        "date": {
        +          "description": "Earliest date with the highest rate.",
        +          "type": "string"
        +        },
        +        "rate": {
        +          "description": "Highest rate.",
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "rate",
        +        "date"
        +      ],
        +      "type": "object"
        +    },
        +    "mean": {
        +      "description": "Unweighted arithmetic mean of all daily observations in the requested range; not an accounting-policy prescription.",
        +      "type": "number"
        +    },
        +    "min": {
        +      "additionalProperties": false,
        +      "description": "Minimum observation.",
        +      "properties": {
        +        "date": {
        +          "description": "Earliest date with the lowest rate.",
        +          "type": "string"
        +        },
        +        "rate": {
        +          "description": "Lowest rate.",
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "rate",
        +        "date"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "mean",
        +    "min",
        +    "max",
        +    "first",
        +    "last",
        +    "change_pct"
        +  ],
        +  "type": "object"
        +}
    • Changedfx_list_currencies3 fields changed
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "currencies",
        -      "count",
        -      "source"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "currencies",
        +      "count",
        +      "as_of",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / as_of
        Added value: +{
        +  "description": "Latest served daily rate date for this current-discovery list; historical availability is checked against historical data.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / source / description
        Previous value: -"Always \"ECB via Frankfurter\" — the upstream data provider."New value: +"Always \"Frankfurter v1\" — the upstream data provider."
  2. 1 tool update
    • Changedfx_get_timeseries2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Explains a result that would otherwise look broken or incomplete: an empty series (no publication day in the range); an inline page cut short (the start_date to continue from, plus why a long range was not staged when DataCanvas is not configured); or a spilled series (the canvas and table it was staged to, and the tools that read it)."New value: +"Explains a result that would otherwise look broken or incomplete: an empty series (no publication day in the range); an inline page cut short (the start_date to continue from, plus why a long range was not staged when DataCanvas is turned off); or a spilled series (the canvas and table it was staged to, and the tools that read it)."
      • changedOutput schema / properties / spilled / description
        Previous value: -"True when the full result was staged on the DataCanvas (range exceeded threshold)."New value: +"True when the range exceeded the staging threshold and the series exceeded the inline preview budget, so the full result was staged on DataCanvas."
  3. 3 tool updates
    • Changedfx_dataframe_describe1 field changed
      • addedInput schema / properties / canvas_id / pattern
        Added value: +"^[A-Za-z0-9_-]{10}$"
    • Changedfx_dataframe_query1 field changed
      • addedInput schema / properties / canvas_id / pattern
        Added value: +"^[A-Za-z0-9_-]{10}$"
    • Changedfx_get_timeseries1 field changed
      • addedInput schema / properties / canvas_id / pattern
        Added value: +"^[A-Za-z0-9_-]{10}$"
  4. 2 tool updates
    • Changedfx_dataframe_query5 fields changed
      • addedInput schema / properties / row_limit
        Added value: +{
        +  "default": 150,
        +  "description": "Most rows to return (1–10000, default 150). When the query produces more, truncated is true — page with ORDER BY <column> LIMIT <n> OFFSET <m> in the SQL, or aggregate, rather than raising this toward the maximum.",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Present when truncated is true: how many rows came back and the ORDER BY … LIMIT … OFFSET query shape that fetches the next page.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / row_count / description
        Previous value: -"Rows returned. Equals the materialized row count; when truncated is true this is the row cap, not the full result size. Narrow the SELECT (add WHERE/LIMIT or aggregate) to see all rows."New value: +"Rows returned — always the length of rows. When truncated is true this equals row_limit, not the full result size."
      • changedOutput schema / properties / rows / description
        Previous value: -"Result rows, capped at the canvas row limit (default 10 000). Each key is a column name from the query."New value: +"Result rows, at most row_limit (default 150). Each key is a column name from the query."
      • changedOutput schema / properties / truncated / description
        Previous value: -"True when the query produced more rows than the canvas row cap and the result was capped. Refine the query to materialize the complete result."New value: +"True when the query produced more rows than row_limit and rows holds only the first row_limit of them. Fetch the rest with ORDER BY <column> LIMIT <n> OFFSET <m> — ORDER BY is required for deterministic paging — or aggregate to shrink the result."
    • Changedfx_get_timeseries10 fields changed
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "base_currency",
        -      "quote_currency",
        -      "start_date",
        -      "end_date",
        -      "rates",
        -      "rate_count",
        -      "rate_type",
        -      "source",
        -      "spilled"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "quote_currency",
        +      "start_date",
        +      "end_date",
        +      "rates",
        +      "rate_count",
        +      "truncated",
        +      "rate_type",
        +      "source",
        +      "spilled"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • changedOutput schema / properties / canvas_id / description
        Previous value: -"Canvas ID — present when spilled is true. Pass to fx_dataframe_query."New value: +"Canvas ID — present when spilled is true. Pass to fx_dataframe_describe to inspect the staged table, then to fx_dataframe_query to run SQL."
      • changedOutput schema / properties / end_date / description
        Previous value: -"Last date in the returned series. Always inside the requested range — earlier than the requested end when that day had no ECB fix, and equal to it when the series is empty."New value: +"Last publication date in the requested range. Always inside the requested range — earlier than the requested end when that day had no ECB fix, and equal to it when the series is empty. Later than the last key in rates when truncated is true."
      • addedOutput schema / properties / next_start_date
        Added value: +{
        +  "description": "Present only when an inline page was cut short: the first publication date not in rates. Pass it as start_date with the same end_date to get the next page. Absent on the final page.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Explains a result that would otherwise look broken — an empty series, or a long range that stayed inline because DataCanvas is not configured."New value: +"Explains a result that would otherwise look broken or incomplete: an empty series (no publication day in the range); an inline page cut short (the start_date to continue from, plus why a long range was not staged when DataCanvas is not configured); or a spilled series (the canvas and table it was staged to, and the tools that read it)."
      • changedOutput schema / properties / rate_count / description
        Previous value: -"Total number of data points (publication days) inside the requested range."New value: +"Total publication days in the requested range (the start_date through end_date passed on this call) — not the number of entries in rates, which is smaller when truncated is true. On a continuation call it counts the days from that start_date onward."
      • changedOutput schema / properties / rates / description
        Previous value: -"Date → rate map for the inline result. Publication days inside the requested range only. Truncated to a preview when the result was spilled to canvas; empty when the range contains no publication day at all."New value: +"Date → rate map in date order, publication days inside the requested range only. Holds every publication day when truncated is false; otherwise the first 500 of an inline page (continue with next_start_date) or the preview of a spilled series (the full series is on the canvas). Empty when the range contains no publication day at all."
      • changedOutput schema / properties / start_date / description
        Previous value: -"First date in the returned series. Always inside the requested range — later than the requested start when that day had no ECB fix, and equal to it when the series is empty."New value: +"First publication date in the requested range, and the first key in rates. Always inside the requested range — later than the requested start when that day had no ECB fix, and equal to it when the series is empty."
      • changedOutput schema / properties / table_name / description
        Previous value: -"Canvas table name — present when spilled is true. Use in fx_dataframe_query SQL."New value: +"Canvas table name — present when spilled is true. Use it as the FROM target in fx_dataframe_query SQL; fx_dataframe_describe lists its columns."
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "description": "True when rates holds only part of the series: an inline page (next_start_date continues it) or a spilled preview (spilled is true). False when rates holds every publication day in the requested range.",
        +  "type": "boolean"
        +}
  5. 3 tool updates
    • Changedfx_convert_currency1 field changed
      • changedInput schema / properties / quote_currency / description
        Previous value: -"ISO 4217 target currency code (e.g. EUR). The amount will be expressed in this currency."New value: +"ISO 4217 target currency code (e.g. EUR). The amount will be expressed in this currency. Call fx_list_currencies to get valid codes."
    • Changedfx_get_rate1 field changed
      • changedInput schema / properties / quote_currency / description
        Previous value: -"ISO 4217 quote currency code (e.g. EUR). The rate is expressed as \"how many quote units per 1 base unit\"."New value: +"ISO 4217 quote currency code (e.g. EUR). The rate is expressed as \"how many quote units per 1 base unit\". Call fx_list_currencies to get valid codes."
    • Changedfx_get_rates4 fields changed
      • changedInput schema / properties / symbols / description
        Previous value: -"Optional list of quote currency codes to filter the response. Omit to return all ~30 supported currencies (the base is not among them). Including base_currency here is valid — it comes back with a rate of 1."New value: +"Optional list of quote currency codes to filter the response. When provided, must contain at least one currency code — omit the field entirely, not an empty array, to return all ~30 supported currencies (the base is not among them). Including base_currency here is valid — it comes back with a rate of 1."
      • addedInput schema / properties / symbols / minItems
        Added value: +1
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "base_currency",
        -      "rate_date",
        -      "rates",
        -      "rate_type",
        -      "source"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "rate_date",
        +      "rates",
        +      "date_snapped",
        +      "rate_type",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / date_snapped
        Added value: +{
        +  "description": "True when the API returned a different date than requested — ECB silently snaps weekend/holiday requests to the prior business day. Always false when date is omitted.",
        +  "type": "boolean"
        +}
  6. 7 tool updates
    • Changedfx_convert_currency6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "quote_currency",
        +      "base_amount",
        +      "quote_amount",
        +      "rate",
        +      "rate_date",
        +      "date_snapped",
        +      "rate_type",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the ECB published no rate for this date. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "invalid_date_format",
        +            "unsupported_currency",
        +            "date_out_of_range",
        +            "upstream_no_data"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "base_currency",
        -  "quote_currency",
        -  "base_amount",
        -  "quote_amount",
        -  "rate",
        -  "rate_date",
        -  "date_snapped",
        -  "rate_type",
        -  "source"
        -]
    • Changedfx_dataframe_describe6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "canvas_id",
        +      "tables",
        +      "expires_at"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not exist or has been evicted. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "canvas_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "canvas_id",
        -  "tables",
        -  "expires_at"
        -]
    • Changedfx_dataframe_query6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "rows",
        +      "row_count",
        +      "truncated",
        +      "canvas_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not exist or has been evicted. `missing_table`: The SQL references a table that is not staged on this canvas, or whose TTL expired. `invalid_query`: SQL is not a SELECT, references unknown columns, or has a syntax error. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "canvas_not_found",
        +            "missing_table",
        +            "invalid_query"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "rows",
        -  "row_count",
        -  "truncated",
        -  "canvas_id"
        -]
    • Changedfx_get_rate6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "quote_currency",
        +      "rate",
        +      "rate_date",
        +      "date_snapped",
        +      "rate_type",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Both currencies are supported but the ECB published no rate for this date. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "invalid_date_format",
        +            "unsupported_currency",
        +            "date_out_of_range",
        +            "upstream_no_data"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "base_currency",
        -  "quote_currency",
        -  "rate",
        -  "rate_date",
        -  "date_snapped",
        -  "rate_type",
        -  "source"
        -]
    • Changedfx_get_rates6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "rate_date",
        +      "rates",
        +      "rate_type",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_format`: date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or an entry in symbols is not in the ECB currency set. `date_out_of_range`: date is before 1999-01-04 or in the future. `upstream_no_data`: Every requested currency is supported but the ECB published no rates for this date. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "invalid_date_format",
        +            "unsupported_currency",
        +            "date_out_of_range",
        +            "upstream_no_data"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "base_currency",
        -  "rate_date",
        -  "rates",
        -  "rate_type",
        -  "source"
        -]
    • Changedfx_get_timeseries6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "base_currency",
        +      "quote_currency",
        +      "start_date",
        +      "end_date",
        +      "rates",
        +      "rate_count",
        +      "rate_type",
        +      "source",
        +      "spilled"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_format`: start_date or end_date is not a real calendar date written as YYYY-MM-DD. `unsupported_currency`: base_currency or quote_currency is not in the ECB currency set. `date_out_of_range`: start_date is before 1999-01-04 or end_date is in the future. `invalid_range`: start_date is after end_date. `upstream_no_data`: Both currencies are supported but the ECB published no rates across this range. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "invalid_date_format",
        +            "unsupported_currency",
        +            "date_out_of_range",
        +            "invalid_range",
        +            "upstream_no_data"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "base_currency",
        -  "quote_currency",
        -  "start_date",
        -  "end_date",
        -  "rates",
        -  "rate_count",
        -  "rate_type",
        -  "source",
        -  "spilled"
        -]
    • Changedfx_list_currencies6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "currencies",
        +      "count",
        +      "source"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode.",
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "currencies",
        -  "count",
        -  "source"
        -]
  7. 3 tool updates
    • Changedfx_convert_currency2 fields changed
      • changedInput schema / properties / amount / description
        Previous value: -"Amount in the base currency to convert. Must be a positive number."New value: +"Amount in the base currency to convert. Must be greater than zero."
      • addedInput schema / properties / amount / exclusiveMinimum
        Added value: +0
    • Changedfx_get_rates1 field changed
      • changedInput schema / properties / symbols / description
        Previous value: -"Optional list of quote currency codes to filter the response. Omit to return all ~30 supported currencies."New value: +"Optional list of quote currency codes to filter the response. Omit to return all ~30 supported currencies (the base is not among them). Including base_currency here is valid — it comes back with a rate of 1."
    • Changedfx_get_timeseries5 fields changed
      • changedOutput schema / properties / end_date / description
        Previous value: -"Actual last date in the returned series (may differ from requested if that date had no ECB fix)."New value: +"Last date in the returned series. Always inside the requested range — earlier than the requested end when that day had no ECB fix, and equal to it when the series is empty."
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Explains a result that would otherwise look broken — an empty series, or a long range that stayed inline because DataCanvas is not configured.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / rate_count / description
        Previous value: -"Total number of data points (business days) in the range."New value: +"Total number of data points (publication days) inside the requested range."
      • changedOutput schema / properties / rates / description
        Previous value: -"Date → rate map for the inline result. Business days only. Empty when the result was spilled to canvas."New value: +"Date → rate map for the inline result. Publication days inside the requested range only. Truncated to a preview when the result was spilled to canvas; empty when the range contains no publication day at all."
      • changedOutput schema / properties / start_date / description
        Previous value: -"Actual first date in the returned series (may differ from requested if that date had no ECB fix)."New value: +"First date in the returned series. Always inside the requested range — later than the requested start when that day had no ECB fix, and equal to it when the series is empty."
  8. 1 tool update
    • Changedfx_dataframe_query3 fields changed
      • changedOutput schema / properties / row_count / description
        Previous value: -"Total rows in the full result set before the row cap was applied."New value: +"Rows returned. Equals the materialized row count; when truncated is true this is the row cap, not the full result size. Narrow the SELECT (add WHERE/LIMIT or aggregate) to see all rows."
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "description": "True when the query produced more rows than the canvas row cap and the result was capped. Refine the query to materialize the complete result.",
        +  "type": "boolean"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "rows",
        -  "row_count",
        -  "canvas_id"
        -]New value: +[
        +  "rows",
        +  "row_count",
        +  "truncated",
        +  "canvas_id"
        +]
  9. 7 tool updates
    • First observedfx_convert_currency
    • First observedfx_dataframe_describe
    • First observedfx_dataframe_query
    • First observedfx_get_rate
    • First observedfx_get_rates
    • First observedfx_get_timeseries
    • First observedfx_list_currencies

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Provides access to currency exchange rates and conversion tools using the Frankfurter API, including latest rates, historical data, and time series from sources like the European Central Bank.
    5
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables currency exchange rate lookups, amount conversion, historical rate retrieval, and listing of supported currencies via the Frankfurter API.
    373 npm
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides real-time and historical foreign exchange rates for 31+ currencies, enabling currency conversion, historical rate lookups, and time series analysis using data from the Frankfurter API.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Provides live and historical foreign-exchange rates from the European Central Bank via Frankfurter API, enabling currency conversion, rate lookup, and trend analysis without API keys.
    5
    4 npm
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.