treasury-fiscaldata-mcp-server
Server Details
Query US Treasury national debt, interest rates, exchange rates, and fiscal datasets via MCP.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/treasury-fiscaldata-mcp-server
- GitHub Stars
- 2
- Server Listing
- @cyanheads/treasury-fiscaldata-mcp-server
TDQS
Scored across 7 tools
The dataframe describe/query pair and the dataset discovery/query tools are clearly distinct, and the specialized getters have well-defined dataset-specific purposes. There is some overlap between treasury_query_dataset and the specialized getters, but the descriptions make the boundaries clear enough for correct tool selection.
Most tools follow a clear treasury_<verb>_<object> pattern such as treasury_get_debt and treasury_list_datasets. However, treasury_dataframe_describe and treasury_dataframe_query invert the verb/object order, creating a minor but noticeable inconsistency.
Seven tools is well-scoped for a Treasury data-access server: dataset discovery, generic endpoint querying, dataframe utilities, and three specialized getters. Each tool occupies a reasonable role, and the count is neither bloated nor too thin.
The server covers the full read-only workflow: discover datasets, query arbitrary endpoints, stage results, and run SQL over staged data. Direct specialized access to revenue/spending or savings bonds is absent, but the generic query tool covers those datasets, so agents can work around the gap.
Available Tools
7 toolstreasury_dataframe_describeDescribe Treasury DataframesARead-onlyIdempotentInspect
List DataCanvas dataframes materialized by treasury_query_dataset, treasury_get_debt, treasury_get_interest_rates, and treasury_get_exchange_rates. Each entry surfaces source tool, query parameters, creation/expiry timestamps, row count, and column schema. Use this tool before treasury_dataframe_query to discover table names and column types. Requires CANVAS_PROVIDER_TYPE=duckdb.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional dataframe table name (df_XXXXX_XXXXX) to describe a single dataframe. Omit to list all active dataframes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| dataframes | No | Active dataframes for this tenant, newest first. Empty when none are registered. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the base safety profile is covered. The description adds meaningful behavioral context: the list includes source tool, query parameters, timestamps, row count, and schema, and the tool requires a specific DuckDB provider. No contradictions.
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?
Three sentences, each earning its place: action/resource, returned entry fields, and usage direction plus prerequisite. Information is front-loaded and there is no redundant wording or fluff.
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 has an output schema, so return values need not be spelled out. The description covers scope, entry contents, usage ordering, and environment requirement, while annotations handle safety. Nothing an agent needs to call it correctly is missing.
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 100% for the single optional 'name' parameter, so the schema already carries the semantic weight. The top-level description does not add parameter-level detail beyond what the schema states, matching the baseline for full coverage.
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 ('List') and uniquely identifies the resource: DataCanvas dataframes materialized by four named source tools. It further distinguishes itself from treasury_dataframe_query by framing the tool as metadata discovery rather than data query.
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?
Explicitly states when to use the tool: 'Use this tool before treasury_dataframe_query to discover table names and column types.' It also gives a prerequisite (CANVAS_PROVIDER_TYPE=duckdb). However, it does not explicitly contrast with sibling treasury_list_datasets, leaving a minor gap in alternative differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_dataframe_queryQuery Treasury DataframesARead-onlyIdempotentInspect
Run a single-statement SELECT against DataCanvas dataframes registered by treasury_query_dataset, treasury_get_debt, treasury_get_interest_rates, and treasury_get_exchange_rates. Read-only: writes, DDL, DROP, COPY, PRAGMA, ATTACH, and external-file table functions are rejected. System catalogs (information_schema, pg_catalog, sqlite_master, duckdb_*) are denied at the bridge layer. All Treasury dataframe columns are VARCHAR — CAST to DECIMAL or DATE for arithmetic and date comparisons. Use treasury_dataframe_describe to list available table names and column schemas before querying.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | Single-statement SELECT against df_<id> tables. All values in Treasury dataframes are VARCHAR (strings) per the API contract — CAST to DECIMAL or DATE for arithmetic and date comparisons. Example: SELECT record_date, CAST(tot_pub_debt_out_amt AS DECIMAL) AS debt FROM df_xxxxx ORDER BY record_date DESC LIMIT 10. | |
| preview | No | Rows in the immediate response. Defaults to row_limit and may not exceed it. Set lower when using register_as. | |
| row_limit | No | Hard cap on rows the query may produce. Default 1000, max 10000. A query matching more rows than this stops at the cap and row_count_capped comes back true — raise it, or use register_as to materialize the whole result. | |
| register_as | No | Persist the result as a new dataframe under this exact name, to chain analyses. The name is used verbatim — any name works, and a df_ prefix keeps it consistent with the tables the data tools mint. Echoed back in registered_as. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The row cap that was applied — preview when supplied, otherwise row_limit. |
| rows | No | Materialized rows, bounded by preview / row_limit. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of rows returned in this response. |
| notice | No | Guidance when the query returned no rows, or when results were capped by preview or row_limit. |
| columns | No | Column names in projection order. |
| row_count | No | Rows the query produced, up to row_limit. Exceeds rows.length when preview returned fewer. Read with row_count_capped: when that is true this number is row_limit itself, and the size of the full result is not in this response. |
| truncated | No | True when the returned rows were capped below the full result set. |
| expires_at | No | ISO 8601 expiry timestamp for the newly registered dataframe, when applicable. |
| registered_as | No | Set when register_as was supplied and the new dataframe was materialized. |
| row_count_capped | No | True when the query matched more rows than row_limit, so row_count is that cap rather than a total. False means row_count is exact — including when it happens to equal row_limit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and idempotent, and the description adds concrete enforcement details: writes, DDL, DROP, COPY, PRAGMA, ATTACH, external-file functions, and system catalogs are rejected or denied. The VARCHAR-column warning tells the agent how data will behave and what CASTing is needed for arithmetic and date comparisons. No statement contradicts the annotations.
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?
Four dense sentences, front-loaded with the core action and followed by restrictions, type caveat, and prerequisite. Every sentence earns its place; there is no fluff or restatement of the title.
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 description covers what the tool does, what SQL is permitted, what is denied, the VARCHAR type constraint, and how to discover valid table names. Combined with the rich input schema for row_limit, preview, and register_as, plus the presence of an output schema, an agent has everything needed to invoke the tool correctly.
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 100%, so the schema already documents sql, preview, row_limit, and register_as. The description adds value by directing the agent to treasury_dataframe_describe before querying, which is essential for constructing valid `sql` table names, and by clarifying that tables are DataCanvas dataframes registered by specific tools. It repeats some CAST guidance already present in the sql parameter description, so it is not a full 5.
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?
Opens with a specific verb and resource — 'Run a single-statement SELECT against DataCanvas dataframes' — and names the four registration tools that produce those dataframes. This clearly distinguishes it from treasury_dataframe_describe, which is positioned as the listing counterpart rather than the query tool. The single-statement SELECT restriction removes ambiguity about what kind of SQL this tool accepts.
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 explicitly tells the agent to use treasury_dataframe_describe to discover available table names and schemas before querying, giving a concrete prerequisite. It also states that only SELECT is allowed and lists rejected statement types, which helps the agent avoid invalid calls. It does not explicitly route between this tool and raw-data retrieval tools like treasury_query_dataset, so it stops short of full when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_get_debtGet National DebtARead-onlyIdempotentInspect
Fetch national debt (Debt to the Penny) — total public debt outstanding broken into publicly-held debt and intragovernmental holdings. Three modes: "latest" returns the most recent business day's record; "date" returns the record for a specific date (must be a business day — the API only records debt on days markets are open); "series" returns a date range, staging the full result as a DataCanvas table when canvas_id is set or the range matches more than 500 rows — read the table's column schema with treasury_dataframe_describe, then run SQL over it with treasury_dataframe_query. Records go back to 1993-04-01.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ISO 8601 date (YYYY-MM-DD) for mode=date. Must be a business day; the API only records debt on days the market is open. | |
| mode | No | "latest" returns the most recent day's record. "date" returns the record for a specific date. "series" returns a date range — use with start_date and end_date. | latest |
| end_date | No | ISO 8601 end date for mode=series (inclusive). Defaults to today. | |
| canvas_id | No | Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when the range matches more than 500 rows. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| start_date | No | ISO 8601 start date for mode=series (inclusive). Fiscal Data has daily debt records back to 1993-04-01. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The preview cap applied to the inline series array. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Series rows returned inline. |
| notice | No | Guidance when the inline series is a preview, when the series was staged as a DataCanvas table, or when paging stopped before the full matched set. |
| series | No | Inline preview of the mode=series records — at most 20 rows, newest first. Compare series.length against retrieved_records to detect the cap; the full retrieved set is reachable through canvas_id when one is returned. |
| canvas_id | No | DuckDB table name (df_XXXXX_XXXXX) holding the full retrieved series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged. |
| truncated | No | True when the inline series array holds fewer rows than were retrieved. |
| total_debt | No | Total public debt outstanding in USD, as a plain decimal string — no separators, no currency symbol, two decimal places. Convert as needed. |
| record_date | No | Date of this debt record (YYYY-MM-DD). For series mode, the most recent date. |
| total_records | No | Records matching the date range upstream. Exceeds retrieved_records when the match is larger than the series row bound. |
| debt_held_public | No | Debt held by the public (external creditors, Fed, foreign governments) in USD. |
| canvas_expires_at | No | ISO 8601 expiry for the canvas dataframe. |
| retrieved_records | No | Records actually fetched for mode=series across every page, and the row count of the canvas table when one was registered. Never larger than total_records. |
| intragovernmental_holdings | No | Intragovernmental holdings (debt owed to federal trust funds, Social Security, etc.) in USD. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds meaningful behavioral context: records exist only on market-open business days, series results may be staged as a DataCanvas table, and that staging requires duckdb. No contradiction with the annotations; the staging side-effect is disclosed rather than hidden.
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 clause earns its place: it front-loads the core purpose, then expands into modes and the staging workflow in a logical progression. There is no filler and no repetition of what the schema already states.
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 output schema exists, return-value explanation is unnecessary. The description fully covers mode selection, staging behavior, downstream tools, and the date range of available records, providing everything an agent needs to invoke the tool correctly.
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 100%, so the baseline is 3, but the description adds value beyond the schema: 'latest' is clarified as the most recent business day, 'series' is tied to start/end date usage, canvas_id is explained as a staging request where the server chooses the name, and the historical availability from 1993-04-01 is stated.
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 opens with a specific verb-resource pair ('Fetch national debt (Debt to the Penny)') and distinguishes the content breakdown (publicly-held debt vs intragovernmental holdings). The three modes are clearly enumerated, making it easy to tell this tool apart from the dataframe tools and other treasury getters.
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 explicitly explains when to use each mode, and it routes the series-staging workflow to treasury_dataframe_describe and treasury_dataframe_query. It also tells the agent when staging auto-triggers (range > 500 rows) and when it is requested via canvas_id, leaving no ambiguity about next steps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_get_exchange_ratesGet Treasury Exchange RatesARead-onlyIdempotentInspect
Official Treasury reporting exchange rates for ~165 countries — the rates US federal agencies are required to use when converting foreign currency to USD for official reporting. Published quarterly (March 31, June 30, Sep 30, Dec 31); mode "latest" returns the most recently published quarter. Rate is expressed as foreign currency units per 1 USD (e.g., a Japan-Yen rate of 159.41 means 1 USD = 159.41 JPY). These are NOT market exchange rates and are not suitable for financial transaction pricing. Mode "series" stages the result as a DataCanvas table when canvas_id is set or the range matches more than 500 rows — read the table's column schema with treasury_dataframe_describe, then run SQL over it with treasury_dataframe_query.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | "latest" returns the most recently published quarter's rates. "series" returns a date range of quarterly reports. | latest |
| end_date | No | ISO 8601 end date for mode=series. | |
| canvas_id | No | Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when a series matches more than 500 rows, which multi-year multi-country pulls do (~19,000 rows for the full history). The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| countries | No | Filter to specific countries by exact country name (e.g., ["Japan", "Germany", "France"]). Case-sensitive, matches the "country" field. Omit for every country in the quarter (~165). | |
| start_date | No | ISO 8601 start date for mode=series. Rates are published end-of-quarter (March 31, June 30, Sep 30, Dec 31). |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The preview cap applied to the inline rates array. |
| note | No | Contextual note reminding that these are official reporting rates, not market rates. |
| error | No | Present when the call failed. Absent on success. |
| rates | No | Exchange rates for the requested countries/quarter, newest first. Whole in mode=latest — a quarter is a bounded set. In mode=series an inline preview of at most 20 rows; compare its length against retrieved_records to detect the cap, and reach the rest through canvas_id when one is returned. |
| shown | No | Rate rows returned inline. |
| notice | No | Guidance when a requested country matched no records, when the inline series is a preview, when the series was staged as a DataCanvas table, or when the returned rows were published in more than one quarter. |
| canvas_id | No | DuckDB table name (df_XXXXX_XXXXX) holding the staged series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged. |
| truncated | No | True when the inline rates array holds fewer rows than were retrieved. |
| as_of_date | No | Most recent quarter-end record_date among the returned rows (YYYY-MM-DD). Not necessarily a date every row shares — check mixed_record_dates. |
| total_records | No | In mode=latest, the number of rows in rates. In mode=series, the full upstream match — larger than rates.length whenever the preview cap applied, and larger than retrieved_records when paging stopped first. |
| effective_date | No | Effective date of the as_of_date row (YYYY-MM-DD). Every row carries its own effective_date; this one does not describe the rest. |
| canvas_expires_at | No | ISO 8601 expiry for the canvas dataframe. |
| retrieved_records | No | Rows actually fetched for mode=series across every page, and the row count of the canvas table when one was registered. Never larger than total_records. |
| mixed_record_dates | No | True when the retrieved rows were not all published on as_of_date — including rows past the inline preview. Read each row's record_date rather than applying the top-level date to the set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description discloses important behavior: quarterly publication dates, the exact rate convention (foreign currency per 1 USD), automatic staging for large results, the canvas_id naming behavior, and the CANVAS_PROVIDER_TYPE=duckdb requirement. No contradictions with annotations.
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 information-dense but well organized: core purpose first, then caveats, then mode and staging workflow. Every sentence contributes meaningful guidance without redundancy.
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 5-parameter schema, output schema, and annotations, the description covers all behavior an agent needs: units, publication schedule, staging triggers, downstream analysis steps, and environment requirements. Nothing essential is missing.
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 already 100%, and the description adds extra meaning, especially for canvas_id: it explains how the server picks the table name, when staging triggers automatically, and what to do with the returned canvas_id. It also clarifies the scale of a full multi-year pull.
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 a specific verb and resource: fetching official Treasury reporting exchange rates for ~165 countries. It clearly distinguishes this tool from market-rate and sibling treasury data tools by its exact domain and required-use context.
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?
It gives strong usage context: when to use 'latest' vs 'series', when staging occurs, and that the data is not for financial transaction pricing. It also routes to treasury_dataframe_describe and treasury_dataframe_query for series results, but it does not explicitly contrast with siblings like treasury_get_interest_rates or treasury_get_debt.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_get_interest_ratesGet Treasury Interest RatesARead-onlyIdempotentInspect
Average interest rates Treasury pays on its outstanding securities by security type. Answers "what is the government's cost of borrowing?" Covers every type Treasury reports — marketable issues, non-marketable series, and the aggregate totals — and which types it reports changes over the years, so omit security_type to see the ones a given period carries. Rates are percentages, not basis points. Updated monthly (end-of-month records). Mode "latest" returns the most recent month's rates for all or one security type; "series" returns a time history, staging the result as a DataCanvas table when canvas_id is set or the range matches more than 200 rows — read the table's column schema with treasury_dataframe_describe, then run SQL over it with treasury_dataframe_query.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | "latest" returns the most recent month's rates. "series" returns a time range. | latest |
| end_date | No | ISO 8601 end date for mode=series. Defaults to today. | |
| canvas_id | No | Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when a series matches more than 200 rows. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| start_date | No | ISO 8601 start date for mode=series (YYYY-MM-DD, must be end-of-month for meaningful results). | |
| security_type | No | Filter to one security type, matched exactly against the security_desc field — full case and punctuation, as in "Treasury Inflation-Protected Securities (TIPS)". Omit for every type in the period, which is how to read the set of types on offer; the response names them when a filter matches nothing. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The preview cap applied to the inline series array. |
| error | No | Present when the call failed. Absent on success. |
| rates | No | Interest rate records, newest first. Whole in mode=latest — a month is a bounded set. In mode=series an inline preview of at most 20 rows; compare its length against total_records to detect the cap, and reach the rest through canvas_id when one is returned. |
| shown | No | Series rows returned inline. |
| notice | No | Guidance when no records match (where the requested security type does have records, or the types the most recent month carries, or the empty date range), when the inline series is a preview, or when the series was staged as a DataCanvas table. |
| canvas_id | No | DuckDB table name (df_XXXXX_XXXXX) holding the staged series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged. |
| truncated | No | True when the inline series array holds fewer rows than were retrieved. |
| as_of_date | No | Most recent record date returned (YYYY-MM-DD). |
| total_records | No | In mode=latest, the number of rows in rates. In mode=series, the full upstream match — larger than rates.length whenever the preview cap applied. |
| canvas_expires_at | No | ISO 8601 expiry for the canvas dataframe. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and idempotent behavior, so the bar is lower. The description adds substantial behavioral nuance: rates are percentages not basis points, the set of security types changes over years, data is updated monthly, and large series trigger automatic DataCanvas staging. It also discloses that canvas_id staging requires duckdb. These details go far beyond the annotations and significantly aid correct invocation.
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 well-structured, starting with the core purpose and then layering details about coverage, units, update frequency, and modes. Every sentence contributes necessary information; the length is justified given the tool's complexity (5 params, two modes, staging behavior). It could be slightly trimmed in wording, but it remains focused and front-loaded with the most important facts.
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 tool's complexity and that an output schema exists, the description covers all essential operational aspects: how to use modes, parameter nuances, staging trigger conditions, and the follow-up workflow with sibling tools. It even explains the 'omit security_type' strategy for discovering available types. Nothing an agent needs to call it correctly and interpret results is missing.
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?
Although schema coverage is 100% (all parameters documented), the description adds crucial semantic depth: security_type can be omitted to list all types and the response names types when a filter matches nothing; start_date should be end-of-month; canvas_id only requests staging and the actual table name is returned; the exact match requirement for security_type is clarified. These enrich the schema descriptions to a level that prevents common errors.
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: obtaining average interest rates on Treasury securities by type, with a specific verb and resource. It explicitly differentiates from siblings by naming the domain (interest rates vs debt, exchange rates) and covers the full scope of security types. The inclusion of a clarifying 'answers the government's cost of borrowing' makes the purpose immediately obvious.
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 guidance on how to use the tool's modes ('latest' vs 'series'), when to omit security_type to discover available types, and the meaning of end-of-month for start_date. It also references sibling tools (treasury_dataframe_describe, treasury_dataframe_query) for post-processing staged results. However, it does not explicitly state when to choose this tool over alternatives like treasury_get_debt or treasury_get_exchange_rates, leaving that to the agent's domain inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_list_datasetsList Treasury Fiscal Data DatasetsARead-onlyIdempotentInspect
Browse the curated catalog of US Treasury Fiscal Data API endpoints. Returns endpoint paths, field names, descriptions, and update cadence for each dataset. Use this tool before treasury_query_dataset to discover the correct endpoint path and field names — a typo in either causes a 400 error from the API. The catalog is a curated subset of the full API — pass any endpoint path directly to treasury_query_dataset to query datasets not listed here. The catalog covers debt, interest rates, exchange rates, revenue/spending, savings bonds, and securities datasets.
| Name | Required | Description | Default |
|---|---|---|---|
| search | No | Keyword filter against dataset name and description (case-insensitive substring match). Useful for narrowing results when the category is uncertain. | |
| category | No | Filter by category. Omit to list all datasets. Options: debt, interest_rates, exchange_rates, revenue_spending, savings_bonds, securities, other. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| total | No | Total matching datasets. |
| datasets | No | Matching datasets. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered without description help. The description adds meaningful context beyond that: the catalog is a curated subset (so omission is expected behavior, not a bug), and the 400-error failure mode from upstream. It does not contradict the annotations.
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?
Four sentences, each earning its place: purpose and return content, then usage guidance, then the curated-subset caveat. Front-loaded with the most important information and zero filler or repetition of the schema/annotations.
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 simple (2 optional params, 0 required, both fully documented) and has an output schema, so return values need no elaboration. The description covers what it returns, when to use it, the important incompleteness caveat, and failure behavior — nothing an agent needs to call it correctly is missing.
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 100% — both 'search' (case-insensitive substring match) and 'category' (enumerated options, omit to list all) are fully documented in the schema. The description adds no parameter-specific detail beyond the schema, so it rests at the baseline 3 rather than compensating for any coverage gap.
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?
Uses a specific verb ('Browse') with a clear resource ('curated catalog of US Treasury Fiscal Data API endpoints') and details the return content: endpoint paths, field names, descriptions, and update cadence. It explicitly differentiates itself from treasury_query_dataset as the listing vs. querying counterpart, so an agent can distinguish it from all six siblings without opening schemas.
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?
States explicitly to use this tool before treasury_query_dataset to discover correct endpoint paths and field names, warning that a typo in either causes a 400 error. It also gives a when-not condition: since the catalog is curated/subset, pass endpoint paths directly to treasury_query_dataset for unlisted datasets. Both the primary use and the alternative path are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
treasury_query_datasetQuery Treasury Fiscal Data DatasetARead-onlyIdempotentInspect
Query any Treasury Fiscal Data endpoint by path, field list, filters, sort, and page. Call treasury_list_datasets first to get the correct endpoint path and exact field names — a typo in either causes a 400. Filter syntax: each condition is { field, operator, value } where operator is eq/gt/gte/lt/lte/in (e.g., record_date:gte:2024-01-01). Multiple conditions are ANDed together. All response values are strings per the API contract, including numbers and dates; "null" (string) means no value. Supply canvas_id to stage the page result as a DataCanvas table — read its column schema with treasury_dataframe_describe, then run SQL over it with treasury_dataframe_query (requires CANVAS_PROVIDER_TYPE=duckdb on the server).
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Sort expression: field name optionally prefixed with "-" for descending (e.g., "-record_date" for newest-first). | |
| fields | No | Fields to return. Omit to return all fields. Specify field names exactly as listed by treasury_list_datasets — a typo causes a 400. | |
| filters | No | Filter conditions (ANDed together). Multiple filters on different fields are combined in one filter= parameter. | |
| endpoint | Yes | Endpoint path returned by treasury_list_datasets (e.g., "/v2/accounting/od/debt_to_penny"). Include the leading slash. | |
| canvas_id | No | Set any non-empty value to stage this page as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Omit to receive results inline only. Requires CANVAS_PROVIDER_TYPE=duckdb on the server. | |
| page_size | No | Rows per page. Default 100. Raise to 10000 to minimize round trips for small datasets. For large time-series pulls, use canvas_id with treasury_dataframe_query instead. | |
| page_number | No | Page to fetch (1-indexed). Check total_pages in the response to know if more pages exist. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Rows returned. All values are strings per API contract — including numeric and date fields. Convert in the calling context. Null values appear as the string "null". |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Guidance when results are empty, a field typo is suspected, the endpoint was not found in the catalog, or staging was requested. |
| endpoint | No | Endpoint that was queried. |
| canvas_id | No | DuckDB table name (df_XXXXX_XXXXX) holding this page. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged. |
| page_size | No | Rows per page. |
| totalCount | No | Total rows matching the query across all pages — discloses that this page is a subset. |
| page_number | No | Current page (1-indexed). |
| total_count | No | Total rows matching the query (across all pages). |
| total_pages | No | Total pages at the current page_size. |
| field_labels | No | Human-readable label for each returned field. |
| applied_filters | No | Filter expression sent to the API, for verification. |
| canvas_expires_at | No | ISO 8601 expiry for the canvas dataframe. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses that typos cause a 400, that all response values are strings including dates and numbers, that 'null' (string) means no value, that multiple filters are ANDed, and that canvas staging is server-side with a generated table name. This is substantive behavioral context well above the annotation baseline.
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 and logically ordered: core action, prerequisite, filter syntax, response semantics, staging workflow. It is longer than minimal but every section earns its place, with only minor redundancy against schema details like the typo warning.
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 rich schema, output schema, and annotations, the description covers the full operational flow: prerequisites, parameter semantics, response quirks, and the downstream DataCanvas path. Nothing an agent needs to call this tool correctly is missing.
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 100%, so the baseline is 3. The description adds filter operator syntax with an example (record_date:gte:2024-01-01), explains AND semantics, and clarifies that 'null' is a string, adding value beyond the schema while not carrying the full burden.
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 opens with a specific verb and resource: 'Query any Treasury Fiscal Data endpoint by path, field list, filters, sort, and page.' It clearly distinguishes this tool from treasury_list_datasets (which discovers endpoints) and treasury_dataframe_describe/query (which operate on staged DataCanvas tables).
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?
It gives an explicit prerequisite: 'Call treasury_list_datasets first to get the correct endpoint path and exact field names.' It also routes large pulls to the DataCanvas workflow with treasury_dataframe_queryhol, explicitly naming the alternative and the condition for choosing it.
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.
5 tool updates
- Changed
treasury_dataframe_describe1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb. Other values are possible when a failure originates below the handler."
- Changed
treasury_dataframe_query1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb `system_catalog_access`: SQL references a denied DuckDB system catalog (information_schema, pg_catalog, sqlite_master, duckdb_*) `invalid_sql`: SQL is not a SELECT, contains DDL/DML, or uses disallowed table functions `missing_table`: A df_<id> table named in the SQL is not on the canvas — its TTL expired, it was dropped, or it was never registered `invalid_query_bounds`: preview exceeds row_limit, or row_limit exceeds the row ceiling this server allows Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb. `system_catalog_access`: SQL references a denied DuckDB system catalog (information_schema, pg_catalog, sqlite_master, duckdb_*). `invalid_sql`: SQL is not a SELECT, contains DDL/DML, or uses disallowed table functions. `missing_table`: A df_<id> table named in the SQL is not on the canvas — its TTL expired, it was dropped, or it was never registered. `invalid_query_bounds`: preview exceeds row_limit, or row_limit exceeds the row ceiling this server allows. Other values are possible when a failure originates below the handler."
- Changed
treasury_get_debt1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `no_data_for_date`: No debt record exists for the requested date (API returns HTTP 200 with empty data[], not 404 — total-count is 0) Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_data_for_date`: No debt record exists for the requested date (API returns HTTP 200 with empty data[], not 404 — total-count is 0). Other values are possible when a failure originates below the handler."
- Changed
treasury_get_exchange_rates1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `country_not_found`: One or more requested countries have no records — API returns HTTP 200 with empty data[]; total-count is 0 or fewer countries were returned than requested Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `country_not_found`: One or more requested countries have no records — API returns HTTP 200 with empty data[]; total-count is 0 or fewer countries were returned than requested. Other values are possible when a failure originates below the handler."
- Changed
treasury_query_dataset1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `invalid_endpoint`: The endpoint path does not exist (API returns 404 HTML) `invalid_field`: A field name in fields= or filter= does not exist on this endpoint — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Field 'X' does not exist...\"} `invalid_filter`: The filter expression uses an unsupported operator — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Operator ':op:' is not supported...\"} `page_out_of_range`: page_number is past the last page of the matched set — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Page #N is out of range...\"} Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_endpoint`: The endpoint path does not exist (API returns 404 HTML). `invalid_field`: A field name in fields= or filter= does not exist on this endpoint — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Field 'X' does not exist...\"}. `invalid_filter`: The filter expression uses an unsupported operator — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Operator ':op:' is not supported...\"}. `page_out_of_range`: page_number is past the last page of the matched set — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Page #N is out of range...\"}. Other values are possible when a failure originates below the handler."
7 tool updates
- Changed
treasury_dataframe_describe6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataframes" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb Other values are possible when a failure originates below the handler.", + "examples": [ + "canvas_unavailable" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "dataframes" -]
- Changed
treasury_dataframe_query6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "columns", + "row_count", + "row_count_capped", + "rows" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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_unavailable`: CANVAS_PROVIDER_TYPE is not set to duckdb `system_catalog_access`: SQL references a denied DuckDB system catalog (information_schema, pg_catalog, sqlite_master, duckdb_*) `invalid_sql`: SQL is not a SELECT, contains DDL/DML, or uses disallowed table functions `missing_table`: A df_<id> table named in the SQL is not on the canvas — its TTL expired, it was dropped, or it was never registered `invalid_query_bounds`: preview exceeds row_limit, or row_limit exceeds the row ceiling this server allows Other values are possible when a failure originates below the handler.", + "examples": [ + "canvas_unavailable", + "system_catalog_access", + "invalid_sql", + "missing_table", + "invalid_query_bounds" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "columns", - "row_count", - "row_count_capped", - "rows" -]
- Changed
treasury_get_debt6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "record_date", + "total_debt", + "debt_held_public", + "intragovernmental_holdings" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `no_data_for_date`: No debt record exists for the requested date (API returns HTTP 200 with empty data[], not 404 — total-count is 0) Other values are possible when a failure originates below the handler.", + "examples": [ + "no_data_for_date" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "record_date", - "total_debt", - "debt_held_public", - "intragovernmental_holdings" -]
- Changed
treasury_get_exchange_rates6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "as_of_date", + "effective_date", + "mixed_record_dates", + "rates", + "total_records", + "note" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `country_not_found`: One or more requested countries have no records — API returns HTTP 200 with empty data[]; total-count is 0 or fewer countries were returned than requested Other values are possible when a failure originates below the handler.", + "examples": [ + "country_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" +} - removed
Output schema / requiredRemoved value: -[ - "as_of_date", - "effective_date", - "mixed_record_dates", - "rates", - "total_records", - "note" -]
- Changed
treasury_get_interest_rates6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "as_of_date", + "rates", + "total_records" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "as_of_date", - "rates", - "total_records" -]
- Changed
treasury_list_datasets6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "datasets", + "total" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "datasets", - "total" -]
- Changed
treasury_query_dataset7 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / filters / items / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "endpoint", + "data", + "total_count", + "total_pages", + "page_number", + "page_size", + "field_labels" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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_endpoint`: The endpoint path does not exist (API returns 404 HTML) `invalid_field`: A field name in fields= or filter= does not exist on this endpoint — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Field 'X' does not exist...\"} `invalid_filter`: The filter expression uses an unsupported operator — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Operator ':op:' is not supported...\"} `page_out_of_range`: page_number is past the last page of the matched set — API returns JSON {\"error\":\"Invalid Query Param\",\"message\":\"...Page #N is out of range...\"} Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_endpoint", + "invalid_field", + "invalid_filter", + "page_out_of_range" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "endpoint", - "data", - "total_count", - "total_pages", - "page_number", - "page_size", - "field_labels" -]
1 tool update
- Changed
treasury_get_interest_rates3 fields changed- changed
Input schema / properties / security_type / descriptionPrevious value: -"Filter to one security type. Omit for all types. Use the exact string — the API does exact-match filtering on security_desc."New value: +"Filter to one security type, matched exactly against the security_desc field — full case and punctuation, as in \"Treasury Inflation-Protected Securities (TIPS)\". Omit for every type in the period, which is how to read the set of types on offer; the response names them when a filter matches nothing." - removed
Input schema / properties / security_type / enumRemoved value: -[ - "Treasury Bills", - "Treasury Notes", - "Treasury Bonds", - "Treasury Inflation-Protected Securities (TIPS)", - "Treasury Floating Rate Notes (FRN)", - "Total Marketable", - "Total Non-marketable", - "Total Interest-bearing Debt" -] - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no records match (lists valid security types, or notes the empty date range), when the inline series is a preview, or when the series was staged as a DataCanvas table."New value: +"Guidance when no records match (where the requested security type does have records, or the types the most recent month carries, or the empty date range), when the inline series is a preview, or when the series was staged as a DataCanvas table."
5 tool updates
- Changed
treasury_dataframe_query5 fields changed- changed
Input schema / properties / register_as / descriptionPrevious value: -"Persist result as a new dataframe. Use to chain analyses. The name must match df_XXXXX_XXXXX format or be a fresh df_<id>."New value: +"Persist the result as a new dataframe under this exact name, to chain analyses. The name is used verbatim — any name works, and a df_ prefix keeps it consistent with the tables the data tools mint. Echoed back in registered_as." - changed
Input schema / properties / row_limit / descriptionPrevious value: -"Hard cap on rows in the response. Default 1000, max 10000."New value: +"Hard cap on rows the query may produce. Default 1000, max 10000. A query matching more rows than this stops at the cap and row_count_capped comes back true — raise it, or use register_as to materialize the whole result." - changed
Output schema / properties / row_count / descriptionPrevious value: -"Total rows the query produced (may exceed rows.length when capped)."New value: +"Rows the query produced, up to row_limit. Exceeds rows.length when preview returned fewer. Read with row_count_capped: when that is true this number is row_limit itself, and the size of the full result is not in this response." - added
Output schema / properties / row_count_cappedAdded value: +{ + "description": "True when the query matched more rows than row_limit, so row_count is that cap rather than a total. False means row_count is exact — including when it happens to equal row_limit.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "columns", - "row_count", - "rows" -]New value: +[ + "columns", + "row_count", + "row_count_capped", + "rows" +]
- Changed
treasury_get_debt5 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name (df_XXXXX_XXXXX) to register series results into for SQL analysis. When provided, or when the series exceeds 500 rows, the full result is registered and the name is returned in canvas_id. Use treasury_dataframe_query to run SQL against it. Requires CANVAS_PROVIDER_TYPE=duckdb."New value: +"Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when the range matches more than 500 rows. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb." - changed
Input schema / properties / start_date / descriptionPrevious value: -"ISO 8601 start date for mode=series (inclusive). Fiscal Data has daily debt records back to 1993-01-04."New value: +"ISO 8601 start date for mode=series (inclusive). Fiscal Data has daily debt records back to 1993-04-01." - changed
Output schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name when series was spilled. Use treasury_dataframe_query to run SQL."New value: +"DuckDB table name (df_XXXXX_XXXXX) holding the full retrieved series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when the inline series is a preview, or when paging stopped before the full matched set."New value: +"Guidance when the inline series is a preview, when the series was staged as a DataCanvas table, or when paging stopped before the full matched set." - changed
Output schema / properties / total_debt / descriptionPrevious value: -"Total public debt outstanding in USD (string — convert as needed). Example: \"39176301795549.40\"."New value: +"Total public debt outstanding in USD, as a plain decimal string — no separators, no currency symbol, two decimal places. Convert as needed."
- Changed
treasury_get_exchange_rates17 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name (df_XXXXX_XXXXX) to register series results into for SQL analysis. Useful when pulling multi-year history for many countries (~18,800 rows total). When provided, or when mode=series and results exceed 500 rows, the result is registered and canvas_id is returned. Use treasury_dataframe_query to query it. Requires CANVAS_PROVIDER_TYPE=duckdb."New value: +"Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when a series matches more than 500 rows, which multi-year multi-country pulls do (~19,000 rows for the full history). The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb." - changed
Input schema / properties / countries / descriptionPrevious value: -"Filter to specific countries by exact country name (e.g., [\"Japan\", \"Germany\", \"France\"]). Case-sensitive, matches the \"country\" field. Omit for all ~130 countries in the quarter."New value: +"Filter to specific countries by exact country name (e.g., [\"Japan\", \"Germany\", \"France\"]). Case-sensitive, matches the \"country\" field. Omit for every country in the quarter (~165)." - changed
Output schema / properties / as_of_date / descriptionPrevious value: -"Quarter-end date of the most recent rates (YYYY-MM-DD)."New value: +"Most recent quarter-end record_date among the returned rows (YYYY-MM-DD). Not necessarily a date every row shares — check mixed_record_dates." - changed
Output schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name for series results. Use treasury_dataframe_query to run SQL."New value: +"DuckDB table name (df_XXXXX_XXXXX) holding the staged series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged." - added
Output schema / properties / capAdded value: +{ + "description": "The preview cap applied to the inline rates array.", + "type": "number" +} - changed
Output schema / properties / effective_date / descriptionPrevious value: -"Effective date of the rates (same as record_date)."New value: +"Effective date of the as_of_date row (YYYY-MM-DD). Every row carries its own effective_date; this one does not describe the rest." - added
Output schema / properties / mixed_record_datesAdded value: +{ + "description": "True when the retrieved rows were not all published on as_of_date — including rows past the inline preview. Read each row's record_date rather than applying the top-level date to the set.", + "type": "boolean" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when a requested country was not found or returned no records."New value: +"Guidance when a requested country matched no records, when the inline series is a preview, when the series was staged as a DataCanvas table, or when the returned rows were published in more than one quarter." - changed
Output schema / properties / rates / descriptionPrevious value: -"Exchange rates for the requested countries/quarter."New value: +"Exchange rates for the requested countries/quarter, newest first. Whole in mode=latest — a quarter is a bounded set. In mode=series an inline preview of at most 20 rows; compare its length against retrieved_records to detect the cap, and reach the rest through canvas_id when one is returned." - added
Output schema / properties / rates / items / properties / effective_dateAdded value: +{ + "description": "Date this rate takes effect (YYYY-MM-DD). Later than record_date when Treasury amends a rate mid-quarter, in which case the quarter carries more than one row for the country.", + "type": "string" +} - changed
Output schema / properties / rates / items / properties / record_date / descriptionPrevious value: -"Quarter-end record date (YYYY-MM-DD)."New value: +"Quarter-end record date this rate was published under (YYYY-MM-DD)." - changed
Output schema / properties / rates / items / requiredPrevious value: -[ - "country", - "currency", - "country_currency_desc", - "exchange_rate", - "record_date" -]New value: +[ + "country", + "currency", + "country_currency_desc", + "exchange_rate", + "record_date", + "effective_date" +] - added
Output schema / properties / retrieved_recordsAdded value: +{ + "description": "Rows actually fetched for mode=series across every page, and the row count of the canvas table when one was registered. Never larger than total_records.", + "type": "number" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Rate rows returned inline.", + "type": "number" +} - changed
Output schema / properties / total_records / descriptionPrevious value: -"Total records returned."New value: +"In mode=latest, the number of rows in rates. In mode=series, the full upstream match — larger than rates.length whenever the preview cap applied, and larger than retrieved_records when paging stopped first." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the inline rates array holds fewer rows than were retrieved.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "as_of_date", - "effective_date", - "rates", - "total_records", - "note" -]New value: +[ + "as_of_date", + "effective_date", + "mixed_record_dates", + "rates", + "total_records", + "note" +]
- Changed
treasury_get_interest_rates8 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name (df_XXXXX_XXXXX) to register series results into for SQL analysis. When provided, or when mode=series and results exceed 200 rows, the result is registered and canvas_id is returned. Use treasury_dataframe_query to query it. Requires CANVAS_PROVIDER_TYPE=duckdb."New value: +"Set any non-empty value to stage mode=series results as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. Staging also happens on its own when a series matches more than 200 rows. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Requires CANVAS_PROVIDER_TYPE=duckdb." - changed
Output schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas table name for series results. Use treasury_dataframe_query to run SQL."New value: +"DuckDB table name (df_XXXXX_XXXXX) holding the staged series. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged." - added
Output schema / properties / capAdded value: +{ + "description": "The preview cap applied to the inline series array.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no records match — lists valid security types or notes the empty date range."New value: +"Guidance when no records match (lists valid security types, or notes the empty date range), when the inline series is a preview, or when the series was staged as a DataCanvas table." - changed
Output schema / properties / rates / descriptionPrevious value: -"Interest rate records."New value: +"Interest rate records, newest first. Whole in mode=latest — a month is a bounded set. In mode=series an inline preview of at most 20 rows; compare its length against total_records to detect the cap, and reach the rest through canvas_id when one is returned." - added
Output schema / properties / shownAdded value: +{ + "description": "Series rows returned inline.", + "type": "number" +} - changed
Output schema / properties / total_records / descriptionPrevious value: -"Total matching records."New value: +"In mode=latest, the number of rows in rates. In mode=series, the full upstream match — larger than rates.length whenever the preview cap applied." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the inline series array holds fewer rows than were retrieved.", + "type": "boolean" +}
- Changed
treasury_query_dataset4 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas ID to spill results into for SQL analysis. Omit to receive results inline. Requires CANVAS_PROVIDER_TYPE=duckdb on the server. When provided, the full page result is registered as a dataframe and a canvas_id is returned for use with treasury_dataframe_query."New value: +"Set any non-empty value to stage this page as a DataCanvas table for SQL analysis — the value only requests staging; the server picks the table name. The assigned name (df_XXXXX_XXXXX) comes back in the output canvas_id; pass it to treasury_dataframe_describe, then treasury_dataframe_query. Omit to receive results inline only. Requires CANVAS_PROVIDER_TYPE=duckdb on the server." - changed
Input schema / properties / filters / items / properties / value / anyOfPrevious value: -[ - { - "description": "Single filter value. Dates use YYYY-MM-DD format.", - "type": "string" - }, - { - "description": "List of values for \"in\" operator.", - "items": { - "type": "string" - }, - "type": "array" - } -]New value: +[ + { + "description": "Single filter value. Dates use YYYY-MM-DD format.", + "minLength": 1, + "type": "string" + }, + { + "description": "List of values for \"in\" operator.", + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } +] - changed
Output schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas ID where this page is registered. Use with treasury_dataframe_query to run SQL."New value: +"DuckDB table name (df_XXXXX_XXXXX) holding this page. Pass it to treasury_dataframe_describe for the column schema, then use it as the FROM target in treasury_dataframe_query SQL. Absent when nothing was staged." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when results are empty, a field typo is suspected, or the endpoint was not found in the catalog."New value: +"Guidance when results are empty, a field typo is suspected, the endpoint was not found in the catalog, or staging was requested."
2 tool updates
- Changed
treasury_dataframe_query5 fields changed- changed
Input schema / properties / preview / descriptionPrevious value: -"Rows in the immediate response. Defaults to row_limit. Set lower when using register_as."New value: +"Rows in the immediate response. Defaults to row_limit and may not exceed it. Set lower when using register_as." - added
Output schema / properties / capAdded value: +{ + "description": "The row cap that was applied — preview when supplied, otherwise row_limit.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when the query returned no rows, or when results were capped by row_limit."New value: +"Guidance when the query returned no rows, or when results were capped by preview or row_limit." - added
Output schema / properties / shownAdded value: +{ + "description": "Number of rows returned in this response.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the returned rows were capped below the full result set.", + "type": "boolean" +}
- Changed
treasury_get_debt7 fields changed- added
Output schema / properties / capAdded value: +{ + "description": "The preview cap applied to the inline series array.", + "type": "number" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the inline series is a preview, or when paging stopped before the full matched set.", + "type": "string" +} - added
Output schema / properties / retrieved_recordsAdded value: +{ + "description": "Records actually fetched for mode=series across every page, and the row count of the canvas table when one was registered. Never larger than total_records.", + "type": "number" +} - changed
Output schema / properties / series / descriptionPrevious value: -"All records for mode=series (may be truncated when spilled to canvas)."New value: +"Inline preview of the mode=series records — at most 20 rows, newest first. Compare series.length against retrieved_records to detect the cap; the full retrieved set is reachable through canvas_id when one is returned." - added
Output schema / properties / shownAdded value: +{ + "description": "Series rows returned inline.", + "type": "number" +} - changed
Output schema / properties / total_records / descriptionPrevious value: -"Total matching records for mode=series."New value: +"Records matching the date range upstream. Exceeds retrieved_records when the match is larger than the series row bound." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the inline series array holds fewer rows than were retrieved.", + "type": "boolean" +}
1 tool update
- Changed
treasury_query_dataset1 field changed- added
Output schema / properties / totalCountAdded value: +{ + "description": "Total rows matching the query across all pages — discloses that this page is a subset.", + "type": "number" +}
1 tool update
- Changed
treasury_list_datasets1 field changed- changed
Input schema / properties / search / descriptionPrevious value: -"Keyword filter against dataset name and description (case-insensitive substring match). Useful for narrowing 80+ datasets when the category is uncertain."New value: +"Keyword filter against dataset name and description (case-insensitive substring match). Useful for narrowing results when the category is uncertain."
7 tool updates
- First observed
treasury_dataframe_describe - First observed
treasury_dataframe_query - First observed
treasury_get_debt - First observed
treasury_get_exchange_rates - First observed
treasury_get_interest_rates - First observed
treasury_list_datasets - First observed
treasury_query_dataset
Related MCP Connectors
Treasury MCP — US Treasury Fiscal Data public API (free, no auth)
Treasury Fiscal MCP — US Treasury Fiscal Data API
Query U.S. Census Bureau data, variables, and geography via MCP.
USAspending MCP — Federal spending data from USAspending.gov API
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables querying US Treasury Fiscal Data through the Treasury Fiscal Data API, providing access to financial data such as debt, spending, and revenue.4 npmMIT
- AlicenseNot gradedqualityAmaintenanceQuery SEC EDGAR filings, XBRL financials, and company data through MCP.698 npm10Apache 2.0
- FlicenseNot gradedqualityAmaintenanceQuery normalized U.S. House and Senate STOCK Act disclosures, member trading histories, and aggregate trading statistics through MCP.-
- AlicenseNot gradedqualityDmaintenanceEnables querying U.S. Treasury fiscal data including debt, interest rates, auctions, and more via natural language, with no API key required.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.