cryptoiz-mcp 4.6.0 → 4.7.0

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/package.json +1 -1
  2. package/src/index.js +22 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptoiz-mcp",
3
- "version": "4.6.0",
3
+ "version": "4.7.0",
4
4
  "description": "CryptoIZ MCP Server — Solana DEX signals with x402 micropayments. Pay $0.01 USDC per call.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -28,7 +28,15 @@ const PRICE_LABELS = {
28
28
  async function payAndFetch(url, tool = 'get_alpha_scanner') {
29
29
  const AMOUNT = PRICES[tool] || 10000;
30
30
  if (!SVM_PRIVATE_KEY) return { error: 'SVM_PRIVATE_KEY not set.' };
31
- const first = await fetch(url);
31
+ // Timeout: 20s for initial check, 30s for paid request
32
+ const fetchWithTimeout = (u, opts = {}, ms = 20000) => {
33
+ const ctrl = new AbortController();
34
+ const t = setTimeout(() => ctrl.abort(), ms);
35
+ return fetch(u, { ...opts, signal: ctrl.signal }).finally(() => clearTimeout(t));
36
+ };
37
+ let first;
38
+ try { first = await fetchWithTimeout(url, {}, 20000); }
39
+ catch (e) { return { error: `Gateway timeout or unreachable: ${e.message}` }; }
32
40
  if (first.status !== 402) return first.json();
33
41
  try {
34
42
  const keypair = Keypair.fromSecretKey(bs58.decode(SVM_PRIVATE_KEY));
@@ -39,7 +47,7 @@ async function payAndFetch(url, tool = 'get_alpha_scanner') {
39
47
  const sig = await connection.sendTransaction(tx, [keypair]);
40
48
  await connection.confirmTransaction(sig, 'confirmed');
41
49
  const payment = Buffer.from(JSON.stringify({ signature: sig, network: 'solana', x402Version: 1 })).toString('base64');
42
- const paid = await fetch(url, { headers: { 'x-payment': payment } });
50
+ const paid = await fetchWithTimeout(url, { headers: { 'x-payment': payment } }, 30000);
43
51
  return paid.json();
44
52
  } catch (err) {
45
53
  return { error: `Payment failed: ${err.message}` };
@@ -419,7 +427,7 @@ const TOOLS = [
419
427
  // ══════════════════════════════════════════════════════════════════
420
428
  // SERVER
421
429
  // ══════════════════════════════════════════════════════════════════
422
- const server = new Server({ name: 'cryptoiz-mcp', version: '4.5.0' }, { capabilities: { tools: {} } });
430
+ const server = new Server({ name: 'cryptoiz-mcp', version: '4.6.0' }, { capabilities: { tools: {} } });
423
431
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
424
432
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
425
433
  const { name, arguments: args } = request.params;
@@ -459,8 +467,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
459
467
  if (name === 'get_token_ca') {
460
468
  const tokenName = args?.token_name || '';
461
469
  if (!tokenName) return { content: [{ type: 'text', text: '❌ Please provide a token_name. Example: "Aliens"' }], isError: true };
462
- const data = await payAndFetch(`${GATEWAY_URL}?tool=get_alpha_scanner`, 'get_alpha_scanner');
463
- return { content: [{ type: 'text', text: await getTokenCA(tokenName, data) }] };
470
+ // FREE tool fetch without payment using free-ca endpoint
471
+ try {
472
+ const controller = new AbortController();
473
+ const timeout = setTimeout(() => controller.abort(), 15000);
474
+ const res = await fetch(`${GATEWAY_URL}?tool=get_token_ca&name=${encodeURIComponent(tokenName)}`, { signal: controller.signal });
475
+ clearTimeout(timeout);
476
+ const data = await res.json();
477
+ return { content: [{ type: 'text', text: await getTokenCA(tokenName, data) }] };
478
+ } catch (err) {
479
+ return { content: [{ type: 'text', text: `❌ CA lookup failed: ${err.message}` }], isError: true };
480
+ }
464
481
  }
465
482
 
466
483
  return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };