fred-mcp-server
Version:
Federal Reserve Economic Data (FRED) MCP Server - Access all 800,000+ economic time series with search, browse, and data retrieval capabilities
136 lines (135 loc) • 4.74 kB
JavaScript
/**
* FRED Search API Client
*
* Provides search functionality for discovering FRED series
*/
import { makeRequest } from "../common/request.js";
import { z } from "zod";
/**
* Schema for a single search result series
*/
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(),
});
/**
* Schema for search response
*/
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),
});
/**
* Searches for FRED series based on criteria
*/
export async function searchSeries(options = {}) {
try {
const queryParams = {};
// 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("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",
text: JSON.stringify(formattedResults, null, 2)
}]
};
}
catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to search FRED series: ${error.message}`);
}
throw error;
}
}
/**
* Gets detailed information about a specific series
*/
export async function getSeriesInfo(seriesId) {
try {
const queryParams = {
series_id: seriesId
};
const response = await makeRequest("series", queryParams);
if (!response.seriess || response.seriess.length === 0) {
throw new Error(`Series ${seriesId} not found`);
}
const series = response.seriess[0];
return {
content: [{
type: "text",
text: JSON.stringify({
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
}, null, 2)
}]
};
}
catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to get series info: ${error.message}`);
}
throw error;
}
}