treasury-fiscaldata-mcp-server

v0.1.10 pre-1.0

Query US Treasury national debt, interest rates, exchange rates, and fiscal datasets via MCP.

treasury-fiscaldata.caseyjhand.com/mcp
claude mcp add --transport http treasury-fiscaldata-mcp-server https://treasury-fiscaldata.caseyjhand.com/mcp
codex mcp add treasury-fiscaldata-mcp-server --url https://treasury-fiscaldata.caseyjhand.com/mcp
{
  "mcpServers": {
    "treasury-fiscaldata-mcp-server": {
      "url": "https://treasury-fiscaldata.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http treasury-fiscaldata-mcp-server https://treasury-fiscaldata.caseyjhand.com/mcp
{
  "mcpServers": {
    "treasury-fiscaldata-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://treasury-fiscaldata.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "treasury-fiscaldata-mcp-server": {
      "type": "http",
      "url": "https://treasury-fiscaldata.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://treasury-fiscaldata.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

treasury_list_datasets

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_list_datasets",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "category": {
      "description": "Filter by category. Omit to list all datasets. Options: debt, interest_rates, exchange_rates, revenue_spending, savings_bonds, securities, other.",
      "type": "string",
      "enum": [
        "debt",
        "interest_rates",
        "exchange_rates",
        "revenue_spending",
        "savings_bonds",
        "securities",
        "other"
      ]
    },
    "search": {
      "description": "Keyword filter against dataset name and description (case-insensitive substring match). Useful for narrowing results when the category is uncertain.",
      "type": "string"
    }
  },
  "additionalProperties": false
}
view source ↗

treasury_query_dataset

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).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_query_dataset",
    "arguments": {
      "endpoint": "<endpoint>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "endpoint": {
      "type": "string",
      "description": "Endpoint path returned by treasury_list_datasets (e.g., \"/v2/accounting/od/debt_to_penny\"). Include the leading slash."
    },
    "fields": {
      "description": "Fields to return. Omit to return all fields. Specify field names exactly as listed by treasury_list_datasets — a typo causes a 400.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "filters": {
      "description": "Filter conditions (ANDed together). Multiple filters on different fields are combined in one filter= parameter.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "Field name to filter on."
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "gt",
              "gte",
              "lt",
              "lte",
              "in"
            ],
            "description": "Comparison operator. \"in\" matches any value in the provided list."
          },
          "value": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "description": "Single filter value. Dates use YYYY-MM-DD format."
              },
              {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "List of values for \"in\" operator."
              }
            ],
            "description": "Filter value. For \"in\", pass an array of strings. Dates use YYYY-MM-DD format."
          }
        },
        "required": [
          "field",
          "operator",
          "value"
        ],
        "additionalProperties": false,
        "description": "One filter condition."
      }
    },
    "sort": {
      "description": "Sort expression: field name optionally prefixed with \"-\" for descending (e.g., \"-record_date\" for newest-first).",
      "type": "string"
    },
    "page_size": {
      "default": 100,
      "description": "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.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "page_number": {
      "default": 1,
      "description": "Page to fetch (1-indexed). Check total_pages in the response to know if more pages exist.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "canvas_id": {
      "description": "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.",
      "type": "string"
    }
  },
  "required": [
    "endpoint",
    "page_size",
    "page_number"
  ],
  "additionalProperties": false
}
view source ↗

treasury_get_debt

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_get_debt",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "latest",
      "description": "\"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.",
      "type": "string",
      "enum": [
        "latest",
        "date",
        "series"
      ]
    },
    "date": {
      "description": "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.",
      "type": "string"
    },
    "start_date": {
      "description": "ISO 8601 start date for mode=series (inclusive). Fiscal Data has daily debt records back to 1993-04-01.",
      "type": "string"
    },
    "end_date": {
      "description": "ISO 8601 end date for mode=series (inclusive). Defaults to today.",
      "type": "string"
    },
    "canvas_id": {
      "description": "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.",
      "type": "string"
    }
  },
  "required": [
    "mode"
  ],
  "additionalProperties": false
}
view source ↗

treasury_get_interest_rates

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_get_interest_rates",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "latest",
      "description": "\"latest\" returns the most recent month's rates. \"series\" returns a time range.",
      "type": "string",
      "enum": [
        "latest",
        "series"
      ]
    },
    "security_type": {
      "description": "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.",
      "type": "string"
    },
    "start_date": {
      "description": "ISO 8601 start date for mode=series (YYYY-MM-DD, must be end-of-month for meaningful results).",
      "type": "string"
    },
    "end_date": {
      "description": "ISO 8601 end date for mode=series. Defaults to today.",
      "type": "string"
    },
    "canvas_id": {
      "description": "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.",
      "type": "string"
    }
  },
  "required": [
    "mode"
  ],
  "additionalProperties": false
}
view source ↗

treasury_get_exchange_rates

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_get_exchange_rates",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "latest",
      "description": "\"latest\" returns the most recently published quarter's rates. \"series\" returns a date range of quarterly reports.",
      "type": "string",
      "enum": [
        "latest",
        "series"
      ]
    },
    "countries": {
      "description": "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).",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "start_date": {
      "description": "ISO 8601 start date for mode=series. Rates are published end-of-quarter (March 31, June 30, Sep 30, Dec 31).",
      "type": "string"
    },
    "end_date": {
      "description": "ISO 8601 end date for mode=series.",
      "type": "string"
    },
    "canvas_id": {
      "description": "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.",
      "type": "string"
    }
  },
  "required": [
    "mode"
  ],
  "additionalProperties": false
}
view source ↗

treasury_dataframe_describe

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_dataframe_describe",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "description": "Optional dataframe table name (df_XXXXX_XXXXX) to describe a single dataframe. Omit to list all active dataframes.",
      "type": "string"
    }
  },
  "additionalProperties": false
}
view source ↗

treasury_dataframe_query

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "treasury_dataframe_query",
    "arguments": {
      "sql": "<sql>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "sql": {
      "type": "string",
      "minLength": 1,
      "description": "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."
    },
    "register_as": {
      "description": "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.",
      "type": "string"
    },
    "preview": {
      "description": "Rows in the immediate response. Defaults to row_limit and may not exceed it. Set lower when using register_as.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000
    },
    "row_limit": {
      "default": 1000,
      "description": "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.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    }
  },
  "required": [
    "sql",
    "row_limit"
  ],
  "additionalProperties": false
}
view source ↗