usaspending-mcp-server
Health Uyari
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Access US federal award, recipient, agency, and spending analytics data from USAspending.gov via MCP. STDIO or Streamable HTTP.
@cyanheads/usaspending-mcp-server
Access US federal award, recipient, agency, and spending analytics data from USAspending.gov via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://usaspending.caseyjhand.com/mcp
Overview
Where federal money goes, from USAspending.gov: awards, recipients, agencies, and spending. Search and trace awards down to transactions, subawards, and funding accounts; profile recipients and agencies; and aggregate spending by geography, category, time, and disaster appropriation.
Tools
| Tool | Description |
|---|---|
usaspending_list_agencies |
List every top-tier federal agency with its toptier code, slug, and current-year budget totals |
usaspending_autocomplete_filters |
Look up NAICS, PSC, CFDA, agency, or recipient codes from a free-text description |
usaspending_search_awards |
Search awards by keyword, recipient, agency, award type, NAICS code, assistance listing, PSC, DEF code, location, or date range |
usaspending_get_award |
Fetch one award's full record: amounts, recipient, agencies, codes, parent IDV, DEF-code funding |
usaspending_get_award_transactions |
List the transactions (modifications, amendments) on an award |
usaspending_get_award_subawards |
List the subcontracts or subgrants under a prime award |
usaspending_get_award_federal_accounts |
List the Treasury federal accounts that funded an award, with the amount from each |
usaspending_get_idv_awards |
List the child orders and sub-IDVs placed under an IDV |
usaspending_search_recipients |
Search recipients by name, UEI, or DUNS |
usaspending_get_recipient |
Fetch a recipient's profile: address, business types, parent, and award totals |
usaspending_get_agency |
Fetch an agency's mission, latest-year budget totals, sub-agencies, and DEF codes |
usaspending_spending_by_geography |
Aggregate spending by state, county, or congressional district |
usaspending_spending_by_category |
Aggregate spending by NAICS, PSC, agency, CFDA program, or recipient |
usaspending_spending_over_time |
Aggregate spending by fiscal year, quarter, or month |
usaspending_disaster_spending |
Break down disaster and emergency supplemental spending by agency, program, recipient, or geography |
usaspending_search_federal_accounts |
Search federal accounts by title keyword or agency identifier |
usaspending_get_federal_account |
Fetch a federal account's budget totals and its Treasury Account Symbol components |
usaspending_get_federal_account_breakdown |
Break a federal account's obligations down by program activity or object class |
Capability reference
usaspending_list_agencies tool
- Takes only
sort(agency_name,budget_authority_amount,obligated_amount,outlay_amount) andorder; returns every agency in one unpaginated response - Rows carry
toptier_codeandagency_slug, both accepted byusaspending_get_agency, plus current-yearbudget_authority_amount,obligated_amount, andoutlay_amount
usaspending_autocomplete_filters tool
type(naics,psc,cfda,awarding_agency,recipient) plussearch_text;limit1–500, default 10- Rows carry
codeandname, anduei/dunsfor recipients; no match fails asno_match. Acfdacode goes inassistance_listingsand apsccode inpsc_codesonusaspending_search_awardsand the three spending analytics tools - Agency rows carry the matched agency's own
name,abbreviation, andtier(toptierorsubtier), plus its parent'stoptier_nameandtoptier_code. Theagency_namefilters are top-tier only and taketoptier_name, so a sub-agency such as the U.S. Geological Survey filters at its whole department naicsmatches official NAICS title text: "software" resolves, "cybersecurity" does not, so search with the industry term a title would use
usaspending_search_awards tool
- Filters:
keyword,agency_name,recipient_name,naics_codes,assistance_listings(Assistance Listing numbers such as93.866, fromusaspending_autocomplete_filterstype: cfda),psc_codes(1–4 characters, where a prefix such asY1covers the codes under it; contracts and IDVs only),def_codes(Disaster Emergency Fund Codes such asZ; PSC and DEF codes are sent uppercased),time_period(YYYY-MM-DDfrom 2007-10-01 on; either end may be given alone), andlocation_filter(countrydefaults toUSA, and a territory code such asPRIbecomesUSAplus its state;stateas a postal or 2-digit FIPS code,FM/MH/PW/UMand armed-forcesAA/AE/APincluded, or under another country as that country's own 2-letter subdivision code such asONwithCAN;countyas 3 digits withstateor the 5-digit FIPS code alone; echoed asapplied_location);award_type_codesdefaults to contracts (A–D) and must stay in one group: IDVsIDV_A–IDV_E, grants02–05/F001/F002, direct payments06/10/F006/F007, loans07/08/F003/F004, or other assistance09/11/-1/F005/F008/F009/F010;limitup to 100 - Rows carry
generated_internal_idforusaspending_get_awardandagency_slugforusaspending_get_agency; loan rows carryloan_value,subsidy_cost, andissued_datein place of amounts and dates. There is no total, andpage_metadata.has_nextis true on any full page. The nestedfiltersobject takes the analytics tools'filterskeys, exceptrecipient_id, and wins per field over the flat ones. Failures areassistance_listings_type_mismatch(listings with a non-assistance group),psc_codes_type_mismatch(PSC codes with an assistance group),unsupported_sort,date_range_inverted,date_before_earliest, andinvalid_location(an unknown state, a 3-digit county without a state, a county under an armed-forces code (AA/AE/AP), a county or FIPS-number state under another country, or parts naming different states) sortdepends on the group: loans takeLoan Value(default),Subsidy Cost,Issued Date,Recipient Name, orAwarding Agency; the othersAward Amount(default),Total Outlays,Start Date,End Date(not IDVs),Recipient Name, orAwarding Agency. Page numbers stop at a 50,000-result offset (pagination_limit_exceeded); past it, page with thelast_record_sort_value+last_record_unique_idcursor, returned below a 10,000-result offset
usaspending_get_award tool
award_idis agenerated_unique_award_id, thegenerated_internal_idfrom search; an unknown ID fails asaward_not_found- Returns
category,total_obligation,total_outlays,subaward_count, NAICS / PSC codes,account_obligations_by_defc, and, on loans,total_loan_valueandtotal_subsidy_cost assistance_listingslists every Assistance Listing on an assistance award, in upstream order, asnumber,title, andobligation; anumbergoes inusaspending_search_awardsassistance_listingsrecipientcarriesuei,parent_uei,business_categories(category names, not thebusiness_typescodes ofusaspending_get_recipient), and a three-lettercountry_codeon itslocation, as doesplace_of_performance; a location with no fields upstream is omittedrecipient.recipient_idandrecipient.parent_recipient_idchain tousaspending_get_recipientandparent_award.generated_unique_award_idto the parent IDV;category: "idv"awards list their children viausaspending_get_idv_awards
usaspending_get_award_transactions tool
award_idplussort(action_date,federal_action_obligation,modification_number);limitup to 100- Rows carry
action_date,modification_number,action_type, and a signedfederal_action_obligation(negative is a deobligation)
usaspending_get_award_subawards tool
award_idplussort(subaward_number,description,action_date,amount,recipient_name);limitup to 100- Rows carry
subaward_number,amount,action_date,recipient_name,recipient_uei, and place of performance;subaward_countonusaspending_get_awardsays whether any exist
usaspending_get_award_federal_accounts tool
award_idis agenerated_unique_award_id;limitup to 100, withpage_metadata.countas the total- Rows carry
federal_account(AGENCY-MAIN, e.g.080-0120) forusaspending_get_federal_account,total_transaction_obligated_amount, and the funding agency with itsfunding_agency_slug
usaspending_get_idv_awards tool
- Parent IDV
award_id;typeischild_awards(task and delivery orders, the default),child_idvs, orgrandchild_awards;limitup to 100 - Rows carry
generated_unique_award_idforusaspending_get_award,obligated_amount, and performance dates; there is no total, andhas_nextis true on any full page
usaspending_search_recipients tool
keywordmatches names, UEI, or DUNS, partial matches included; surrounding whitespace is trimmed, and blank text applies no keyword filter with a notice. Optionalaward_typestill scopes the totals;limitup to 100- Rows carry
id(a hash suffixed-Pparent,-Cchild, or-Rstandalone) forusaspending_get_recipient, plusuei,duns,recipient_level, andamount;page_metadata.totalis the full match count
usaspending_get_recipient tool
recipient_idfromusaspending_search_recipientsorusaspending_get_award; optionalfiscal_year(2001–2030) scopes the totals to that fiscal year, which otherwise cover the trailing 12 months; an unknown ID fails asrecipient_not_found- Returns address,
business_types,parent_name/parent_uei,alternate_names,total_transaction_amount,total_transactions, and loan face-value totals, withperiodnaming the window (FY2020ortrailing 12 months). Totals span every award type; for totals by type, useusaspending_spending_over_timewithfilters.recipient_idandaward_type_codes
usaspending_get_agency tool
- One of
toptier_code(e.g.097) oragency_slug(e.g.department-of-defense);pagewalks the sub-agency list 10 at a time. Failures aremissing_input,conflicting_input(both identifiers sent), andagency_not_found - Returns
mission, plusbudgetary_resources_amount,obligated_amount, andoutlay_amountfor the most recentfiscal_yearwith reported budget data (a newly opened year with no amounts yet is skipped),sub_agencieswith obligations and transaction and new-award counts for that same year (sub_agency_fiscal_yearnames it; without a budget year within 5 seconds the breakdown covers the current fiscal year), anddef_codes - A failed budget or sub-agency request still returns the overview: the missing fields are omitted and
unavailable_sectionsnames each section with itsreason(api_unavailable,api_timeout, orupstream_error) and whether a retry may load it
usaspending_spending_by_geography tool
scope(place_of_performance,recipient_location) andgeo_layer(state,county,district) are required;filterstakeskeywords,award_type_codes,agency_name,recipient_id,naics_codes,assistance_listings,psc_codes,def_codes(the same code filters asusaspending_search_awards, echoed asapplied_*), andtime_period_start/time_period_end(YYYY-MM-DD; either alone fills the other, as inusaspending_search_awards,applied_time_period_*echoes the range sent, a start after the end fails asdate_range_inverted, and a range starting before 2007-10-01 fails asdate_before_earliest);limit1–500, default 50- Award types may mix groups. When every one named is a contract or IDV,
assistance_listingsfails asassistance_listings_type_mismatch; when every one is assistance,psc_codesfails aspsc_codes_type_mismatch. Code-filtered amounts cover whole matching awards, and DEF-filtered totals can be negative - Rows carry
shape_code,display_name,aggregated_amount,population, andper_capita, ranked by amount;total_areas_availablecounts every match before the cap shape_codes(1–500) returns only the listed areas, in theshape_codeform of the layer: postal code forstate(NY), 5-digit state + county FIPS forcounty(36117), 4-digit state FIPS + district fordistrict(3623). Selection runs over every matched area, so it reaches areas ranked pastlimit; the codes are echoed asapplied_shape_codes, and a code that matches no area is named in thenotice- With no filters, every award type is aggregated and
applied_award_type_defaultsays so;subawards: trueswitches to subaward data
usaspending_spending_by_category tool
categoryisnaics,psc,awarding_agency,awarding_subagency,funding_agency,funding_subagency,cfda, orrecipient_duns; takes the samefiltersobject asusaspending_spending_by_geography;limitup to 100- Rows carry
id,code,name, andamount, ranked by obligation;recipient_dunsrows carry the DUNS ascodeplusrecipient_idandueiwhen upstream has them, andrecipient_idchains tousaspending_get_recipient
usaspending_spending_over_time tool
groupisfiscal_year,quarter, ormonth(fiscal month, where 1 is October); the samefiltersobject, withaward_type_codesdefaulting to contracts, soassistance_listingsneeds an assistance group named;subawards: trueswitches to subaward data- Rows carry
time_period,aggregated_amount, and per-typecontracts,grants,direct_payments,idvs,loans, andother
usaspending_disaster_spending tool
dimensionisoverview,agency,cfda,recipient, orgeography;filters.def_codesis optional foroverviewand required for every other dimension (missing_def_codeswhen absent/empty). Codes such as["L", "M", "N", "O", "P"]isolate COVID-19 funding and are echoed asapplied_def_codes.limitis up to 100 on every dimension butoverview;spending_type(award, the default, ortotal) applies to agency only, and geography takesfilters.geo_layer(state,county)- Rows carry
obligation,outlay, andaward_count, plustotal_budgetary_resourceson agency rows underspending_type: total;overviewreturns totals andfunding_by_def_code. A recipient row'sidchains tousaspending_get_recipient. Recipientfilters.querynarrows by search text; it is trimmed and echoed asapplied_query, with blanks applying no query. A recipient total of 10,000 is a reachable ceiling and a lower bound on possible matches, flaggedtruncated; narrow withfilters.queryto reach the tail. Geography areas are ranked byaggregated_amountand paged withlimitandpage, with the full area count astotal; a page with areas below it is flaggedtruncated, andtruncationCeilingis the lowest amount shown. Spending with no recorded place of performance ranks as one unattributed area - Agency, cfda, and recipient also return
totalsacross every matching row:obligation,outlay, and eithertotal_budgetary_resources(agency,total) oraward_count. Overview can still time out with codes supplied: narrowfilters.def_codes, retry later, or use the agency breakdown withspending_type: totalfor obligations, outlays, and budgetary resources - Notices preserve upstream messages, ignored filters, cap guidance, and empty-page recovery on both output surfaces.
queryis ignored outside recipient,geo_layeroutside geography, andaward_type_codeson overview. An empty page whose offset reaches a positive total directs callers to an earlier page with the same filters; an empty interior page reports the total without claiming exhaustion, and an absent total stays unknown
usaspending_search_federal_accounts tool
- Optional
keywordand 3-digitagency_identifier;sort_fieldisaccount_name,account_number,budgetary_resources(default), ormanaging_agency;limitup to 100 - Rows carry
account_number(e.g.097-8097) for the federal-account tools,managing_agency, andbudgetary_resources;page_metadata.countis the total
usaspending_get_federal_account tool
account_codein AGENCY-MAIN format, fromaccount_numberin search results orfederal_accounton an award; an unknown code fails asaccount_not_found- Returns
total_obligated_amount,total_gross_outlay_amount, andtotal_budgetary_resourcesforfiscal_year, pluschildren: one entry per Treasury Account Symbol with its own amounts
usaspending_get_federal_account_breakdown tool
account_codeplusdimension(program_activityorobject_class);limitup to 100, withpage_metadata.totalas the row count- Rows carry
code,name, andobligations;program_activityrows addtype, eitherPAC/PANorPARK
Features
Built 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.
USAspending-specific:
- USAspending.gov API v2, keyless: the data is public under the DATA Act
- Award search and the spending analytics tools cover action dates from 2007-10-01 on (an earlier start date fails as
date_before_earliest), and DoD contract data lags publication by 90 days usaspending_spending_by_categoryputs eight category sub-routes behind onecategoryenum, andusaspending_disaster_spendingputs five disaster endpoints behinddimension- Each request runs under one wall-clock budget (45 s by default); a slow answer gets the whole budget in one attempt, and only fast failures are retried. Failures surface as
api_timeoutorapi_unavailablewith each tool's recovery hint, and a rejected request carries USAspending's own explanation in the error message
Agent-friendly output:
- Chaining IDs as explicit fields:
generated_internal_id,agency_slug,recipient.recipient_id,federal_account, andaccount_number, so agents follow the money without parsing display strings - Honest pagination:
page_metadata.has_nexton every list, atotalorcountwhere the upstream publishes one, andtruncated/shown/caponly when rows are known to exist beyond those returned. A full page with no such evidence keepshas_nextwithout claiming truncation - Empty results are notices, not errors: account funding, account breakdown, and recipient search distinguish a known zero total from an empty page past the total, which directs callers to an earlier page with the same filters. Without a total, notices describe only the page; award search never supplies a total. The ID-keyed list tools (transactions, subawards, funding accounts, IDV children, account breakdown) return an empty list for an unknown ID rather than failing
- Typed failures with recovery hints:
award_not_found,recipient_not_found,agency_not_found,account_not_found,no_match,conflicting_input,date_before_earliest,date_range_inverted,unsupported_sort,assistance_listings_type_mismatch,psc_codes_type_mismatch,invalid_location,pagination_limit_exceeded,incomplete_cursor,missing_def_codes
Getting started
Public Hosted Instance
A public instance is available at https://usaspending.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"usaspending-mcp-server": {
"type": "streamable-http",
"url": "https://usaspending.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add the following to your MCP client configuration file. No API key is required.
{
"mcpServers": {
"usaspending-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/usaspending-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"usaspending-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/usaspending-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"usaspending-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/usaspending-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
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No API key or account: USAspending.gov is open to anonymous requests.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/usaspending-mcp-server.git
- Navigate into the directory:
cd usaspending-mcp-server
- Install dependencies:
bun install
- Configure environment (optional):
cp .env.example .env
# edit .env if you need to override defaults
Configuration
No variable is required; the defaults work out of the box.
| Variable | Description | Default |
|---|---|---|
USASPENDING_BASE_URL |
USAspending.gov API v2 base URL. | https://api.usaspending.gov/api/v2/ |
USASPENDING_TIMEOUT_MS |
Per-attempt HTTP timeout, in ms (1000–120000). Each attempt is cut at this or at the time left in the request budget, whichever is smaller; a timed-out attempt is not retried. | 45000 |
USASPENDING_RETRY_BUDGET_MS |
Wall-clock budget for one request, every attempt and backoff included, in ms (1000–300000). Fast failures such as a 503 retry inside it. | 45000, or USASPENDING_TIMEOUT_MS when higher |
MCP_TRANSPORT_TYPE |
Transport: stdio or http. |
stdio |
MCP_HTTP_PORT |
HTTP server port. | 3010 |
MCP_SESSION_MODE |
HTTP session mode: stateless, stateful, or auto. |
stateless |
MCP_AUTH_MODE |
Authentication: none, jwt, or oauth. |
none |
MCP_LOG_LEVEL |
Log level (debug, info, warning, error, etc.). |
info |
LOG_TOOL_FAILURE_PAYLOADS |
Log each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted. |
false |
LOGS_DIR |
Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE |
Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. |
in-memory |
OTEL_ENABLED |
Enable OpenTelemetry. | false |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT |
Opt-in OTLP log export endpoint; the base OTEL_EXPORTER_OTLP_ENDPOINT never enables it. |
— |
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun 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
Docker
docker build -t usaspending-mcp-server .
docker run --rm -p 3010:3010 usaspending-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/usaspending-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts |
createApp() entry point: registers the tools and initializes the USAspending service. |
src/config |
Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools/definitions |
Tool definitions (*.tool.ts) plus shared filter, date, pagination, and formatting helpers. |
src/services/usaspending |
USAspending.gov API client: request timeouts, retry budget, raw response types. |
tests/ |
Unit tests for tools, the service, config, and scripts. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools via the barrel in
src/mcp-server/tools/definitions/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi