cryptoiz-mcp 4.16.6 → 4.16.7

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 (4) hide show
  1. package/README.md +5 -100
  2. package/index.js +154 -445
  3. package/package.json +21 -53
  4. package/setup.js +51 -132
package/README.md CHANGED
@@ -1,100 +1,5 @@
1
- # CryptoIZ MCP Server
2
-
3
- AI-powered Solana DEX whale intelligence for Claude Desktop. Pay per call with USDC on Solana via x402 Dexter protocol.
4
-
5
- ## Quick Install (2 commands)
6
-
7
- ```bash
8
- npm install -g cryptoiz-mcp
9
- npx cryptoiz-mcp-setup YOUR_SOLANA_PRIVATE_KEY
10
- ```
11
-
12
- Auto-detects OS, finds Claude Desktop config (including Windows MSIX), writes correct config. Restart Claude Desktop and type `get_status`.
13
-
14
- ## Prerequisites
15
-
16
- 1. **Node.js** v18+ from nodejs.org
17
- 2. **Claude Desktop** from claude.ai/download
18
- 3. **Solana wallet** with $1-5 USDC (no SOL needed, Dexter sponsors gas)
19
-
20
- ## Tools and Pricing
21
-
22
- | Tool | Price | Data |
23
- |------|-------|------|
24
- | get_whale_alpha | $0.05 | 20 smart money whale/dolphin signals |
25
- | get_whale_divergence | $0.02 | 20 divergence signals (3 types) |
26
- | get_whale_accumulation | $0.02 | Tokens in accumulation phase |
27
- | get_whale_neutral | $0.02 | Tokens in neutral phase |
28
- | get_whale_distribution | $0.02 | Tokens in distribution phase |
29
- | get_btc_regime | $0.01 | BTC macro + Fear/Greed + technicals |
30
- | get_btc_futures_signal | $0.03 | MTF BTC futures scalping signal (4h regime + 5m entry) |
31
- | get_token_ca | FREE | Contract address lookup |
32
- | get_status | FREE | Server health check |
33
-
34
- ## Manual Config (if auto-installer fails)
35
-
36
- ### macOS
37
- Config: ~/Library/Application Support/Claude/claude_desktop_config.json
38
-
39
- ```json
40
- {
41
- "mcpServers": {
42
- "cryptoiz": {
43
- "command": "npx",
44
- "args": ["-y", "cryptoiz-mcp"],
45
- "env": {
46
- "SVM_PRIVATE_KEY": "your-base58-private-key"
47
- }
48
- }
49
- }
50
- }
51
- ```
52
-
53
- ### Windows
54
- IMPORTANT: npx does NOT work on Windows. Use absolute paths.
55
-
56
- Config location depends on install type:
57
- - MSIX (most common): %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json
58
- - Standard: %APPDATA%\Claude\claude_desktop_config.json
59
-
60
- Check: run `dir "$env:LOCALAPPDATA\Packages\Claude*"` in PowerShell. If folder exists = MSIX.
61
-
62
- ```json
63
- {
64
- "mcpServers": {
65
- "cryptoiz": {
66
- "command": "C:\\Program Files\\nodejs\\node.exe",
67
- "args": ["C:\\Users\\YOUR_USERNAME\\AppData\\Roaming\\npm\\node_modules\\cryptoiz-mcp\\index.js"],
68
- "env": {
69
- "SVM_PRIVATE_KEY": "your-base58-private-key"
70
- }
71
- }
72
- }
73
- }
74
- ```
75
-
76
- ## Troubleshooting
77
-
78
- **"No servers added" after setup:**
79
- Config written to wrong path. Windows MSIX reads from LocalAppData, not AppData. Copy:
80
- ```powershell
81
- copy "$env:APPDATA\Claude\claude_desktop_config.json" "$env:LOCALAPPDATA\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json"
82
- ```
83
-
84
- **"spawn npx ENOENT" on Windows:**
85
- Use absolute paths, not npx. See Windows config above.
86
-
87
- **Server disconnected:**
88
- Check logs: Get-Content "$env:APPDATA\Claude\logs\mcp-server-cryptoiz.log" -Tail 30
89
-
90
- ## Security
91
-
92
- Private key stored only in local config. Never sent to CryptoIZ. Gas sponsored by Dexter. Use a dedicated wallet.
93
-
94
- ## Links
95
-
96
- - Guide: https://cryptoiz.org/McpLanding
97
- - Platform: https://cryptoiz.org
98
- - Dexter: https://dexter.cash/sellers/DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX
99
- - Twitter: @cryptoiz_IDN
100
- - npm: https://www.npmjs.com/package/cryptoiz-mcp
1
+ # cryptoiz-mcp
2
+
3
+ CryptoIZ MCP Server - Solana DEX whale intelligence via Claude Desktop.
4
+
5
+ Setup: https://cryptoiz.org/McpLanding
package/index.js CHANGED
@@ -1,445 +1,154 @@
1
- #!/usr/bin/env node
2
- // CryptoIZ MCP Server v4.16.3
3
- // Whale Intelligence Suite: 7 paid tools + 2 free
4
- // x402 V2: Dexter facilitator (gas sponsored) + V1 backward compat
5
- // ZERO template literals — Windows PowerShell safe
6
- // v4.16.3: Added x-client-version header for server-side update notifications
7
- // Removed deprecated DEV_KEY bypass (gateway-side already disabled)
8
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
11
- import { Connection, Keypair, PublicKey, Transaction, SystemProgram, VersionedTransaction, TransactionMessage } from '@solana/web3.js';
12
- import bs58 from 'bs58';
13
-
14
- var VERSION = 'v4.16.4';
15
- var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
16
-
17
- // Per-tool endpoints for Dexter settlement naming
18
- var TOOL_ENDPOINTS = {
19
- get_whale_alpha: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-alpha-scanner',
20
- get_whale_divergence: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-divergence',
21
- get_whale_accumulation: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-accumulation',
22
- get_whale_neutral: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-neutral',
23
- get_whale_distribution: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-distribution',
24
- get_btc_regime: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-btc-regime',
25
- get_btc_futures_signal: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-btc-futures',
26
- // Backward compat: old names -> same proxy endpoints
27
- get_alpha_scanner: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-alpha-scanner',
28
- get_divergence: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-divergence',
29
- get_accumulation: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-accumulation',
30
- };
31
-
32
- var RECIPIENT = 'DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX';
33
- var USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
34
- var DEXTER_FEE_PAYER = 'DEXVS3su4dZQWTvvPnLDJLRK1CeeKG6K3QqdzthgAkNV';
35
- var SOL_RPC = 'https://api.mainnet-beta.solana.com';
36
- var TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
37
- var ATA_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
38
-
39
- // ===== Update notification (logged once per session) =====
40
- var _updateNotified = false;
41
- function maybeNotifyUpdate(data, headers) {
42
- if (_updateNotified) return;
43
- if (!data || !data.update_available) {
44
- // Also check response headers as fallback
45
- if (!headers || headers.get('x-update-available') !== '1') return;
46
- }
47
- _updateNotified = true;
48
- var sev = (data && data.update_severity) || 'unknown';
49
- var latest = (data && data.version_latest) || (headers && headers.get('x-server-version')) || '?';
50
- var cmd = (data && data.update_command) || 'npx cryptoiz-mcp-setup@latest';
51
- var changelog = (data && data.changelog_url) || '';
52
- console.error('');
53
- console.error('[cryptoiz-mcp] ============================================');
54
- console.error('[cryptoiz-mcp] UPDATE AVAILABLE: ' + VERSION + ' -> ' + latest);
55
- console.error('[cryptoiz-mcp] Severity: ' + sev);
56
- if (data && data.update_message) {
57
- console.error('[cryptoiz-mcp] ' + data.update_message);
58
- }
59
- console.error('[cryptoiz-mcp] To update: ' + cmd);
60
- if (changelog) {
61
- console.error('[cryptoiz-mcp] Changelog: ' + changelog);
62
- }
63
- console.error('[cryptoiz-mcp] ============================================');
64
- console.error('');
65
- }
66
-
67
- function getKeypair() {
68
- var privKey = process.env.SVM_PRIVATE_KEY;
69
- if (!privKey) throw new Error('SVM_PRIVATE_KEY env var not set');
70
- try {
71
- var decoded = bs58.decode(privKey);
72
- return Keypair.fromSecretKey(decoded);
73
- } catch(e) {
74
- throw new Error('Invalid SVM_PRIVATE_KEY: ' + e.message);
75
- }
76
- }
77
-
78
- function findATA(wallet, mint) {
79
- var walletPk = new PublicKey(wallet);
80
- var mintPk = new PublicKey(mint);
81
- var ataProgramPk = new PublicKey(ATA_PROGRAM);
82
- var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
83
- var seeds = [walletPk.toBuffer(), tokenProgramPk.toBuffer(), mintPk.toBuffer()];
84
- var ata = PublicKey.findProgramAddressSync(seeds, ataProgramPk);
85
- return ata[0];
86
- }
87
-
88
- // ===== V2: Build partially-signed tx for Dexter facilitator =====
89
- var COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';
90
- var MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
91
-
92
- async function buildV2PaymentPayload(amount, feePayerAddr) {
93
- var kp = getKeypair();
94
- var conn = new Connection(SOL_RPC, 'confirmed');
95
- var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
96
- var recipientATA = findATA(RECIPIENT, USDC_MINT);
97
- var feePayerPk = new PublicKey(feePayerAddr);
98
- var computeBudgetPk = new PublicKey(COMPUTE_BUDGET_PROGRAM);
99
- var memoProgramPk = new PublicKey(MEMO_PROGRAM);
100
- var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
101
- var usdcMintPk = new PublicKey(USDC_MINT);
102
- var setLimitData = Buffer.alloc(5);
103
- setLimitData.writeUInt8(2, 0);
104
- setLimitData.writeUInt32LE(20000, 1);
105
- var setLimitIx = { programId: computeBudgetPk, keys: [], data: setLimitData };
106
- var setPriceData = Buffer.alloc(9);
107
- setPriceData.writeUInt8(3, 0);
108
- setPriceData.writeUInt32LE(1, 1);
109
- setPriceData.writeUInt32LE(0, 5);
110
- var setPriceIx = { programId: computeBudgetPk, keys: [], data: setPriceData };
111
- var transferKeys = [
112
- { pubkey: userATA, isSigner: false, isWritable: true },
113
- { pubkey: usdcMintPk, isSigner: false, isWritable: false },
114
- { pubkey: recipientATA, isSigner: false, isWritable: true },
115
- { pubkey: kp.publicKey, isSigner: true, isWritable: false },
116
- ];
117
- var transferData = Buffer.alloc(10);
118
- transferData.writeUInt8(12, 0);
119
- var lo = amount & 0xFFFFFFFF;
120
- var hi = Math.floor(amount / 0x100000000) & 0xFFFFFFFF;
121
- transferData.writeUInt32LE(lo, 1);
122
- transferData.writeUInt32LE(hi, 5);
123
- transferData.writeUInt8(6, 9);
124
- var transferIx = { programId: tokenProgramPk, keys: transferKeys, data: transferData };
125
- var nonceBytes = new Uint8Array(16);
126
- for (var i = 0; i < 16; i++) { nonceBytes[i] = Math.floor(Math.random() * 256); }
127
- var nonceHex = '';
128
- for (var j = 0; j < 16; j++) {
129
- var h = nonceBytes[j].toString(16);
130
- nonceHex = nonceHex + (h.length < 2 ? '0' + h : h);
131
- }
132
- var memoData = Buffer.from(nonceHex, 'utf8');
133
- var memoIx = { programId: memoProgramPk, keys: [], data: memoData };
134
- var bhResult = await conn.getLatestBlockhash('confirmed');
135
- var message = new TransactionMessage({
136
- payerKey: feePayerPk,
137
- recentBlockhash: bhResult.blockhash,
138
- instructions: [setLimitIx, setPriceIx, transferIx, memoIx],
139
- }).compileToV0Message();
140
- var vtx = new VersionedTransaction(message);
141
- vtx.sign([kp]);
142
- var serialized = vtx.serialize();
143
- var txB64 = Buffer.from(serialized).toString('base64');
144
- console.error('[cryptoiz-mcp] V2 tx: 4 ix (Limit=20000 + Price=1 + TransferChecked + Memo), feePayer=' + feePayerAddr.substring(0, 8) + '..., nonce=' + nonceHex.substring(0, 8) + '...');
145
- return txB64;
146
- }
147
-
148
- // ===== V1 FALLBACK: Send USDC on-chain, return signature =====
149
- async function sendUSDC(amount) {
150
- var kp = getKeypair();
151
- var conn = new Connection(SOL_RPC, 'confirmed');
152
- var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
153
- var recipientATA = findATA(RECIPIENT, USDC_MINT);
154
- var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
155
- var keys = [
156
- { pubkey: userATA, isSigner: false, isWritable: true },
157
- { pubkey: recipientATA, isSigner: false, isWritable: true },
158
- { pubkey: kp.publicKey, isSigner: true, isWritable: false },
159
- ];
160
- var data = Buffer.alloc(9);
161
- data.writeUInt8(3, 0);
162
- var lo = amount & 0xFFFFFFFF;
163
- var hi = Math.floor(amount / 0x100000000) & 0xFFFFFFFF;
164
- data.writeUInt32LE(lo, 1);
165
- data.writeUInt32LE(hi, 5);
166
- var transferIx = {
167
- programId: tokenProgramPk,
168
- keys: keys,
169
- data: data,
170
- };
171
- var bhResult = await conn.getLatestBlockhash('confirmed');
172
- var tx = new Transaction({
173
- feePayer: kp.publicKey,
174
- blockhash: bhResult.blockhash,
175
- lastValidBlockHeight: bhResult.lastValidBlockHeight,
176
- });
177
- tx.add(transferIx);
178
- tx.sign(kp);
179
- var rawTx = tx.serialize();
180
- var sig = await conn.sendRawTransaction(rawTx, { skipPreflight: false });
181
- await conn.confirmTransaction({
182
- signature: sig,
183
- blockhash: bhResult.blockhash,
184
- lastValidBlockHeight: bhResult.lastValidBlockHeight
185
- }, 'confirmed');
186
- return sig;
187
- }
188
-
189
- // ===== Headers helper: every gateway request carries x-client-version =====
190
- function clientHeaders(extra) {
191
- // Strip leading 'v' for cleanliness — gateway accepts both
192
- var v = VERSION.replace(/^v/i, '');
193
- var h = { 'x-client-version': v };
194
- if (extra) {
195
- for (var k in extra) { if (Object.prototype.hasOwnProperty.call(extra, k)) h[k] = extra[k]; }
196
- }
197
- return h;
198
- }
199
-
200
- // ===== TOOL CALL HANDLER =====
201
- async function callTool(toolName, args) {
202
- var queryParts = [];
203
-
204
- // Use per-tool endpoint if available, otherwise gateway
205
- var baseUrl = TOOL_ENDPOINTS[toolName] || GATEWAY;
206
-
207
- if (!TOOL_ENDPOINTS[toolName]) {
208
- // Free tools go to gateway with tool param
209
- queryParts.push('tool=' + toolName);
210
- }
211
-
212
- // Handle timeframe for divergence tools (new and old name)
213
- if ((toolName === 'get_whale_divergence' || toolName === 'get_divergence') && args && args.timeframe) {
214
- queryParts.push('tf=' + args.timeframe);
215
- }
216
-
217
- if ((toolName === 'get_token_ca') && args && args.name) {
218
- queryParts.push('name=' + encodeURIComponent(args.name));
219
- }
220
-
221
- var url = queryParts.length > 0 ? baseUrl + '?' + queryParts.join('&') : baseUrl;
222
-
223
- // Step 1: Fetch gateway — expect 402 or 200 (free tools)
224
- var resp1 = await fetch(url, { headers: clientHeaders() });
225
- if (resp1.status === 200) {
226
- var data200 = await resp1.json();
227
- maybeNotifyUpdate(data200, resp1.headers);
228
- return data200;
229
- }
230
- if (resp1.status !== 402) {
231
- var errText = await resp1.text();
232
- throw new Error('Gateway error ' + resp1.status + ': ' + errText);
233
- }
234
-
235
- // Step 2: Parse 402 response — try V2 header first, fallback to body
236
- var paymentRequirements = null;
237
- var useV2 = false;
238
-
239
- var prHeader = resp1.headers.get('payment-required');
240
- if (prHeader) {
241
- try {
242
- var prDecoded = Buffer.from(prHeader, 'base64').toString('utf8');
243
- var prArray = JSON.parse(prDecoded);
244
- if (Array.isArray(prArray) && prArray.length > 0) {
245
- paymentRequirements = prArray[0];
246
- useV2 = true;
247
- }
248
- } catch(e) {
249
- console.error('[cryptoiz-mcp] Failed to parse PAYMENT-REQUIRED header:', e.message);
250
- }
251
- }
252
-
253
- // Fallback: read from body (V1 compat)
254
- if (!paymentRequirements) {
255
- var body402 = await resp1.json();
256
- if (body402.accepts && body402.accepts.length > 0) {
257
- paymentRequirements = body402.accepts[0];
258
- } else {
259
- throw new Error('402 response missing payment requirements');
260
- }
261
- }
262
-
263
- var amount = parseInt(paymentRequirements.maxAmountRequired || paymentRequirements.amount || '10000');
264
- var displayAmount = (amount / 1000000).toFixed(4);
265
- var hasFeePayer = paymentRequirements.extra && paymentRequirements.extra.feePayer;
266
-
267
- console.error('[cryptoiz-mcp] Payment required: ' + displayAmount + ' USDC for ' + toolName + (hasFeePayer ? ' (V2 Dexter)' : ' (V1 self-pay)'));
268
-
269
- // Step 3: Build and send payment
270
- var paymentHeader = '';
271
- var headerName = '';
272
-
273
- if (useV2 && paymentRequirements.extra && paymentRequirements.extra.feePayer) {
274
- var v2FeePayer = paymentRequirements.extra.feePayer;
275
- console.error('[cryptoiz-mcp] V2 mode: 4-ix tx (Limit+Price+TransferChecked+Memo), feePayer=' + v2FeePayer.substring(0, 8) + '...');
276
- try {
277
- var txB64 = await buildV2PaymentPayload(amount, v2FeePayer);
278
- var v2Payload = {
279
- x402Version: 2,
280
- accepted: {
281
- scheme: paymentRequirements.scheme || 'exact',
282
- network: paymentRequirements.network || 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
283
- },
284
- payload: {
285
- transaction: txB64,
286
- },
287
- };
288
- paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
289
- headerName = 'payment-signature';
290
- console.error('[cryptoiz-mcp] V2 tx ready, sending via payment-signature header');
291
- } catch(e) {
292
- console.error('[cryptoiz-mcp] V2 build failed: ' + e.message + ', falling back to V1');
293
- useV2 = false;
294
- }
295
- } else {
296
- useV2 = false;
297
- }
298
-
299
- if (!useV2) {
300
- console.error('[cryptoiz-mcp] V1 mode: sending USDC on-chain...');
301
- var sig = await sendUSDC(amount);
302
- console.error('[cryptoiz-mcp] V1 TX confirmed: ' + sig);
303
- var v1Payload = { signature: sig };
304
- paymentHeader = Buffer.from(JSON.stringify(v1Payload)).toString('base64');
305
- headerName = 'x-payment';
306
- }
307
-
308
- // Step 4: Retry with payment header
309
- var headers2obj = {};
310
- headers2obj[headerName] = paymentHeader;
311
- var resp2 = await fetch(url, { headers: clientHeaders(headers2obj) });
312
-
313
- // V2 settle failed? Auto-fallback to V1
314
- if (resp2.status !== 200 && useV2) {
315
- var v2ErrBody = await resp2.text();
316
- console.error('[cryptoiz-mcp] V2 settle failed (' + resp2.status + '): ' + v2ErrBody.substring(0, 200));
317
- console.error('[cryptoiz-mcp] Auto-fallback to V1 (sendUSDC on-chain)...');
318
- try {
319
- var fallbackSig = await sendUSDC(amount);
320
- console.error('[cryptoiz-mcp] V1 fallback TX confirmed: ' + fallbackSig);
321
- var v1FallbackPayload = { signature: fallbackSig };
322
- var v1FallbackHeader = Buffer.from(JSON.stringify(v1FallbackPayload)).toString('base64');
323
- resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': v1FallbackHeader }) });
324
- } catch(fallbackErr) {
325
- console.error('[cryptoiz-mcp] V1 fallback also failed: ' + fallbackErr.message);
326
- throw new Error('V2 failed (' + v2ErrBody.substring(0, 100) + '), V1 fallback also failed: ' + fallbackErr.message);
327
- }
328
- }
329
-
330
- if (resp2.status !== 200) {
331
- var errBody = await resp2.text();
332
- throw new Error('Payment failed (' + resp2.status + '): ' + errBody);
333
- }
334
-
335
- var receipt = resp2.headers.get('payment-response') || resp2.headers.get('x-payment-response');
336
- if (receipt) {
337
- try {
338
- var receiptData = JSON.parse(Buffer.from(receipt, 'base64').toString('utf8'));
339
- console.error('[cryptoiz-mcp] Payment receipt: TX=' + (receiptData.transaction || 'n/a') + ' via ' + (receiptData.version || 'unknown'));
340
- } catch(e) {
341
- // ignore receipt parse errors
342
- }
343
- }
344
-
345
- var data = await resp2.json();
346
- maybeNotifyUpdate(data, resp2.headers);
347
- return data;
348
- }
349
-
350
- // ===== MCP SERVER SETUP =====
351
- var TOOLS = [
352
- {
353
- name: 'get_whale_alpha',
354
- description: 'Get top 20 smart money alpha signals from CryptoIZ Solana DEX scanner. Shows whale/dolphin accumulation patterns, entry timing, and risk scores. Cost: $0.05 USDC.',
355
- inputSchema: { type: 'object', properties: {}, required: [] },
356
- },
357
- {
358
- name: 'get_whale_divergence',
359
- description: 'Get divergence signals - hidden accumulation, breakout accumulation, classic divergence between price and whale activity. Cost: $0.02 USDC.',
360
- inputSchema: {
361
- type: 'object',
362
- properties: {
363
- timeframe: { type: 'string', description: 'Timeframe: 4h (default) or 1d', enum: ['4h', '1d'] },
364
- },
365
- required: [],
366
- },
367
- },
368
- {
369
- name: 'get_whale_accumulation',
370
- description: 'Get tokens in accumulation phase with holder tier analysis (whale/dolphin/shrimp deltas). Smart money is entering these tokens. Cost: $0.02 USDC.',
371
- inputSchema: { type: 'object', properties: {}, required: [] },
372
- },
373
- {
374
- name: 'get_whale_neutral',
375
- description: 'Get tokens in neutral phase - no clear accumulation or distribution. Watch for phase transitions. Cost: $0.02 USDC.',
376
- inputSchema: { type: 'object', properties: {}, required: [] },
377
- },
378
- {
379
- name: 'get_whale_distribution',
380
- description: 'Get tokens in distribution phase - whale selling detected. Smart money is exiting. Consider closing positions or avoiding. Cost: $0.02 USDC.',
381
- inputSchema: { type: 'object', properties: {}, required: [] },
382
- },
383
- {
384
- name: 'get_btc_regime',
385
- description: 'Get Bitcoin macro regime, fear/greed index, futures signals, and technicals (RSI, EMA, MACD). Cost: $0.01 USDC.',
386
- inputSchema: { type: 'object', properties: {}, required: [] },
387
- },
388
- {
389
- name: 'get_btc_futures_signal',
390
- description: 'BTC futures scalping signal (35x leverage). Multi-timeframe: 4h regime filter (bull/bear) + 5m RSI entry trigger. Returns direction, entry, TP, SL, leverage recommendation, conviction score. Backtested 54% WR, PF 1.67, Sharpe 5.0 on 90d. Cost: $0.03 USDC.',
391
- inputSchema: { type: 'object', properties: {}, required: [] },
392
- },
393
- {
394
- name: 'get_token_ca',
395
- description: 'Look up a Solana token contract address by name. FREE - no payment required.',
396
- inputSchema: {
397
- type: 'object',
398
- properties: {
399
- name: { type: 'string', description: 'Token name to search for' },
400
- },
401
- required: ['name'],
402
- },
403
- },
404
- {
405
- name: 'get_status',
406
- description: 'Check CryptoIZ MCP server status, available tools, and pricing. FREE.',
407
- inputSchema: { type: 'object', properties: {}, required: [] },
408
- },
409
- ];
410
-
411
- var server = new Server(
412
- { name: 'cryptoiz-mcp', version: VERSION },
413
- { capabilities: { tools: {} } }
414
- );
415
-
416
- server.setRequestHandler(ListToolsRequestSchema, async function() {
417
- return { tools: TOOLS };
418
- });
419
-
420
- server.setRequestHandler(CallToolRequestSchema, async function(request) {
421
- var toolName = request.params.name;
422
- var args = request.params.arguments || {};
423
- try {
424
- var result = await callTool(toolName, args);
425
- return {
426
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
427
- };
428
- } catch(e) {
429
- return {
430
- content: [{ type: 'text', text: 'Error: ' + e.message }],
431
- isError: true,
432
- };
433
- }
434
- });
435
-
436
- async function main() {
437
- var transport = new StdioServerTransport();
438
- await server.connect(transport);
439
- console.error('[cryptoiz-mcp] ' + VERSION + ' running on stdio (x402 V2 Dexter + V1 compat)');
440
- }
441
-
442
- main().catch(function(e) {
443
- console.error('[cryptoiz-mcp] Fatal:', e.message);
444
- process.exit(1);
445
- });
1
+ 'use strict';
2
+ var VERSION = 'v4.16.7';
3
+ var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
4
+ var TOOL_ENDPOINTS = {
5
+ get_whale_alpha: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-alpha-scanner',
6
+ get_whale_divergence: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-divergence',
7
+ get_whale_accumulation: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-accumulation',
8
+ get_whale_neutral: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-neutral',
9
+ get_whale_distribution: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-distribution',
10
+ get_btc_regime: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-btc-regime',
11
+ get_btc_futures_signal: 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-btc-futures',
12
+ get_token_ca: GATEWAY,
13
+ get_status: GATEWAY,
14
+ };
15
+ var RECIPIENT = 'DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX';
16
+ var USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
17
+ var SOL_RPC = 'https://api.mainnet-beta.solana.com';
18
+ var TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
19
+ var ATA_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
20
+ var MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
21
+
22
+ var _updateNotified = false;
23
+ function notifyUpdate(data, headers) {
24
+ if (_updateNotified) return;
25
+ if (!headers || headers.get('x-update-available') !== '1') return;
26
+ _updateNotified = true;
27
+ var latest = (data && data.version_latest) || '?';
28
+ var cmd = (data && data.update_command) || 'npm install -g cryptoiz-mcp@latest';
29
+ console.error('[cryptoiz-mcp] UPDATE: ' + VERSION + ' -> ' + latest + ' | Run: ' + cmd);
30
+ }
31
+
32
+ var Connection = require('@solana/web3.js').Connection;
33
+ var PublicKey = require('@solana/web3.js').PublicKey;
34
+ var Transaction = require('@solana/web3.js').Transaction;
35
+ var Keypair = require('@solana/web3.js').Keypair;
36
+ var bs58 = require('bs58');
37
+ var Server = require('@modelcontextprotocol/sdk/server/index.js').Server;
38
+ var StdioServerTransport = require('@modelcontextprotocol/sdk/server/stdio.js').StdioServerTransport;
39
+ var CallToolRequestSchema = require('@modelcontextprotocol/sdk/types.js').CallToolRequestSchema;
40
+ var ListToolsRequestSchema = require('@modelcontextprotocol/sdk/types.js').ListToolsRequestSchema;
41
+
42
+ function getKeypair() {
43
+ var privKey = process.env.SVM_PRIVATE_KEY;
44
+ if (!privKey) throw new Error('SVM_PRIVATE_KEY not set in environment');
45
+ return Keypair.fromSecretKey(bs58.decode(privKey));
46
+ }
47
+
48
+ function findATA(wallet, mint) {
49
+ var walletPk = new PublicKey(wallet);
50
+ var mintPk = new PublicKey(mint);
51
+ var ataPk = new PublicKey(ATA_PROGRAM);
52
+ var tokPk = new PublicKey(TOKEN_PROGRAM);
53
+ return PublicKey.findProgramAddressSync([walletPk.toBuffer(), tokPk.toBuffer(), mintPk.toBuffer()], ataPk)[0];
54
+ }
55
+
56
+ // V1: direct on-chain USDC transfer + x402 memo for indexer
57
+ async function sendUSDC(amount, toolName) {
58
+ var kp = getKeypair();
59
+ var conn = new Connection(SOL_RPC, 'confirmed');
60
+ var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
61
+ var recipientATA = findATA(RECIPIENT, USDC_MINT);
62
+ // TransferChecked ix
63
+ var keys = [
64
+ { pubkey: userATA, isSigner: false, isWritable: true },
65
+ { pubkey: new PublicKey(USDC_MINT), isSigner: false, isWritable: false },
66
+ { pubkey: recipientATA, isSigner: false, isWritable: true },
67
+ { pubkey: kp.publicKey, isSigner: true, isWritable: false },
68
+ ];
69
+ var data = Buffer.alloc(9);
70
+ data[0] = 0x0c;
71
+ data.writeUInt32LE(amount & 0xFFFFFFFF, 1);
72
+ data.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
73
+ data[8] = 6;
74
+ var transferIx = { programId: new PublicKey(TOKEN_PROGRAM), keys: keys, data: data };
75
+ // Memo ix for x402scan indexer
76
+ var nonce = Date.now().toString(16) + Math.floor(Math.random() * 0xffff).toString(16);
77
+ var memoIx = {
78
+ programId: new PublicKey(MEMO_PROGRAM),
79
+ keys: [],
80
+ data: Buffer.from('x402:v1:' + (toolName || 'tool') + ':' + nonce, 'utf8')
81
+ };
82
+ var bh = await conn.getLatestBlockhash('confirmed');
83
+ var tx = new Transaction({ feePayer: kp.publicKey, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight });
84
+ tx.add(memoIx);
85
+ tx.add(transferIx);
86
+ tx.sign(kp);
87
+ var sig = await conn.sendRawTransaction(tx.serialize(), { skipPreflight: false });
88
+ await conn.confirmTransaction({ signature: sig, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight }, 'confirmed');
89
+ console.error('[cryptoiz-mcp] TX: ' + sig);
90
+ return sig;
91
+ }
92
+
93
+ function clientHeaders(extra) {
94
+ var h = { 'x-client-version': VERSION.replace(/^v/i, '') };
95
+ if (extra) for (var k in extra) if (Object.prototype.hasOwnProperty.call(extra, k)) h[k] = extra[k];
96
+ return h;
97
+ }
98
+
99
+ async function callTool(toolName, args) {
100
+ var queryParts = ['tool=' + toolName];
101
+ if (toolName === 'get_whale_divergence' && args && args.timeframe) queryParts.push('tf=' + args.timeframe);
102
+ if (toolName === 'get_token_ca' && args && args.name) queryParts.push('name=' + encodeURIComponent(args.name));
103
+ var url = (TOOL_ENDPOINTS[toolName] || GATEWAY) + '?' + queryParts.join('&');
104
+ // Step 1: discovery
105
+ var resp1 = await fetch(url, { headers: clientHeaders() });
106
+ if (resp1.status === 200) { var d = await resp1.json(); notifyUpdate(d, resp1.headers); return d; }
107
+ if (resp1.status !== 402) throw new Error('Server error ' + resp1.status + ': ' + (await resp1.text()).substring(0, 200));
108
+ // Step 2: parse payment requirements
109
+ var payReq = null;
110
+ var prHeader = resp1.headers.get('payment-required');
111
+ if (prHeader) { try { var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8')); if (arr && arr[0]) payReq = arr[0]; } catch(_e) {} }
112
+ if (!payReq) { var b402 = await resp1.json(); if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0]; }
113
+ if (!payReq) throw new Error('No payment requirements in 402');
114
+ var amount = parseInt(payReq.maxAmountRequired || payReq.amount || '10000');
115
+ console.error('[cryptoiz-mcp] Paying ' + (amount/1000000).toFixed(4) + ' USDC for ' + toolName);
116
+ // Step 3: V1 direct transfer
117
+ var sig = await sendUSDC(amount, toolName);
118
+ // Step 4: submit
119
+ var resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': Buffer.from(JSON.stringify({ signature: sig })).toString('base64') }) });
120
+ if (resp2.status !== 200) throw new Error('Payment failed ' + resp2.status + ': ' + (await resp2.text()).substring(0, 300));
121
+ var data = await resp2.json();
122
+ notifyUpdate(data, resp2.headers);
123
+ return data;
124
+ }
125
+
126
+ var TOOLS = [
127
+ { name: 'get_whale_alpha', description: 'Alpha scanner - early accumulation tokens. Cost: $0.05 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
128
+ { name: 'get_whale_divergence', description: 'Whale divergence signals. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: { timeframe: { type: 'string', enum: ['4h', '1d'] } }, additionalProperties: false } },
129
+ { name: 'get_whale_accumulation', description: 'Accumulation phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
130
+ { name: 'get_whale_neutral', description: 'Neutral phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
131
+ { name: 'get_whale_distribution', description: 'Distribution phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
132
+ { name: 'get_btc_regime', description: 'BTC macro regime. Cost: $0.01 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
133
+ { name: 'get_btc_futures_signal', description: 'BTC futures signal. Cost: $0.03 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
134
+ { name: 'get_token_ca', description: 'Token contract address by name. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
135
+ { name: 'get_status', description: 'CryptoIZ MCP status. FREE', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
136
+ ];
137
+
138
+ var server = new Server({ name: 'cryptoiz-mcp', version: VERSION }, { capabilities: { tools: {} } });
139
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
140
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
141
+ try {
142
+ var result = await callTool(request.params.name, request.params.arguments || {});
143
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
144
+ } catch(e) {
145
+ return { content: [{ type: 'text', text: 'Error: ' + e.message }], isError: true };
146
+ }
147
+ });
148
+
149
+ async function main() {
150
+ var transport = new StdioServerTransport();
151
+ await server.connect(transport);
152
+ console.error('[cryptoiz-mcp] ' + VERSION + ' running (V1 direct)');
153
+ }
154
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,53 +1,21 @@
1
- {
2
- "name": "cryptoiz-mcp",
3
- "version": "4.16.6",
4
- "mcpName": "io.github.dadang11/cryptoiz",
5
- "description": "CryptoIZ MCP Server - Solana DEX whale intelligence via Claude Desktop with x402 USDC micropayments (V2 Dexter facilitator)",
6
- "main": "index.js",
7
- "type": "module",
8
- "bin": {
9
- "cryptoiz-mcp": "./index.js",
10
- "cryptoiz-mcp-setup": "./setup.js"
11
- },
12
- "files": [
13
- "index.js",
14
- "setup.js",
15
- "package.json",
16
- "README.md"
17
- ],
18
- "dependencies": {
19
- "@modelcontextprotocol/sdk": "^1.0.4",
20
- "@solana/web3.js": "^1.95.8",
21
- "bs58": "^6.0.0"
22
- },
23
- "engines": {
24
- "node": ">=18.0.0"
25
- },
26
- "keywords": [
27
- "mcp",
28
- "mcp-server",
29
- "claude",
30
- "solana",
31
- "crypto",
32
- "trading",
33
- "x402",
34
- "usdc",
35
- "dexter",
36
- "whale-tracking",
37
- "whale-intelligence",
38
- "smart-money",
39
- "alpha-signals",
40
- "divergence",
41
- "accumulation",
42
- "distribution",
43
- "defi",
44
- "dex"
45
- ],
46
- "author": "CryptoIZ",
47
- "license": "MIT",
48
- "homepage": "https://cryptoiz.org/McpLanding",
49
- "repository": {
50
- "type": "git",
51
- "url": "https://github.com/dadang11/cryptoiz-mcp"
52
- }
53
- }
1
+ {
2
+ "name": "cryptoiz-mcp",
3
+ "version": "4.16.7",
4
+ "description": "CryptoIZ MCP Server - Solana DEX whale intelligence via Claude Desktop with x402 USDC micropayments",
5
+ "main": "index.js",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "cryptoiz-mcp": "./index.js",
9
+ "cryptoiz-mcp-setup": "./setup.js"
10
+ },
11
+ "files": ["index.js", "setup.js", "package.json", "README.md"],
12
+ "dependencies": {
13
+ "@modelcontextprotocol/sdk": "^1.0.4",
14
+ "@solana/web3.js": "^1.95.8",
15
+ "bs58": "^6.0.0"
16
+ },
17
+ "engines": { "node": ">=18.0.0" },
18
+ "author": "CryptoIZ",
19
+ "license": "MIT",
20
+ "repository": { "type": "git", "url": "git+https://github.com/dadang11/cryptoiz-mcp.git" }
21
+ }
package/setup.js CHANGED
@@ -1,132 +1,51 @@
1
- #!/usr/bin/env node
2
- import fs from 'fs';
3
- import path from 'path';
4
- import os from 'os';
5
- import { execSync } from 'child_process';
6
-
7
- var VERSION = 'v4.15.14';
8
- function print(msg) { process.stdout.write(msg + '\n'); }
9
-
10
- function findConfigPath() {
11
- var p = os.platform(), candidates = [];
12
- if (p === 'darwin') {
13
- candidates.push(path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'));
14
- } else if (p === 'win32') {
15
- var localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
16
- try {
17
- var packagesDir = path.join(localAppData, 'Packages');
18
- if (fs.existsSync(packagesDir)) {
19
- var dirs = fs.readdirSync(packagesDir);
20
- for (var i = 0; i < dirs.length; i++) {
21
- if (dirs[i].startsWith('Claude_')) {
22
- candidates.push(path.join(packagesDir, dirs[i], 'LocalCache', 'Roaming', 'Claude', 'claude_desktop_config.json'));
23
- }
24
- }
25
- }
26
- } catch(e) {}
27
- var appdata = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
28
- candidates.push(path.join(appdata, 'Claude', 'claude_desktop_config.json'));
29
- } else {
30
- candidates.push(path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json'));
31
- }
32
- for (var j = 0; j < candidates.length; j++) {
33
- if (fs.existsSync(candidates[j])) return candidates[j];
34
- }
35
- return candidates[0] || null;
36
- }
37
-
38
- function findPackagePath() {
39
- if (os.platform() !== 'win32') return null;
40
- var prefix = '';
41
- try { prefix = execSync('npm config get prefix', { encoding: 'utf8' }).trim(); } catch(e) {
42
- prefix = path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'npm');
43
- }
44
- var c = [
45
- path.join(prefix, 'node_modules', 'cryptoiz-mcp', 'index.js'),
46
- path.join(prefix, 'lib', 'node_modules', 'cryptoiz-mcp', 'index.js'),
47
- ];
48
- for (var i = 0; i < c.length; i++) { if (fs.existsSync(c[i])) return c[i]; }
49
- return null;
50
- }
51
-
52
- function buildEntry(key) {
53
- if (os.platform() === 'win32') {
54
- var pkgPath = findPackagePath();
55
- if (!pkgPath) { print('ERROR: Run npm install -g cryptoiz-mcp first'); process.exit(1); }
56
- return { command: process.execPath, args: [pkgPath], env: { SVM_PRIVATE_KEY: key } };
57
- }
58
- return { command: 'npx', args: ['-y', 'cryptoiz-mcp@' + VERSION.replace('v','')], env: { SVM_PRIVATE_KEY: key } };
59
- }
60
-
61
- function injectConfig(cfgPath, entry) {
62
- var config = {};
63
- if (fs.existsSync(cfgPath)) {
64
- try { config = JSON.parse(fs.readFileSync(cfgPath, 'utf8')); } catch(e) {
65
- fs.copyFileSync(cfgPath, cfgPath + '.backup.' + Date.now());
66
- print('Config had error. Backup created.');
67
- }
68
- }
69
- if (!config.mcpServers) config.mcpServers = {};
70
- if (config.mcpServers.cryptoiz) print('Updating existing CryptoIZ entry...');
71
- config.mcpServers.cryptoiz = entry;
72
- var dir = path.dirname(cfgPath);
73
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
74
- fs.writeFileSync(cfgPath, JSON.stringify(config, null, 2), 'utf8');
75
- }
76
-
77
- var key = (process.argv[2] || '').trim();
78
-
79
- print('');
80
- print('========================================');
81
- print(' CryptoIZ MCP Installer ' + VERSION);
82
- print('========================================');
83
- print('OS: ' + os.platform() + ' ' + os.arch());
84
-
85
- if (!key) {
86
- print('');
87
- print('Usage:');
88
- print(' npx cryptoiz-mcp-setup YOUR_PRIVATE_KEY');
89
- print('');
90
- print('Example:');
91
- print(' npx cryptoiz-mcp-setup 5MaiiCavjCmn9Hs1o...');
92
- print('');
93
- print('SECURITY:');
94
- print('- Use a DEDICATED wallet (not main wallet)');
95
- print('- Fund with $1-5 USDC only, no SOL needed');
96
- print('- Export: Phantom > Settings > Security > Export Private Key');
97
- print('');
98
- print('Guide: cryptoiz.org/McpLanding');
99
- process.exit(1);
100
- }
101
-
102
- var chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
103
- if (key.length < 40 || key.length > 100) { print('ERROR: Invalid key length (' + key.length + ' chars). Expected 44-88.'); process.exit(1); }
104
- for (var i = 0; i < key.length; i++) {
105
- if (chars.indexOf(key[i]) === -1) { print('ERROR: Invalid base58 character at position ' + i + ': "' + key[i] + '"'); process.exit(1); }
106
- }
107
-
108
- var cfgPath = findConfigPath();
109
- if (!cfgPath) { print('ERROR: Claude Desktop not found.'); process.exit(1); }
110
- print('Config: ' + cfgPath);
111
-
112
- if (os.platform() === 'win32') {
113
- print('[Windows] absolute paths mode');
114
- var pkg = findPackagePath();
115
- if (!pkg) { print('Run: npm install -g cryptoiz-mcp'); process.exit(1); }
116
- print('Node: ' + process.execPath);
117
- print('Package: ' + pkg);
118
- }
119
-
120
- injectConfig(cfgPath, buildEntry(key));
121
-
122
- print('');
123
- print('SETUP COMPLETE!');
124
- print('Config: ' + cfgPath);
125
- print('');
126
- print('Next:');
127
- print('1. Close Claude Desktop completely');
128
- print('2. Reopen Claude Desktop');
129
- print('3. Type: get_status');
130
- print('');
131
- print('Guide: cryptoiz.org/McpLanding');
132
- print('');
1
+ 'use strict';
2
+ var VERSION = 'v4.16.7';
3
+ var fs = require('fs');
4
+ var os = require('os');
5
+ var path = require('path');
6
+
7
+ var privKey = process.argv[2];
8
+ if (!privKey) {
9
+ console.log('Usage: npx cryptoiz-mcp-setup YOUR_SOLANA_PRIVATE_KEY');
10
+ process.exit(1);
11
+ }
12
+
13
+ var config = {
14
+ mcpServers: {
15
+ cryptoiz: {
16
+ command: 'C:\\Program Files\\nodejs\\node.exe',
17
+ args: [require.resolve('./index.js')],
18
+ env: { SVM_PRIVATE_KEY: privKey }
19
+ }
20
+ }
21
+ };
22
+
23
+ var configPaths = [
24
+ path.join(process.env.LOCALAPPDATA || '', 'Packages', 'Claude_pzs8sxrjxfjjc', 'LocalCache', 'Roaming', 'Claude', 'claude_desktop_config.json'),
25
+ path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json'),
26
+ path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
27
+ ];
28
+
29
+ var written = false;
30
+ for (var i = 0; i < configPaths.length; i++) {
31
+ var p = configPaths[i];
32
+ try {
33
+ var dir = path.dirname(p);
34
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
35
+ var existing = {};
36
+ if (fs.existsSync(p)) {
37
+ try { existing = JSON.parse(fs.readFileSync(p, 'utf8')); } catch(_e) {}
38
+ }
39
+ existing.mcpServers = existing.mcpServers || {};
40
+ existing.mcpServers.cryptoiz = config.mcpServers.cryptoiz;
41
+ fs.writeFileSync(p, JSON.stringify(existing, null, 2), 'utf8');
42
+ console.log('Config written to: ' + p);
43
+ written = true;
44
+ } catch(_e) {}
45
+ }
46
+
47
+ if (written) {
48
+ console.log('Done! Restart Claude Desktop to activate CryptoIZ MCP.');
49
+ } else {
50
+ console.log('Could not write config. Please manually add config to Claude Desktop settings.');
51
+ }