fdic-mcp-server 1.2.3 → 1.2.5

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/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
32
32
  var import_express = __toESM(require("express"));
33
33
 
34
34
  // src/constants.ts
35
- var VERSION = true ? "1.2.3" : process.env.npm_package_version ?? "0.0.0-dev";
35
+ var VERSION = true ? "1.2.5" : process.env.npm_package_version ?? "0.0.0-dev";
36
36
  var FDIC_API_BASE_URL = "https://banks.data.fdic.gov/api";
37
37
  var CHARACTER_LIMIT = 5e4;
38
38
  var DEFAULT_FDIC_MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
@@ -32802,7 +32802,9 @@ function buildAnalysisOutput(params) {
32802
32802
  sort_by: params.sortBy,
32803
32803
  sort_order: params.sortOrder,
32804
32804
  warnings: params.warnings,
32805
- insights: buildTopLevelInsights(params.comparisons),
32805
+ insights: buildTopLevelInsights(
32806
+ params.insightComparisons ?? params.comparisons
32807
+ ),
32806
32808
  ...buildPaginationInfo(params.analyzedCount, offset, count),
32807
32809
  comparisons: params.comparisons
32808
32810
  };
@@ -33093,7 +33095,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33093
33095
  server.server,
33094
33096
  progressToken,
33095
33097
  0.3,
33096
- "Fetching financial time series"
33098
+ include_demographics ? "Fetching financial and demographic time series" : "Fetching financial time series"
33097
33099
  );
33098
33100
  const [financialSeriesResult, demographicsSeriesResult] = await Promise.all([
33099
33101
  fetchSeriesRecords(
@@ -33120,14 +33122,6 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33120
33122
  ...financialSeriesResult.warnings,
33121
33123
  ...demographicsSeriesResult.warnings
33122
33124
  );
33123
- if (include_demographics) {
33124
- await sendProgressNotification(
33125
- server.server,
33126
- progressToken,
33127
- 0.7,
33128
- "Fetching demographics time series"
33129
- );
33130
- }
33131
33125
  await sendProgressNotification(
33132
33126
  server.server,
33133
33127
  progressToken,
@@ -33153,7 +33147,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33153
33147
  server.server,
33154
33148
  progressToken,
33155
33149
  0.3,
33156
- "Fetching financial snapshots"
33150
+ include_demographics ? "Fetching financial and demographic snapshots" : "Fetching financial snapshots"
33157
33151
  );
33158
33152
  const [financialSnapshotsResult, demographicSnapshotsResult] = await Promise.all([
33159
33153
  fetchBatchedRecordsForDates(
@@ -33178,14 +33172,6 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33178
33172
  ...financialSnapshotsResult.warnings,
33179
33173
  ...demographicSnapshotsResult.warnings
33180
33174
  );
33181
- if (include_demographics) {
33182
- await sendProgressNotification(
33183
- server.server,
33184
- progressToken,
33185
- 0.7,
33186
- "Fetching demographic snapshots"
33187
- );
33188
- }
33189
33175
  await sendProgressNotification(
33190
33176
  server.server,
33191
33177
  progressToken,
@@ -33230,6 +33216,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33230
33216
  sortOrder: sort_order,
33231
33217
  warnings,
33232
33218
  comparisons: ranked,
33219
+ insightComparisons: sortedComparisons,
33233
33220
  limitCount: ranked.length
33234
33221
  });
33235
33222
  const text = truncateIfNeeded(
@@ -33983,6 +33970,8 @@ function parseAllowedOrigins(rawOrigins, port) {
33983
33970
  `https://127.0.0.1:${port}`
33984
33971
  ];
33985
33972
  }
33973
+ var DEFAULT_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
33974
+ var DEFAULT_SESSION_SWEEP_INTERVAL_MS = 5 * 60 * 1e3;
33986
33975
  async function closeSession(sessions, sessionId) {
33987
33976
  const session = sessions.get(sessionId);
33988
33977
  if (!session) {
@@ -33994,6 +33983,20 @@ async function closeSession(sessions, sessionId) {
33994
33983
  await session.transport.close().catch(() => {
33995
33984
  });
33996
33985
  }
33986
+ function touchSession(session, now) {
33987
+ session.lastActivityAt = now;
33988
+ }
33989
+ async function sweepIdleSessions(sessions, idleTimeoutMs, now) {
33990
+ const expiredSessionIds = [];
33991
+ for (const [sessionId, session] of sessions.entries()) {
33992
+ if (now - session.lastActivityAt >= idleTimeoutMs) {
33993
+ expiredSessionIds.push(sessionId);
33994
+ }
33995
+ }
33996
+ await Promise.all(
33997
+ expiredSessionIds.map((sessionId) => closeSession(sessions, sessionId))
33998
+ );
33999
+ }
33997
34000
  function sendInvalidSessionResponse(res) {
33998
34001
  res.status(400).json({
33999
34002
  jsonrpc: "2.0",
@@ -34009,7 +34012,13 @@ function createApp(options = {}) {
34009
34012
  const port = options.port ?? 3e3;
34010
34013
  const allowedOrigins = options.allowedOrigins ?? parseAllowedOrigins(void 0, port);
34011
34014
  const sessions = /* @__PURE__ */ new Map();
34015
+ const sessionIdleTimeoutMs = options.sessionIdleTimeoutMs ?? DEFAULT_SESSION_IDLE_TIMEOUT_MS;
34016
+ const sessionSweepIntervalMs = options.sessionSweepIntervalMs ?? DEFAULT_SESSION_SWEEP_INTERVAL_MS;
34012
34017
  app.use(import_express.default.json());
34018
+ const sessionSweepTimer = setInterval(() => {
34019
+ void sweepIdleSessions(sessions, sessionIdleTimeoutMs, Date.now());
34020
+ }, sessionSweepIntervalMs);
34021
+ sessionSweepTimer.unref?.();
34013
34022
  app.get("/health", (_req, res) => {
34014
34023
  res.json({ status: "ok", server: "fdic-mcp-server", version: VERSION });
34015
34024
  });
@@ -34030,6 +34039,7 @@ function createApp(options = {}) {
34030
34039
  });
34031
34040
  return;
34032
34041
  }
34042
+ touchSession(session, Date.now());
34033
34043
  await session.transport.handleRequest(req, res, req.body);
34034
34044
  if (req.method === "DELETE") {
34035
34045
  await closeSession(sessions, sessionId);
@@ -34047,7 +34057,11 @@ function createApp(options = {}) {
34047
34057
  enableDnsRebindingProtection: true,
34048
34058
  allowedOrigins,
34049
34059
  onsessioninitialized: (newSessionId) => {
34050
- sessions.set(newSessionId, { server, transport });
34060
+ sessions.set(newSessionId, {
34061
+ server,
34062
+ transport,
34063
+ lastActivityAt: Date.now()
34064
+ });
34051
34065
  }
34052
34066
  });
34053
34067
  transport.onclose = () => {
package/dist/server.js CHANGED
@@ -46,7 +46,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
46
46
  var import_express = __toESM(require("express"));
47
47
 
48
48
  // src/constants.ts
49
- var VERSION = true ? "1.2.3" : process.env.npm_package_version ?? "0.0.0-dev";
49
+ var VERSION = true ? "1.2.5" : process.env.npm_package_version ?? "0.0.0-dev";
50
50
  var FDIC_API_BASE_URL = "https://banks.data.fdic.gov/api";
51
51
  var CHARACTER_LIMIT = 5e4;
52
52
  var DEFAULT_FDIC_MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
@@ -32816,7 +32816,9 @@ function buildAnalysisOutput(params) {
32816
32816
  sort_by: params.sortBy,
32817
32817
  sort_order: params.sortOrder,
32818
32818
  warnings: params.warnings,
32819
- insights: buildTopLevelInsights(params.comparisons),
32819
+ insights: buildTopLevelInsights(
32820
+ params.insightComparisons ?? params.comparisons
32821
+ ),
32820
32822
  ...buildPaginationInfo(params.analyzedCount, offset, count),
32821
32823
  comparisons: params.comparisons
32822
32824
  };
@@ -33107,7 +33109,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33107
33109
  server.server,
33108
33110
  progressToken,
33109
33111
  0.3,
33110
- "Fetching financial time series"
33112
+ include_demographics ? "Fetching financial and demographic time series" : "Fetching financial time series"
33111
33113
  );
33112
33114
  const [financialSeriesResult, demographicsSeriesResult] = await Promise.all([
33113
33115
  fetchSeriesRecords(
@@ -33134,14 +33136,6 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33134
33136
  ...financialSeriesResult.warnings,
33135
33137
  ...demographicsSeriesResult.warnings
33136
33138
  );
33137
- if (include_demographics) {
33138
- await sendProgressNotification(
33139
- server.server,
33140
- progressToken,
33141
- 0.7,
33142
- "Fetching demographics time series"
33143
- );
33144
- }
33145
33139
  await sendProgressNotification(
33146
33140
  server.server,
33147
33141
  progressToken,
@@ -33167,7 +33161,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33167
33161
  server.server,
33168
33162
  progressToken,
33169
33163
  0.3,
33170
- "Fetching financial snapshots"
33164
+ include_demographics ? "Fetching financial and demographic snapshots" : "Fetching financial snapshots"
33171
33165
  );
33172
33166
  const [financialSnapshotsResult, demographicSnapshotsResult] = await Promise.all([
33173
33167
  fetchBatchedRecordsForDates(
@@ -33192,14 +33186,6 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33192
33186
  ...financialSnapshotsResult.warnings,
33193
33187
  ...demographicSnapshotsResult.warnings
33194
33188
  );
33195
- if (include_demographics) {
33196
- await sendProgressNotification(
33197
- server.server,
33198
- progressToken,
33199
- 0.7,
33200
- "Fetching demographic snapshots"
33201
- );
33202
- }
33203
33189
  await sendProgressNotification(
33204
33190
  server.server,
33205
33191
  progressToken,
@@ -33244,6 +33230,7 @@ Returns concise comparison text plus structured deltas, derived metrics, and ins
33244
33230
  sortOrder: sort_order,
33245
33231
  warnings,
33246
33232
  comparisons: ranked,
33233
+ insightComparisons: sortedComparisons,
33247
33234
  limitCount: ranked.length
33248
33235
  });
33249
33236
  const text = truncateIfNeeded(
@@ -33997,6 +33984,8 @@ function parseAllowedOrigins(rawOrigins, port) {
33997
33984
  `https://127.0.0.1:${port}`
33998
33985
  ];
33999
33986
  }
33987
+ var DEFAULT_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
33988
+ var DEFAULT_SESSION_SWEEP_INTERVAL_MS = 5 * 60 * 1e3;
34000
33989
  async function closeSession(sessions, sessionId) {
34001
33990
  const session = sessions.get(sessionId);
34002
33991
  if (!session) {
@@ -34008,6 +33997,20 @@ async function closeSession(sessions, sessionId) {
34008
33997
  await session.transport.close().catch(() => {
34009
33998
  });
34010
33999
  }
34000
+ function touchSession(session, now) {
34001
+ session.lastActivityAt = now;
34002
+ }
34003
+ async function sweepIdleSessions(sessions, idleTimeoutMs, now) {
34004
+ const expiredSessionIds = [];
34005
+ for (const [sessionId, session] of sessions.entries()) {
34006
+ if (now - session.lastActivityAt >= idleTimeoutMs) {
34007
+ expiredSessionIds.push(sessionId);
34008
+ }
34009
+ }
34010
+ await Promise.all(
34011
+ expiredSessionIds.map((sessionId) => closeSession(sessions, sessionId))
34012
+ );
34013
+ }
34011
34014
  function sendInvalidSessionResponse(res) {
34012
34015
  res.status(400).json({
34013
34016
  jsonrpc: "2.0",
@@ -34023,7 +34026,13 @@ function createApp(options = {}) {
34023
34026
  const port = options.port ?? 3e3;
34024
34027
  const allowedOrigins = options.allowedOrigins ?? parseAllowedOrigins(void 0, port);
34025
34028
  const sessions = /* @__PURE__ */ new Map();
34029
+ const sessionIdleTimeoutMs = options.sessionIdleTimeoutMs ?? DEFAULT_SESSION_IDLE_TIMEOUT_MS;
34030
+ const sessionSweepIntervalMs = options.sessionSweepIntervalMs ?? DEFAULT_SESSION_SWEEP_INTERVAL_MS;
34026
34031
  app.use(import_express.default.json());
34032
+ const sessionSweepTimer = setInterval(() => {
34033
+ void sweepIdleSessions(sessions, sessionIdleTimeoutMs, Date.now());
34034
+ }, sessionSweepIntervalMs);
34035
+ sessionSweepTimer.unref?.();
34027
34036
  app.get("/health", (_req, res) => {
34028
34037
  res.json({ status: "ok", server: "fdic-mcp-server", version: VERSION });
34029
34038
  });
@@ -34044,6 +34053,7 @@ function createApp(options = {}) {
34044
34053
  });
34045
34054
  return;
34046
34055
  }
34056
+ touchSession(session, Date.now());
34047
34057
  await session.transport.handleRequest(req, res, req.body);
34048
34058
  if (req.method === "DELETE") {
34049
34059
  await closeSession(sessions, sessionId);
@@ -34061,7 +34071,11 @@ function createApp(options = {}) {
34061
34071
  enableDnsRebindingProtection: true,
34062
34072
  allowedOrigins,
34063
34073
  onsessioninitialized: (newSessionId) => {
34064
- sessions.set(newSessionId, { server, transport });
34074
+ sessions.set(newSessionId, {
34075
+ server,
34076
+ transport,
34077
+ lastActivityAt: Date.now()
34078
+ });
34065
34079
  }
34066
34080
  });
34067
34081
  transport.onclose = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdic-mcp-server",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "MCP server for the FDIC BankFind Suite API",
5
5
  "mcpName": "io.github.jflamb/fdic-mcp-server",
6
6
  "main": "dist/server.js",