macro-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@macro-mcpWhat was Germany's GDP growth in 2023?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
macro-mcp
MCP server for international macro statistics, company identity and FX rates. Every source is free and keyless.
Why
Most finance MCP servers wrap one API with one tool per endpoint. That does not survive going international: there is no global EDGAR, no shared company key, and each provider codes countries differently. This takes a different route.
One grammar, many providers. SDMX is ISO 17369, and the BIS, ECB, IMF, OECD, Eurostat, World Bank, ILO and a dozen national offices all publish through it. One set of tools reaches all of them. Sources that do not speak SDMX are adapted to the same grammar rather than given tools of their own: Singapore's Table Builder is plain JSON, but a table becomes a dataflow, its rows become one dimension's codes, and its periods are rewritten from
2024 Janto2024-01so they join against everything else.LEI as the join key. GLEIF covers 2.8M entities across 200+ jurisdictions, free, including the ownership graph. Tickers and CIKs do not travel.
Rate conventions are explicit. Converting flows at an end-of-period rate is a silent error, so the convention is a required argument, not a default. The ECB quotes everything against the euro, so a pair without EUR is a cross derived from two fixings; the response says so rather than presenting it as a published rate.
No translation layer. SDMX names are multilingual and providers ship English in the same response, so search matches every localization and returns English where it exists.
cropsfinds ISTAT'sColtivazioni;chomagefinds INSEE's unemployment series. Entity names come from GLEIF's registered alternative-language name, which is a legal fact rather than a translation.
Related MCP server: publicfinance
Install
Nothing to clone and no keys to obtain. Point an MCP client at the repository and uv does the rest:
{
"mcpServers": {
"macro": {
"command": "uvx",
"args": ["--from", "git+https://github.com/rabidlego25/macro-mcp", "macro-mcp"]
}
}
}uvx resolves and caches the environment on the first run, and that run is
slow: four minutes and 306MB here, nearly all of it downloading pandas and
lxml. Every start after it was under two seconds. Run the command once in a
terminal before registering it, since a client that starts servers with a
timeout will give up long before the first one finishes.
To work on the server rather than use it, clone and run from the checkout:
uv sync{
"mcpServers": {
"macro": {
"command": "uv",
"args": ["run", "--directory", "/path/to/macro-mcp", "macro-mcp"]
}
}
}Tools
Discovery is progressive: a single codelist can hold hundreds of entries, so metadata is never returned whole.
Tool | Purpose |
| Providers by region, with quirks and metadata support |
| Search a provider's dataflows |
| Dimensions with code counts and a sample |
| Resolve one dimension's codes, including country codes |
| Observations for a dimension key, as compact series |
| Releases of a dataflow, oldest first |
| One key across vintages, with the revisions between them |
| GLEIF search by legal name |
| Look up one LEI |
| Direct parent, ultimate parent, direct children |
| One day's ECB euro reference rate, marked when derived |
| Average or end-of-period rate, in the same shape as |
The same restraint applies to data. A flat row per observation repeats the whole
key on every row, which on a 16-dimension flow is around 450 wasted bytes an
observation, so fetch_data hoists the invariant part of the key, groups the
rest into series and returns [period, value] pairs. A year of daily Bund
yields goes from 173KB to 6KB.
{
"key": {"FREQ": "M"},
"units": {"UNIT_MEASURE": "Per cent per year", "UNIT_MULT": "Units"},
"columns": ["period", "value"],
"series": [{"key": {"REF_AREA": "JP"}, "observations": [["2024-01", -0.1]]}],
"range": ["2024-01", "2024-12"], "total": 24
}Units
A bare 634751300000000.0 is not an answer to what Japan's GDP was. It is
¥634.75tn or ¥634.75bn depending on a multiplier the provider ships and sdmx1
discards unless asked. So fetch_data returns what the number is measured in,
resolved from the provider's code to its label: BIS sends UNIT_MEASURE="368",
which is no more use than the number was.
Providers spell it differently and attach it at different levels. BIS and ILO
write UNIT_MEASURE/UNIT_MULT, ECB adds UNIT_INDEX_BASE, Bundesbank
prefixes its own BBK_UNIT, IMF publishes no unit at all but does populate
SCALE, and Singapore states one per row. So units are matched by pattern
rather than by a list, at whatever level they arrive.
They are returned beside the key, never inside it: a unit is not a dimension,
and an agent that echoed one back to fetch_data would get an error from the
provider. A unit that is invariant across the response is hoisted once; one
that varies lands on each series, so a response mixing percent with an index
says so instead of interleaving the two silently.
Nothing else a provider attaches is returned. BIS ships around 2.5KB of compilation notes and source references per series, against a response format whose whole point is 6KB.
names gives the English label for every code in the response, so a series
keyed XDC or CP01 reads without another round trip. It comes off the
structure the units already needed, and only the codes that actually appear are
returned. range is the span actually returned, so truncation is visible
rather than inferred from a total that does not match. Truncation keeps the most recent
observations, and limit is shared across the series in the response rather
than spent oldest-first over the whole of it. Otherwise a two-country request
came back with only the country whose history ran latest. The split is max-min
fair, so a short series hands its unused share to a long one and a response that
fits under the budget is never clipped. Where there are more series than the
budget can seat, the ones left out are named under dropped_series instead of
going missing. Periods with no value are omitted and counted under empty.
limit bounds the download as well as the response. The provider is asked for
only the newest limit + 1 observations per series, through SDMX's own
lastNObservations. Three observations cost 10KB from BIS rather than 314KB,
3KB from ECB's daily reference rates rather than 1.4MB, and 4KB from the
Bundesbank 10-year Bund yield rather than 2.3MB; twelve months of Japanese CPI
cost 53KB and 4.4s from IMF rather than 1.5MB and 12.1s.
The extra one is what keeps truncation visible: asked for exactly limit, a
clipped series comes back the same length as a complete one. When a series does
arrive at the cap, total is a floor rather than the length of the series, and
the truncated note says so: counting the rest would mean downloading it.
Point in time
A series read today is as-revised, not as-known, which quietly gives a backtest
numbers nobody had at the time. IMF republishes whole dataflows as monthly
vintages beside the current one, so compare_vintages can read the same key
from each and report what moved:
{"period": "2024", "was": 634226000000000.0, "now": 634751300000000.0,
"between": ["ANEA_2026_APR_VINTAGE", "ANEA"], "change_pct": 0.0828}Japan's 2024 nominal GDP, revised up by ¥525.3bn since the April 2026 vintage.
Coverage varies between vintages as well as values. One 2026 vintage of the
national accounts carries 18,068 observations and another 204, so a vintage
that does not have the key is listed under no_data rather than counted as
agreeing with its neighbours.
Caching
Metadata is cached to disk under $XDG_CACHE_HOME/macro-mcp for a week.
Structures are large and slow to build (ISTAT takes 29s cold and 1.5s warm,
Eurostat 52s and 11s) and providers republish them rarely. In-process
memoisation alone threw all of that away when the server exited.
Nothing else is cached. The policy denies by default and names the structure
endpoints it will keep, rather than naming the data paths it will skip. That
ordering matters: the first version listed the data paths, and Singapore's
/tabledata/ was not among them, so observations would have been served up to a
week stale. Under default-deny, an adapter whose paths nobody declared costs a
round trip instead of correctness.
The data patterns are declared first because the first match wins and BIS puts
/data/dataflow/ in its data URLs, which the structure patterns would
otherwise claim. Set MACRO_MCP_NO_CACHE=1 to bypass caching entirely.
Pacing and retries
Every request goes through one transport adapter that bounds how hard a provider is asked and absorbs the failures that are not answers.
Per host, not per provider. Four requests in flight at once by default, and no delay. HKMA is the exception at one at a time, 4/s: it started answering 502 on every path after eight parallel requests and did not recover for minutes.
Transient statuses are retried. 429, 500, 502, 503 and 504 get three attempts with exponential backoff and jitter, so ISTAT's intermittent 500s no longer reach the agent as errors. A 404 is an answer and is not repeated, and neither is a TLS failure: UY110's self-signed certificate will not verify on the second attempt either.
Retry-Afteris honoured, and held against the whole host. A 429 is addressed to this client rather than to the request that drew it, so everything queued behind it waits too.
The adapter sits below the cache, so a cached read neither waits nor spends a slot. The state is per process: two servers on one machine do not coordinate, and the shared User-Agent means a provider throttling it throttles every install at once.
Tests
uv run pytest # offline, ~1s
MACRO_MCP_LIVE=1 uv run pytest -m "not revisable" # + structure, ~70s
MACRO_MCP_LIVE=1 uv run pytest -m revisable # what the data didThe live suite is split because its two halves mean opposite things. Unmarked
tests assert structure (a flow exists, a key resolves, a period joins) and a
failure means a provider moved or this server broke. Tests marked revisable
assert that a number is still the number it was, and a failure there means a
CPI was rebased or a national account revised: the provider doing its job, and
the event this project exists to surface. They run as separate CI jobs, and
only the first can fail the build.
The offline suite replays saved responses in tests/fixtures/. Every case in it
was a real failure, and each asserts a value rather than the absence of an
exception, because these paths fail by returning a plausible wrong answer with a
200 status rather than by raising.
One test spawns the server as its own process and speaks JSON-RPC to it over
stdin, which is the only thing that covers main(), the stdio transport and
the handshake. It is how the empty serverInfo.version was found. The rest of
the tools are exercised through call_tool, not by calling the functions
underneath, so argument validation, the published schema and the JSON an agent
actually parses are all in the path. What those tools publish is asserted
literally: the names, which arguments may be omitted, what they then default
to, and the docstrings themselves. Every part of it can drift from the code
beneath without failing anything else.
The recorded responses are mounted under a real sdmx1 session rather than fed
to the parser directly, so a test drives URL construction, the Accept header,
sdmx1 and the packing here together. That is where several of the failures
were: an SDMX key is positional, so getting the dimension order wrong returns
somebody else's series with a 200 status. ECB stands in for the spine that 27
of the 29 providers traverse; Bundesbank, Hong Kong, Singapore and BIS have
fixtures of their own because each is an exception to it.
The live suite pins historical values, so a failure means a provider moved, renamed something, or revised a series.
Evals
Twenty questions a person would actually ask, run through the tools against
live providers, with every call and response kept in evals/log. Thirteen were
answered, three partly, four blocked, one of those because HKMA was down.
Almost nothing crashed. The server returned 200 and a well-formed response and
the agent was stuck anyway, which is the failure this project is about: an
empty result that echoed nothing back, a 15-digit GDP figure with no currency
attached, a search for "national accounts" that reported one hit and hid the
flow, and a search for Banco Santander led by an unrelated company that matched
the city. Six of the thirteen findings are fixed and verified against the live
providers; evals/README.md lists what was fixed, what was only improved, and
what still stands.
Current problems and limitations
Defects and constraints in this server, as distinct from properties of the data (below) and gaps in provider coverage (further below). Roughly worst first.
Observations are never cached, so every fetch pays full price. That is deliberate (see Caching) but it means repeated identical queries re-download each time. It bites hardest on HKMA: a bound coarser than the endpoint's own period cannot be sent to the service, so the adapter pulls the full history (up to 6,302 rows) and filters locally, on every call.
sdmx1cannot query SDMX 3.0 data. It builds?c=TIME_PERIODinstead ofc[TIME_PERIOD]=ge:…, puts the source id where the agency belongs in the path, and raisesTypeError: unhashable type: 'MemberValue'when a key is passed as a dict. Nothing hits this today because IMF is wired to its 2.1 endpoint, but the first genuinely 3.0-only provider will need an adapter.Point-in-time is IMF-only. No other provider here republishes vintages, so
compare_vintagescannot answer the question anywhere else. It also spends its request budget before it knows which vintages carry the key, so asking for five can leave fewer readable; those appear underno_datarather than being topped up, since the alternative is an unbounded number of calls to a slow service.HKMA datasets are searchable only by slug. It publishes no titles through the API, so
find_dataflowsmatcheshk-interbank-ir-dailyand not the words a person would use for it. Its quarterly datasets also report the month the quarter ended (2024-03), which is indistinguishable from a monthly period when joined against another provider.The disk cache only grows. Entries expire after a week but nothing prunes or vacuums the SQLite file, which reached 96MB here across a few live runs. Delete
$XDG_CACHE_HOME/macro-mcpwhen it gets large.Pacing is per process and the User-Agent is shared. Two servers on one machine, or two installs anywhere, do not coordinate, so the limits in
transport.HOSTSbound one client rather than the traffic a provider actually sees. Nothing here can fix that; a hosted deployment would have to.A paced host is a slow host. HKMA is asked one request at a time, so reading several of its datasets in one turn now costs at least 250ms each rather than going out together. That is the trade the 502s bought.
A cold fetch downloads the structure twice.
sdmx1resolves a dict key by fetching the DSD itself, and_unit_labelsthen fetches it again through_dsd, which does not know about the first: the same 497KB URL twice on ECB, 3.5MB twice on an IMF vintage. Callingdescribe_flowfirst, which is the prescribed order, saves one of the two, and after the first fetch of a flow the process pays neither again. Passing a rendered key string rather than a dict would fix it.sdmx1memoises structures on the Client class, not the instance. SoMACRO_MCP_NO_CACHE=1does not force a fresh structure read within one process, and neither does discarding the client: the dict outlives both. The live suite is weaker than it reads for that reason, and a before-and-after measurement taken in one process is worthless: the second half reads what the first downloaded.The download is capped per series, not per response.
lastNObservationsbounds each series the key matches, so a wildcard over 300 series still fetcheslimit + 1observations for every one of them.limitbounds what comes back; only the key bounds what is fetched.totalis a floor once the cap binds. It used to be the length of the series, which was free only because the whole series had been downloaded. Now it counts what arrived, and a series that came back at the cap has older observations nobody counted. Thetruncatednote says which of the two it is; there is no way to report the exact length without paying for it again.Not every provider honours the cap, and one applied it wrongly. It is sent to all of them. BIS, ECB, IMF, Bundesbank and OECD truncate at the source; UNSD and UNICEF returned the same bytes with the parameter as without, so they appear to ignore it. ILO does something worse: it drops whole series, returning 13 of 39 at the default
limitand 39 at 2001. That shipped for a while and is the reason the first capped fetch of a provider is now checked against adetail=nodatacount of the keys, and the verdict recorded against the cap it was measured at. A provider that refuses the parameter, or comes back short, is asked again without it and remembered for the life of the process.A query that matches nothing costs two requests. A service that answers 200 to a parameter it does not understand looks exactly like a key that matched nothing, so an empty capped response is checked against an uncapped one before it is believed. Both are cheap when the query really is empty, but
compare_vintagespays it once per vintage that does not carry the key.A narrow query gains nothing from the cap and pays a little. It bounds the history, so a key already pinned to one series inside a one-year window is the same size either way: comparing four vintages of Japanese GDP moves 21.3KB of observations before the cap and 25.3KB after, the difference being the extra request above.
Nothing bounds the structure metadata, which is the larger half. That same vintage comparison spends 31MB on five DSDs of around 3.5MB each against 21KB of observations. It is paid once a week rather than once a call (see Caching) but on a cold process the download cap addresses the smaller part of the bill.
The cap does not reach the non-SDMX adapters. Singapore and Hong Kong have no such parameter, so
limitstill bounds only their responses.limitbinds evenly, not by importance. The budget is split max-min fair across the series in a response, so nothing is clipped while there is room and a short series hands its surplus to a long one. Once it does bind, though, every long series is cut to the same depth regardless of which one the question was about, and a response with more series than the budget can seat drops the excess, named underdropped_seriesbut dropped all the same. Narrowstart/end, or raiselimit, when querying several series at once.The first BIS fetch of a session pays for a failed parse. BIS serves structure-specific data referencing a DSD
sdmx1cannot resolve, so the payload is downloaded and parsed once before the generic form is tried. The provider is remembered after that and every later fetch goes generic-first, but the knowledge dies with the process, andsdmx1prints its parse stack and the failing element to stdout on the way, though the MCP SDK claims that descriptor and diverts it to stderr, so it is noise rather than corruption. Not hardcoded to BIS on purpose: IMF answers 500 to the generic header, so a wrong guess would take a provider down rather than waste a header.Units are only as good as the provider's own metadata. HKMA states none at all, so its numbers come back bare. Bundesbank labels its unit in German (
PROZENT) because the English one is published as an empty element, and its multiplier resolves to a raw0because noCL_BBK_UNIT_MULTcodelist is served. A raw code is left in place rather than guessed at.Resolving a unit code needs the flow's structure.
fetch_datanow reads the DSD to turn368into "Per cent per year", so a cold fetch against a provider whose structures are slow (ISTAT is 29s cold) pays for that metadata once a week.describe_flowhas usually already warmed it, since the prescribed order goes through it.The non-SDMX adapters expose a single dimension. Singapore and Hong Kong return one wide table per dataset, so
SERIESis the only thing to slice on. There is noREF_AREAto filter, because there is no country dimension.sdmx1emits aDeprecationWarningfrom its own internals (it passes a deprecatedprovider=to itself). Left visible rather than filtered, since suppressing it would also hide the same warning if it came from here.
What it will not do for you
Properties of the data itself. The server surfaces these; it does not silently fix them.
Geo codelists mix aggregates and members (EU27 next to France). Summing both double-counts, and nothing errors.
Nominal, PPP and constant-price series are not interchangeable.
Fiscal years differ. India, Japan and Australia are not calendar-year.
Seasonal adjustment differs: X-13 in the US, TRAMO/SEATS across much of Europe.
Most providers publish revisions without point-in-time access, so history reads as-revised rather than as-known. IMF is the exception, and
compare_vintagesreads it; everywhere else the caveat still stands.Entity search matches broadly and may rank a subsidiary above its parent. Hits carry country and status; use
entity_ownershipto walk up the group.
Known gaps
What is not covered, and why.
Asian national sources are mostly gated. Headline macro for Asia is already covered by the international providers: BIS carries all of JP, CN, IN, KR, SG, HK, TW, TH, MY, ID, PH, VN, PK and BD for policy rates and property prices, and the IMF, World Bank and ILO are comparably broad. What is missing is national detail, and there the constraint bites: e-Stat (Japan), ECOS (Korea), KOSIS and data.gov.in all require registration, so they cannot be included while the project stays keyless. Singapore is in via
SINGSTATand Hong Kong viaHKMA. Malaysia's OpenDOSM (api.data.gov.my) is keyless and works, but exposes no catalogue endpoint at all, so dataset ids would have to be invented from the documentation rather than derived from it.HKMA's dataset list is a snapshot. HKMA publishes no catalogue endpoint, so the 125 datasets in
hkma.pywere read off the documentation and then verified one request each against the live API. That table goes stale as HKMA adds and retires datasets; a retired one is reported as such rather than as a bare 404. Regenerate it withuv run python -m scripts.hkma_catalogue.IMF publishes three endpoints and only one serves data.
sdmx1shipsIMF(sdmxcentral, which answers 501 on data),IMF_DATA(SDMX 2.1) andIMF_DATA3(SDMX 3.0). The 3.0 service returns structures but a header and one empty row for every flow, soIMF_DATAis the one wired up. Its dimensions carry no local representation, so codes are reachable only through the concept each dimension identifies, and it writes monthly periods as2024-M01, which is rewritten to2024-01so the series joins against everything else.Endpoints drift.
sdmx1hardcodes base URLs that go stale as institutions move.URL_FIXEScorrects ABS (the old host stopped resolving) and Lithuania (moved to an APEX path);AGENCYcorrects INEGI, whose flows are filed under a different agency id. Re-verify these if a provider starts failing.Bundesbank needs its own adapter (
bundesbank.py). It serves valid SDMX-ML from non-standard paths, writes URNs missing their class segment, publishes codelists separately from the DSD, and returns 100MB+ for an unpinned query.Genuinely down: DG COMP 404s on every path and Uruguay serves a self-signed certificate. ISTAT returns intermittent 500s. See
QUIRKS.WB_WDI, StatCan, NBB and AR1 serve data but not dataflow metadata, so flow ids must be known in advance.
list_providersflags this. Which providers serve what is measured, not assumed:sdmx1's own capability table is a static declaration that disagrees with the live services in both directions. Regenerate the measured one withMACRO_MCP_NO_CACHE=1 uv run python -m scripts.probe, which retries once so a dropped connection is not recorded as a missing endpoint.Filings are out of scope. There is no free global equivalent until ESAP opens its API in July 2027.
Available Tools
12 toolscompare_vintagesB
One key read across several vintages, with the revisions between them.
"revisions" lists each period whose value changed and between which two
vintages. Vintages that do not carry the key at all are listed under
"no_data": coverage varies between them, not only values.| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| key | Yes | ||
| flow | Yes | ||
| limit | No | ||
| start | No | ||
| provider | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of disclosing behavior. It usefully explains the output structure: 'revisions' lists changed periods with the two vintages, and 'no_data' lists vintages missing the key. It does not disclose any side effects, auth requirements, or rate limits, but the tool appears to be a read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded, with the core purpose stated first and the key output behaviors following. Every sentence contributes meaning, and there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given six parameters, no output schema, no annotations, and sibling tools with overlapping concerns, the description is not complete enough. It explains the response's revisions and no_data fields but leaves parameter usage, date filtering, limit behavior, and comparison with fetch_data or list_vintages unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not explain the six parameters beyond implying that 'key' is central to the comparison. Provider, flow, start, end, and limit semantics are left entirely to the schema, which lacks descriptions. This is a significant gap that the description does not compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool reads one key across several vintages and describes the revisions between them. It conveys a specific operation and resource, though it could more explicitly differentiate itself from sibling tools like list_vintages or fetch_data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for comparing values of a key across vintages, which gives a sense of when it applies. However, it provides no explicit guidance about when to prefer this over fetch_data or list_vintages, nor does it mention exclusions or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_flowC
Dimensions of a dataflow with code counts and a short sample.
| Name | Required | Description | Default |
|---|---|---|---|
| flow | Yes | ||
| provider | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It reveals what the tool returns (dimensions, code counts, sample) but does not state whether it is read-only, whether it requires special permissions, or what side effects or limitations exist. The word 'describe' weakly implies a safe read operation, but this is not explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one short sentence with no filler words; it front-loads the core output content. It is concise but perhaps too sparse to fully serve as a standalone definition, though no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With two required string parameters, no annotations, no output schema, and no param guidance, the description leaves critical gaps: what counts as a 'flow', how 'provider' should be specified, and what the 'short sample' contains. The description gives a rough idea of the tool's purpose but not enough detail for an agent to call it confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both required parameters, and the description adds no meaning for 'provider' or 'flow'. It does not explain their format, possible values, or how they identify a dataflow. The description fails to compensate for the lack of schema-level documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource ('dataflow') and states the specific output content: dimensions, code counts, and a short sample. Although it is a noun fragment rather than a verb phrase, the tool name 'describe_flow' makes the operation clear. It does not explicitly distinguish itself from siblings like fetch_data or find_dataflows, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as find_dataflows, fetch_data, or search_codes. The description only implies that this tool provides descriptive metadata rather than actual data, but it never states a usage scenario, prerequisites, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
entity_ownershipC
Direct parent, ultimate parent and direct children for an LEI.
| Name | Required | Description | Default |
|---|---|---|---|
| lei | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden of behavioral disclosure. It states the kind of data returned (parent/children relationships) but does not mention read-only semantics, failure behavior, required identifier format, or whether results can be empty.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise phrase with no filler or redundant information. It is easy to parse, though it is slightly too terse to fully carry the behavioral and usage context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description should explain more about the return shape and edge cases. It names the three relationship types but leaves the agent guessing about structure, null cases, or how multiple children are represented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It mentions that the input is an LEI but adds no format, length, validation, or example details beyond the schema's 'lei' property. The single parameter is simple, but the description does not meaningfully extend the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific resource (ownership relationships) and the input (an LEI), naming the exact outputs: direct parent, ultimate parent, and direct children. It is not a tautology and is distinguishable from sibling tools like get_entity and find_entity, though it lacks an explicit verb such as 'get' or 'list'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided about when to choose entity_ownership over siblings like get_entity or find_entity. The description offers no context for when an agent should prefer this tool for ownership information versus other entity-related tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_dataA
Fetch observations. key maps dimension ids to codes, e.g. {"FREQ": "M", "CURRENCY": "USD"}.
A dimension takes several codes joined by +, so {"REF_AREA": "JP+XM"} asks
for both in one request rather than two. A dimension left out of the key
matches every code, which is how to ask which countries a flow covers:
fetch it with only FREQ pinned and read the series keys.
Returns the invariant part of the key once under "key", and observations as
[period, value] pairs grouped into "series" by whichever dimensions vary.
"names" gives the label for every code in the response, so a series keyed
XDC or CP01 can be read without asking search_codes again.
"units" says what the numbers are measured in, including any multiplier:
read it before comparing or converting. "range" is the period span actually
returned; periods with no value are omitted and counted under "empty".
"total" counts what the provider sent, which is the whole series unless
"truncated" says it is a floor: only the newest observations are fetched,
so a longer history exists and was not counted. Narrow start/end to read
it.
An empty response echoes the key it was given and says so under "note".
Any single entry in the key can empty a result and they all look alike, so
drop a dimension to find which one.| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| key | Yes | ||
| flow | Yes | ||
| limit | No | ||
| start | No | ||
| provider | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure and does so thoroughly. It explains return structure ('key', 'series', 'names', 'units', 'range'), missing data handling ('empty'), truncation semantics ('total' vs 'truncated'), and empty-response behavior. This far exceeds what would be expected for a data-fetch operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place. It opens with 'Fetch observations,' then systematically walks through request semantics, response structure, edge cases, and debugging guidance. No filler or repetition of trivial details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema, the description remarkably explains the full response shape, including 'key', 'series', 'names', 'units', 'range', 'empty', 'total', and 'truncated'. It also documents the empty-response behavior and a debugging technique. For a complex data tool with nested objects and no output schema, this is exceptionally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description compensates for 0% schema coverage by thoroughly explaining the 'key' parameter: how codes map to dimensions, how '+' joins codes, and how omitting a dimension matches all codes. 'start' and 'end' are also mentioned in the context of reading truncated histories. 'provider', 'flow', and 'limit' remain implied by their names, but the most complex parameter is well-covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Fetch observations.' The description goes beyond the generic name by explaining what the returned observations contain and how they are organized, making it clearly distinct from sibling tools like search_codes, list_providers, or describe_flow. The detail about series, keys, and codes leaves no ambiguity about this tool's role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when to use this tool, including how to ask which countries a flow covers by 'fetching with only FREQ pinned' and how to read labels 'without asking search_codes again.' It does not explicitly name all alternatives or state when not to use it, but the usage patterns and hints about narrowing start/end are strong contextual guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_dataflowsC
Search a provider's dataflows by id or name.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| search | No | ||
| provider | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It only states search by id or name, but does not disclose return behavior, pagination, limit semantics, or what happens with an empty search. The minimal wording gives little beyond the basic operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler. It is suitably front-loaded with the action and target. However, it could be slightly expanded to include useful behavioral or parameter details without losing conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With three parameters, no annotations, and no output schema, the description is too sparse. It omits return value details, limit semantics, and usage context. An agent would need to infer how to invoke the tool correctly, especially around the optional parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It clarifies that 'provider' scopes the search and that 'search' matches by id or name, but it does not explain the 'limit' parameter, default behavior, or search format (exact vs partial). This leaves significant parameter ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and object: 'Search a provider's dataflows by id or name.' This clearly indicates the tool's function and differentiates it from siblings by the resource type. It does not explicitly distinguish from search_codes, but 'dataflows' is a distinct enough resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to prefer this tool over alternatives like search_codes or describe_flow. The description implies that it is used for searching dataflows, but it provides no explicit context, exclusions, or conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_entityB
Search GLEIF by legal name. Verify country and status on every hit.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| limit | No | ||
| country | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds useful context by warning that hits require country and status verification, implying name matches may not be unique or authoritative. However, it does not mention return shape, no-match behavior, or optional filter effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short, purposeful sentences with no filler. The core search action is front-loaded, and the verification warning earns its place by giving agents actionable guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is relatively simple and the description covers its primary purpose and the most important safety nuance. Still, without an output schema, annotations, or parameter details, the agent is left to infer what country and limit mean and what the response contains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that the name parameter is a legal name, but says nothing about the limit or country parameters, including defaults or filtering semantics. This is a significant gap for a tool with three parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Search GLEIF by legal name.' This makes the tool's core purpose clear and distinguishes it from the sibling get_entity, which likely retrieves a specific known entity rather than searching by name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The instruction to 'Verify country and status on every hit' conveys a key usage caveat, but the description does not explicitly say when this tool should be preferred over related siblings like get_entity or entity_ownership. The usage context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fx_period_rateB
Euro reference rates by convention: "average" to convert flows (GDP, revenue), "end_of_period" for stocks (debt, balance sheet). Dates are ISO, e.g. 2024-01. Returns the same shape as fetch_data.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| freq | No | M | |
| limit | No | ||
| start | Yes | ||
| currency | Yes | ||
| convention | No | average |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It discloses that the return shape matches fetch_data and that dates follow ISO format, which is useful. It does not mention read-only behavior, authentication, pagination, or error handling, so the behavioral picture is incomplete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler: the convention mapping, date format, and return shape are each covered in one efficient sentence. It is well-structured and front-loads the most important usage guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations, no output schema, and no parameter descriptions, the description provides key domain context and a useful link to fetch_data. However, it omits important details such as currency-code format, frequency/limit semantics, and explicit differentiation from fx_spot, so an agent might still make incorrect assumptions when calling it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains the non-obvious 'convention' parameter and date format, but leaves currency, start, end, freq, and limit mostly to inference. For a six-parameter tool, this is not enough compensation for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies the tool as returning Euro reference rates and distinguishes between 'average' and 'end_of_period' conventions, which makes the resource and its main use concrete. It lacks an explicit verb phrase and does not directly contrast itself with fx_spot, but the purpose is still clear enough for an agent to separate it from spot-rate tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit convention guidance: use 'average' for flows and 'end_of_period' for stocks, and it specifies ISO date formatting. However, it does not explicitly say when to choose this tool over sibling tools like fx_spot or fetch_data, so tool-selection context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fx_spotA
ECB euro reference rate: how many quote buy one base. Omit date for
the latest.
These are a 14:15 CET fixing on TARGET business days, not a traded spot
rate, and a closed day returns the last publication before it. Every ECB
rate is quoted against the euro, so a pair without EUR is a cross derived
from two fixings — the response marks it "derived": true. Report that.| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | ||
| date | No | ||
| quote | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so exceptionally: it discloses the 14:15 CET fixing time, TARGET business days, closed-day fallback behavior, and the fact that non-EUR pairs are derived crosses marked with 'derived': true. It even instructs the agent to report that flag.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core rate semantics appear first, followed by essential caveats and a direct instruction. Every sentence earns its place, with no filler or repetition of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema and no annotations, the description covers the essential operational context: source, timing, holiday behavior, cross derivation, and a response field. It does not describe the full response shape or date format, but it is sufficient for correct invocation in most cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clearly explains the base/quote relationship and that omitting date gives the latest rate. However, it does not specify the expected date format or further constrain the date parameter beyond the schema's default empty string.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description precisely defines the tool's purpose: it provides the ECB euro reference rate and states the rate semantics as 'how many quote buy one base.' It also distinguishes itself by clarifying this is a daily fixing, not a traded spot rate, which separates it from the sibling fx_period_rate and generic spot tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: omit date for latest, and closed days return the last publication before them. It does not explicitly name alternatives or state when not to use this tool versus fx_period_rate, but the fixing-vs-traded-rate distinction implies the appropriate use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_entityC
Look up one LEI.
| Name | Required | Description | Default |
|---|---|---|---|
| lei | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavioral traits, but 'look up one LEI' only implies a read operation. It does not say whether lookup is exact-match, what a successful response contains, or what happens for unknown LEIs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no wasted words. It is concise, though the brevity comes at the cost of useful detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, no annotations, and several related sibling tools, this one-sentence description is incomplete. An agent cannot determine the return shape, exact-match behavior, or when to prefer get_entity over find_entity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must clarify the lone lei parameter. It adds only the phrase 'one LEI', which restates the parameter name without explaining format, length, or expected value semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('look up') and a concrete resource ('one LEI'), making the tool's core purpose clear. It does not differentiate itself from the sibling tool find_entity, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use get_entity instead of related siblings like find_entity or entity_ownership. There is no context, precondition, or alternative mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_providersA
Statistical providers by region, with known per-provider quirks.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description must carry the behavioral burden. It provides some useful context by mentioning 'known per-provider quirks,' which suggests the output includes caveats. However, it doesn't describe the output format, whether the operation is read-only, or any other behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise phrase, front-loaded with the core action and resource. No words are wasted, and the mention of per-provider quirks adds meaningful context without bloating the text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter listing tool, the description covers the essential purpose and grouping. It lacks explicit return-value details, but the absence of an output schema makes some ambiguity acceptable. Still, it could be more explicit about what the returned provider list contains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description doesn't need to add parameter-level detail since there are none to document.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: listing statistical providers, with a region-based organization. It is clear and understandable, though it doesn't explicitly differentiate from sibling tools like list_vintages, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for retrieving providers by region, but it doesn't explicitly state when to use it, when not to use it, or how it relates to alternatives. The usage context is inferable but not directly stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_vintagesB
Vintages of a dataflow, oldest first, with the current flow last.
A vintage is the dataset as it stood when published, so it shows what was known at the time rather than what the figure was later revised to.
| Name | Required | Description | Default |
|---|---|---|---|
| flow | Yes | ||
| provider | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It reveals ordering behavior ('oldest first, with the current flow last') and an important semantic distinction (vintage shows what was known at publication time, not later revisions). This goes beyond a bare 'list vintages' statement and materially helps an agent understand what response content to expect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences deliver the essential information with no fluff. The first sentence front-loads what the tool returns and its ordering; the second adds a crucial definition of 'vintage' that earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter list tool, the description covers the core concept and ordering well. However, it lacks any explanation of the provider and flow parameters, does not describe the return format or output fields, and provides no pointer to related tools. It is adequate but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate, but it only implicitly connects 'dataflow' to the 'flow' parameter. The 'provider' parameter is entirely unexplained, and no details about valid values, formats, or relationships between provider and flow are provided. This leaves a significant gap for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool returns vintages of a dataflow, with oldest first and current flow last, and explains the meaning of 'vintage' in a way that disambiguates the resource. However, it does not explicitly differentiate this tool from sibling tools such as compare_vintages or describe_flow, so it stops short of the highest score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance is given about when to use this tool versus alternatives. The description implies that it is relevant when you need historical published datasets, but it never mentions compare_vintages or other sibling tools, nor does it state any conditions for choosing this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_codesB
Find valid codes for one dimension. Use this to map a country name onto a provider's geo codelist.
| Name | Required | Description | Default |
|---|---|---|---|
| flow | Yes | ||
| limit | No | ||
| query | No | ||
| provider | Yes | ||
| dimension | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It usefully indicates a read-like search behavior and dimension-specific codelist mapping, but it does not explain what 'valid codes' means, how query matching works, or what the response contains. This is partial disclosure, not a complete behavioral contract.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler; the primary action is front-loaded and the concrete use case follows immediately. It is appropriately concise, though slightly vague wording like 'valid codes' prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given five parameters, zero schema descriptions, no output schema, and no annotations, the description is not sufficient for confident invocation. Notably, the required 'flow' parameter is unexplained, and the description provides no return contract or guidance about pagination/search behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies the roles of provider, dimension, and query ('country name') through the geo-codelist example, but it completely omits 'flow' and 'limit.' Since 'flow' is required and remains opaque in both the schema and description, parameter understanding is incomplete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: finding valid codes for a single dimension, with a concrete example of mapping a country name to a provider's geo codelist. It is specific enough to distinguish it from data-fetching or entity-lookup tools, though it does not explicitly name or contrast siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Use this to map a country name onto a provider's geo codelist' gives a clear, concrete context for when the tool should be used. However, it does not mention exclusions or alternatives, such as when to prefer find_entity or get_entity instead.
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.
12 tool updates
v0.1.0- First observed
compare_vintages - First observed
describe_flow - First observed
entity_ownership - First observed
fetch_data - First observed
find_dataflows - First observed
find_entity - First observed
fx_period_rate - First observed
fx_spot - First observed
get_entity - First observed
list_providers - First observed
list_vintages - First observed
search_codes
TDQS
Scored across 12 tools
Each tool targets a distinct resource and action: provider discovery, dataflow search, dimension description, code lookup, data fetching, vintage listing/comparison, entity search/get/ownership, and FX spot/period rates. Even find_entity vs get_entity are clearly separated by search vs. specific LEI lookup.
The majority follow a consistent verb_noun pattern like list_providers, describe_flow, fetch_data, and compare_vintages. The deviations are minor and readable: entity_ownership is noun_noun, and fx_spot/fx_period_rate use a domain prefix instead of a verb.
Twelve tools is well-scoped for a macro data toolkit spanning statistical dataflows, GLEIF entity data, and FX rates. Each tool earns its place and none feel redundant or missing.
The statistical side is well covered from provider discovery through dataflow inspection, code lookup, data fetching, and vintage comparison. Entity search, lookup, and ownership are covered, and FX has both spot and period-rate conventions with no obvious gaps.
Maintenance
Related MCP Connectors
Macro indicators from World Bank, FRED, IMF, and OECD via unified query surface.
Macroeconomic and other official data from 170+ publishers, resolved from natural language with provenance.
Macro data for AI agents: GDP, inflation, unemployment and more (World Bank, US BLS). No keys.
Macro data for AI agents: GDP, inflation, unemployment and more (World Bank, US BLS). No keys.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables querying economic statistics from over 80 providers via DBnomics, with tools to list providers and datasets.2 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to access SEC EDGAR filings, US Treasury rates, BLS labor statistics, and economic indicators without API keys.621 npmMIT
- FlicenseNot gradedqualityDmaintenanceProvides macro-economic data from World Bank, IMF, FRED, OECD, and RBI through a unified get_indicator interface.1-

AxionQuant MCP Serverofficial
AlicenseCqualityBmaintenanceEnables AI agents and LLM apps to answer natural-language financial questions using live market data, including stocks, crypto, forex, futures, indices, ETFs, economic data, news, sentiment, SEC filings, earnings, financials, insider trading, ESG, credit ratings, and web traffic.13266 npmMIT