@fre4x/fred 1.1.2 → 1.1.3

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.
Files changed (3) hide show
  1. package/README.md +8 -8
  2. package/dist/index.js +187 -127
  3. 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
- | `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 |
13
+ | `search_series` | Full-text search across all FRED series |
14
+ | `get_series_info` | Metadata for a series — units, frequency, range, last update |
15
+ | `get_series_data` | Observation time-series for any series (e.g. `GDP`, `UNRATE`, `CPIAUCSL`) |
16
+ | `get_category_series` | All series under a given FRED category |
17
+ | `get_releases` | Index of all FRED data releases |
18
+ | `get_release_series` | Series belonging to a specific release |
19
+ | `get_sources` | All primary data sources in FRED |
20
+ | `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-db/db.json
7068
+ // ../node_modules/form-data/node_modules/mime-types/node_modules/mime-db/db.json
7069
7069
  var require_db = __commonJS({
7070
- "../node_modules/form-data/node_modules/mime-db/db.json"(exports, module) {
7070
+ "../node_modules/form-data/node_modules/mime-types/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-db/index.js
15593
+ // ../node_modules/form-data/node_modules/mime-types/node_modules/mime-db/index.js
15594
15594
  var require_mime_db = __commonJS({
15595
- "../node_modules/form-data/node_modules/mime-db/index.js"(exports, module) {
15595
+ "../node_modules/form-data/node_modules/mime-types/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 parseUrl2 = __require("url").parse;
16767
+ var parseUrl = __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 = parseUrl2(params);
17020
+ params = parseUrl(params);
17021
17021
  options = populate({
17022
17022
  port: params.port,
17023
17023
  path: params.pathname,
@@ -17074,6 +17074,76 @@ 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
+
17077
17147
  // ../node_modules/ms/index.js
17078
17148
  var require_ms = __commonJS({
17079
17149
  "../node_modules/ms/index.js"(exports, module) {
@@ -18191,7 +18261,7 @@ var require_follow_redirects = __commonJS({
18191
18261
  removeMatchingHeaders(/^content-/i, this._options.headers);
18192
18262
  }
18193
18263
  var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
18194
- var currentUrlParts = parseUrl2(this._currentUrl);
18264
+ var currentUrlParts = parseUrl(this._currentUrl);
18195
18265
  var currentHost = currentHostHeader || currentUrlParts.host;
18196
18266
  var currentUrl = /^\w+:/.test(location) ? this._currentUrl : url3.format(Object.assign(currentUrlParts, { host: currentHost }));
18197
18267
  var redirectUrl = resolveUrl(location, currentUrl);
@@ -18230,7 +18300,7 @@ var require_follow_redirects = __commonJS({
18230
18300
  if (isURL(input)) {
18231
18301
  input = spreadUrlObject(input);
18232
18302
  } else if (isString2(input)) {
18233
- input = spreadUrlObject(parseUrl2(input));
18303
+ input = spreadUrlObject(parseUrl(input));
18234
18304
  } else {
18235
18305
  callback = options;
18236
18306
  options = validateUrl(input);
@@ -18266,7 +18336,7 @@ var require_follow_redirects = __commonJS({
18266
18336
  }
18267
18337
  function noop2() {
18268
18338
  }
18269
- function parseUrl2(input) {
18339
+ function parseUrl(input) {
18270
18340
  var parsed;
18271
18341
  if (useNativeURL) {
18272
18342
  parsed = new URL2(input);
@@ -18279,7 +18349,7 @@ var require_follow_redirects = __commonJS({
18279
18349
  return parsed;
18280
18350
  }
18281
18351
  function resolveUrl(relative, base) {
18282
- return useNativeURL ? new URL2(relative, base) : parseUrl2(url3.resolve(base, relative));
18352
+ return useNativeURL ? new URL2(relative, base) : parseUrl(url3.resolve(base, relative));
18283
18353
  }
18284
18354
  function validateUrl(input) {
18285
18355
  if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
@@ -18368,22 +18438,26 @@ var require_follow_redirects = __commonJS({
18368
18438
  // ../packages/shared/dist/errors.js
18369
18439
  function createApiError(message, statusCode) {
18370
18440
  let hint = "Check your network connection and retry.";
18441
+ let type = "Service Error";
18371
18442
  if (statusCode === 429) {
18372
- hint = "Rate limit exceeded. Suggestion: Wait for 60 seconds (Exponential Backoff) before retrying or reduce concurrent calls.";
18443
+ type = "Rate Limit";
18444
+ hint = "Request volume is too high. Suggestion: Wait briefly before retrying or reduce concurrent calls.";
18373
18445
  } else if (statusCode === 401 || statusCode === 403) {
18374
- hint = "Authentication failed. Suggestion: Verify your API key or token in the environment configuration.";
18446
+ type = "Authentication Error";
18447
+ hint = "The request could not be authorized. Suggestion: Verify your API key or token in the environment configuration.";
18375
18448
  } else if (statusCode && statusCode >= 500) {
18376
- hint = "Upstream service is having issues. Suggestion: This is a temporary external error. Try again in a few minutes.";
18449
+ type = "Upstream Error";
18450
+ hint = "The remote service is experiencing temporary issues. Suggestion: Try again in a few minutes.";
18377
18451
  } else if (statusCode === 404) {
18378
- hint = "The requested resource was not found. Suggestion: Check if the ID or Ticker is correct, or search for it first.";
18452
+ type = "Not Found";
18453
+ hint = "The requested information could not be found. Suggestion: Check if the ID, Ticker, or query parameters are correct.";
18379
18454
  }
18380
- const detail = statusCode ? ` (HTTP ${statusCode})` : "";
18381
18455
  return {
18382
18456
  isError: true,
18383
18457
  content: [
18384
18458
  {
18385
18459
  type: "text",
18386
- text: `API Error${detail}: ${message}
18460
+ text: `${type}: ${message}
18387
18461
 
18388
18462
  **Next Action**: ${hint}`
18389
18463
  }
@@ -32447,7 +32521,8 @@ config(en_default());
32447
32521
  var zod_default = external_exports;
32448
32522
 
32449
32523
  // ../packages/shared/dist/pagination.js
32450
- var z2 = external_exports || zod_default || zod_exports;
32524
+ var zodCompat = zod_exports;
32525
+ var z2 = zodCompat.z ?? zodCompat.default?.z ?? zodCompat.default ?? zodCompat;
32451
32526
  var paginationSchema = z2.object({
32452
32527
  limit: z2.number().int().min(1).max(100).default(20).describe("Maximum results to return (1\u2013100, default 20)"),
32453
32528
  offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination (default 0)")
@@ -32465,6 +32540,14 @@ function applyPagination(items, params) {
32465
32540
  };
32466
32541
  }
32467
32542
 
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
+
32468
32551
  // ../node_modules/zod/v3/helpers/util.js
32469
32552
  var util;
32470
32553
  (function(util4) {
@@ -43051,7 +43134,7 @@ function normalizeValue(value) {
43051
43134
  if (value === false || value == null) {
43052
43135
  return value;
43053
43136
  }
43054
- return utils_default.isArray(value) ? value.map(normalizeValue) : String(value).replace(/[\r\n]+$/, "");
43137
+ return utils_default.isArray(value) ? value.map(normalizeValue) : String(value);
43055
43138
  }
43056
43139
  function parseTokens(str) {
43057
43140
  const tokens = /* @__PURE__ */ Object.create(null);
@@ -43355,74 +43438,8 @@ function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
43355
43438
  return requestedURL;
43356
43439
  }
43357
43440
 
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
-
43425
43441
  // ../node_modules/axios/lib/adapters/http.js
43442
+ var import_proxy_from_env = __toESM(require_proxy_from_env(), 1);
43426
43443
  var import_follow_redirects = __toESM(require_follow_redirects(), 1);
43427
43444
  import http from "http";
43428
43445
  import https from "https";
@@ -43431,7 +43448,7 @@ import util3 from "util";
43431
43448
  import zlib from "zlib";
43432
43449
 
43433
43450
  // ../node_modules/axios/lib/env/data.js
43434
- var VERSION = "1.14.0";
43451
+ var VERSION = "1.13.6";
43435
43452
 
43436
43453
  // ../node_modules/axios/lib/helpers/parseProtocol.js
43437
43454
  function parseProtocol(url3) {
@@ -43952,9 +43969,6 @@ var Http2Sessions = class {
43952
43969
  } else {
43953
43970
  entries.splice(i, 1);
43954
43971
  }
43955
- if (!session.closed) {
43956
- session.close();
43957
- }
43958
43972
  return;
43959
43973
  }
43960
43974
  }
@@ -44000,7 +44014,7 @@ function dispatchBeforeRedirect(options, responseDetails) {
44000
44014
  function setProxy(options, configProxy, location) {
44001
44015
  let proxy = configProxy;
44002
44016
  if (!proxy && proxy !== false) {
44003
- const proxyUrl = getProxyForUrl(location);
44017
+ const proxyUrl = import_proxy_from_env.default.getProxyForUrl(location);
44004
44018
  if (proxyUrl) {
44005
44019
  proxy = new URL(proxyUrl);
44006
44020
  }
@@ -45046,16 +45060,14 @@ var factory = (env) => {
45046
45060
  const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? /* @__PURE__ */ ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer()));
45047
45061
  const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
45048
45062
  let duplexAccessed = false;
45049
- const body = new ReadableStream2();
45050
45063
  const hasContentType = new Request(platform_default.origin, {
45051
- body,
45064
+ body: new ReadableStream2(),
45052
45065
  method: "POST",
45053
45066
  get duplex() {
45054
45067
  duplexAccessed = true;
45055
45068
  return "half";
45056
45069
  }
45057
45070
  }).headers.has("Content-Type");
45058
- body.cancel();
45059
45071
  return duplexAccessed && !hasContentType;
45060
45072
  });
45061
45073
  const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response("").body));
@@ -45841,20 +45853,30 @@ var {
45841
45853
  // src/api.ts
45842
45854
  var FRED_BASE_URL = "https://api.stlouisfed.org/fred";
45843
45855
  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
+ }
45844
45875
  var FredApiClient = class {
45845
45876
  client;
45846
- apiKey;
45847
45877
  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;
45855
45878
  this.client = axios_default.create({
45856
45879
  baseURL: FRED_BASE_URL,
45857
- params: { api_key: this.apiKey, file_type: "json" },
45858
45880
  httpsAgent
45859
45881
  });
45860
45882
  }
@@ -45862,13 +45884,13 @@ var FredApiClient = class {
45862
45884
  const { data } = await this.client.get(
45863
45885
  "/series/search",
45864
45886
  {
45865
- params: {
45887
+ params: buildRequestParams({
45866
45888
  search_text: query,
45867
45889
  limit,
45868
45890
  offset,
45869
45891
  order_by: "popularity",
45870
45892
  sort_order: "desc"
45871
- }
45893
+ })
45872
45894
  }
45873
45895
  );
45874
45896
  return data;
@@ -45877,7 +45899,7 @@ var FredApiClient = class {
45877
45899
  const { data } = await this.client.get(
45878
45900
  "/series",
45879
45901
  {
45880
- params: { series_id: seriesId }
45902
+ params: buildRequestParams({ series_id: seriesId })
45881
45903
  }
45882
45904
  );
45883
45905
  return data;
@@ -45886,12 +45908,12 @@ var FredApiClient = class {
45886
45908
  const { data } = await this.client.get(
45887
45909
  "/series/observations",
45888
45910
  {
45889
- params: {
45911
+ params: buildRequestParams({
45890
45912
  series_id: seriesId,
45891
45913
  limit,
45892
45914
  offset,
45893
45915
  sort_order: "desc"
45894
- }
45916
+ })
45895
45917
  }
45896
45918
  );
45897
45919
  return data;
@@ -45900,13 +45922,13 @@ var FredApiClient = class {
45900
45922
  const { data } = await this.client.get(
45901
45923
  "/category/series",
45902
45924
  {
45903
- params: {
45925
+ params: buildRequestParams({
45904
45926
  category_id: categoryId,
45905
45927
  limit,
45906
45928
  offset,
45907
45929
  order_by: "popularity",
45908
45930
  sort_order: "desc"
45909
- }
45931
+ })
45910
45932
  }
45911
45933
  );
45912
45934
  return data;
@@ -45915,7 +45937,12 @@ var FredApiClient = class {
45915
45937
  const { data } = await this.client.get(
45916
45938
  "/releases",
45917
45939
  {
45918
- params: { limit, offset }
45940
+ params: buildRequestParams({
45941
+ limit,
45942
+ offset,
45943
+ order_by: "release_id",
45944
+ sort_order: "desc"
45945
+ })
45919
45946
  }
45920
45947
  );
45921
45948
  return data;
@@ -45924,20 +45951,31 @@ var FredApiClient = class {
45924
45951
  const { data } = await this.client.get(
45925
45952
  "/release/series",
45926
45953
  {
45927
- params: { release_id: releaseId, limit, offset }
45954
+ params: buildRequestParams({
45955
+ release_id: releaseId,
45956
+ limit,
45957
+ offset,
45958
+ order_by: "popularity",
45959
+ sort_order: "desc"
45960
+ })
45928
45961
  }
45929
45962
  );
45930
45963
  return data;
45931
45964
  }
45932
45965
  async getSources() {
45933
- const { data } = await this.client.get("/sources");
45966
+ const { data } = await this.client.get(
45967
+ "/sources",
45968
+ {
45969
+ params: buildRequestParams({})
45970
+ }
45971
+ );
45934
45972
  return data;
45935
45973
  }
45936
45974
  async getSource(sourceId) {
45937
45975
  const { data } = await this.client.get(
45938
45976
  "/source",
45939
45977
  {
45940
- params: { source_id: sourceId }
45978
+ params: buildRequestParams({ source_id: sourceId })
45941
45979
  }
45942
45980
  );
45943
45981
  return data;
@@ -46138,9 +46176,10 @@ var MOCK_FIXTURES = {
46138
46176
  };
46139
46177
 
46140
46178
  // src/index.ts
46179
+ var PACKAGE_VERSION = getPackageVersion(import.meta.url);
46141
46180
  var server = new McpServer({
46142
46181
  name: "fred-mcp-server",
46143
- version: "1.0.0"
46182
+ version: PACKAGE_VERSION
46144
46183
  });
46145
46184
  var clientInstance = null;
46146
46185
  function getClient() {
@@ -46150,25 +46189,36 @@ function getClient() {
46150
46189
  return clientInstance;
46151
46190
  }
46152
46191
  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
+ };
46153
46203
  if (typeof err !== "object" || err === null) {
46154
- return String(err);
46204
+ return sanitize(String(err));
46155
46205
  }
46156
46206
  const error48 = err;
46157
46207
  const responseData = error48.response?.data;
46158
46208
  if (typeof responseData === "string" && responseData.trim()) {
46159
- return responseData.trim();
46209
+ return sanitize(responseData.trim());
46160
46210
  }
46161
46211
  if (responseData && typeof responseData === "object") {
46162
46212
  const data = responseData;
46163
46213
  const nestedMessage = data.error_message ?? data.message ?? data.error ?? data.detail;
46164
46214
  if (nestedMessage !== void 0 && nestedMessage !== null) {
46165
- return String(nestedMessage);
46215
+ return sanitize(String(nestedMessage));
46166
46216
  }
46167
46217
  }
46168
46218
  if (error48.message !== void 0 && error48.message !== null) {
46169
- return String(error48.message);
46219
+ return sanitize(String(error48.message));
46170
46220
  }
46171
- return "Request failed.";
46221
+ return sanitize("Request failed.");
46172
46222
  }
46173
46223
  function handleFredError(err) {
46174
46224
  if (typeof err === "object" && err !== null) {
@@ -46245,7 +46295,7 @@ function formatSources(sources, total, offset, limit) {
46245
46295
  ` + rows.join("\n") + formatPaginationFooter(offset, limit, total);
46246
46296
  }
46247
46297
  server.registerTool(
46248
- "fred_search_series",
46298
+ "search_series",
46249
46299
  {
46250
46300
  title: "Search FRED Series",
46251
46301
  description: "Search FRED economic data series by text query.",
@@ -46278,7 +46328,7 @@ server.registerTool(
46278
46328
  }
46279
46329
  );
46280
46330
  server.registerTool(
46281
- "fred_get_series_info",
46331
+ "get_series_info",
46282
46332
  {
46283
46333
  title: "Get FRED Series Info",
46284
46334
  description: "Get metadata for a specific FRED series.",
@@ -46316,7 +46366,7 @@ server.registerTool(
46316
46366
  }
46317
46367
  );
46318
46368
  server.registerTool(
46319
- "fred_get_series_data",
46369
+ "get_series_data",
46320
46370
  {
46321
46371
  title: "Get FRED Series Data",
46322
46372
  description: "Get observation data points for a specific FRED series.",
@@ -46371,7 +46421,7 @@ server.registerTool(
46371
46421
  }
46372
46422
  );
46373
46423
  server.registerTool(
46374
- "fred_get_category_series",
46424
+ "get_category_series",
46375
46425
  {
46376
46426
  title: "Get FRED Category Series",
46377
46427
  description: "Get series belonging to a specific FRED category.",
@@ -46405,6 +46455,11 @@ server.registerTool(
46405
46455
  limit,
46406
46456
  offset
46407
46457
  );
46458
+ if (!res.seriess || res.seriess.length === 0) {
46459
+ return createNotFoundError(
46460
+ `Category '${category_id}' not found.`
46461
+ );
46462
+ }
46408
46463
  const text = formatSeriesList(res.seriess, res.count, offset);
46409
46464
  return { content: [{ type: "text", text: truncateToLimit(text) }] };
46410
46465
  } catch (err) {
@@ -46413,7 +46468,7 @@ server.registerTool(
46413
46468
  }
46414
46469
  );
46415
46470
  server.registerTool(
46416
- "fred_get_releases",
46471
+ "get_releases",
46417
46472
  {
46418
46473
  title: "Get FRED Releases",
46419
46474
  description: "Get all economic data releases from FRED.",
@@ -46443,7 +46498,7 @@ server.registerTool(
46443
46498
  }
46444
46499
  );
46445
46500
  server.registerTool(
46446
- "fred_get_release_series",
46501
+ "get_release_series",
46447
46502
  {
46448
46503
  title: "Get FRED Release Series",
46449
46504
  description: "Get series belonging to a specific FRED release.",
@@ -46477,6 +46532,11 @@ server.registerTool(
46477
46532
  limit,
46478
46533
  offset
46479
46534
  );
46535
+ if (!res.seriess || res.seriess.length === 0) {
46536
+ return createNotFoundError(
46537
+ `Release '${release_id}' not found.`
46538
+ );
46539
+ }
46480
46540
  const text = formatSeriesList(res.seriess, res.count, offset);
46481
46541
  return { content: [{ type: "text", text: truncateToLimit(text) }] };
46482
46542
  } catch (err) {
@@ -46485,7 +46545,7 @@ server.registerTool(
46485
46545
  }
46486
46546
  );
46487
46547
  server.registerTool(
46488
- "fred_get_sources",
46548
+ "get_sources",
46489
46549
  {
46490
46550
  title: "Get FRED Sources",
46491
46551
  description: "Get all data sources available in FRED.",
@@ -46532,7 +46592,7 @@ server.registerTool(
46532
46592
  }
46533
46593
  );
46534
46594
  server.registerTool(
46535
- "fred_get_source",
46595
+ "get_source",
46536
46596
  {
46537
46597
  title: "Get FRED Source",
46538
46598
  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.2",
3
+ "version": "1.1.3",
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 -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);\"",
14
+ "build": "node ../scripts/build-package.mjs",
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": "node ../scripts/run-official-inspector.mjs node dist/index.js",
20
- "test": "vitest run --passWithNoTests --exclude dist"
19
+ "inspector": "npm run build && node ../scripts/run-official-inspector.mjs node dist/index.js",
20
+ "test": "node ../scripts/run-vitest.mjs 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.26.0",
32
+ "@modelcontextprotocol/sdk": "^1.27.1",
33
33
  "axios": "^1.13.5",
34
- "zod": "^4.0.0"
34
+ "zod": "^4.3.6"
35
35
  },
36
36
  "devDependencies": {
37
- "@types/node": "^25.3.0",
37
+ "@types/node": "^25.3.5",
38
38
  "tsx": "^4.21.0",
39
39
  "typescript": "^5.9.3",
40
40
  "vitest": "^4.0.18"