Query US Treasury national debt, interest rates, exchange rates, and fiscal datasets via MCP.
Query US Treasury national debt, interest rates, exchange rates, and fiscal datasets via MCP.
Public Hosted Server: https://treasury-fiscaldata.caseyjhand.com/mcp
US Treasury Fiscal Data — national debt, interest rates, exchange rates, and other fiscal datasets. Browse a curated catalog of 17 endpoints, query any endpoint directly, or stage large pulls as DuckDB dataframes for SQL analysis, from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
treasury_list_datasets | Browse the curated catalog of 17 Treasury Fiscal Data endpoints with field names, descriptions, and update cadence |
treasury_query_dataset | Query any Treasury Fiscal Data endpoint by path, field list, filters, sort, and page — with optional DataCanvas spill |
treasury_get_debt | Fetch national debt (Debt to the Penny) — latest record, specific date, or date-range series with optional DataCanvas spill |
treasury_get_interest_rates | Average interest rates Treasury pays on outstanding securities by type — marketable issues, non-marketable series, and aggregate totals |
treasury_get_exchange_rates | Official Treasury statutory exchange rates for ~165 countries, published quarterly |
treasury_dataframe_describe | List DataCanvas dataframes materialized by the treasury_* tools with schema, row count, and TTL |
treasury_dataframe_query | Run a single-statement SELECT against DataCanvas dataframes using standard DuckDB SQL |
treasury_list_datasets tooldebt, interest_rates, exchange_rates, revenue_spending, savings_bonds, securities, otherbun run verify:catalog, so a dataset Treasury moves or renames fails a gate rather than reaching a callertreasury_query_dataset tool{ field, operator, value } with operator eq, gt, gte, lt, lte, in; multiple filters ANDed togetherpage_size (1–10000, default 100) and page_number; sort any field, descending with a - prefix"null" means no valueinvalid_endpoint, invalid_field, invalid_filter, page_out_of_rangecanvas_id stages the page as a DataCanvas table (df_XXXXX_XXXXX) — read its schema with treasury_dataframe_describe, then SQL it with treasury_dataframe_query (requires CANVAS_PROVIDER_TYPE=duckdb)treasury_get_debt toolmode=latest — most recent business-day record; mode=date — a specific business day (YYYY-MM-DD; the API only records debt on market-open days); mode=series — a date range, newest-firstmode=series auto-stages to a DataCanvas table when the range exceeds 500 rows, or on request via canvas_id; paging stops at 50,000 rows, with the response naming how many of the match were retrievedcanvas_idno_data_for_date error when no record exists for a requested datetreasury_get_interest_rates toolmode=latest — most recent month's rates for all or one security type; mode=series — a time-range historysecurity_type filter that matches nothing gets back the types the most recent month actually holds"3.696"), not basis pointsmode=series auto-stages to DataCanvas when results exceed 200 rows, or on request via canvas_id; inline series preview is capped at 20 rows, newest firsttreasury_get_exchange_rates toolmode=latest collapses to one row per currency — newest record_date, then newest effective_date — so an amendment supersedes the rate it replaced and a country with two legal tenders keeps both; mixed_record_dates flags a result whose rows span more than one quartermode=series auto-stages to DataCanvas when results exceed 500 rows; full published history is ~19,000 rows back to 2001-03-31, well within the 50,000-row paging capcountry_not_found error when a requested country has no recordstreasury_dataframe_describe toolCANVAS_PROVIDER_TYPE=duckdb; canvas_unavailable error otherwisetruncated / max_rows flag when the source pull was capped before full materializationCANVAS_TTL_MStreasury_dataframe_query toolinformation_schema, pg_catalog, sqlite_master, duckdb_*) are deniedDECIMAL or DATE for arithmetic and date comparisonsrow_limit caps rows produced (default 1000, max 10000); preview bounds the inline response and may not exceed row_limitregister_as persists the result as a new dataframe with a fresh TTL, for chained multi-step analysiscanvas_unavailable, system_catalog_access, invalid_sql, missing_table, invalid_query_boundsBuilt on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Fiscal Data-specific:
treasury_query_dataset for datasets outside the catalogdf_<id> dataframes queryable via DuckDB SQL, with automatic staging thresholds per toolAgent-friendly output:
applied_filters) and field-label maps (field_labels) let agents verify what was sent and read raw field namestruncated / retrieved_records / row_count_capped fields instead of silently dropping rowstreasury_dataframe_describeA public instance is available at https://treasury-fiscaldata.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"treasury-fiscaldata-mcp-server": {
"type": "streamable-http",
"url": "https://treasury-fiscaldata.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"treasury-fiscaldata-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/treasury-fiscaldata-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"treasury-fiscaldata-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/treasury-fiscaldata-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"treasury-fiscaldata-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/treasury-fiscaldata-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
For large time-series pulls or multi-dataset analysis, use the DataCanvas SQL workflow:
CANVAS_PROVIDER_TYPE=duckdb in your server environment.canvas_id — e.g., treasury_get_debt with mode=series and a canvas_id value, or treasury_query_dataset with canvas_id. The tool registers the results as a df_XXXXX_XXXXX dataframe and returns the table name.treasury_dataframe_describe — lists column names, types (all VARCHAR for Treasury data), row count, and TTL.treasury_dataframe_query — standard DuckDB SELECT with joins, aggregates, window functions, and CTEs. CAST VARCHAR columns to DECIMAL or DATE for arithmetic.-- Example: debt trend over the last year, month-end records only
SELECT
record_date,
CAST(tot_pub_debt_out_amt AS DECIMAL) / 1e12 AS total_debt_trillions
FROM df_xxxxx
WHERE CAST(record_date AS DATE) >= CURRENT_DATE - INTERVAL 1 YEAR
ORDER BY record_date DESC
CANVAS_PROVIDER_TYPE=duckdb (DuckDB is bundled as @duckdb/node-api).git clone https://github.com/cyanheads/treasury-fiscaldata-mcp-server.git
cd treasury-fiscaldata-mcp-server
bun install
cp .env.example .env
# edit .env as needed — no required vars; CANVAS_PROVIDER_TYPE=duckdb to enable SQL
| Variable | Description | Default |
|---|---|---|
CANVAS_PROVIDER_TYPE | Canvas engine. Unset resolves to none, and the treasury_dataframe_* tools then reject every call — set it to duckdb to enable DataCanvas SQL. | none |
CANVAS_TTL_MS | Per-table TTL for DataCanvas dataframes in milliseconds. | 86400000 (24h) |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_SESSION_MODE | HTTP session handling: auto, stateful, or stateless. Setting it overrides the server's own declaration; leaving it unset falls through to that declaration, not to the schema default. | stateless (declared in src/index.ts) |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, notice, warning, error). | info |
LOGS_DIR | Directory for log files (Node.js/Bun only). | <project-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry spans and metrics. | false |
See .env.example for the full list of optional overrides.
Build and run:
bun run rebuild
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
bun run verify:catalog # Probe every catalog endpoint and field against the live API
verify:catalog is the one check that needs the network, which is why it is separate from devcheck and the test suite. Run it after editing src/services/fiscal-data/datasets.ts and before a release.
docker build -t treasury-fiscaldata-mcp-server .
docker run --rm -e CANVAS_PROVIDER_TYPE=duckdb -p 3010:3010 treasury-fiscaldata-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/treasury-fiscaldata-mcp-server. DuckDB native modules are pre-built in the build stage and copied to the production stage — no extra build tools required at runtime. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and inits services. |
src/config/ | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools/definitions/ | Tool definitions (*.tool.ts) — 5 data tools + 2 DataCanvas tools. |
src/services/fiscal-data/ | Treasury Fiscal Data API client, embedded endpoint catalog, and types. |
src/services/canvas-bridge/ | Adapter over the framework DataCanvas: df_<id> minting, per-table TTL, system-catalog SQL deny. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md and AGENTS.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @cyanheads/treasury-fiscaldata-mcp-serverMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cyanheads-treasury-fiscaldata-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/treasury-fiscaldata-mcp-server"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cyanheads/treasury-fiscaldata-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.