@fundtracer/mcp 1.0.3 → 1.0.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.
Files changed (2) hide show
  1. package/fundtracer-mcp.js +84 -17
  2. package/package.json +1 -1
package/fundtracer-mcp.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ #!/usr/bin/env node
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
5
  var __esm = (fn, res) => function __init() {
@@ -219,6 +220,31 @@ var init_tools = __esm({
219
220
  }
220
221
  });
221
222
 
223
+ // src/mcp/mcpLogger.ts
224
+ import { getFirestore } from "../firebase.js";
225
+ async function logMcpRequest(entry) {
226
+ try {
227
+ const db = getFirestore();
228
+ if (!db) {
229
+ console.warn("[MCP-LOGGER] getFirestore() returned null");
230
+ return;
231
+ }
232
+ await db.collection("mcpLogs").add(entry);
233
+ console.log("[MCP-LOGGER] Logged:", entry.toolName, "for user:", entry.userId, "status:", entry.status);
234
+ } catch (err2) {
235
+ mcpLogWarnings++;
236
+ if (mcpLogWarnings <= 3 || mcpLogWarnings % 10 === 0) {
237
+ console.error("[MCP-LOGGER] Failed to log MCP request:", err2?.message || err2);
238
+ }
239
+ }
240
+ }
241
+ var mcpLogWarnings;
242
+ var init_mcpLogger = __esm({
243
+ "src/mcp/mcpLogger.ts"() {
244
+ mcpLogWarnings = 0;
245
+ }
246
+ });
247
+
222
248
  // src/mcp/api-handlers.ts
223
249
  var api_handlers_exports = {};
224
250
  __export(api_handlers_exports, {
@@ -233,19 +259,60 @@ function err(message) {
233
259
  }
234
260
  function api() {
235
261
  const key = process.env.FUNDTRACER_MCP_API_KEY || "";
262
+ const headers = {
263
+ Authorization: `Bearer ${key}`,
264
+ "x-auth-token": key,
265
+ "Content-Type": "application/json"
266
+ };
267
+ if (_mcpCtx?.userId) {
268
+ headers["X-MCP-UserId"] = _mcpCtx.userId;
269
+ }
236
270
  return axios.create({
237
271
  baseURL: API_BASE,
238
272
  timeout: 6e4,
239
- headers: {
240
- Authorization: `Bearer ${key}`,
241
- "Content-Type": "application/json"
242
- }
273
+ headers
243
274
  });
244
275
  }
245
- var API_BASE, analyzeWallet, traceFunds, compareWallets, analyzeContract, detectSybilClusters, getPortfolio, getTransactions, lookupEntity, getGasPrices, getTokenInfo, TOOL_HANDLERS;
276
+ function withLogging(toolName, handler) {
277
+ return async (args, ctx) => {
278
+ _mcpCtx = ctx;
279
+ const start = Date.now();
280
+ try {
281
+ const result = await handler(args, ctx);
282
+ logMcpRequest({
283
+ userId: ctx.userId,
284
+ toolName,
285
+ args: JSON.stringify(args).substring(0, 500),
286
+ status: result.isError ? "error" : "success",
287
+ responsePreview: JSON.stringify(result).substring(0, 300),
288
+ duration: Date.now() - start,
289
+ createdAt: Date.now(),
290
+ keyPrefix: ctx.apiKeyPrefix
291
+ });
292
+ return result;
293
+ } catch (error) {
294
+ logMcpRequest({
295
+ userId: ctx.userId,
296
+ toolName,
297
+ args: JSON.stringify(args).substring(0, 500),
298
+ status: "error",
299
+ responsePreview: error.message.substring(0, 300),
300
+ duration: Date.now() - start,
301
+ createdAt: Date.now(),
302
+ keyPrefix: ctx.apiKeyPrefix
303
+ });
304
+ throw error;
305
+ } finally {
306
+ _mcpCtx = null;
307
+ }
308
+ };
309
+ }
310
+ var API_BASE, _mcpCtx, analyzeWallet, traceFunds, compareWallets, analyzeContract, detectSybilClusters, getPortfolio, getTransactions, lookupEntity, getGasPrices, getTokenInfo, TOOL_HANDLERS;
246
311
  var init_api_handlers = __esm({
247
312
  "src/mcp/api-handlers.ts"() {
313
+ init_mcpLogger();
248
314
  API_BASE = process.env.FUNDTRACER_API_URL || "https://api.fundtracer.xyz";
315
+ _mcpCtx = null;
249
316
  analyzeWallet = async (args, ctx) => {
250
317
  const { address, chainId, transactionLimit } = args;
251
318
  try {
@@ -399,16 +466,16 @@ var init_api_handlers = __esm({
399
466
  }
400
467
  };
401
468
  TOOL_HANDLERS = {
402
- analyze_wallet: analyzeWallet,
403
- trace_funds: traceFunds,
404
- compare_wallets: compareWallets,
405
- analyze_contract: analyzeContract,
406
- detect_sybil_clusters: detectSybilClusters,
407
- get_portfolio: getPortfolio,
408
- get_transactions: getTransactions,
409
- lookup_entity: lookupEntity,
410
- get_gas_prices: getGasPrices,
411
- get_token_info: getTokenInfo
469
+ analyze_wallet: withLogging("analyze_wallet", analyzeWallet),
470
+ trace_funds: withLogging("trace_funds", traceFunds),
471
+ compare_wallets: withLogging("compare_wallets", compareWallets),
472
+ analyze_contract: withLogging("analyze_contract", analyzeContract),
473
+ detect_sybil_clusters: withLogging("detect_sybil_clusters", detectSybilClusters),
474
+ get_portfolio: withLogging("get_portfolio", getPortfolio),
475
+ get_transactions: withLogging("get_transactions", getTransactions),
476
+ lookup_entity: withLogging("lookup_entity", lookupEntity),
477
+ get_gas_prices: withLogging("get_gas_prices", getGasPrices),
478
+ get_token_info: withLogging("get_token_info", getTokenInfo)
412
479
  };
413
480
  }
414
481
  });
@@ -430,8 +497,8 @@ async function validateMcpApiKey(rawKey) {
430
497
  return validateViaHttp(rawKey);
431
498
  }
432
499
  async function validateWithFirestore(rawKey) {
433
- const { getFirestore } = await import("../firebase.js");
434
- const db = getFirestore();
500
+ const { getFirestore: getFirestore2 } = await import("../firebase.js");
501
+ const db = getFirestore2();
435
502
  if (!db) return null;
436
503
  const keyDoc = await db.collection("apiKeys").doc(rawKey).get();
437
504
  if (keyDoc.exists) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fundtracer/mcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "FundTracer MCP Server — blockchain analysis for AI assistants (Claude Desktop, Claude Code, Cursor, etc.)",
5
5
  "type": "module",
6
6
  "main": "fundtracer-mcp.js",