Skip to main content
Glama
agilesix
by agilesix
search-new-awards.ts4.5 kB
/** * Search New Awards Tool * Search for newly awarded contracts by their action date */ import { z } from 'zod'; import type { USASpendingClient } from '../clients/usaspending'; import { buildAwardFilters } from '../builders/filter-builder'; import { TRANSACTION_FIELDS, transformTransactionResult } from '../builders/field-mapper'; export interface SearchNewAwardsParams { awardStartDate: string; awardEndDate?: string; keywords?: string[]; recipientName?: string; agencyName?: string; naicsCodes?: string[]; pscCodes?: string[]; minAmount?: number; maxAmount?: number; awardTypeCodes?: string[]; limit?: number; } export function registerSearchNewAwardsTool(server: any, client: USASpendingClient) { server.tool( "search_new_awards", "Search for newly awarded contracts by their award date (Action Date). Returns only BASE awards (Modification Number = 0), not modifications to existing awards. Use this when you need to find contracts that were actually signed/awarded during a specific date range (e.g., 'awards signed yesterday', 'new contracts this week').", { awardStartDate: z.string().describe("Start date in YYYY-MM-DD format - the earliest award signing date to include. This is when the contract was actually signed/executed."), awardEndDate: z.string().optional().describe("End date in YYYY-MM-DD format for award signing dates. Defaults to awardStartDate if not provided (single day search)."), keywords: z.array(z.string()).optional().describe("Keywords to search in award descriptions (e.g., ['digital services', 'software development', 'agile'])"), recipientName: z.string().optional().describe("Contractor/recipient name to search for (e.g., 'Agile Six', 'Oddball', 'GDIT')"), agencyName: z.string().optional().describe("Awarding agency name (e.g., 'Department of Veterans Affairs', 'VA')"), naicsCodes: z.array(z.string()).optional().describe("NAICS codes to filter by (e.g., ['541511'] for Custom Computer Programming, ['541512'] for Computer Systems Design)"), pscCodes: z.array(z.string()).optional().describe("Product Service Codes to filter by (e.g., ['D307'] for IT/Telecom, ['D302'] for Systems Development)"), minAmount: z.number().optional().describe("Minimum award amount in dollars"), maxAmount: z.number().optional().describe("Maximum award amount in dollars"), awardTypeCodes: z.array(z.string()).optional().describe("Award type codes: A=BPA Call, B=Purchase Order, C=Delivery Order, D=Definitive Contract. Default is contracts only ['A','B','C','D']"), limit: z.number().min(1).max(100).optional().describe("Number of results to return (max 100, default 10)"), }, async (params: SearchNewAwardsParams) => { try { const endDate = params.awardEndDate || params.awardStartDate; // Build filters using centralized filter builder const filters = buildAwardFilters({ keywords: params.keywords, recipientName: params.recipientName, agencyName: params.agencyName, naicsCodes: params.naicsCodes, pscCodes: params.pscCodes, activityStartDate: params.awardStartDate, activityEndDate: endDate, minAmount: params.minAmount, maxAmount: params.maxAmount, awardTypeCodes: params.awardTypeCodes, }); // Use transaction endpoint to search by action date const searchParams: any = { filters, fields: TRANSACTION_FIELDS, limit: params.limit || 10, page: 1, sort: "Transaction Amount", order: "desc" as const, }; const result = await client.searchTransactions(searchParams); // Filter for base awards only (Modification Number = "0") const newAwardsOnly = result.results?.filter((tx: any) => { const modNum = String(tx["Modification Number"] || "").trim(); return modNum === "0" || modNum === ""; }) || []; const summary = `Found ${newAwardsOnly.length} new awards signed between ${params.awardStartDate} and ${endDate} (filtered from ${result.results?.length || 0} total transactions)`; return { content: [ { type: "text", text: JSON.stringify( { summary, total: newAwardsOnly.length, awards: newAwardsOnly.map(transformTransactionResult), }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } } ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/agilesix/usaspending-mcp-nextjs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server