cryptoiz-mcp 2.0.1 → 2.1.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.
- package/package.json +1 -1
- package/src/index.js +290 -167
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,25 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* CryptoIZ MCP Server v2.0.0
|
|
4
|
-
* Solana DEX signals with x402 micropayments — $0.01 USDC per call
|
|
5
|
-
*
|
|
6
|
-
* Setup di Claude Desktop:
|
|
7
|
-
* {
|
|
8
|
-
* "mcpServers": {
|
|
9
|
-
* "cryptoiz": {
|
|
10
|
-
* "command": "npx",
|
|
11
|
-
* "args": ["cryptoiz-mcp"],
|
|
12
|
-
* "env": {
|
|
13
|
-
* "SVM_PRIVATE_KEY": "your-solana-private-key-base58"
|
|
14
|
-
* }
|
|
15
|
-
* }
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
*
|
|
19
|
-
* User harus punya USDC di wallet Solana mereka.
|
|
20
|
-
* Setiap call = $0.01 USDC otomatis terkirim ke CryptoIZ.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
24
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
25
4
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -32,108 +11,280 @@ const SVM_PRIVATE_KEY = process.env.SVM_PRIVATE_KEY || '';
|
|
|
32
11
|
const CRYPTOIZ_WALLET = new PublicKey('DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX');
|
|
33
12
|
const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
34
13
|
const SOL_RPC = 'https://api.mainnet-beta.solana.com';
|
|
35
|
-
const AMOUNT = 10000;
|
|
14
|
+
const AMOUNT = 10000;
|
|
36
15
|
|
|
37
|
-
// ───
|
|
16
|
+
// ─── Footer branding (selalu muncul di setiap response) ──────────────────────
|
|
17
|
+
const FOOTER = `
|
|
18
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
19
|
+
🌐 cryptoiz.org — Platform AI Trading Solana
|
|
20
|
+
📊 Alpha Scanner · Divergence · Accumulation · BTC Regime
|
|
21
|
+
🐦 Twitter/X : @cryptoiz_IDN
|
|
22
|
+
💬 Telegram : t.me/agus_artemiss
|
|
23
|
+
💡 Untuk data lebih lengkap, analisis mendalam, dan sinyal premium
|
|
24
|
+
kunjungi cryptoiz.org dan subscribe platform kami.
|
|
25
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`;
|
|
38
26
|
|
|
27
|
+
// ─── Payment handler ──────────────────────────────────────────────────────────
|
|
39
28
|
async function payAndFetch(url) {
|
|
40
29
|
if (!SVM_PRIVATE_KEY) {
|
|
41
|
-
return {
|
|
42
|
-
error: 'SVM_PRIVATE_KEY tidak ditemukan.',
|
|
43
|
-
setup: 'Tambahkan SVM_PRIVATE_KEY (private key Solana kamu) ke config Claude Desktop.',
|
|
44
|
-
help: 'cryptoiz.org/McpApiKey',
|
|
45
|
-
};
|
|
30
|
+
return { error: 'SVM_PRIVATE_KEY tidak ditemukan.', setup: 'Tambahkan SVM_PRIVATE_KEY ke config Claude Desktop.', help: 'cryptoiz.org' };
|
|
46
31
|
}
|
|
47
|
-
|
|
48
|
-
// First request
|
|
49
32
|
const first = await fetch(url);
|
|
50
33
|
if (first.status !== 402) return first.json();
|
|
51
|
-
|
|
52
|
-
// 402 received — pay USDC
|
|
53
34
|
try {
|
|
54
35
|
const keypair = Keypair.fromSecretKey(bs58.decode(SVM_PRIVATE_KEY));
|
|
55
36
|
const connection = new Connection(SOL_RPC, 'confirmed');
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
);
|
|
60
|
-
const toAta = await getOrCreateAssociatedTokenAccount(
|
|
61
|
-
connection, keypair, USDC_MINT, CRYPTOIZ_WALLET
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const tx = new Transaction().add(
|
|
65
|
-
createTransferInstruction(fromAta.address, toAta.address, keypair.publicKey, AMOUNT)
|
|
66
|
-
);
|
|
67
|
-
|
|
37
|
+
const fromAta = await getOrCreateAssociatedTokenAccount(connection, keypair, USDC_MINT, keypair.publicKey);
|
|
38
|
+
const toAta = await getOrCreateAssociatedTokenAccount(connection, keypair, USDC_MINT, CRYPTOIZ_WALLET);
|
|
39
|
+
const tx = new Transaction().add(createTransferInstruction(fromAta.address, toAta.address, keypair.publicKey, AMOUNT));
|
|
68
40
|
const signature = await connection.sendTransaction(tx, [keypair]);
|
|
69
41
|
await connection.confirmTransaction(signature, 'confirmed');
|
|
70
|
-
|
|
71
|
-
// Retry with payment proof
|
|
72
|
-
const payment = Buffer.from(
|
|
73
|
-
JSON.stringify({ signature, network: 'solana', x402Version: 1 })
|
|
74
|
-
).toString('base64');
|
|
75
|
-
|
|
42
|
+
const payment = Buffer.from(JSON.stringify({ signature, network: 'solana', x402Version: 1 })).toString('base64');
|
|
76
43
|
const paidRes = await fetch(url, { headers: { 'x-payment': payment } });
|
|
77
44
|
return paidRes.json();
|
|
78
|
-
|
|
79
45
|
} catch (err) {
|
|
80
|
-
return {
|
|
81
|
-
error: `Payment gagal: ${err.message}`,
|
|
82
|
-
hint: 'Pastikan wallet kamu punya USDC dan SOL untuk gas.',
|
|
83
|
-
};
|
|
46
|
+
return { error: `Payment gagal: ${err.message}`, hint: 'Pastikan wallet punya USDC dan SOL untuk gas.' };
|
|
84
47
|
}
|
|
85
48
|
}
|
|
86
49
|
|
|
50
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
51
|
+
const fmt = (n, d=2) => n != null ? parseFloat(n).toFixed(d) : 'N/A';
|
|
52
|
+
const fmtMC = mc => { if (!mc) return 'N/A'; if (mc >= 1e6) return `$${(mc/1e6).toFixed(2)}M`; return `$${(mc/1000).toFixed(0)}K`; };
|
|
53
|
+
const fmtD = d => d > 0 ? `+${d}` : `${d}`;
|
|
54
|
+
const fmtRisk = r => parseFloat(r) > 0 ? `⚠️ ${fmt(r)}%` : `✅ 0%`;
|
|
55
|
+
const fmtPrice = p => p ? `$${parseFloat(p).toFixed(6)}` : 'N/A';
|
|
56
|
+
|
|
57
|
+
function entryAdvice(s) {
|
|
58
|
+
const lines = [];
|
|
59
|
+
if (s.entry_class === 'ALPHA_EARLY' && s.phase?.includes('ACCUM')) {
|
|
60
|
+
lines.push('💡 SINYAL KUAT: Fase akumulasi awal dengan smart money masuk. Potensi entry terbaik sebelum harga naik.');
|
|
61
|
+
} else if (s.entry_class === 'ALPHA_BUILDING') {
|
|
62
|
+
lines.push('💡 MEMBANGUN: Akumulasi sedang berlanjut. Timing masih baik namun hati-hati dengan risiko.');
|
|
63
|
+
} else {
|
|
64
|
+
lines.push('👁️ WATCHLIST: Belum memenuhi semua kriteria entry. Monitor terus untuk konfirmasi.');
|
|
65
|
+
}
|
|
66
|
+
if (s.whale_delta > 0 && s.dolphin_delta > 0) lines.push('✅ Whale & Dolphin sama-sama masuk — sinyal kuat smart money akumulasi.');
|
|
67
|
+
if (s.smart_money_trap_risk > 30) lines.push('⚠️ Trap Risk tinggi — waspadai jebakan sebelum entry.');
|
|
68
|
+
if (s.liquidity_drain_risk > 30) lines.push('⚠️ Liquidity Risk tinggi — pastikan ada likuiditas cukup saat exit.');
|
|
69
|
+
if (s.safety_score >= 80) lines.push('🛡️ Safety score tinggi — risiko manipulasi rendah.');
|
|
70
|
+
return lines.join('\n ');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function divergenceAdvice(s) {
|
|
74
|
+
if (s.divergence_type === 'bullish') return '💡 BULLISH DIVERGENCE: Harga turun tapi whale/dolphin masuk. Potensi reversal ke atas — perhatikan untuk entry.';
|
|
75
|
+
if (s.divergence_type === 'bearish') return '⚠️ BEARISH DIVERGENCE: Harga naik tapi whale/dolphin keluar. Potensi reversal ke bawah — hati-hati jika sudah hold.';
|
|
76
|
+
return '📊 Divergence terdeteksi — analisa lebih lanjut diperlukan.';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function accumAdvice(s) {
|
|
80
|
+
if (s.strength_label?.includes('VERY_STRONG')) return '💡 VERY STRONG: Smart money sangat aktif akumulasi. Kandidat entry terkuat.';
|
|
81
|
+
if (s.strength_label?.includes('STRONG')) return '💡 STRONG: Akumulasi kuat terdeteksi. Perhatikan untuk entry opportunity.';
|
|
82
|
+
return '👁️ FORMING: Akumulasi mulai terbentuk. Monitor untuk konfirmasi lebih lanjut.';
|
|
83
|
+
}
|
|
84
|
+
|
|
87
85
|
// ─── Formatters ───────────────────────────────────────────────────────────────
|
|
88
86
|
|
|
89
87
|
function formatAlpha(data) {
|
|
90
|
-
if (data.error) return
|
|
91
|
-
if (!data.signals?.length) return
|
|
88
|
+
if (data.error) return `❌ ${data.error}\n${data.setup||''}\n📱 Setup: cryptoiz.org`;
|
|
89
|
+
if (!data.signals?.length) return `Tidak ada sinyal Alpha Scanner saat ini.\n${FOOTER}`;
|
|
90
|
+
|
|
92
91
|
const lines = [
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
`╔══════════════════════════════════════╗`,
|
|
93
|
+
`║ CRYPTOIZ ALPHA ENTRY SCANNER ║`,
|
|
94
|
+
`╚══════════════════════════════════════╝`,
|
|
95
|
+
`📅 ${data.fetched_at?.split('T')[0]} | Total Sinyal: ${data.total}`,
|
|
96
|
+
``,
|
|
97
|
+
`📖 APA INI?`,
|
|
98
|
+
`Alpha Scanner menggunakan AI untuk mendeteksi token Solana`,
|
|
99
|
+
`yang sedang diakumulasi oleh whale & dolphin (smart money)`,
|
|
100
|
+
`sebelum harga bergerak. Score 0-100 berdasarkan:`,
|
|
101
|
+
`• Accumulation Score — seberapa aktif smart money masuk`,
|
|
102
|
+
`• Timing Score — seberapa tepat timing entry`,
|
|
103
|
+
`• Safety Score — seberapa aman dari manipulasi`,
|
|
104
|
+
``,
|
|
105
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
106
|
+
...data.signals.map((s, i) => [
|
|
107
|
+
``,
|
|
108
|
+
`${i+1}. ━━━ ${s.name} ━━━━━━━━━━━━━━━━━━━`,
|
|
109
|
+
` 🔗 Address : ${s.token_address}`,
|
|
110
|
+
` 📊 Alpha Score: ${fmt(s.alpha_score)} / 100 | Kelas: ${s.entry_class}`,
|
|
111
|
+
` 📍 Phase : ${s.phase} | Regime: ${s.regime}`,
|
|
112
|
+
` 🎯 Keyakinan : ${fmt(s.phase_confidence)}% | Umur Phase: ${s.phase_age_bars} bars`,
|
|
113
|
+
``,
|
|
114
|
+
` HOLDER SIGNALS:`,
|
|
115
|
+
` 🐋 Whale : ${fmtD(s.whale_delta)} (${fmt(s.whale_pct)}% supply)`,
|
|
116
|
+
` 🐬 Dolphin : ${fmtD(s.dolphin_delta)} (${fmt(s.dolphin_pct)}% supply)`,
|
|
117
|
+
` 🦐 Shrimp : ${fmtD(s.shrimp_delta)} (keluar = bullish)`,
|
|
118
|
+
``,
|
|
119
|
+
` SUB-SCORES:`,
|
|
120
|
+
` 📈 Accum : ${fmt(s.accumulation_score)} | Timing: ${fmt(s.timing_score)} | Safety: ${fmt(s.safety_score)}`,
|
|
121
|
+
``,
|
|
122
|
+
` RISIKO:`,
|
|
123
|
+
` 💧 Liquidity : ${fmtRisk(s.liquidity_drain_risk)}`,
|
|
124
|
+
` 🪤 Trap Risk : ${fmtRisk(s.smart_money_trap_risk)}`,
|
|
125
|
+
``,
|
|
126
|
+
` MARKET DATA:`,
|
|
127
|
+
` 💰 Market Cap : ${fmtMC(s.market_cap_usd)}`,
|
|
128
|
+
` 💵 Price : ${fmtPrice(s.price_usd)}`,
|
|
129
|
+
` 📉 Drop Peak : ${s.price_drop_pct != null ? fmt(s.price_drop_pct)+'%' : 'N/A'}`,
|
|
130
|
+
``,
|
|
131
|
+
` REKOMENDASI:`,
|
|
132
|
+
` ${entryAdvice(s)}`,
|
|
133
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
134
|
+
].join('\n')),
|
|
135
|
+
FOOTER,
|
|
104
136
|
];
|
|
105
137
|
return lines.join('\n');
|
|
106
138
|
}
|
|
107
139
|
|
|
108
140
|
function formatDivergence(data) {
|
|
109
|
-
if (data.error) return
|
|
110
|
-
if (!data.signals?.length) return `Tidak ada divergence signal (${data.timeframe})
|
|
141
|
+
if (data.error) return `❌ ${data.error}\n${FOOTER}`;
|
|
142
|
+
if (!data.signals?.length) return `Tidak ada divergence signal (${data.timeframe}).\n${FOOTER}`;
|
|
143
|
+
|
|
111
144
|
const lines = [
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
145
|
+
`╔══════════════════════════════════════╗`,
|
|
146
|
+
`║ CRYPTOIZ DIVERGENCE SCANNER ║`,
|
|
147
|
+
`╚══════════════════════════════════════╝`,
|
|
148
|
+
`📅 ${data.fetched_at?.split('T')[0]} | Timeframe: ${data.timeframe?.toUpperCase()} | Total: ${data.total}`,
|
|
149
|
+
``,
|
|
150
|
+
`📖 APA INI?`,
|
|
151
|
+
`Divergence terjadi ketika harga bergerak berlawanan dengan`,
|
|
152
|
+
`aktivitas smart money (whale/dolphin). Ini adalah sinyal awal`,
|
|
153
|
+
`sebelum harga berbalik arah:`,
|
|
154
|
+
`• BULLISH: Harga turun tapi smart money masuk → potensi naik`,
|
|
155
|
+
`• BEARISH: Harga naik tapi smart money keluar → potensi turun`,
|
|
156
|
+
``,
|
|
157
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
115
158
|
...data.signals.map((s, i) => {
|
|
116
|
-
const type = s.divergence_type === 'bullish' ? 'BULLISH
|
|
117
|
-
return
|
|
159
|
+
const type = s.divergence_type === 'bullish' ? '🟢 BULLISH' : s.divergence_type === 'bearish' ? '🔴 BEARISH' : `⚪ ${(s.divergence_type||'').toUpperCase()}`;
|
|
160
|
+
return [
|
|
161
|
+
``,
|
|
162
|
+
`${i+1}. ━━━ ${s.name||s.symbol} [${type}] ━━━`,
|
|
163
|
+
` 🔗 Address : ${s.token_address}`,
|
|
164
|
+
` 📊 Div. Score : ${fmt(s.divergence_score)} | Confidence: ${fmt(s.confidence_score)}%`,
|
|
165
|
+
` 📍 Phase : ${s.phase_label}`,
|
|
166
|
+
``,
|
|
167
|
+
` HOLDER SIGNALS:`,
|
|
168
|
+
` 🐋 Whale : ${fmtD(s.whale_delta)}`,
|
|
169
|
+
` 🐬 Dolphin : ${fmtD(s.dolphin_delta)}`,
|
|
170
|
+
``,
|
|
171
|
+
` MARKET DATA:`,
|
|
172
|
+
` 💰 Market Cap : ${fmtMC(s.market_cap_usd)}`,
|
|
173
|
+
` 💵 Price Now : ${fmtPrice(s.price_usd)}`,
|
|
174
|
+
` 📉 Price Chg : ${s.price_change_pct ? fmt(s.price_change_pct)+'%' : 'N/A'}`,
|
|
175
|
+
` 🕐 Detected : ${s.detected_at ? new Date(s.detected_at).toLocaleString('id-ID') : 'N/A'}`,
|
|
176
|
+
``,
|
|
177
|
+
` REKOMENDASI:`,
|
|
178
|
+
` ${divergenceAdvice(s)}`,
|
|
179
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
180
|
+
].join('\n');
|
|
118
181
|
}),
|
|
119
|
-
|
|
120
|
-
|
|
182
|
+
FOOTER,
|
|
183
|
+
];
|
|
184
|
+
return lines.join('\n');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function formatAccumulation(data) {
|
|
188
|
+
if (data.error) return `❌ ${data.error}\n${FOOTER}`;
|
|
189
|
+
if (!data.tokens?.length) return `Tidak ada token dalam fase akumulasi.\n${FOOTER}`;
|
|
190
|
+
|
|
191
|
+
const lines = [
|
|
192
|
+
`╔══════════════════════════════════════╗`,
|
|
193
|
+
`║ CRYPTOIZ ACCUMULATION SCANNER ║`,
|
|
194
|
+
`╚══════════════════════════════════════╝`,
|
|
195
|
+
`📅 ${data.fetched_at?.split('T')[0]} | Total: ${data.total} token akumulasi`,
|
|
196
|
+
``,
|
|
197
|
+
`📖 APA INI?`,
|
|
198
|
+
`Accumulation Dashboard mendeteksi token yang sedang dalam`,
|
|
199
|
+
`fase akumulasi berdasarkan 4 dimensi analisis:`,
|
|
200
|
+
`• Structure Score — pola price action & holder tier`,
|
|
201
|
+
`• AccDist Score — distribusi akumulasi vs distribusi`,
|
|
202
|
+
`• Holder Score — kualitas & konsistensi holder`,
|
|
203
|
+
`• Market Score — kondisi pasar & volume`,
|
|
204
|
+
`Composite Score = gabungan keempat dimensi di atas.`,
|
|
205
|
+
``,
|
|
206
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
207
|
+
...data.tokens.map((t, i) => [
|
|
208
|
+
``,
|
|
209
|
+
`${i+1}. ━━━ ${t.name} ━━━━━━━━━━━━━━━━━━━`,
|
|
210
|
+
` 🔗 Address : ${t.token_address}`,
|
|
211
|
+
` 📊 Composite : ${fmt(t.composite_score)} / 100`,
|
|
212
|
+
` 💪 Strength : ${t.strength_label}`,
|
|
213
|
+
` 🔄 AccDist : ${t.accdist_label} (Score: ${fmt(t.accdist_score)})`,
|
|
214
|
+
``,
|
|
215
|
+
` SUB-SCORES:`,
|
|
216
|
+
` 📐 Structure : ${fmt(t.structure_score)}`,
|
|
217
|
+
` 👥 Holder : ${fmt(t.holder_score)}`,
|
|
218
|
+
` 📉 Market : ${fmt(t.market_score)}`,
|
|
219
|
+
``,
|
|
220
|
+
` REKOMENDASI:`,
|
|
221
|
+
` ${accumAdvice(t)}`,
|
|
222
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
223
|
+
].join('\n')),
|
|
224
|
+
FOOTER,
|
|
121
225
|
];
|
|
122
226
|
return lines.join('\n');
|
|
123
227
|
}
|
|
124
228
|
|
|
125
|
-
function
|
|
126
|
-
if (data.error) return
|
|
127
|
-
|
|
229
|
+
function formatBTC(data) {
|
|
230
|
+
if (data.error) return `❌ ${data.error}\n${FOOTER}`;
|
|
231
|
+
const s = data.btc_signal || {};
|
|
232
|
+
const f = data.futures_signal || {};
|
|
233
|
+
const ind = data.indicators || {};
|
|
234
|
+
|
|
235
|
+
const stateEmoji = s.state === 'bull' ? '🟢' : s.state === 'bear' ? '🔴' : '🟡';
|
|
236
|
+
const signalEmoji = f.signal === 'LONG' ? '🟢' : f.signal === 'SHORT' ? '🔴' : '🟡';
|
|
237
|
+
|
|
128
238
|
const lines = [
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
239
|
+
`╔══════════════════════════════════════╗`,
|
|
240
|
+
`║ CRYPTOIZ BTC REGIME MONITOR ║`,
|
|
241
|
+
`╚══════════════════════════════════════╝`,
|
|
242
|
+
`📅 ${data.fetched_at?.split('T')[0]}`,
|
|
243
|
+
``,
|
|
244
|
+
`📖 APA INI?`,
|
|
245
|
+
`BTC Regime Monitor menganalisis kondisi makro Bitcoin`,
|
|
246
|
+
`untuk membantu kamu memahami apakah pasar sedang bullish,`,
|
|
247
|
+
`bearish, atau neutral. Ini penting karena kondisi BTC`,
|
|
248
|
+
`sangat mempengaruhi pergerakan altcoin di Solana.`,
|
|
249
|
+
``,
|
|
250
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
251
|
+
``,
|
|
252
|
+
`${stateEmoji} KONDISI BTC SAAT INI: ${(s.state||'').toUpperCase()}`,
|
|
253
|
+
` 💵 Harga BTC : $${s.last_price ? parseFloat(s.last_price).toLocaleString() : 'N/A'}`,
|
|
254
|
+
` 📊 BTC Score : ${s.score || 'N/A'} (0=sangat bear, 10=sangat bull)`,
|
|
255
|
+
` 📈 Trend : ${s.trend || 'N/A'}`,
|
|
256
|
+
``,
|
|
257
|
+
`SENTIMENT:`,
|
|
258
|
+
` 😱 Fear & Greed: ${s.fear_label || 'N/A'} (${s.fear_value || 'N/A'}/100)`,
|
|
259
|
+
` 💡 ${s.fear_value <= 25 ? 'Extreme Fear = peluang beli sering muncul di level ini' : s.fear_value >= 75 ? 'Extreme Greed = hati-hati, pasar bisa reversal' : 'Sentimen netral — ikuti sinyal teknikal'}`,
|
|
260
|
+
``,
|
|
261
|
+
`FUTURES DATA:`,
|
|
262
|
+
` ${signalEmoji} Signal Futures : ${f.signal || 'N/A'}`,
|
|
263
|
+
` 📊 OI Regime : ${f.oi_regime || 'N/A'}`,
|
|
264
|
+
` 💸 Funding : ${f.funding_regime || 'N/A'}`,
|
|
265
|
+
` 💵 Perp Price : $${f.perp_price ? parseFloat(f.perp_price).toLocaleString() : 'N/A'}`,
|
|
266
|
+
` 📝 Alasan : ${f.reason || 'N/A'}`,
|
|
267
|
+
``,
|
|
268
|
+
ind.rsi ? [
|
|
269
|
+
`INDIKATOR TEKNIKAL (1H):`,
|
|
270
|
+
` RSI : ${fmt(ind.rsi)} ${parseFloat(ind.rsi) < 30 ? '(Oversold ✅)' : parseFloat(ind.rsi) > 70 ? '(Overbought ⚠️)' : '(Normal)'}`,
|
|
271
|
+
` EMA 20 : $${ind.ema_20 ? parseFloat(ind.ema_20).toLocaleString() : 'N/A'}`,
|
|
272
|
+
` EMA 50 : $${ind.ema_50 ? parseFloat(ind.ema_50).toLocaleString() : 'N/A'}`,
|
|
273
|
+
` MACD : ${fmt(ind.macd)} | Signal: ${fmt(ind.macd_signal)}`,
|
|
274
|
+
``,
|
|
275
|
+
].join('\n') : '',
|
|
276
|
+
`REKOMENDASI UNTUK ALTCOIN SOLANA:`,
|
|
277
|
+
s.state === 'bull' ? ` 🟢 BTC bullish → kondisi BAGUS untuk cari entry altcoin Solana.
|
|
278
|
+
Fokus pada token dengan Alpha Score tinggi di cryptoiz.org.` :
|
|
279
|
+
s.state === 'bear' ? ` 🔴 BTC bearish → HATI-HATI entry altcoin.
|
|
280
|
+
Prioritaskan token dengan Safety Score tinggi dan liq risk rendah.` :
|
|
281
|
+
` 🟡 BTC neutral → Selektif dalam memilih entry.
|
|
282
|
+
Tunggu konfirmasi signal sebelum masuk posisi besar.`,
|
|
283
|
+
` 📊 Cek kondisi terkini di: cryptoiz.org/BTC`,
|
|
284
|
+
``,
|
|
285
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
286
|
+
`⚠️ Bukan financial advice. Selalu DYOR.`,
|
|
287
|
+
FOOTER,
|
|
137
288
|
];
|
|
138
289
|
return lines.join('\n');
|
|
139
290
|
}
|
|
@@ -141,112 +292,84 @@ function formatAccum(data) {
|
|
|
141
292
|
function formatStatus() {
|
|
142
293
|
const hasKey = !!SVM_PRIVATE_KEY;
|
|
143
294
|
return [
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
295
|
+
`╔══════════════════════════════════════╗`,
|
|
296
|
+
`║ CryptoIZ MCP Server v2.1.0 ║`,
|
|
297
|
+
`╚══════════════════════════════════════╝`,
|
|
147
298
|
``,
|
|
148
|
-
`
|
|
149
|
-
`
|
|
150
|
-
`
|
|
151
|
-
`
|
|
152
|
-
`
|
|
299
|
+
`STATUS KONEKSI:`,
|
|
300
|
+
` ✅ CONNECTED ke CryptoIZ Data Engine`,
|
|
301
|
+
` ${hasKey ? '✅ PAYMENT READY — x402 Solana USDC' : '❌ PAYMENT NOT SET — tambahkan SVM_PRIVATE_KEY'}`,
|
|
302
|
+
` 💰 Harga : $0.01 USDC per call`,
|
|
303
|
+
` 🏦 Wallet CRZ : DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX`,
|
|
153
304
|
``,
|
|
154
|
-
`
|
|
155
|
-
`
|
|
156
|
-
`
|
|
305
|
+
`TOOLS TERSEDIA:`,
|
|
306
|
+
` 1. get_alpha_scanner — Token Solana dengan akumulasi terkuat`,
|
|
307
|
+
` Termasuk: address, MC, price, holder signals, sub-scores, risks`,
|
|
308
|
+
``,
|
|
309
|
+
` 2. get_divergence — Divergence bullish/bearish`,
|
|
310
|
+
` Termasuk: address, MC, price, confidence, waktu deteksi`,
|
|
311
|
+
``,
|
|
312
|
+
` 3. get_accumulation — Token fase akumulasi (composite score)`,
|
|
313
|
+
` Termasuk: address, 4 sub-scores, strength label`,
|
|
314
|
+
``,
|
|
315
|
+
` 4. get_btc_regime — Kondisi makro Bitcoin`,
|
|
316
|
+
` Termasuk: price, fear & greed, OI regime, funding, indikator`,
|
|
317
|
+
``,
|
|
318
|
+
` 5. get_status — Info server ini`,
|
|
319
|
+
``,
|
|
320
|
+
`CARA PAKAI:`,
|
|
321
|
+
` • Tanya: "Sinyal Solana hari ini?"`,
|
|
322
|
+
` • Tanya: "Ada divergence bullish?"`,
|
|
323
|
+
` • Tanya: "Token mana yang diakumulasi whale?"`,
|
|
324
|
+
` • Tanya: "Kondisi BTC sekarang?"`,
|
|
325
|
+
FOOTER,
|
|
157
326
|
].join('\n');
|
|
158
327
|
}
|
|
159
328
|
|
|
160
|
-
// ───
|
|
161
|
-
|
|
329
|
+
// ─── Tool definitions ─────────────────────────────────────────────────────────
|
|
162
330
|
const TOOLS = [
|
|
163
|
-
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
properties: {
|
|
169
|
-
min_score: { type: 'number', description: 'Minimum alpha score (0-100).' },
|
|
170
|
-
},
|
|
171
|
-
required: [],
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
name: 'get_divergence',
|
|
176
|
-
description: 'Ambil divergence signals dari CryptoIZ — deteksi bullish/bearish divergence whale/dolphin di Solana. Biaya: $0.01 USDC.',
|
|
177
|
-
inputSchema: {
|
|
178
|
-
type: 'object',
|
|
179
|
-
properties: {
|
|
180
|
-
timeframe: { type: 'string', enum: ['4h', '1d'], description: 'Timeframe. Default: 4h.' },
|
|
181
|
-
limit: { type: 'number', description: 'Max results (1-50). Default: 20.' },
|
|
182
|
-
},
|
|
183
|
-
required: [],
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
name: 'get_accumulation',
|
|
188
|
-
description: 'Ambil token dalam fase akumulasi dari CryptoIZ Accumulation Dashboard. Biaya: $0.01 USDC.',
|
|
189
|
-
inputSchema: {
|
|
190
|
-
type: 'object',
|
|
191
|
-
properties: {
|
|
192
|
-
min_composite: { type: 'number', description: 'Minimum composite score (0-100).' },
|
|
193
|
-
},
|
|
194
|
-
required: [],
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
name: 'get_status',
|
|
199
|
-
description: 'Cek status koneksi CryptoIZ MCP, payment setup, dan tools yang tersedia.',
|
|
200
|
-
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
201
|
-
},
|
|
331
|
+
{ name: 'get_alpha_scanner', description: 'Ambil sinyal token Solana terkuat dari CryptoIZ Alpha Scanner. Termasuk contract address, market cap, price, holder signals (whale/dolphin/shrimp), sub-scores (accum/timing/safety), dan risiko. Biaya $0.01 USDC via Solana.', inputSchema: { type: 'object', properties: { min_score: { type: 'number', description: 'Minimum alpha score (0-100).' }, entry_class: { type: 'string', enum: ['ALPHA_EARLY','ALPHA_BUILDING','WATCHLIST_ONLY'], description: 'Filter entry class.' } }, required: [] } },
|
|
332
|
+
{ name: 'get_divergence', description: 'Ambil divergence signals dari CryptoIZ — deteksi bullish/bearish divergence antara harga dan aktivitas whale/dolphin. Termasuk address, MC, price, confidence score, waktu deteksi. Biaya $0.01 USDC.', inputSchema: { type: 'object', properties: { timeframe: { type: 'string', enum: ['4h','1d'], description: 'Timeframe. Default: 4h.' }, limit: { type: 'number', description: 'Max hasil (1-50). Default: 20.' } }, required: [] } },
|
|
333
|
+
{ name: 'get_accumulation', description: 'Ambil token dalam fase akumulasi dari CryptoIZ Accumulation Dashboard. Composite score dari 4 dimensi: Structure, AccDist, Holder, Market. Termasuk address. Biaya $0.01 USDC.', inputSchema: { type: 'object', properties: { min_composite: { type: 'number', description: 'Minimum composite score (0-100).' } }, required: [] } },
|
|
334
|
+
{ name: 'get_btc_regime', description: 'Ambil kondisi makro Bitcoin dari CryptoIZ BTC Monitor. Termasuk: state (bull/bear/neutral), Fear & Greed Index, OI regime, funding rate, sinyal futures, dan indikator teknikal. Penting untuk konteks altcoin Solana. Biaya $0.01 USDC.', inputSchema: { type: 'object', properties: {}, required: [] } },
|
|
335
|
+
{ name: 'get_status', description: 'Cek status koneksi CryptoIZ MCP, info payment, dan daftar tools tersedia.', inputSchema: { type: 'object', properties: {}, required: [] } },
|
|
202
336
|
];
|
|
203
337
|
|
|
204
338
|
// ─── Server ───────────────────────────────────────────────────────────────────
|
|
205
|
-
|
|
206
|
-
const server = new Server(
|
|
207
|
-
{ name: 'cryptoiz-mcp', version: '2.0.1' },
|
|
208
|
-
{ capabilities: { tools: {} } }
|
|
209
|
-
);
|
|
210
|
-
|
|
339
|
+
const server = new Server({ name: 'cryptoiz-mcp', version: '2.1.0' }, { capabilities: { tools: {} } });
|
|
211
340
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
212
|
-
|
|
213
341
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
214
342
|
const { name, arguments: args } = request.params;
|
|
215
|
-
|
|
216
343
|
try {
|
|
217
|
-
if (name === 'get_status') {
|
|
218
|
-
return { content: [{ type: 'text', text: formatStatus() }] };
|
|
219
|
-
}
|
|
344
|
+
if (name === 'get_status') return { content: [{ type: 'text', text: formatStatus() }] };
|
|
220
345
|
|
|
221
346
|
if (name === 'get_alpha_scanner') {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
if (args?.
|
|
225
|
-
data.signals = data.signals.filter(s => s.alpha_score >= args.min_score);
|
|
226
|
-
data.total = data.signals.length;
|
|
227
|
-
}
|
|
347
|
+
const data = await payAndFetch(`${GATEWAY_URL}?tool=get_alpha_scanner`);
|
|
348
|
+
if (args?.min_score && data.signals) { data.signals = data.signals.filter(s => s.alpha_score >= args.min_score); data.total = data.signals.length; }
|
|
349
|
+
if (args?.entry_class && data.signals) { data.signals = data.signals.filter(s => s.entry_class === args.entry_class); data.total = data.signals.length; }
|
|
228
350
|
return { content: [{ type: 'text', text: formatAlpha(data) }] };
|
|
229
351
|
}
|
|
230
352
|
|
|
231
353
|
if (name === 'get_divergence') {
|
|
232
|
-
const
|
|
233
|
-
if (args?.timeframe)
|
|
234
|
-
if (args?.limit)
|
|
235
|
-
const data = await payAndFetch(`${GATEWAY_URL}?${
|
|
354
|
+
const p = new URLSearchParams({ tool: 'get_divergence' });
|
|
355
|
+
if (args?.timeframe) p.set('tf', args.timeframe);
|
|
356
|
+
if (args?.limit) p.set('limit', String(args.limit));
|
|
357
|
+
const data = await payAndFetch(`${GATEWAY_URL}?${p}`);
|
|
236
358
|
return { content: [{ type: 'text', text: formatDivergence(data) }] };
|
|
237
359
|
}
|
|
238
360
|
|
|
239
361
|
if (name === 'get_accumulation') {
|
|
240
362
|
const data = await payAndFetch(`${GATEWAY_URL}?tool=get_accumulation`);
|
|
241
|
-
if (args?.min_composite && data.tokens) {
|
|
242
|
-
|
|
243
|
-
data.total = data.tokens.length;
|
|
244
|
-
}
|
|
245
|
-
return { content: [{ type: 'text', text: formatAccum(data) }] };
|
|
363
|
+
if (args?.min_composite && data.tokens) { data.tokens = data.tokens.filter(t => t.composite_score >= args.min_composite); data.total = data.tokens.length; }
|
|
364
|
+
return { content: [{ type: 'text', text: formatAccumulation(data) }] };
|
|
246
365
|
}
|
|
247
366
|
|
|
248
|
-
|
|
367
|
+
if (name === 'get_btc_regime') {
|
|
368
|
+
const data = await payAndFetch(`${GATEWAY_URL}?tool=get_btc_regime`);
|
|
369
|
+
return { content: [{ type: 'text', text: formatBTC(data) }] };
|
|
370
|
+
}
|
|
249
371
|
|
|
372
|
+
return { content: [{ type: 'text', text: `Tool tidak dikenal: ${name}` }], isError: true };
|
|
250
373
|
} catch (err) {
|
|
251
374
|
return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
|
|
252
375
|
}
|