@fre4x/fred 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/index.js +127 -187
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ The Federal Reserve publishes the data that governments and institutions use to
|
|
|
10
10
|
|
|
11
11
|
| Tool | What it reaches |
|
|
12
12
|
|------|----------------|
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
13
|
+
| `fred_search_series` | Full-text search across all FRED series |
|
|
14
|
+
| `fred_get_series_info` | Metadata for a series — units, frequency, range, last update |
|
|
15
|
+
| `fred_get_series_data` | Observation time-series for any series (e.g. `GDP`, `UNRATE`, `CPIAUCSL`) |
|
|
16
|
+
| `fred_get_category_series` | All series under a given FRED category |
|
|
17
|
+
| `fred_get_releases` | Index of all FRED data releases |
|
|
18
|
+
| `fred_get_release_series` | Series belonging to a specific release |
|
|
19
|
+
| `fred_get_sources` | All primary data sources in FRED |
|
|
20
|
+
| `fred_get_source` | Details for one source |
|
|
21
21
|
|
|
22
22
|
All list tools support pagination via `limit` / `offset`.
|
|
23
23
|
|
package/dist/index.js
CHANGED
|
@@ -7065,9 +7065,9 @@ var require_combined_stream = __commonJS({
|
|
|
7065
7065
|
}
|
|
7066
7066
|
});
|
|
7067
7067
|
|
|
7068
|
-
// ../node_modules/form-data/node_modules/mime-
|
|
7068
|
+
// ../node_modules/form-data/node_modules/mime-db/db.json
|
|
7069
7069
|
var require_db = __commonJS({
|
|
7070
|
-
"../node_modules/form-data/node_modules/mime-
|
|
7070
|
+
"../node_modules/form-data/node_modules/mime-db/db.json"(exports, module) {
|
|
7071
7071
|
module.exports = {
|
|
7072
7072
|
"application/1d-interleaved-parityfec": {
|
|
7073
7073
|
source: "iana"
|
|
@@ -15590,9 +15590,9 @@ var require_db = __commonJS({
|
|
|
15590
15590
|
}
|
|
15591
15591
|
});
|
|
15592
15592
|
|
|
15593
|
-
// ../node_modules/form-data/node_modules/mime-
|
|
15593
|
+
// ../node_modules/form-data/node_modules/mime-db/index.js
|
|
15594
15594
|
var require_mime_db = __commonJS({
|
|
15595
|
-
"../node_modules/form-data/node_modules/mime-
|
|
15595
|
+
"../node_modules/form-data/node_modules/mime-db/index.js"(exports, module) {
|
|
15596
15596
|
module.exports = require_db();
|
|
15597
15597
|
}
|
|
15598
15598
|
});
|
|
@@ -16764,7 +16764,7 @@ var require_form_data = __commonJS({
|
|
|
16764
16764
|
var path = __require("path");
|
|
16765
16765
|
var http3 = __require("http");
|
|
16766
16766
|
var https3 = __require("https");
|
|
16767
|
-
var
|
|
16767
|
+
var parseUrl2 = __require("url").parse;
|
|
16768
16768
|
var fs = __require("fs");
|
|
16769
16769
|
var Stream = __require("stream").Stream;
|
|
16770
16770
|
var crypto2 = __require("crypto");
|
|
@@ -17017,7 +17017,7 @@ var require_form_data = __commonJS({
|
|
|
17017
17017
|
var options;
|
|
17018
17018
|
var defaults2 = { method: "post" };
|
|
17019
17019
|
if (typeof params === "string") {
|
|
17020
|
-
params =
|
|
17020
|
+
params = parseUrl2(params);
|
|
17021
17021
|
options = populate({
|
|
17022
17022
|
port: params.port,
|
|
17023
17023
|
path: params.pathname,
|
|
@@ -17074,76 +17074,6 @@ var require_form_data = __commonJS({
|
|
|
17074
17074
|
}
|
|
17075
17075
|
});
|
|
17076
17076
|
|
|
17077
|
-
// ../node_modules/proxy-from-env/index.js
|
|
17078
|
-
var require_proxy_from_env = __commonJS({
|
|
17079
|
-
"../node_modules/proxy-from-env/index.js"(exports) {
|
|
17080
|
-
"use strict";
|
|
17081
|
-
var parseUrl = __require("url").parse;
|
|
17082
|
-
var DEFAULT_PORTS = {
|
|
17083
|
-
ftp: 21,
|
|
17084
|
-
gopher: 70,
|
|
17085
|
-
http: 80,
|
|
17086
|
-
https: 443,
|
|
17087
|
-
ws: 80,
|
|
17088
|
-
wss: 443
|
|
17089
|
-
};
|
|
17090
|
-
var stringEndsWith = String.prototype.endsWith || function(s) {
|
|
17091
|
-
return s.length <= this.length && this.indexOf(s, this.length - s.length) !== -1;
|
|
17092
|
-
};
|
|
17093
|
-
function getProxyForUrl(url3) {
|
|
17094
|
-
var parsedUrl = typeof url3 === "string" ? parseUrl(url3) : url3 || {};
|
|
17095
|
-
var proto = parsedUrl.protocol;
|
|
17096
|
-
var hostname3 = parsedUrl.host;
|
|
17097
|
-
var port = parsedUrl.port;
|
|
17098
|
-
if (typeof hostname3 !== "string" || !hostname3 || typeof proto !== "string") {
|
|
17099
|
-
return "";
|
|
17100
|
-
}
|
|
17101
|
-
proto = proto.split(":", 1)[0];
|
|
17102
|
-
hostname3 = hostname3.replace(/:\d*$/, "");
|
|
17103
|
-
port = parseInt(port) || DEFAULT_PORTS[proto] || 0;
|
|
17104
|
-
if (!shouldProxy(hostname3, port)) {
|
|
17105
|
-
return "";
|
|
17106
|
-
}
|
|
17107
|
-
var proxy = getEnv("npm_config_" + proto + "_proxy") || getEnv(proto + "_proxy") || getEnv("npm_config_proxy") || getEnv("all_proxy");
|
|
17108
|
-
if (proxy && proxy.indexOf("://") === -1) {
|
|
17109
|
-
proxy = proto + "://" + proxy;
|
|
17110
|
-
}
|
|
17111
|
-
return proxy;
|
|
17112
|
-
}
|
|
17113
|
-
function shouldProxy(hostname3, port) {
|
|
17114
|
-
var NO_PROXY = (getEnv("npm_config_no_proxy") || getEnv("no_proxy")).toLowerCase();
|
|
17115
|
-
if (!NO_PROXY) {
|
|
17116
|
-
return true;
|
|
17117
|
-
}
|
|
17118
|
-
if (NO_PROXY === "*") {
|
|
17119
|
-
return false;
|
|
17120
|
-
}
|
|
17121
|
-
return NO_PROXY.split(/[,\s]/).every(function(proxy) {
|
|
17122
|
-
if (!proxy) {
|
|
17123
|
-
return true;
|
|
17124
|
-
}
|
|
17125
|
-
var parsedProxy = proxy.match(/^(.+):(\d+)$/);
|
|
17126
|
-
var parsedProxyHostname = parsedProxy ? parsedProxy[1] : proxy;
|
|
17127
|
-
var parsedProxyPort = parsedProxy ? parseInt(parsedProxy[2]) : 0;
|
|
17128
|
-
if (parsedProxyPort && parsedProxyPort !== port) {
|
|
17129
|
-
return true;
|
|
17130
|
-
}
|
|
17131
|
-
if (!/^[.*]/.test(parsedProxyHostname)) {
|
|
17132
|
-
return hostname3 !== parsedProxyHostname;
|
|
17133
|
-
}
|
|
17134
|
-
if (parsedProxyHostname.charAt(0) === "*") {
|
|
17135
|
-
parsedProxyHostname = parsedProxyHostname.slice(1);
|
|
17136
|
-
}
|
|
17137
|
-
return !stringEndsWith.call(hostname3, parsedProxyHostname);
|
|
17138
|
-
});
|
|
17139
|
-
}
|
|
17140
|
-
function getEnv(key) {
|
|
17141
|
-
return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || "";
|
|
17142
|
-
}
|
|
17143
|
-
exports.getProxyForUrl = getProxyForUrl;
|
|
17144
|
-
}
|
|
17145
|
-
});
|
|
17146
|
-
|
|
17147
17077
|
// ../node_modules/ms/index.js
|
|
17148
17078
|
var require_ms = __commonJS({
|
|
17149
17079
|
"../node_modules/ms/index.js"(exports, module) {
|
|
@@ -18261,7 +18191,7 @@ var require_follow_redirects = __commonJS({
|
|
|
18261
18191
|
removeMatchingHeaders(/^content-/i, this._options.headers);
|
|
18262
18192
|
}
|
|
18263
18193
|
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
|
18264
|
-
var currentUrlParts =
|
|
18194
|
+
var currentUrlParts = parseUrl2(this._currentUrl);
|
|
18265
18195
|
var currentHost = currentHostHeader || currentUrlParts.host;
|
|
18266
18196
|
var currentUrl = /^\w+:/.test(location) ? this._currentUrl : url3.format(Object.assign(currentUrlParts, { host: currentHost }));
|
|
18267
18197
|
var redirectUrl = resolveUrl(location, currentUrl);
|
|
@@ -18300,7 +18230,7 @@ var require_follow_redirects = __commonJS({
|
|
|
18300
18230
|
if (isURL(input)) {
|
|
18301
18231
|
input = spreadUrlObject(input);
|
|
18302
18232
|
} else if (isString2(input)) {
|
|
18303
|
-
input = spreadUrlObject(
|
|
18233
|
+
input = spreadUrlObject(parseUrl2(input));
|
|
18304
18234
|
} else {
|
|
18305
18235
|
callback = options;
|
|
18306
18236
|
options = validateUrl(input);
|
|
@@ -18336,7 +18266,7 @@ var require_follow_redirects = __commonJS({
|
|
|
18336
18266
|
}
|
|
18337
18267
|
function noop2() {
|
|
18338
18268
|
}
|
|
18339
|
-
function
|
|
18269
|
+
function parseUrl2(input) {
|
|
18340
18270
|
var parsed;
|
|
18341
18271
|
if (useNativeURL) {
|
|
18342
18272
|
parsed = new URL2(input);
|
|
@@ -18349,7 +18279,7 @@ var require_follow_redirects = __commonJS({
|
|
|
18349
18279
|
return parsed;
|
|
18350
18280
|
}
|
|
18351
18281
|
function resolveUrl(relative, base) {
|
|
18352
|
-
return useNativeURL ? new URL2(relative, base) :
|
|
18282
|
+
return useNativeURL ? new URL2(relative, base) : parseUrl2(url3.resolve(base, relative));
|
|
18353
18283
|
}
|
|
18354
18284
|
function validateUrl(input) {
|
|
18355
18285
|
if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
|
|
@@ -18438,26 +18368,22 @@ var require_follow_redirects = __commonJS({
|
|
|
18438
18368
|
// ../packages/shared/dist/errors.js
|
|
18439
18369
|
function createApiError(message, statusCode) {
|
|
18440
18370
|
let hint = "Check your network connection and retry.";
|
|
18441
|
-
let type = "Service Error";
|
|
18442
18371
|
if (statusCode === 429) {
|
|
18443
|
-
|
|
18444
|
-
hint = "Request volume is too high. Suggestion: Wait briefly before retrying or reduce concurrent calls.";
|
|
18372
|
+
hint = "Rate limit exceeded. Suggestion: Wait for 60 seconds (Exponential Backoff) before retrying or reduce concurrent calls.";
|
|
18445
18373
|
} else if (statusCode === 401 || statusCode === 403) {
|
|
18446
|
-
|
|
18447
|
-
hint = "The request could not be authorized. Suggestion: Verify your API key or token in the environment configuration.";
|
|
18374
|
+
hint = "Authentication failed. Suggestion: Verify your API key or token in the environment configuration.";
|
|
18448
18375
|
} else if (statusCode && statusCode >= 500) {
|
|
18449
|
-
|
|
18450
|
-
hint = "The remote service is experiencing temporary issues. Suggestion: Try again in a few minutes.";
|
|
18376
|
+
hint = "Upstream service is having issues. Suggestion: This is a temporary external error. Try again in a few minutes.";
|
|
18451
18377
|
} else if (statusCode === 404) {
|
|
18452
|
-
|
|
18453
|
-
hint = "The requested information could not be found. Suggestion: Check if the ID, Ticker, or query parameters are correct.";
|
|
18378
|
+
hint = "The requested resource was not found. Suggestion: Check if the ID or Ticker is correct, or search for it first.";
|
|
18454
18379
|
}
|
|
18380
|
+
const detail = statusCode ? ` (HTTP ${statusCode})` : "";
|
|
18455
18381
|
return {
|
|
18456
18382
|
isError: true,
|
|
18457
18383
|
content: [
|
|
18458
18384
|
{
|
|
18459
18385
|
type: "text",
|
|
18460
|
-
text:
|
|
18386
|
+
text: `API Error${detail}: ${message}
|
|
18461
18387
|
|
|
18462
18388
|
**Next Action**: ${hint}`
|
|
18463
18389
|
}
|
|
@@ -32521,8 +32447,7 @@ config(en_default());
|
|
|
32521
32447
|
var zod_default = external_exports;
|
|
32522
32448
|
|
|
32523
32449
|
// ../packages/shared/dist/pagination.js
|
|
32524
|
-
var
|
|
32525
|
-
var z2 = zodCompat.z ?? zodCompat.default?.z ?? zodCompat.default ?? zodCompat;
|
|
32450
|
+
var z2 = external_exports || zod_default || zod_exports;
|
|
32526
32451
|
var paginationSchema = z2.object({
|
|
32527
32452
|
limit: z2.number().int().min(1).max(100).default(20).describe("Maximum results to return (1\u2013100, default 20)"),
|
|
32528
32453
|
offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination (default 0)")
|
|
@@ -32540,14 +32465,6 @@ function applyPagination(items, params) {
|
|
|
32540
32465
|
};
|
|
32541
32466
|
}
|
|
32542
32467
|
|
|
32543
|
-
// ../packages/shared/dist/package.js
|
|
32544
|
-
import { createRequire as createJsonRequire } from "node:module";
|
|
32545
|
-
function getPackageVersion(moduleUrl) {
|
|
32546
|
-
const require2 = createJsonRequire(moduleUrl);
|
|
32547
|
-
const packageJson = require2("../package.json");
|
|
32548
|
-
return packageJson.version ?? "0.0.0";
|
|
32549
|
-
}
|
|
32550
|
-
|
|
32551
32468
|
// ../node_modules/zod/v3/helpers/util.js
|
|
32552
32469
|
var util;
|
|
32553
32470
|
(function(util4) {
|
|
@@ -43134,7 +43051,7 @@ function normalizeValue(value) {
|
|
|
43134
43051
|
if (value === false || value == null) {
|
|
43135
43052
|
return value;
|
|
43136
43053
|
}
|
|
43137
|
-
return utils_default.isArray(value) ? value.map(normalizeValue) : String(value);
|
|
43054
|
+
return utils_default.isArray(value) ? value.map(normalizeValue) : String(value).replace(/[\r\n]+$/, "");
|
|
43138
43055
|
}
|
|
43139
43056
|
function parseTokens(str) {
|
|
43140
43057
|
const tokens = /* @__PURE__ */ Object.create(null);
|
|
@@ -43438,8 +43355,74 @@ function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
|
|
|
43438
43355
|
return requestedURL;
|
|
43439
43356
|
}
|
|
43440
43357
|
|
|
43358
|
+
// ../node_modules/proxy-from-env/index.js
|
|
43359
|
+
var DEFAULT_PORTS = {
|
|
43360
|
+
ftp: 21,
|
|
43361
|
+
gopher: 70,
|
|
43362
|
+
http: 80,
|
|
43363
|
+
https: 443,
|
|
43364
|
+
ws: 80,
|
|
43365
|
+
wss: 443
|
|
43366
|
+
};
|
|
43367
|
+
function parseUrl(urlString) {
|
|
43368
|
+
try {
|
|
43369
|
+
return new URL(urlString);
|
|
43370
|
+
} catch {
|
|
43371
|
+
return null;
|
|
43372
|
+
}
|
|
43373
|
+
}
|
|
43374
|
+
function getProxyForUrl(url3) {
|
|
43375
|
+
var parsedUrl = (typeof url3 === "string" ? parseUrl(url3) : url3) || {};
|
|
43376
|
+
var proto = parsedUrl.protocol;
|
|
43377
|
+
var hostname3 = parsedUrl.host;
|
|
43378
|
+
var port = parsedUrl.port;
|
|
43379
|
+
if (typeof hostname3 !== "string" || !hostname3 || typeof proto !== "string") {
|
|
43380
|
+
return "";
|
|
43381
|
+
}
|
|
43382
|
+
proto = proto.split(":", 1)[0];
|
|
43383
|
+
hostname3 = hostname3.replace(/:\d*$/, "");
|
|
43384
|
+
port = parseInt(port) || DEFAULT_PORTS[proto] || 0;
|
|
43385
|
+
if (!shouldProxy(hostname3, port)) {
|
|
43386
|
+
return "";
|
|
43387
|
+
}
|
|
43388
|
+
var proxy = getEnv(proto + "_proxy") || getEnv("all_proxy");
|
|
43389
|
+
if (proxy && proxy.indexOf("://") === -1) {
|
|
43390
|
+
proxy = proto + "://" + proxy;
|
|
43391
|
+
}
|
|
43392
|
+
return proxy;
|
|
43393
|
+
}
|
|
43394
|
+
function shouldProxy(hostname3, port) {
|
|
43395
|
+
var NO_PROXY = getEnv("no_proxy").toLowerCase();
|
|
43396
|
+
if (!NO_PROXY) {
|
|
43397
|
+
return true;
|
|
43398
|
+
}
|
|
43399
|
+
if (NO_PROXY === "*") {
|
|
43400
|
+
return false;
|
|
43401
|
+
}
|
|
43402
|
+
return NO_PROXY.split(/[,\s]/).every(function(proxy) {
|
|
43403
|
+
if (!proxy) {
|
|
43404
|
+
return true;
|
|
43405
|
+
}
|
|
43406
|
+
var parsedProxy = proxy.match(/^(.+):(\d+)$/);
|
|
43407
|
+
var parsedProxyHostname = parsedProxy ? parsedProxy[1] : proxy;
|
|
43408
|
+
var parsedProxyPort = parsedProxy ? parseInt(parsedProxy[2]) : 0;
|
|
43409
|
+
if (parsedProxyPort && parsedProxyPort !== port) {
|
|
43410
|
+
return true;
|
|
43411
|
+
}
|
|
43412
|
+
if (!/^[.*]/.test(parsedProxyHostname)) {
|
|
43413
|
+
return hostname3 !== parsedProxyHostname;
|
|
43414
|
+
}
|
|
43415
|
+
if (parsedProxyHostname.charAt(0) === "*") {
|
|
43416
|
+
parsedProxyHostname = parsedProxyHostname.slice(1);
|
|
43417
|
+
}
|
|
43418
|
+
return !hostname3.endsWith(parsedProxyHostname);
|
|
43419
|
+
});
|
|
43420
|
+
}
|
|
43421
|
+
function getEnv(key) {
|
|
43422
|
+
return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || "";
|
|
43423
|
+
}
|
|
43424
|
+
|
|
43441
43425
|
// ../node_modules/axios/lib/adapters/http.js
|
|
43442
|
-
var import_proxy_from_env = __toESM(require_proxy_from_env(), 1);
|
|
43443
43426
|
var import_follow_redirects = __toESM(require_follow_redirects(), 1);
|
|
43444
43427
|
import http from "http";
|
|
43445
43428
|
import https from "https";
|
|
@@ -43448,7 +43431,7 @@ import util3 from "util";
|
|
|
43448
43431
|
import zlib from "zlib";
|
|
43449
43432
|
|
|
43450
43433
|
// ../node_modules/axios/lib/env/data.js
|
|
43451
|
-
var VERSION = "1.
|
|
43434
|
+
var VERSION = "1.14.0";
|
|
43452
43435
|
|
|
43453
43436
|
// ../node_modules/axios/lib/helpers/parseProtocol.js
|
|
43454
43437
|
function parseProtocol(url3) {
|
|
@@ -43969,6 +43952,9 @@ var Http2Sessions = class {
|
|
|
43969
43952
|
} else {
|
|
43970
43953
|
entries.splice(i, 1);
|
|
43971
43954
|
}
|
|
43955
|
+
if (!session.closed) {
|
|
43956
|
+
session.close();
|
|
43957
|
+
}
|
|
43972
43958
|
return;
|
|
43973
43959
|
}
|
|
43974
43960
|
}
|
|
@@ -44014,7 +44000,7 @@ function dispatchBeforeRedirect(options, responseDetails) {
|
|
|
44014
44000
|
function setProxy(options, configProxy, location) {
|
|
44015
44001
|
let proxy = configProxy;
|
|
44016
44002
|
if (!proxy && proxy !== false) {
|
|
44017
|
-
const proxyUrl =
|
|
44003
|
+
const proxyUrl = getProxyForUrl(location);
|
|
44018
44004
|
if (proxyUrl) {
|
|
44019
44005
|
proxy = new URL(proxyUrl);
|
|
44020
44006
|
}
|
|
@@ -45060,14 +45046,16 @@ var factory = (env) => {
|
|
|
45060
45046
|
const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? /* @__PURE__ */ ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer()));
|
|
45061
45047
|
const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
|
|
45062
45048
|
let duplexAccessed = false;
|
|
45049
|
+
const body = new ReadableStream2();
|
|
45063
45050
|
const hasContentType = new Request(platform_default.origin, {
|
|
45064
|
-
body
|
|
45051
|
+
body,
|
|
45065
45052
|
method: "POST",
|
|
45066
45053
|
get duplex() {
|
|
45067
45054
|
duplexAccessed = true;
|
|
45068
45055
|
return "half";
|
|
45069
45056
|
}
|
|
45070
45057
|
}).headers.has("Content-Type");
|
|
45058
|
+
body.cancel();
|
|
45071
45059
|
return duplexAccessed && !hasContentType;
|
|
45072
45060
|
});
|
|
45073
45061
|
const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response("").body));
|
|
@@ -45853,30 +45841,20 @@ var {
|
|
|
45853
45841
|
// src/api.ts
|
|
45854
45842
|
var FRED_BASE_URL = "https://api.stlouisfed.org/fred";
|
|
45855
45843
|
var httpsAgent = new https2.Agent({ keepAlive: true });
|
|
45856
|
-
function getApiKey() {
|
|
45857
|
-
const key = process.env.FRED_API_KEY;
|
|
45858
|
-
if (!key) {
|
|
45859
|
-
throw new Error(
|
|
45860
|
-
"FRED_API_KEY environment variable not set. Please set it to use this server."
|
|
45861
|
-
);
|
|
45862
|
-
}
|
|
45863
|
-
return key;
|
|
45864
|
-
}
|
|
45865
|
-
function buildRequestParams(params) {
|
|
45866
|
-
const filteredEntries = Object.entries(params).filter(
|
|
45867
|
-
([, value]) => value !== void 0
|
|
45868
|
-
);
|
|
45869
|
-
return Object.fromEntries([
|
|
45870
|
-
...filteredEntries,
|
|
45871
|
-
["api_key", getApiKey()],
|
|
45872
|
-
["file_type", "json"]
|
|
45873
|
-
]);
|
|
45874
|
-
}
|
|
45875
45844
|
var FredApiClient = class {
|
|
45876
45845
|
client;
|
|
45846
|
+
apiKey;
|
|
45877
45847
|
constructor() {
|
|
45848
|
+
const key = process.env.FRED_API_KEY;
|
|
45849
|
+
if (!key) {
|
|
45850
|
+
throw new Error(
|
|
45851
|
+
"FRED_API_KEY environment variable not set. Please set it to use this server."
|
|
45852
|
+
);
|
|
45853
|
+
}
|
|
45854
|
+
this.apiKey = key;
|
|
45878
45855
|
this.client = axios_default.create({
|
|
45879
45856
|
baseURL: FRED_BASE_URL,
|
|
45857
|
+
params: { api_key: this.apiKey, file_type: "json" },
|
|
45880
45858
|
httpsAgent
|
|
45881
45859
|
});
|
|
45882
45860
|
}
|
|
@@ -45884,13 +45862,13 @@ var FredApiClient = class {
|
|
|
45884
45862
|
const { data } = await this.client.get(
|
|
45885
45863
|
"/series/search",
|
|
45886
45864
|
{
|
|
45887
|
-
params:
|
|
45865
|
+
params: {
|
|
45888
45866
|
search_text: query,
|
|
45889
45867
|
limit,
|
|
45890
45868
|
offset,
|
|
45891
45869
|
order_by: "popularity",
|
|
45892
45870
|
sort_order: "desc"
|
|
45893
|
-
}
|
|
45871
|
+
}
|
|
45894
45872
|
}
|
|
45895
45873
|
);
|
|
45896
45874
|
return data;
|
|
@@ -45899,7 +45877,7 @@ var FredApiClient = class {
|
|
|
45899
45877
|
const { data } = await this.client.get(
|
|
45900
45878
|
"/series",
|
|
45901
45879
|
{
|
|
45902
|
-
params:
|
|
45880
|
+
params: { series_id: seriesId }
|
|
45903
45881
|
}
|
|
45904
45882
|
);
|
|
45905
45883
|
return data;
|
|
@@ -45908,12 +45886,12 @@ var FredApiClient = class {
|
|
|
45908
45886
|
const { data } = await this.client.get(
|
|
45909
45887
|
"/series/observations",
|
|
45910
45888
|
{
|
|
45911
|
-
params:
|
|
45889
|
+
params: {
|
|
45912
45890
|
series_id: seriesId,
|
|
45913
45891
|
limit,
|
|
45914
45892
|
offset,
|
|
45915
45893
|
sort_order: "desc"
|
|
45916
|
-
}
|
|
45894
|
+
}
|
|
45917
45895
|
}
|
|
45918
45896
|
);
|
|
45919
45897
|
return data;
|
|
@@ -45922,13 +45900,13 @@ var FredApiClient = class {
|
|
|
45922
45900
|
const { data } = await this.client.get(
|
|
45923
45901
|
"/category/series",
|
|
45924
45902
|
{
|
|
45925
|
-
params:
|
|
45903
|
+
params: {
|
|
45926
45904
|
category_id: categoryId,
|
|
45927
45905
|
limit,
|
|
45928
45906
|
offset,
|
|
45929
45907
|
order_by: "popularity",
|
|
45930
45908
|
sort_order: "desc"
|
|
45931
|
-
}
|
|
45909
|
+
}
|
|
45932
45910
|
}
|
|
45933
45911
|
);
|
|
45934
45912
|
return data;
|
|
@@ -45937,12 +45915,7 @@ var FredApiClient = class {
|
|
|
45937
45915
|
const { data } = await this.client.get(
|
|
45938
45916
|
"/releases",
|
|
45939
45917
|
{
|
|
45940
|
-
params:
|
|
45941
|
-
limit,
|
|
45942
|
-
offset,
|
|
45943
|
-
order_by: "release_id",
|
|
45944
|
-
sort_order: "desc"
|
|
45945
|
-
})
|
|
45918
|
+
params: { limit, offset }
|
|
45946
45919
|
}
|
|
45947
45920
|
);
|
|
45948
45921
|
return data;
|
|
@@ -45951,31 +45924,20 @@ var FredApiClient = class {
|
|
|
45951
45924
|
const { data } = await this.client.get(
|
|
45952
45925
|
"/release/series",
|
|
45953
45926
|
{
|
|
45954
|
-
params:
|
|
45955
|
-
release_id: releaseId,
|
|
45956
|
-
limit,
|
|
45957
|
-
offset,
|
|
45958
|
-
order_by: "popularity",
|
|
45959
|
-
sort_order: "desc"
|
|
45960
|
-
})
|
|
45927
|
+
params: { release_id: releaseId, limit, offset }
|
|
45961
45928
|
}
|
|
45962
45929
|
);
|
|
45963
45930
|
return data;
|
|
45964
45931
|
}
|
|
45965
45932
|
async getSources() {
|
|
45966
|
-
const { data } = await this.client.get(
|
|
45967
|
-
"/sources",
|
|
45968
|
-
{
|
|
45969
|
-
params: buildRequestParams({})
|
|
45970
|
-
}
|
|
45971
|
-
);
|
|
45933
|
+
const { data } = await this.client.get("/sources");
|
|
45972
45934
|
return data;
|
|
45973
45935
|
}
|
|
45974
45936
|
async getSource(sourceId) {
|
|
45975
45937
|
const { data } = await this.client.get(
|
|
45976
45938
|
"/source",
|
|
45977
45939
|
{
|
|
45978
|
-
params:
|
|
45940
|
+
params: { source_id: sourceId }
|
|
45979
45941
|
}
|
|
45980
45942
|
);
|
|
45981
45943
|
return data;
|
|
@@ -46176,10 +46138,9 @@ var MOCK_FIXTURES = {
|
|
|
46176
46138
|
};
|
|
46177
46139
|
|
|
46178
46140
|
// src/index.ts
|
|
46179
|
-
var PACKAGE_VERSION = getPackageVersion(import.meta.url);
|
|
46180
46141
|
var server = new McpServer({
|
|
46181
46142
|
name: "fred-mcp-server",
|
|
46182
|
-
version:
|
|
46143
|
+
version: "1.0.0"
|
|
46183
46144
|
});
|
|
46184
46145
|
var clientInstance = null;
|
|
46185
46146
|
function getClient() {
|
|
@@ -46189,36 +46150,25 @@ function getClient() {
|
|
|
46189
46150
|
return clientInstance;
|
|
46190
46151
|
}
|
|
46191
46152
|
function extractErrorMessage(err) {
|
|
46192
|
-
const sanitize = (value) => {
|
|
46193
|
-
const apiKey = process.env.FRED_API_KEY;
|
|
46194
|
-
let sanitized = value.replace(
|
|
46195
|
-
/([?&]api_key=)[^&\s]+/gi,
|
|
46196
|
-
"$1[REDACTED]"
|
|
46197
|
-
);
|
|
46198
|
-
if (apiKey) {
|
|
46199
|
-
sanitized = sanitized.split(apiKey).join("[REDACTED]");
|
|
46200
|
-
}
|
|
46201
|
-
return sanitized;
|
|
46202
|
-
};
|
|
46203
46153
|
if (typeof err !== "object" || err === null) {
|
|
46204
|
-
return
|
|
46154
|
+
return String(err);
|
|
46205
46155
|
}
|
|
46206
46156
|
const error48 = err;
|
|
46207
46157
|
const responseData = error48.response?.data;
|
|
46208
46158
|
if (typeof responseData === "string" && responseData.trim()) {
|
|
46209
|
-
return
|
|
46159
|
+
return responseData.trim();
|
|
46210
46160
|
}
|
|
46211
46161
|
if (responseData && typeof responseData === "object") {
|
|
46212
46162
|
const data = responseData;
|
|
46213
46163
|
const nestedMessage = data.error_message ?? data.message ?? data.error ?? data.detail;
|
|
46214
46164
|
if (nestedMessage !== void 0 && nestedMessage !== null) {
|
|
46215
|
-
return
|
|
46165
|
+
return String(nestedMessage);
|
|
46216
46166
|
}
|
|
46217
46167
|
}
|
|
46218
46168
|
if (error48.message !== void 0 && error48.message !== null) {
|
|
46219
|
-
return
|
|
46169
|
+
return String(error48.message);
|
|
46220
46170
|
}
|
|
46221
|
-
return
|
|
46171
|
+
return "Request failed.";
|
|
46222
46172
|
}
|
|
46223
46173
|
function handleFredError(err) {
|
|
46224
46174
|
if (typeof err === "object" && err !== null) {
|
|
@@ -46295,7 +46245,7 @@ function formatSources(sources, total, offset, limit) {
|
|
|
46295
46245
|
` + rows.join("\n") + formatPaginationFooter(offset, limit, total);
|
|
46296
46246
|
}
|
|
46297
46247
|
server.registerTool(
|
|
46298
|
-
"
|
|
46248
|
+
"fred_search_series",
|
|
46299
46249
|
{
|
|
46300
46250
|
title: "Search FRED Series",
|
|
46301
46251
|
description: "Search FRED economic data series by text query.",
|
|
@@ -46328,7 +46278,7 @@ server.registerTool(
|
|
|
46328
46278
|
}
|
|
46329
46279
|
);
|
|
46330
46280
|
server.registerTool(
|
|
46331
|
-
"
|
|
46281
|
+
"fred_get_series_info",
|
|
46332
46282
|
{
|
|
46333
46283
|
title: "Get FRED Series Info",
|
|
46334
46284
|
description: "Get metadata for a specific FRED series.",
|
|
@@ -46366,7 +46316,7 @@ server.registerTool(
|
|
|
46366
46316
|
}
|
|
46367
46317
|
);
|
|
46368
46318
|
server.registerTool(
|
|
46369
|
-
"
|
|
46319
|
+
"fred_get_series_data",
|
|
46370
46320
|
{
|
|
46371
46321
|
title: "Get FRED Series Data",
|
|
46372
46322
|
description: "Get observation data points for a specific FRED series.",
|
|
@@ -46421,7 +46371,7 @@ server.registerTool(
|
|
|
46421
46371
|
}
|
|
46422
46372
|
);
|
|
46423
46373
|
server.registerTool(
|
|
46424
|
-
"
|
|
46374
|
+
"fred_get_category_series",
|
|
46425
46375
|
{
|
|
46426
46376
|
title: "Get FRED Category Series",
|
|
46427
46377
|
description: "Get series belonging to a specific FRED category.",
|
|
@@ -46455,11 +46405,6 @@ server.registerTool(
|
|
|
46455
46405
|
limit,
|
|
46456
46406
|
offset
|
|
46457
46407
|
);
|
|
46458
|
-
if (!res.seriess || res.seriess.length === 0) {
|
|
46459
|
-
return createNotFoundError(
|
|
46460
|
-
`Category '${category_id}' not found.`
|
|
46461
|
-
);
|
|
46462
|
-
}
|
|
46463
46408
|
const text = formatSeriesList(res.seriess, res.count, offset);
|
|
46464
46409
|
return { content: [{ type: "text", text: truncateToLimit(text) }] };
|
|
46465
46410
|
} catch (err) {
|
|
@@ -46468,7 +46413,7 @@ server.registerTool(
|
|
|
46468
46413
|
}
|
|
46469
46414
|
);
|
|
46470
46415
|
server.registerTool(
|
|
46471
|
-
"
|
|
46416
|
+
"fred_get_releases",
|
|
46472
46417
|
{
|
|
46473
46418
|
title: "Get FRED Releases",
|
|
46474
46419
|
description: "Get all economic data releases from FRED.",
|
|
@@ -46498,7 +46443,7 @@ server.registerTool(
|
|
|
46498
46443
|
}
|
|
46499
46444
|
);
|
|
46500
46445
|
server.registerTool(
|
|
46501
|
-
"
|
|
46446
|
+
"fred_get_release_series",
|
|
46502
46447
|
{
|
|
46503
46448
|
title: "Get FRED Release Series",
|
|
46504
46449
|
description: "Get series belonging to a specific FRED release.",
|
|
@@ -46532,11 +46477,6 @@ server.registerTool(
|
|
|
46532
46477
|
limit,
|
|
46533
46478
|
offset
|
|
46534
46479
|
);
|
|
46535
|
-
if (!res.seriess || res.seriess.length === 0) {
|
|
46536
|
-
return createNotFoundError(
|
|
46537
|
-
`Release '${release_id}' not found.`
|
|
46538
|
-
);
|
|
46539
|
-
}
|
|
46540
46480
|
const text = formatSeriesList(res.seriess, res.count, offset);
|
|
46541
46481
|
return { content: [{ type: "text", text: truncateToLimit(text) }] };
|
|
46542
46482
|
} catch (err) {
|
|
@@ -46545,7 +46485,7 @@ server.registerTool(
|
|
|
46545
46485
|
}
|
|
46546
46486
|
);
|
|
46547
46487
|
server.registerTool(
|
|
46548
|
-
"
|
|
46488
|
+
"fred_get_sources",
|
|
46549
46489
|
{
|
|
46550
46490
|
title: "Get FRED Sources",
|
|
46551
46491
|
description: "Get all data sources available in FRED.",
|
|
@@ -46592,7 +46532,7 @@ server.registerTool(
|
|
|
46592
46532
|
}
|
|
46593
46533
|
);
|
|
46594
46534
|
server.registerTool(
|
|
46595
|
-
"
|
|
46535
|
+
"fred_get_source",
|
|
46596
46536
|
{
|
|
46597
46537
|
title: "Get FRED Source",
|
|
46598
46538
|
description: "Get details for a specific FRED data source.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fre4x/fred",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "A FRED economic data MCP server for LLMs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "node
|
|
14
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && npx esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --format=esm --banner:js=\"import{createRequire}from'module';const require=createRequire(import.meta.url);\" && node -e \"const fs=require('fs');const p='dist/index.js';const c=fs.readFileSync(p,'utf8');const next=c.startsWith('#!/usr/bin/env node')?c:'#!/usr/bin/env node\\n'+c;fs.writeFileSync(p,next);fs.chmodSync(p,0o755);\"",
|
|
15
15
|
"typecheck": "cross-env NODE_OPTIONS=--max-old-space-size=4096 tsc --noEmit",
|
|
16
16
|
"start": "node dist/index.js",
|
|
17
17
|
"dev": "tsx src/index.ts",
|
|
18
18
|
"watch": "tsc -w",
|
|
19
|
-
"inspector": "
|
|
20
|
-
"test": "
|
|
19
|
+
"inspector": "node ../scripts/run-official-inspector.mjs node dist/index.js",
|
|
20
|
+
"test": "vitest run --passWithNoTests --exclude dist"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"mcp",
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"author": "fritzprix",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
33
33
|
"axios": "^1.13.5",
|
|
34
|
-
"zod": "^4.
|
|
34
|
+
"zod": "^4.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/node": "^25.3.
|
|
37
|
+
"@types/node": "^25.3.0",
|
|
38
38
|
"tsx": "^4.21.0",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
40
|
"vitest": "^4.0.18"
|