UNPKG

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

235 lines (234 loc) 7.91 kB
/** * FRED Browse API Client * * Provides comprehensive browsing of FRED categories, releases, and sources */ import { makeRequest } from "../common/request.js"; import { z } from "zod"; /** * Category schema */ const CategorySchema = z.object({ id: z.number(), name: z.string(), parent_id: z.number(), }); /** * Release schema */ const ReleaseSchema = z.object({ id: z.number(), realtime_start: z.string(), realtime_end: z.string(), name: z.string(), press_release: z.boolean(), link: z.string().optional(), notes: z.string().optional(), }); /** * Source schema */ const SourceSchema = z.object({ id: z.number(), realtime_start: z.string(), realtime_end: z.string(), name: z.string(), link: z.string().optional(), notes: z.string().optional(), }); /** * Browse all FRED categories */ export async function browseCategories(categoryId) { try { const endpoint = categoryId ? `category/children` : "category"; const queryParams = {}; if (categoryId) { queryParams.category_id = categoryId; } const response = await makeRequest(endpoint, queryParams); return { content: [{ type: "text", text: JSON.stringify({ categories: response.categories.map(cat => ({ id: cat.id, name: cat.name, parent_id: cat.parent_id })) }, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to browse categories: ${error.message}`); } throw error; } } /** * Get series in a specific category */ export async function getCategorySeries(categoryId, options = {}) { try { const queryParams = { category_id: categoryId }; 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("category/series", queryParams); return { content: [{ type: "text", text: JSON.stringify({ category_id: categoryId, total_series: response.count, showing: `${response.offset + 1}-${Math.min(response.offset + response.limit, response.count)}`, series: response.seriess.map((s) => ({ id: s.id, title: s.title, units: s.units, frequency: s.frequency, observation_range: `${s.observation_start} to ${s.observation_end}`, last_updated: s.last_updated })) }, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to get category series: ${error.message}`); } throw error; } } /** * Browse all FRED releases */ export async function browseReleases(options = {}) { try { const queryParams = {}; 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; const response = await makeRequest("releases", queryParams); return { content: [{ type: "text", text: JSON.stringify({ total_releases: response.count, showing: `${response.offset + 1}-${Math.min(response.offset + response.limit, response.count)}`, releases: response.releases.map(rel => ({ id: rel.id, name: rel.name, press_release: rel.press_release, link: rel.link })) }, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to browse releases: ${error.message}`); } throw error; } } /** * Get series in a specific release */ export async function getReleaseSeries(releaseId, options = {}) { try { const queryParams = { release_id: releaseId }; 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; const response = await makeRequest("release/series", queryParams); return { content: [{ type: "text", text: JSON.stringify({ release_id: releaseId, total_series: response.count, showing: `${response.offset + 1}-${Math.min(response.offset + response.limit, response.count)}`, series: response.seriess.map((s) => ({ id: s.id, title: s.title, units: s.units, frequency: s.frequency, observation_range: `${s.observation_start} to ${s.observation_end}`, last_updated: s.last_updated })) }, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to get release series: ${error.message}`); } throw error; } } /** * Browse all FRED sources */ export async function browseSources(options = {}) { try { const queryParams = {}; 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; const response = await makeRequest("sources", queryParams); return { content: [{ type: "text", text: JSON.stringify({ total_sources: response.count, showing: `${response.offset + 1}-${Math.min(response.offset + response.limit, response.count)}`, sources: response.sources.map(src => ({ id: src.id, name: src.name, link: src.link })) }, null, 2) }] }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to browse sources: ${error.message}`); } throw error; } }