fdic-mcp-server 1.7.0 → 1.7.1
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 +66 -2
- package/dist/server.js +66 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
|
32
32
|
var import_express2 = __toESM(require("express"));
|
|
33
33
|
|
|
34
34
|
// src/constants.ts
|
|
35
|
-
var VERSION = true ? "1.7.
|
|
35
|
+
var VERSION = true ? "1.7.1" : 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;
|
|
@@ -95,6 +95,7 @@ var DEFAULT_CHAT_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
|
95
95
|
var DEFAULT_CHAT_MAX_MESSAGES = 20;
|
|
96
96
|
var DEFAULT_CHAT_MAX_MESSAGE_LENGTH = 500;
|
|
97
97
|
var DEFAULT_CHAT_MAX_TOOL_ROUNDS = 5;
|
|
98
|
+
var DEFAULT_CHAT_GENERATE_RETRIES = 2;
|
|
98
99
|
var genAIModulePromise;
|
|
99
100
|
function loadGenAIModule() {
|
|
100
101
|
genAIModulePromise ??= import("@google/genai");
|
|
@@ -202,6 +203,62 @@ function getResponseParts(response) {
|
|
|
202
203
|
function getResponseText(response) {
|
|
203
204
|
return response.text?.trim() || void 0;
|
|
204
205
|
}
|
|
206
|
+
function wait(ms) {
|
|
207
|
+
return new Promise((resolve) => {
|
|
208
|
+
setTimeout(resolve, ms);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function getErrorCode(error) {
|
|
212
|
+
if (!error || typeof error !== "object") {
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
const record = error;
|
|
216
|
+
const candidate = record.status ?? record.statusCode ?? record.code;
|
|
217
|
+
return typeof candidate === "number" || typeof candidate === "string" ? candidate : void 0;
|
|
218
|
+
}
|
|
219
|
+
function isTransientChatError(error) {
|
|
220
|
+
const code = getErrorCode(error);
|
|
221
|
+
if (code === 408 || code === 409 || code === 425 || code === 429 || code === 500 || code === 502 || code === 503 || code === 504) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
if (code === "ABORTED" || code === "DEADLINE_EXCEEDED" || code === "INTERNAL" || code === "RESOURCE_EXHAUSTED" || code === "UNAVAILABLE") {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
228
|
+
return /timeout|temporar|unavailable|overloaded|internal|deadline/i.test(
|
|
229
|
+
message
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
function logChatFailure(context) {
|
|
233
|
+
const { error } = context;
|
|
234
|
+
console.error(
|
|
235
|
+
JSON.stringify({
|
|
236
|
+
event: "chat_request_failed",
|
|
237
|
+
sessionId: context.sessionId,
|
|
238
|
+
requestIp: context.requestIp,
|
|
239
|
+
messageCount: context.messageCount,
|
|
240
|
+
model: context.model,
|
|
241
|
+
errorName: error instanceof Error ? error.name : void 0,
|
|
242
|
+
errorMessage: error instanceof Error ? error.message : String(error ?? "unknown"),
|
|
243
|
+
errorCode: getErrorCode(error),
|
|
244
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
245
|
+
})
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
async function generateContentWithRetry(ai, request) {
|
|
249
|
+
let attempt = 0;
|
|
250
|
+
while (true) {
|
|
251
|
+
try {
|
|
252
|
+
return await ai.models.generateContent(request);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (attempt >= DEFAULT_CHAT_GENERATE_RETRIES || !isTransientChatError(error)) {
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
attempt += 1;
|
|
258
|
+
await wait(150 * attempt);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
205
262
|
async function executeToolCall(server, name, args) {
|
|
206
263
|
const callTool = getToolCallHandler(server);
|
|
207
264
|
const result = await callTool(
|
|
@@ -235,7 +292,7 @@ async function runConversation(ai, model, functionDeclarations, server, history)
|
|
|
235
292
|
} = await loadGenAIModule();
|
|
236
293
|
const contents = [...history];
|
|
237
294
|
for (let round = 0; round < DEFAULT_CHAT_MAX_TOOL_ROUNDS; round += 1) {
|
|
238
|
-
const response = await ai
|
|
295
|
+
const response = await generateContentWithRetry(ai, {
|
|
239
296
|
model,
|
|
240
297
|
contents,
|
|
241
298
|
config: {
|
|
@@ -361,6 +418,13 @@ function createChatRouter(options) {
|
|
|
361
418
|
reply: conversation.reply
|
|
362
419
|
});
|
|
363
420
|
} catch (error) {
|
|
421
|
+
logChatFailure({
|
|
422
|
+
sessionId,
|
|
423
|
+
requestIp,
|
|
424
|
+
messageCount: validationResult.length,
|
|
425
|
+
model,
|
|
426
|
+
error
|
|
427
|
+
});
|
|
364
428
|
const message = error instanceof Error ? error.message : "Failed to process chat request";
|
|
365
429
|
const status = message === "Chat tool-call limit exceeded" ? 502 : 500;
|
|
366
430
|
res.status(status).json({ error: message });
|
package/dist/server.js
CHANGED
|
@@ -46,7 +46,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
|
46
46
|
var import_express2 = __toESM(require("express"));
|
|
47
47
|
|
|
48
48
|
// src/constants.ts
|
|
49
|
-
var VERSION = true ? "1.7.
|
|
49
|
+
var VERSION = true ? "1.7.1" : 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;
|
|
@@ -109,6 +109,7 @@ var DEFAULT_CHAT_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
|
109
109
|
var DEFAULT_CHAT_MAX_MESSAGES = 20;
|
|
110
110
|
var DEFAULT_CHAT_MAX_MESSAGE_LENGTH = 500;
|
|
111
111
|
var DEFAULT_CHAT_MAX_TOOL_ROUNDS = 5;
|
|
112
|
+
var DEFAULT_CHAT_GENERATE_RETRIES = 2;
|
|
112
113
|
var genAIModulePromise;
|
|
113
114
|
function loadGenAIModule() {
|
|
114
115
|
genAIModulePromise ??= import("@google/genai");
|
|
@@ -216,6 +217,62 @@ function getResponseParts(response) {
|
|
|
216
217
|
function getResponseText(response) {
|
|
217
218
|
return response.text?.trim() || void 0;
|
|
218
219
|
}
|
|
220
|
+
function wait(ms) {
|
|
221
|
+
return new Promise((resolve) => {
|
|
222
|
+
setTimeout(resolve, ms);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function getErrorCode(error) {
|
|
226
|
+
if (!error || typeof error !== "object") {
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
const record = error;
|
|
230
|
+
const candidate = record.status ?? record.statusCode ?? record.code;
|
|
231
|
+
return typeof candidate === "number" || typeof candidate === "string" ? candidate : void 0;
|
|
232
|
+
}
|
|
233
|
+
function isTransientChatError(error) {
|
|
234
|
+
const code = getErrorCode(error);
|
|
235
|
+
if (code === 408 || code === 409 || code === 425 || code === 429 || code === 500 || code === 502 || code === 503 || code === 504) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
if (code === "ABORTED" || code === "DEADLINE_EXCEEDED" || code === "INTERNAL" || code === "RESOURCE_EXHAUSTED" || code === "UNAVAILABLE") {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
242
|
+
return /timeout|temporar|unavailable|overloaded|internal|deadline/i.test(
|
|
243
|
+
message
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
function logChatFailure(context) {
|
|
247
|
+
const { error } = context;
|
|
248
|
+
console.error(
|
|
249
|
+
JSON.stringify({
|
|
250
|
+
event: "chat_request_failed",
|
|
251
|
+
sessionId: context.sessionId,
|
|
252
|
+
requestIp: context.requestIp,
|
|
253
|
+
messageCount: context.messageCount,
|
|
254
|
+
model: context.model,
|
|
255
|
+
errorName: error instanceof Error ? error.name : void 0,
|
|
256
|
+
errorMessage: error instanceof Error ? error.message : String(error ?? "unknown"),
|
|
257
|
+
errorCode: getErrorCode(error),
|
|
258
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
259
|
+
})
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
async function generateContentWithRetry(ai, request) {
|
|
263
|
+
let attempt = 0;
|
|
264
|
+
while (true) {
|
|
265
|
+
try {
|
|
266
|
+
return await ai.models.generateContent(request);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
if (attempt >= DEFAULT_CHAT_GENERATE_RETRIES || !isTransientChatError(error)) {
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
attempt += 1;
|
|
272
|
+
await wait(150 * attempt);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
219
276
|
async function executeToolCall(server, name, args) {
|
|
220
277
|
const callTool = getToolCallHandler(server);
|
|
221
278
|
const result = await callTool(
|
|
@@ -249,7 +306,7 @@ async function runConversation(ai, model, functionDeclarations, server, history)
|
|
|
249
306
|
} = await loadGenAIModule();
|
|
250
307
|
const contents = [...history];
|
|
251
308
|
for (let round = 0; round < DEFAULT_CHAT_MAX_TOOL_ROUNDS; round += 1) {
|
|
252
|
-
const response = await ai
|
|
309
|
+
const response = await generateContentWithRetry(ai, {
|
|
253
310
|
model,
|
|
254
311
|
contents,
|
|
255
312
|
config: {
|
|
@@ -375,6 +432,13 @@ function createChatRouter(options) {
|
|
|
375
432
|
reply: conversation.reply
|
|
376
433
|
});
|
|
377
434
|
} catch (error) {
|
|
435
|
+
logChatFailure({
|
|
436
|
+
sessionId,
|
|
437
|
+
requestIp,
|
|
438
|
+
messageCount: validationResult.length,
|
|
439
|
+
model,
|
|
440
|
+
error
|
|
441
|
+
});
|
|
378
442
|
const message = error instanceof Error ? error.message : "Failed to process chat request";
|
|
379
443
|
const status = message === "Chat tool-call limit exceeded" ? 502 : 500;
|
|
380
444
|
res.status(status).json({ error: message });
|