fred_search
Search FRED economic data by keywords, tags, or filters to find matching series with IDs, titles, and metadata.
Instructions
Search for FRED economic data series by keywords, tags, or filters. Returns matching series with their IDs, titles, and metadata. Use this to find specific series when you know what you're looking for.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| search_text | No | Text to search for in series titles and descriptions | |
| search_type | No | Type of search to perform | |
| tag_names | No | Comma-separated list of tag names to filter by | |
| exclude_tag_names | No | Comma-separated list of tag names to exclude | |
| limit | No | Maximum number of results to return | |
| offset | No | Number of results to skip for pagination | |
| order_by | No | Field to order results by | |
| sort_order | No | Sort order for results | |
| filter_variable | No | Variable to filter by | |
| filter_value | No | Value to filter the variable by |
Implementation Reference
- src/fred/search.ts:66-116 (handler)The main handler function `searchSeries` that executes the FRED search logic. Calls the FRED API 'series/search' endpoint, maps options to query parameters, formats results, and returns MCP content.
export async function searchSeries(options: FREDSearchOptions = {}) { try { const queryParams: Record<string, string | number> = {}; // Add search parameters if (options.search_text) queryParams.search_text = options.search_text; if (options.search_type) queryParams.search_type = options.search_type; if (options.tag_names) queryParams.tag_names = options.tag_names; if (options.exclude_tag_names) queryParams.exclude_tag_names = options.exclude_tag_names; if (options.limit !== undefined) queryParams.limit = options.limit; if (options.offset !== undefined) queryParams.offset = options.offset; if (options.order_by) queryParams.order_by = options.order_by; if (options.sort_order) queryParams.sort_order = options.sort_order; if (options.filter_variable) queryParams.filter_variable = options.filter_variable; if (options.filter_value) queryParams.filter_value = options.filter_value; const response = await makeRequest<SearchResponse>( "series/search", queryParams ); // Format the response for better readability const formattedResults = { total_results: response.count, showing: `${response.offset + 1}-${Math.min(response.offset + response.limit, response.count)}`, results: response.seriess.map(series => ({ id: series.id, title: series.title, units: series.units, frequency: series.frequency, seasonal_adjustment: series.seasonal_adjustment, observation_range: `${series.observation_start} to ${series.observation_end}`, last_updated: series.last_updated, popularity: series.popularity, notes: series.notes?.substring(0, 200) + (series.notes && series.notes.length > 200 ? "..." : "") })) }; return { content: [{ type: "text" as const, text: JSON.stringify(formattedResults, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to search FRED series: ${error.message}`); } throw error; } } - src/fred/search.ts:50-61 (schema)Interface `FREDSearchOptions` defining input parameters for the search (search_text, search_type, tags, limit, offset, order_by, sort_order, filters).
export interface FREDSearchOptions { search_text?: string; search_type?: "full_text" | "series_id"; tag_names?: string; exclude_tag_names?: string; limit?: number; offset?: number; order_by?: "search_rank" | "series_id" | "title" | "units" | "frequency" | "seasonal_adjustment" | "realtime_start" | "realtime_end" | "last_updated" | "observation_start" | "observation_end" | "popularity"; sort_order?: "asc" | "desc"; filter_variable?: "frequency" | "units" | "seasonal_adjustment"; filter_value?: string; } - src/fred/search.ts:33-42 (schema)Zod schema `SearchResponseSchema` for validating the FRED API search response structure, including realtime info, count, offset, limit, and array of series results.
const SearchResponseSchema = z.object({ realtime_start: z.string(), realtime_end: z.string(), order_by: z.string(), sort_order: z.string(), count: z.number(), offset: z.number(), limit: z.number(), seriess: z.array(SearchSeriesSchema), }); - src/fred/search.ts:12-28 (schema)Zod schema `SearchSeriesSchema` for validating individual search result series fields (id, title, frequency, units, popularity, etc.).
const SearchSeriesSchema = z.object({ id: z.string(), realtime_start: z.string(), realtime_end: z.string(), title: z.string(), observation_start: z.string(), observation_end: z.string(), frequency: z.string(), frequency_short: z.string(), units: z.string(), units_short: z.string(), seasonal_adjustment: z.string(), seasonal_adjustment_short: z.string(), last_updated: z.string(), popularity: z.number(), notes: z.string().optional(), }); - src/fred/tools.ts:122-133 (registration)Registration of 'fred_search' tool with the MCP server via `server.tool()`, including the description and the handler that calls `searchSeries`.
// Register search tool server.tool( "fred_search", "Search for FRED economic data series by keywords, tags, or filters. Returns matching series with their IDs, titles, and metadata. Use this to find specific series when you know what you're looking for.", SEARCH_SCHEMA, async (input) => { console.error(`fred_search called with params: ${JSON.stringify(input)}`); const result = await searchSeries(input as FREDSearchOptions); console.error("fred_search complete"); return result; } );