cryptoiz-mcp 4.16.15 → 4.16.17
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/LICENSE +21 -21
- package/README.md +145 -145
- package/index.js +309 -309
- package/package.json +50 -49
- package/setup.js +51 -51
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 CryptoIZ (https://cryptoiz.org)
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CryptoIZ (https://cryptoiz.org)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
# cryptoiz-mcp
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/cryptoiz-mcp)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://x402scan.com/server/cbd8fff5-d636-4331-b22b-3291717a4e9e)
|
|
6
|
-
[](https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz)
|
|
7
|
-
|
|
8
|
-
**CryptoIZ MCP Server** — Solana DEX whale intelligence as a Model Context Protocol (MCP) server. 9 tools (7 paid + 2 free) for Claude Desktop, Cursor, Codex, and any agentcash-compatible client. Native Solana via x402 V2 + Dexter facilitator (gas-sponsored — no SOL needed, only USDC).
|
|
9
|
-
|
|
10
|
-
## ⚡ Recommended Install (1 line)
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npx agentcash add https://mcp.cryptoiz.org
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
That's it. agentcash auto-generates a Solana wallet at `~/.agentcash/wallet.json` (no private key in your Claude config). Fund with $1-5 USDC via `npx agentcash fund` and you're ready.
|
|
17
|
-
|
|
18
|
-
**Why agentcash:**
|
|
19
|
-
- ✅ No private key in Claude Desktop config
|
|
20
|
-
- ✅ Wallet auto-generated and isolated
|
|
21
|
-
- ✅ Gas sponsored by Dexter (zero SOL needed)
|
|
22
|
-
- ✅ Update tools without reinstalling client
|
|
23
|
-
- ✅ One wallet across ALL x402 services (CryptoIZ, HYRE, etc.)
|
|
24
|
-
|
|
25
|
-
## 5 Specialized Sub-Agents
|
|
26
|
-
|
|
27
|
-
Pick what you need:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npx agentcash add https://mcp.cryptoiz.org/agents/alpha # Whale alpha signals only
|
|
31
|
-
npx agentcash add https://mcp.cryptoiz.org/agents/btc # BTC regime + futures
|
|
32
|
-
npx agentcash add https://mcp.cryptoiz.org/agents/phases # Accumulation/Neutral/Distribution
|
|
33
|
-
npx agentcash add https://mcp.cryptoiz.org/agents/divergence # Divergence patterns
|
|
34
|
-
npx agentcash add https://mcp.cryptoiz.org/agents/deep-research # Token deep-dive combo
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Tools & Pricing
|
|
38
|
-
|
|
39
|
-
| Tool | Cost | Description |
|
|
40
|
-
|---|---|---|
|
|
41
|
-
| `get_whale_alpha` | $0.
|
|
42
|
-
| `get_whale_divergence` | $0.
|
|
43
|
-
| `get_whale_accumulation` | $0.
|
|
44
|
-
| `get_whale_neutral` | $0.
|
|
45
|
-
| `get_whale_distribution` | $0.
|
|
46
|
-
| `get_btc_regime` | $0.
|
|
47
|
-
| `get_btc_futures_signal` | $0.
|
|
48
|
-
| `get_token_ca` | FREE | Look up Solana contract address by name |
|
|
49
|
-
| `get_status` | FREE | Server status, available tools, pricing |
|
|
50
|
-
|
|
51
|
-
All payments settle on Solana mainnet via [Dexter facilitator](https://x402.dexter.cash). Recipient: `DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX`.
|
|
52
|
-
|
|
53
|
-
## Legacy Setup (Advanced — not recommended)
|
|
54
|
-
|
|
55
|
-
For users who prefer self-custody with their own Solana wallet:
|
|
56
|
-
|
|
57
|
-
### 1. Install the package globally
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npm install -g cryptoiz-mcp
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 2. Get a Solana wallet private key (base58)
|
|
64
|
-
|
|
65
|
-
You need a Solana wallet with at least **$1 USDC** on mainnet. **No SOL needed** — Dexter sponsors all gas. Recommended: dedicated wallet, NOT your main wallet. Phantom: Settings > Security > Export Private Key.
|
|
66
|
-
|
|
67
|
-
### 3. Edit Claude Desktop config
|
|
68
|
-
|
|
69
|
-
File: `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS).
|
|
70
|
-
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"mcpServers": {
|
|
74
|
-
"cryptoiz": {
|
|
75
|
-
"command": "C:\\Program Files\\nodejs\\node.exe",
|
|
76
|
-
"args": ["C:\\Users\\<YOU>\\AppData\\Roaming\\npm\\node_modules\\cryptoiz-mcp\\index.js"],
|
|
77
|
-
"env": {
|
|
78
|
-
"SVM_PRIVATE_KEY": "<your_base58_solana_private_key>"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 4. Restart Claude Desktop
|
|
86
|
-
|
|
87
|
-
Then ask Claude: `get cryptoiz status` — you should see version `v4.16.
|
|
88
|
-
|
|
89
|
-
## Security
|
|
90
|
-
|
|
91
|
-
- **agentcash flow** (recommended): private key auto-generated and isolated, never in Claude config
|
|
92
|
-
- **Gas-sponsored**: Dexter facilitator pays all gas (you only pay USDC)
|
|
93
|
-
- **Server-side validation**: every payment verified via Dexter `/settle` before serving data
|
|
94
|
-
- **x402 V2 spec compliant**: open standard, no custom protocol
|
|
95
|
-
- **No tracking**: only on-chain transaction signature is recorded for replay protection
|
|
96
|
-
- **Dedicated wallet recommended** for legacy npm install (don't use your main wallet)
|
|
97
|
-
|
|
98
|
-
## Listed at
|
|
99
|
-
|
|
100
|
-
- [MCP Marketplace](https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz)
|
|
101
|
-
- [x402scan](https://x402scan.com/server/cbd8fff5-d636-4331-b22b-3291717a4e9e) — 94+ tx, $2.80+ volume
|
|
102
|
-
- [Official MCP Registry](https://github.com/modelcontextprotocol/registry)
|
|
103
|
-
- MPPscan (pending)
|
|
104
|
-
|
|
105
|
-
## Architecture
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
Claude Desktop / Cursor / Codex
|
|
109
|
-
│ (MCP)
|
|
110
|
-
▼
|
|
111
|
-
agentcash CLI (or cryptoiz-mcp legacy npm)
|
|
112
|
-
│ (HTTP)
|
|
113
|
-
▼
|
|
114
|
-
mcp.cryptoiz.org gateway (Cloudflare Worker + Supabase Edge Function)
|
|
115
|
-
│ (POST /settle)
|
|
116
|
-
▼
|
|
117
|
-
Dexter facilitator (x402.dexter.cash)
|
|
118
|
-
│ (signs + broadcasts)
|
|
119
|
-
▼
|
|
120
|
-
Solana mainnet
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Troubleshooting
|
|
124
|
-
|
|
125
|
-
### "Transaction simulation failed"
|
|
126
|
-
Update to latest: `npx agentcash add https://mcp.cryptoiz.org` (or `npm install -g cryptoiz-mcp@latest` for legacy).
|
|
127
|
-
|
|
128
|
-
### "Server disconnected" on Windows
|
|
129
|
-
Use absolute paths in Claude config (legacy npm only). agentcash flow doesn't have this issue.
|
|
130
|
-
|
|
131
|
-
### Update notifications keep showing
|
|
132
|
-
Run `npm install -g cryptoiz-mcp@latest`, force-kill all `node.exe` processes via Task Manager, then restart Claude Desktop. Or switch to agentcash for auto-updates.
|
|
133
|
-
|
|
134
|
-
## Links
|
|
135
|
-
|
|
136
|
-
- **Platform**: https://cryptoiz.org
|
|
137
|
-
- **Setup guide**: https://cryptoiz.org/McpLanding
|
|
138
|
-
- **Twitter**: [@cryptoiz_IDN](https://twitter.com/cryptoiz_IDN)
|
|
139
|
-
- **Telegram**: https://t.me/agus_artemiss
|
|
140
|
-
- **MCP Marketplace**: https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz
|
|
141
|
-
- **x402scan**: https://x402scan.com/server/mcp.cryptoiz.org
|
|
142
|
-
|
|
143
|
-
## License
|
|
144
|
-
|
|
145
|
-
MIT © CryptoIZ
|
|
1
|
+
# cryptoiz-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/cryptoiz-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://x402scan.com/server/cbd8fff5-d636-4331-b22b-3291717a4e9e)
|
|
6
|
+
[](https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz)
|
|
7
|
+
|
|
8
|
+
**CryptoIZ MCP Server** — Solana DEX whale intelligence as a Model Context Protocol (MCP) server. 9 tools (7 paid + 2 free) for Claude Desktop, Cursor, Codex, and any agentcash-compatible client. Native Solana via x402 V2 + Dexter facilitator (gas-sponsored — no SOL needed, only USDC).
|
|
9
|
+
|
|
10
|
+
## ⚡ Recommended Install (1 line)
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx agentcash add https://mcp.cryptoiz.org
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
That's it. agentcash auto-generates a Solana wallet at `~/.agentcash/wallet.json` (no private key in your Claude config). Fund with $1-5 USDC via `npx agentcash fund` and you're ready.
|
|
17
|
+
|
|
18
|
+
**Why agentcash:**
|
|
19
|
+
- ✅ No private key in Claude Desktop config
|
|
20
|
+
- ✅ Wallet auto-generated and isolated
|
|
21
|
+
- ✅ Gas sponsored by Dexter (zero SOL needed)
|
|
22
|
+
- ✅ Update tools without reinstalling client
|
|
23
|
+
- ✅ One wallet across ALL x402 services (CryptoIZ, HYRE, etc.)
|
|
24
|
+
|
|
25
|
+
## 5 Specialized Sub-Agents
|
|
26
|
+
|
|
27
|
+
Pick what you need:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx agentcash add https://mcp.cryptoiz.org/agents/alpha # Whale alpha signals only
|
|
31
|
+
npx agentcash add https://mcp.cryptoiz.org/agents/btc # BTC regime + futures
|
|
32
|
+
npx agentcash add https://mcp.cryptoiz.org/agents/phases # Accumulation/Neutral/Distribution
|
|
33
|
+
npx agentcash add https://mcp.cryptoiz.org/agents/divergence # Divergence patterns
|
|
34
|
+
npx agentcash add https://mcp.cryptoiz.org/agents/deep-research # Token deep-dive combo
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Tools & Pricing
|
|
38
|
+
|
|
39
|
+
| Tool | Cost | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `get_whale_alpha` | $0.10 USDC | Top 20 alpha signals — whale/dolphin accumulation, entry timing |
|
|
42
|
+
| `get_whale_divergence` | $0.04 USDC | Hidden/breakout/classic divergence signals (4h/1d) |
|
|
43
|
+
| `get_whale_accumulation` | $0.03 USDC | Tokens with smart money accumulating |
|
|
44
|
+
| `get_whale_neutral` | $0.03 USDC | Tokens in transition phase |
|
|
45
|
+
| `get_whale_distribution` | $0.04 USDC | Tokens with whales selling (exit signal) |
|
|
46
|
+
| `get_btc_regime` | $0.02 USDC | BTC macro regime + sentiment + technicals |
|
|
47
|
+
| `get_btc_futures_signal` | $0.06 USDC | BTC futures multi-timeframe signal (54% WR) |
|
|
48
|
+
| `get_token_ca` | FREE | Look up Solana contract address by name |
|
|
49
|
+
| `get_status` | FREE | Server status, available tools, pricing |
|
|
50
|
+
|
|
51
|
+
All payments settle on Solana mainnet via [Dexter facilitator](https://x402.dexter.cash). Recipient: `DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX`.
|
|
52
|
+
|
|
53
|
+
## Legacy Setup (Advanced — not recommended)
|
|
54
|
+
|
|
55
|
+
For users who prefer self-custody with their own Solana wallet:
|
|
56
|
+
|
|
57
|
+
### 1. Install the package globally
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install -g cryptoiz-mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Get a Solana wallet private key (base58)
|
|
64
|
+
|
|
65
|
+
You need a Solana wallet with at least **$1 USDC** on mainnet. **No SOL needed** — Dexter sponsors all gas. Recommended: dedicated wallet, NOT your main wallet. Phantom: Settings > Security > Export Private Key.
|
|
66
|
+
|
|
67
|
+
### 3. Edit Claude Desktop config
|
|
68
|
+
|
|
69
|
+
File: `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS).
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"cryptoiz": {
|
|
75
|
+
"command": "C:\\Program Files\\nodejs\\node.exe",
|
|
76
|
+
"args": ["C:\\Users\\<YOU>\\AppData\\Roaming\\npm\\node_modules\\cryptoiz-mcp\\index.js"],
|
|
77
|
+
"env": {
|
|
78
|
+
"SVM_PRIVATE_KEY": "<your_base58_solana_private_key>"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 4. Restart Claude Desktop
|
|
86
|
+
|
|
87
|
+
Then ask Claude: `get cryptoiz status` — you should see version `v4.16.17` and the tool list.
|
|
88
|
+
|
|
89
|
+
## Security
|
|
90
|
+
|
|
91
|
+
- **agentcash flow** (recommended): private key auto-generated and isolated, never in Claude config
|
|
92
|
+
- **Gas-sponsored**: Dexter facilitator pays all gas (you only pay USDC)
|
|
93
|
+
- **Server-side validation**: every payment verified via Dexter `/settle` before serving data
|
|
94
|
+
- **x402 V2 spec compliant**: open standard, no custom protocol
|
|
95
|
+
- **No tracking**: only on-chain transaction signature is recorded for replay protection
|
|
96
|
+
- **Dedicated wallet recommended** for legacy npm install (don't use your main wallet)
|
|
97
|
+
|
|
98
|
+
## Listed at
|
|
99
|
+
|
|
100
|
+
- [MCP Marketplace](https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz)
|
|
101
|
+
- [x402scan](https://x402scan.com/server/cbd8fff5-d636-4331-b22b-3291717a4e9e) — 94+ tx, $2.80+ volume
|
|
102
|
+
- [Official MCP Registry](https://github.com/modelcontextprotocol/registry)
|
|
103
|
+
- MPPscan (pending)
|
|
104
|
+
|
|
105
|
+
## Architecture
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
Claude Desktop / Cursor / Codex
|
|
109
|
+
│ (MCP)
|
|
110
|
+
▼
|
|
111
|
+
agentcash CLI (or cryptoiz-mcp legacy npm)
|
|
112
|
+
│ (HTTP)
|
|
113
|
+
▼
|
|
114
|
+
mcp.cryptoiz.org gateway (Cloudflare Worker + Supabase Edge Function)
|
|
115
|
+
│ (POST /settle)
|
|
116
|
+
▼
|
|
117
|
+
Dexter facilitator (x402.dexter.cash)
|
|
118
|
+
│ (signs + broadcasts)
|
|
119
|
+
▼
|
|
120
|
+
Solana mainnet
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Troubleshooting
|
|
124
|
+
|
|
125
|
+
### "Transaction simulation failed"
|
|
126
|
+
Update to latest: `npx agentcash add https://mcp.cryptoiz.org` (or `npm install -g cryptoiz-mcp@latest` for legacy).
|
|
127
|
+
|
|
128
|
+
### "Server disconnected" on Windows
|
|
129
|
+
Use absolute paths in Claude config (legacy npm only). agentcash flow doesn't have this issue.
|
|
130
|
+
|
|
131
|
+
### Update notifications keep showing
|
|
132
|
+
Run `npm install -g cryptoiz-mcp@latest`, force-kill all `node.exe` processes via Task Manager, then restart Claude Desktop. Or switch to agentcash for auto-updates.
|
|
133
|
+
|
|
134
|
+
## Links
|
|
135
|
+
|
|
136
|
+
- **Platform**: https://cryptoiz.org
|
|
137
|
+
- **Setup guide**: https://cryptoiz.org/McpLanding
|
|
138
|
+
- **Twitter**: [@cryptoiz_IDN](https://twitter.com/cryptoiz_IDN)
|
|
139
|
+
- **Telegram**: https://t.me/agus_artemiss
|
|
140
|
+
- **MCP Marketplace**: https://mcp-marketplace.io/server/io-github-dadang11-cryptoiz
|
|
141
|
+
- **x402scan**: https://x402scan.com/server/mcp.cryptoiz.org
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT © CryptoIZ
|
package/index.js
CHANGED
|
@@ -1,309 +1,309 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
var VERSION = 'v4.16.15';
|
|
3
|
-
var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
|
|
4
|
-
// FIX v4.16.12: route ALL paid tools to gateway. Per-tool endpoints (mcp-alpha-scanner etc.)
|
|
5
|
-
// have stale hardcoded fee payer that breaks after Dexter key rotation. Gateway has dynamic
|
|
6
|
-
// fee payer fetched from /supported. Single source of truth = no per-tool drift.
|
|
7
|
-
var TOOL_ENDPOINTS = {
|
|
8
|
-
get_whale_alpha: GATEWAY,
|
|
9
|
-
get_whale_divergence: GATEWAY,
|
|
10
|
-
get_whale_accumulation: GATEWAY,
|
|
11
|
-
get_whale_neutral: GATEWAY,
|
|
12
|
-
get_whale_distribution: GATEWAY,
|
|
13
|
-
get_btc_regime: GATEWAY,
|
|
14
|
-
get_btc_futures_signal: GATEWAY,
|
|
15
|
-
get_token_ca: GATEWAY,
|
|
16
|
-
get_status: GATEWAY,
|
|
17
|
-
};
|
|
18
|
-
var RECIPIENT = 'DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX';
|
|
19
|
-
var USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
20
|
-
var SOL_RPC = 'https://api.mainnet-beta.solana.com';
|
|
21
|
-
var TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
|
|
22
|
-
var ATA_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
|
|
23
|
-
var MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
|
|
24
|
-
var COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';
|
|
25
|
-
|
|
26
|
-
var _updateNotified = false;
|
|
27
|
-
function notifyUpdate(data, headers) {
|
|
28
|
-
if (_updateNotified) return;
|
|
29
|
-
if (!headers || headers.get('x-update-available') !== '1') return;
|
|
30
|
-
_updateNotified = true;
|
|
31
|
-
var latest = (data && data.version_latest) || '?';
|
|
32
|
-
var cmd = (data && data.update_command) || 'npm install -g cryptoiz-mcp@latest';
|
|
33
|
-
console.error('[cryptoiz-mcp] UPDATE: ' + VERSION + ' -> ' + latest + ' | Run: ' + cmd);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
var solana = require('@solana/web3.js');
|
|
37
|
-
var Connection = solana.Connection;
|
|
38
|
-
var PublicKey = solana.PublicKey;
|
|
39
|
-
var Transaction = solana.Transaction;
|
|
40
|
-
var TransactionMessage = solana.TransactionMessage;
|
|
41
|
-
var VersionedTransaction = solana.VersionedTransaction;
|
|
42
|
-
var Keypair = solana.Keypair;
|
|
43
|
-
// Fix bs58 v6 ESM-only issue: support both CJS (v5) and ESM-compiled (v6)
|
|
44
|
-
var _bs58mod = require('bs58');
|
|
45
|
-
var bs58 = _bs58mod.default || _bs58mod;
|
|
46
|
-
var Server = require('@modelcontextprotocol/sdk/server/index.js').Server;
|
|
47
|
-
var StdioServerTransport = require('@modelcontextprotocol/sdk/server/stdio.js').StdioServerTransport;
|
|
48
|
-
var CallToolRequestSchema = require('@modelcontextprotocol/sdk/types.js').CallToolRequestSchema;
|
|
49
|
-
var ListToolsRequestSchema = require('@modelcontextprotocol/sdk/types.js').ListToolsRequestSchema;
|
|
50
|
-
|
|
51
|
-
function getKeypair() {
|
|
52
|
-
var privKey = process.env.SVM_PRIVATE_KEY;
|
|
53
|
-
if (!privKey) throw new Error('SVM_PRIVATE_KEY not set in environment');
|
|
54
|
-
return Keypair.fromSecretKey(bs58.decode(privKey));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function findATA(wallet, mint) {
|
|
58
|
-
var walletPk = new PublicKey(wallet);
|
|
59
|
-
var mintPk = new PublicKey(mint);
|
|
60
|
-
var ataPk = new PublicKey(ATA_PROGRAM);
|
|
61
|
-
var tokPk = new PublicKey(TOKEN_PROGRAM);
|
|
62
|
-
return PublicKey.findProgramAddressSync([walletPk.toBuffer(), tokPk.toBuffer(), mintPk.toBuffer()], ataPk)[0];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// V2: Dexter gas-sponsored. 4-ix tx: Limit + Price + TransferChecked + Memo(nonce)
|
|
66
|
-
// Dexter pays SOL gas — user only needs USDC
|
|
67
|
-
async function buildV2PaymentPayload(amount, feePayerAddr) {
|
|
68
|
-
var kp = getKeypair();
|
|
69
|
-
var conn = new Connection(SOL_RPC, 'confirmed');
|
|
70
|
-
var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
|
|
71
|
-
var recipientATA = findATA(RECIPIENT, USDC_MINT);
|
|
72
|
-
var feePayerPk = new PublicKey(feePayerAddr);
|
|
73
|
-
var computeBudgetPk = new PublicKey(COMPUTE_BUDGET_PROGRAM);
|
|
74
|
-
var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
|
|
75
|
-
var usdcMintPk = new PublicKey(USDC_MINT);
|
|
76
|
-
// FIX v4.16.13: ComputeUnitLimit 20000 -> 30000.
|
|
77
|
-
// Memo program needs >13500 CU when content is 'x402:v2:'+32char hex; old (April 6-8)
|
|
78
|
-
// working code used just 32-char nonceHex which fit in 20000 budget. Bumping limit gives
|
|
79
|
-
// headroom for slightly longer memo content. Dexter spec allows up to 40000.
|
|
80
|
-
var setLimitData = Buffer.alloc(5);
|
|
81
|
-
setLimitData[0] = 0x02;
|
|
82
|
-
setLimitData.writeUInt32LE(30000, 1);
|
|
83
|
-
var setLimitIx = { programId: computeBudgetPk, keys: [], data: setLimitData };
|
|
84
|
-
// ComputeUnitPrice(1)
|
|
85
|
-
var setPriceData = Buffer.alloc(9);
|
|
86
|
-
setPriceData[0] = 0x03;
|
|
87
|
-
setPriceData.writeBigUInt64LE(BigInt(1), 1);
|
|
88
|
-
var setPriceIx = { programId: computeBudgetPk, keys: [], data: setPriceData };
|
|
89
|
-
// TransferChecked
|
|
90
|
-
var transferKeys = [
|
|
91
|
-
{ pubkey: userATA, isSigner: false, isWritable: true },
|
|
92
|
-
{ pubkey: usdcMintPk, isSigner: false, isWritable: false },
|
|
93
|
-
{ pubkey: recipientATA, isSigner: false, isWritable: true },
|
|
94
|
-
{ pubkey: kp.publicKey, isSigner: true, isWritable: false },
|
|
95
|
-
];
|
|
96
|
-
var transferData = Buffer.alloc(10);
|
|
97
|
-
transferData[0] = 0x0c;
|
|
98
|
-
transferData.writeUInt32LE(amount & 0xFFFFFFFF, 1);
|
|
99
|
-
transferData.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
|
|
100
|
-
transferData[9] = 6;
|
|
101
|
-
var transferIx = { programId: tokenProgramPk, keys: transferKeys, data: transferData };
|
|
102
|
-
// FIX v4.16.12: RESTORE Memo instruction in V2 (4-ix tx: Limit+Price+TransferChecked+Memo).
|
|
103
|
-
// Empirical: April 6-8 logs prove V2 with memo accepted by Dexter. Removing memo (v4.16.10)
|
|
104
|
-
// didn't fix anything — the actual bug was Dexter key rotation, fixed in gateway v44.
|
|
105
|
-
// Memo also makes TX visible to x402scan (memo carries x402 nonce marker).
|
|
106
|
-
var memoProgramPk = new PublicKey(MEMO_PROGRAM);
|
|
107
|
-
var nonceBytes = new Uint8Array(16);
|
|
108
|
-
for (var i = 0; i < 16; i++) nonceBytes[i] = Math.floor(Math.random() * 256);
|
|
109
|
-
var nonceHex = Array.from(nonceBytes).map(function(b) { return b.toString(16).padStart(2,'0'); }).join('');
|
|
110
|
-
// FIX v4.16.13: memo = just nonceHex (matches April 6-8 working V2 format).
|
|
111
|
-
// Adding 'x402:v2:' prefix made memo too long for 20000 CU budget.
|
|
112
|
-
var memoIx = { programId: memoProgramPk, keys: [], data: Buffer.from(nonceHex, 'utf8') };
|
|
113
|
-
var bh = await conn.getLatestBlockhash('confirmed');
|
|
114
|
-
var message = new TransactionMessage({
|
|
115
|
-
payerKey: feePayerPk,
|
|
116
|
-
recentBlockhash: bh.blockhash,
|
|
117
|
-
instructions: [setLimitIx, setPriceIx, transferIx, memoIx],
|
|
118
|
-
}).compileToV0Message();
|
|
119
|
-
var vtx = new VersionedTransaction(message);
|
|
120
|
-
vtx.sign([kp]);
|
|
121
|
-
var txB64 = Buffer.from(vtx.serialize()).toString('base64');
|
|
122
|
-
console.error('[cryptoiz-mcp] V2 tx built (Dexter gas-sponsored), 4 ix limit=30000');
|
|
123
|
-
return txB64;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// V1: direct on-chain, user pays SOL gas (fallback only)
|
|
127
|
-
async function sendUSDC(amount, toolName) {
|
|
128
|
-
var kp = getKeypair();
|
|
129
|
-
var conn = new Connection(SOL_RPC, 'confirmed');
|
|
130
|
-
var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
|
|
131
|
-
var recipientATA = findATA(RECIPIENT, USDC_MINT);
|
|
132
|
-
var keys = [
|
|
133
|
-
{ pubkey: userATA, isSigner: false, isWritable: true },
|
|
134
|
-
{ pubkey: new PublicKey(USDC_MINT), isSigner: false, isWritable: false },
|
|
135
|
-
{ pubkey: recipientATA, isSigner: false, isWritable: true },
|
|
136
|
-
{ pubkey: kp.publicKey, isSigner: true, isWritable: false },
|
|
137
|
-
];
|
|
138
|
-
// FIX v4.16.10: TransferChecked needs 10 bytes (1 disc + 8 amount + 1 decimals)
|
|
139
|
-
var data = Buffer.alloc(10);
|
|
140
|
-
data[0] = 0x0c;
|
|
141
|
-
data.writeUInt32LE(amount & 0xFFFFFFFF, 1);
|
|
142
|
-
data.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
|
|
143
|
-
data[9] = 6;
|
|
144
|
-
var transferIx = { programId: new PublicKey(TOKEN_PROGRAM), keys: keys, data: data };
|
|
145
|
-
var nonce = Date.now().toString(16) + Math.floor(Math.random()*0xffff).toString(16);
|
|
146
|
-
var memoIx = {
|
|
147
|
-
programId: new PublicKey(MEMO_PROGRAM),
|
|
148
|
-
keys: [],
|
|
149
|
-
data: Buffer.from('x402:v1:' + (toolName || 'tool') + ':' + nonce, 'utf8')
|
|
150
|
-
};
|
|
151
|
-
var bh = await conn.getLatestBlockhash('confirmed');
|
|
152
|
-
var tx = new Transaction({ feePayer: kp.publicKey, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight });
|
|
153
|
-
tx.add(memoIx);
|
|
154
|
-
tx.add(transferIx);
|
|
155
|
-
tx.sign(kp);
|
|
156
|
-
var sig = await conn.sendRawTransaction(tx.serialize(), { skipPreflight: false });
|
|
157
|
-
await conn.confirmTransaction({ signature: sig, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight }, 'confirmed');
|
|
158
|
-
console.error('[cryptoiz-mcp] V1 TX: ' + sig);
|
|
159
|
-
return sig;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function clientHeaders(extra) {
|
|
163
|
-
var h = { 'x-client-version': VERSION.replace(/^v/i, '') };
|
|
164
|
-
if (extra) for (var k in extra) if (Object.prototype.hasOwnProperty.call(extra, k)) h[k] = extra[k];
|
|
165
|
-
return h;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// v4.16.14: input validation per tool — defense in depth, server-side double-validates.
|
|
169
|
-
function validateArgs(toolName, args) {
|
|
170
|
-
if (args == null) return {}; // Empty args ok
|
|
171
|
-
if (typeof args !== 'object' || Array.isArray(args)) {
|
|
172
|
-
throw new Error('Invalid args: expected object, got ' + typeof args);
|
|
173
|
-
}
|
|
174
|
-
var clean = {};
|
|
175
|
-
if (toolName === 'get_whale_divergence') {
|
|
176
|
-
if (args.timeframe != null) {
|
|
177
|
-
if (typeof args.timeframe !== 'string') throw new Error('timeframe must be string');
|
|
178
|
-
if (args.timeframe !== '4h' && args.timeframe !== '1d') throw new Error("timeframe must be '4h' or '1d'");
|
|
179
|
-
clean.timeframe = args.timeframe;
|
|
180
|
-
}
|
|
181
|
-
} else if (toolName === 'get_token_ca') {
|
|
182
|
-
if (args.name == null) throw new Error('name is required for get_token_ca');
|
|
183
|
-
if (typeof args.name !== 'string') throw new Error('name must be string');
|
|
184
|
-
var trimmed = args.name.trim();
|
|
185
|
-
if (trimmed.length < 1 || trimmed.length > 64) throw new Error('name length must be 1-64 chars');
|
|
186
|
-
if (!/^[a-zA-Z0-9 _\-\$\.\u00c0-\uffff]+$/.test(trimmed)) throw new Error('name contains invalid chars');
|
|
187
|
-
clean.name = trimmed;
|
|
188
|
-
}
|
|
189
|
-
// Other tools accept no args — anything passed is silently dropped.
|
|
190
|
-
return clean;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function callTool(toolName, args) {
|
|
194
|
-
args = validateArgs(toolName, args);
|
|
195
|
-
var queryParts = ['tool=' + toolName];
|
|
196
|
-
if (toolName === 'get_whale_divergence' && args && args.timeframe) queryParts.push('tf=' + args.timeframe);
|
|
197
|
-
if (toolName === 'get_token_ca' && args && args.name) queryParts.push('name=' + encodeURIComponent(args.name));
|
|
198
|
-
var url = (TOOL_ENDPOINTS[toolName] || GATEWAY) + '?' + queryParts.join('&');
|
|
199
|
-
|
|
200
|
-
// Step 1: discovery
|
|
201
|
-
var resp1 = await fetch(url, { headers: clientHeaders() });
|
|
202
|
-
if (resp1.status === 200) { var d = await resp1.json(); notifyUpdate(d, resp1.headers); return d; }
|
|
203
|
-
if (resp1.status !== 402) throw new Error('Server error ' + resp1.status + ': ' + (await resp1.text()).substring(0, 200));
|
|
204
|
-
|
|
205
|
-
// Step 2: parse payment requirements
|
|
206
|
-
// FIX v4.16.11: detect V2 by extra.feePayer presence (Dexter sponsorship marker),
|
|
207
|
-
// not by header. Per-tool endpoints (mcp-alpha-scanner, mcp-btc-regime, etc.) only
|
|
208
|
-
// serve 402 in body, no payment-required header. Header check stays as fast path.
|
|
209
|
-
var payReq = null;
|
|
210
|
-
var prHeader = resp1.headers.get('payment-required');
|
|
211
|
-
if (prHeader) {
|
|
212
|
-
try {
|
|
213
|
-
var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8'));
|
|
214
|
-
if (arr && arr[0]) payReq = arr[0];
|
|
215
|
-
} catch(_e) {}
|
|
216
|
-
}
|
|
217
|
-
if (!payReq) {
|
|
218
|
-
var b402 = await resp1.json();
|
|
219
|
-
if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0];
|
|
220
|
-
}
|
|
221
|
-
if (!payReq) throw new Error('No payment requirements in 402');
|
|
222
|
-
// V2 = Dexter sponsored gas = extra.feePayer field present (independent of transport)
|
|
223
|
-
var useV2 = !!(payReq.extra && payReq.extra.feePayer);
|
|
224
|
-
|
|
225
|
-
var amount = parseInt(payReq.maxAmountRequired || payReq.amount || '10000');
|
|
226
|
-
var hasFeePayer = payReq.extra && payReq.extra.feePayer;
|
|
227
|
-
var paymentHeader = '';
|
|
228
|
-
var headerName = '';
|
|
229
|
-
|
|
230
|
-
// Step 3: Try V2 Dexter (gas-sponsored by Dexter — user only needs USDC)
|
|
231
|
-
if (useV2 && hasFeePayer) {
|
|
232
|
-
console.error('[cryptoiz-mcp] V2 mode: Dexter gas-sponsored, paying ' + (amount/1000000).toFixed(4) + ' USDC');
|
|
233
|
-
try {
|
|
234
|
-
var txB64 = await buildV2PaymentPayload(amount, payReq.extra.feePayer);
|
|
235
|
-
// FIX v4.16.10: x402Version:2 (was 1), add 'accepted' (chosen PaymentRequirements
|
|
236
|
-
// verbatim — Dexter /verify needs this to match amount/asset/payTo). Removed bogus
|
|
237
|
-
// signature field — V2 schema only has payload.transaction.
|
|
238
|
-
var v2Payload = {
|
|
239
|
-
x402Version: 2,
|
|
240
|
-
scheme: 'exact',
|
|
241
|
-
network: payReq.network || 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
242
|
-
accepted: payReq,
|
|
243
|
-
payload: { transaction: txB64 },
|
|
244
|
-
extensions: {}
|
|
245
|
-
};
|
|
246
|
-
paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
|
|
247
|
-
headerName = 'payment-signature';
|
|
248
|
-
} catch(v2Err) {
|
|
249
|
-
console.error('[cryptoiz-mcp] V2 build failed: ' + v2Err.message + ' -> fallback V1');
|
|
250
|
-
useV2 = false;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Step 4: V1 fallback (user pays gas — only if V2 failed)
|
|
255
|
-
if (!paymentHeader) {
|
|
256
|
-
console.error('[cryptoiz-mcp] V1 fallback: direct on-chain transfer');
|
|
257
|
-
var sig = await sendUSDC(amount, toolName);
|
|
258
|
-
paymentHeader = Buffer.from(JSON.stringify({ signature: sig })).toString('base64');
|
|
259
|
-
headerName = 'x-payment';
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Step 5: submit payment
|
|
263
|
-
var headers2 = {};
|
|
264
|
-
headers2[headerName] = paymentHeader;
|
|
265
|
-
var resp2 = await fetch(url, { headers: clientHeaders(headers2) });
|
|
266
|
-
|
|
267
|
-
// Step 6: if V2 failed at server, retry with V1
|
|
268
|
-
if (resp2.status !== 200 && useV2) {
|
|
269
|
-
console.error('[cryptoiz-mcp] V2 settle failed, trying V1 fallback...');
|
|
270
|
-
var fallbackSig = await sendUSDC(amount, toolName);
|
|
271
|
-
var v1Header = Buffer.from(JSON.stringify({ signature: fallbackSig })).toString('base64');
|
|
272
|
-
resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': v1Header }) });
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (resp2.status !== 200) throw new Error('Payment failed ' + resp2.status + ': ' + (await resp2.text()).substring(0, 300));
|
|
276
|
-
var data = await resp2.json();
|
|
277
|
-
notifyUpdate(data, resp2.headers);
|
|
278
|
-
return data;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
var TOOLS = [
|
|
282
|
-
{ name: 'get_whale_alpha', description: 'Alpha scanner - early accumulation tokens. Cost: $0.05 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
283
|
-
{ name: 'get_whale_divergence', description: 'Whale divergence signals. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: { timeframe: { type: 'string', enum: ['4h', '1d'] } }, additionalProperties: false } },
|
|
284
|
-
{ name: 'get_whale_accumulation', description: 'Accumulation phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
285
|
-
{ name: 'get_whale_neutral', description: 'Neutral phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
286
|
-
{ name: 'get_whale_distribution', description: 'Distribution phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
287
|
-
{ name: 'get_btc_regime', description: 'BTC macro regime. Cost: $0.01 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
288
|
-
{ name: 'get_btc_futures_signal', description: 'BTC futures signal. Cost: $0.03 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
289
|
-
{ name: 'get_token_ca', description: 'Token contract address. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
|
|
290
|
-
{ name: 'get_status', description: 'CryptoIZ MCP status. FREE', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
291
|
-
];
|
|
292
|
-
|
|
293
|
-
var server = new Server({ name: 'cryptoiz-mcp', version: VERSION }, { capabilities: { tools: {} } });
|
|
294
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
295
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
296
|
-
try {
|
|
297
|
-
var result = await callTool(request.params.name, request.params.arguments || {});
|
|
298
|
-
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
299
|
-
} catch(e) {
|
|
300
|
-
return { content: [{ type: 'text', text: 'Error: ' + e.message }], isError: true };
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
async function main() {
|
|
305
|
-
var transport = new StdioServerTransport();
|
|
306
|
-
await server.connect(transport);
|
|
307
|
-
console.error('[cryptoiz-mcp] ' + VERSION + ' running (V2 Dexter gas-sponsored + V1 fallback)');
|
|
308
|
-
}
|
|
309
|
-
main().catch(console.error);
|
|
1
|
+
'use strict';
|
|
2
|
+
var VERSION = 'v4.16.15';
|
|
3
|
+
var GATEWAY = 'https://rehqwsypjnjirhuiapqh.supabase.co/functions/v1/mcp-x402-gateway';
|
|
4
|
+
// FIX v4.16.12: route ALL paid tools to gateway. Per-tool endpoints (mcp-alpha-scanner etc.)
|
|
5
|
+
// have stale hardcoded fee payer that breaks after Dexter key rotation. Gateway has dynamic
|
|
6
|
+
// fee payer fetched from /supported. Single source of truth = no per-tool drift.
|
|
7
|
+
var TOOL_ENDPOINTS = {
|
|
8
|
+
get_whale_alpha: GATEWAY,
|
|
9
|
+
get_whale_divergence: GATEWAY,
|
|
10
|
+
get_whale_accumulation: GATEWAY,
|
|
11
|
+
get_whale_neutral: GATEWAY,
|
|
12
|
+
get_whale_distribution: GATEWAY,
|
|
13
|
+
get_btc_regime: GATEWAY,
|
|
14
|
+
get_btc_futures_signal: GATEWAY,
|
|
15
|
+
get_token_ca: GATEWAY,
|
|
16
|
+
get_status: GATEWAY,
|
|
17
|
+
};
|
|
18
|
+
var RECIPIENT = 'DsKmdkYx49Xc1WhqMUAztwhdYPTqieyC98VmnnJdgpXX';
|
|
19
|
+
var USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
20
|
+
var SOL_RPC = 'https://api.mainnet-beta.solana.com';
|
|
21
|
+
var TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
|
|
22
|
+
var ATA_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
|
|
23
|
+
var MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
|
|
24
|
+
var COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';
|
|
25
|
+
|
|
26
|
+
var _updateNotified = false;
|
|
27
|
+
function notifyUpdate(data, headers) {
|
|
28
|
+
if (_updateNotified) return;
|
|
29
|
+
if (!headers || headers.get('x-update-available') !== '1') return;
|
|
30
|
+
_updateNotified = true;
|
|
31
|
+
var latest = (data && data.version_latest) || '?';
|
|
32
|
+
var cmd = (data && data.update_command) || 'npm install -g cryptoiz-mcp@latest';
|
|
33
|
+
console.error('[cryptoiz-mcp] UPDATE: ' + VERSION + ' -> ' + latest + ' | Run: ' + cmd);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var solana = require('@solana/web3.js');
|
|
37
|
+
var Connection = solana.Connection;
|
|
38
|
+
var PublicKey = solana.PublicKey;
|
|
39
|
+
var Transaction = solana.Transaction;
|
|
40
|
+
var TransactionMessage = solana.TransactionMessage;
|
|
41
|
+
var VersionedTransaction = solana.VersionedTransaction;
|
|
42
|
+
var Keypair = solana.Keypair;
|
|
43
|
+
// Fix bs58 v6 ESM-only issue: support both CJS (v5) and ESM-compiled (v6)
|
|
44
|
+
var _bs58mod = require('bs58');
|
|
45
|
+
var bs58 = _bs58mod.default || _bs58mod;
|
|
46
|
+
var Server = require('@modelcontextprotocol/sdk/server/index.js').Server;
|
|
47
|
+
var StdioServerTransport = require('@modelcontextprotocol/sdk/server/stdio.js').StdioServerTransport;
|
|
48
|
+
var CallToolRequestSchema = require('@modelcontextprotocol/sdk/types.js').CallToolRequestSchema;
|
|
49
|
+
var ListToolsRequestSchema = require('@modelcontextprotocol/sdk/types.js').ListToolsRequestSchema;
|
|
50
|
+
|
|
51
|
+
function getKeypair() {
|
|
52
|
+
var privKey = process.env.SVM_PRIVATE_KEY;
|
|
53
|
+
if (!privKey) throw new Error('SVM_PRIVATE_KEY not set in environment');
|
|
54
|
+
return Keypair.fromSecretKey(bs58.decode(privKey));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function findATA(wallet, mint) {
|
|
58
|
+
var walletPk = new PublicKey(wallet);
|
|
59
|
+
var mintPk = new PublicKey(mint);
|
|
60
|
+
var ataPk = new PublicKey(ATA_PROGRAM);
|
|
61
|
+
var tokPk = new PublicKey(TOKEN_PROGRAM);
|
|
62
|
+
return PublicKey.findProgramAddressSync([walletPk.toBuffer(), tokPk.toBuffer(), mintPk.toBuffer()], ataPk)[0];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// V2: Dexter gas-sponsored. 4-ix tx: Limit + Price + TransferChecked + Memo(nonce)
|
|
66
|
+
// Dexter pays SOL gas — user only needs USDC
|
|
67
|
+
async function buildV2PaymentPayload(amount, feePayerAddr) {
|
|
68
|
+
var kp = getKeypair();
|
|
69
|
+
var conn = new Connection(SOL_RPC, 'confirmed');
|
|
70
|
+
var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
|
|
71
|
+
var recipientATA = findATA(RECIPIENT, USDC_MINT);
|
|
72
|
+
var feePayerPk = new PublicKey(feePayerAddr);
|
|
73
|
+
var computeBudgetPk = new PublicKey(COMPUTE_BUDGET_PROGRAM);
|
|
74
|
+
var tokenProgramPk = new PublicKey(TOKEN_PROGRAM);
|
|
75
|
+
var usdcMintPk = new PublicKey(USDC_MINT);
|
|
76
|
+
// FIX v4.16.13: ComputeUnitLimit 20000 -> 30000.
|
|
77
|
+
// Memo program needs >13500 CU when content is 'x402:v2:'+32char hex; old (April 6-8)
|
|
78
|
+
// working code used just 32-char nonceHex which fit in 20000 budget. Bumping limit gives
|
|
79
|
+
// headroom for slightly longer memo content. Dexter spec allows up to 40000.
|
|
80
|
+
var setLimitData = Buffer.alloc(5);
|
|
81
|
+
setLimitData[0] = 0x02;
|
|
82
|
+
setLimitData.writeUInt32LE(30000, 1);
|
|
83
|
+
var setLimitIx = { programId: computeBudgetPk, keys: [], data: setLimitData };
|
|
84
|
+
// ComputeUnitPrice(1)
|
|
85
|
+
var setPriceData = Buffer.alloc(9);
|
|
86
|
+
setPriceData[0] = 0x03;
|
|
87
|
+
setPriceData.writeBigUInt64LE(BigInt(1), 1);
|
|
88
|
+
var setPriceIx = { programId: computeBudgetPk, keys: [], data: setPriceData };
|
|
89
|
+
// TransferChecked
|
|
90
|
+
var transferKeys = [
|
|
91
|
+
{ pubkey: userATA, isSigner: false, isWritable: true },
|
|
92
|
+
{ pubkey: usdcMintPk, isSigner: false, isWritable: false },
|
|
93
|
+
{ pubkey: recipientATA, isSigner: false, isWritable: true },
|
|
94
|
+
{ pubkey: kp.publicKey, isSigner: true, isWritable: false },
|
|
95
|
+
];
|
|
96
|
+
var transferData = Buffer.alloc(10);
|
|
97
|
+
transferData[0] = 0x0c;
|
|
98
|
+
transferData.writeUInt32LE(amount & 0xFFFFFFFF, 1);
|
|
99
|
+
transferData.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
|
|
100
|
+
transferData[9] = 6;
|
|
101
|
+
var transferIx = { programId: tokenProgramPk, keys: transferKeys, data: transferData };
|
|
102
|
+
// FIX v4.16.12: RESTORE Memo instruction in V2 (4-ix tx: Limit+Price+TransferChecked+Memo).
|
|
103
|
+
// Empirical: April 6-8 logs prove V2 with memo accepted by Dexter. Removing memo (v4.16.10)
|
|
104
|
+
// didn't fix anything — the actual bug was Dexter key rotation, fixed in gateway v44.
|
|
105
|
+
// Memo also makes TX visible to x402scan (memo carries x402 nonce marker).
|
|
106
|
+
var memoProgramPk = new PublicKey(MEMO_PROGRAM);
|
|
107
|
+
var nonceBytes = new Uint8Array(16);
|
|
108
|
+
for (var i = 0; i < 16; i++) nonceBytes[i] = Math.floor(Math.random() * 256);
|
|
109
|
+
var nonceHex = Array.from(nonceBytes).map(function(b) { return b.toString(16).padStart(2,'0'); }).join('');
|
|
110
|
+
// FIX v4.16.13: memo = just nonceHex (matches April 6-8 working V2 format).
|
|
111
|
+
// Adding 'x402:v2:' prefix made memo too long for 20000 CU budget.
|
|
112
|
+
var memoIx = { programId: memoProgramPk, keys: [], data: Buffer.from(nonceHex, 'utf8') };
|
|
113
|
+
var bh = await conn.getLatestBlockhash('confirmed');
|
|
114
|
+
var message = new TransactionMessage({
|
|
115
|
+
payerKey: feePayerPk,
|
|
116
|
+
recentBlockhash: bh.blockhash,
|
|
117
|
+
instructions: [setLimitIx, setPriceIx, transferIx, memoIx],
|
|
118
|
+
}).compileToV0Message();
|
|
119
|
+
var vtx = new VersionedTransaction(message);
|
|
120
|
+
vtx.sign([kp]);
|
|
121
|
+
var txB64 = Buffer.from(vtx.serialize()).toString('base64');
|
|
122
|
+
console.error('[cryptoiz-mcp] V2 tx built (Dexter gas-sponsored), 4 ix limit=30000');
|
|
123
|
+
return txB64;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// V1: direct on-chain, user pays SOL gas (fallback only)
|
|
127
|
+
async function sendUSDC(amount, toolName) {
|
|
128
|
+
var kp = getKeypair();
|
|
129
|
+
var conn = new Connection(SOL_RPC, 'confirmed');
|
|
130
|
+
var userATA = findATA(kp.publicKey.toBase58(), USDC_MINT);
|
|
131
|
+
var recipientATA = findATA(RECIPIENT, USDC_MINT);
|
|
132
|
+
var keys = [
|
|
133
|
+
{ pubkey: userATA, isSigner: false, isWritable: true },
|
|
134
|
+
{ pubkey: new PublicKey(USDC_MINT), isSigner: false, isWritable: false },
|
|
135
|
+
{ pubkey: recipientATA, isSigner: false, isWritable: true },
|
|
136
|
+
{ pubkey: kp.publicKey, isSigner: true, isWritable: false },
|
|
137
|
+
];
|
|
138
|
+
// FIX v4.16.10: TransferChecked needs 10 bytes (1 disc + 8 amount + 1 decimals)
|
|
139
|
+
var data = Buffer.alloc(10);
|
|
140
|
+
data[0] = 0x0c;
|
|
141
|
+
data.writeUInt32LE(amount & 0xFFFFFFFF, 1);
|
|
142
|
+
data.writeUInt32LE(Math.floor(amount / 0x100000000) & 0xFFFFFFFF, 5);
|
|
143
|
+
data[9] = 6;
|
|
144
|
+
var transferIx = { programId: new PublicKey(TOKEN_PROGRAM), keys: keys, data: data };
|
|
145
|
+
var nonce = Date.now().toString(16) + Math.floor(Math.random()*0xffff).toString(16);
|
|
146
|
+
var memoIx = {
|
|
147
|
+
programId: new PublicKey(MEMO_PROGRAM),
|
|
148
|
+
keys: [],
|
|
149
|
+
data: Buffer.from('x402:v1:' + (toolName || 'tool') + ':' + nonce, 'utf8')
|
|
150
|
+
};
|
|
151
|
+
var bh = await conn.getLatestBlockhash('confirmed');
|
|
152
|
+
var tx = new Transaction({ feePayer: kp.publicKey, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight });
|
|
153
|
+
tx.add(memoIx);
|
|
154
|
+
tx.add(transferIx);
|
|
155
|
+
tx.sign(kp);
|
|
156
|
+
var sig = await conn.sendRawTransaction(tx.serialize(), { skipPreflight: false });
|
|
157
|
+
await conn.confirmTransaction({ signature: sig, blockhash: bh.blockhash, lastValidBlockHeight: bh.lastValidBlockHeight }, 'confirmed');
|
|
158
|
+
console.error('[cryptoiz-mcp] V1 TX: ' + sig);
|
|
159
|
+
return sig;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function clientHeaders(extra) {
|
|
163
|
+
var h = { 'x-client-version': VERSION.replace(/^v/i, '') };
|
|
164
|
+
if (extra) for (var k in extra) if (Object.prototype.hasOwnProperty.call(extra, k)) h[k] = extra[k];
|
|
165
|
+
return h;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// v4.16.14: input validation per tool — defense in depth, server-side double-validates.
|
|
169
|
+
function validateArgs(toolName, args) {
|
|
170
|
+
if (args == null) return {}; // Empty args ok
|
|
171
|
+
if (typeof args !== 'object' || Array.isArray(args)) {
|
|
172
|
+
throw new Error('Invalid args: expected object, got ' + typeof args);
|
|
173
|
+
}
|
|
174
|
+
var clean = {};
|
|
175
|
+
if (toolName === 'get_whale_divergence') {
|
|
176
|
+
if (args.timeframe != null) {
|
|
177
|
+
if (typeof args.timeframe !== 'string') throw new Error('timeframe must be string');
|
|
178
|
+
if (args.timeframe !== '4h' && args.timeframe !== '1d') throw new Error("timeframe must be '4h' or '1d'");
|
|
179
|
+
clean.timeframe = args.timeframe;
|
|
180
|
+
}
|
|
181
|
+
} else if (toolName === 'get_token_ca') {
|
|
182
|
+
if (args.name == null) throw new Error('name is required for get_token_ca');
|
|
183
|
+
if (typeof args.name !== 'string') throw new Error('name must be string');
|
|
184
|
+
var trimmed = args.name.trim();
|
|
185
|
+
if (trimmed.length < 1 || trimmed.length > 64) throw new Error('name length must be 1-64 chars');
|
|
186
|
+
if (!/^[a-zA-Z0-9 _\-\$\.\u00c0-\uffff]+$/.test(trimmed)) throw new Error('name contains invalid chars');
|
|
187
|
+
clean.name = trimmed;
|
|
188
|
+
}
|
|
189
|
+
// Other tools accept no args — anything passed is silently dropped.
|
|
190
|
+
return clean;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function callTool(toolName, args) {
|
|
194
|
+
args = validateArgs(toolName, args);
|
|
195
|
+
var queryParts = ['tool=' + toolName];
|
|
196
|
+
if (toolName === 'get_whale_divergence' && args && args.timeframe) queryParts.push('tf=' + args.timeframe);
|
|
197
|
+
if (toolName === 'get_token_ca' && args && args.name) queryParts.push('name=' + encodeURIComponent(args.name));
|
|
198
|
+
var url = (TOOL_ENDPOINTS[toolName] || GATEWAY) + '?' + queryParts.join('&');
|
|
199
|
+
|
|
200
|
+
// Step 1: discovery
|
|
201
|
+
var resp1 = await fetch(url, { headers: clientHeaders() });
|
|
202
|
+
if (resp1.status === 200) { var d = await resp1.json(); notifyUpdate(d, resp1.headers); return d; }
|
|
203
|
+
if (resp1.status !== 402) throw new Error('Server error ' + resp1.status + ': ' + (await resp1.text()).substring(0, 200));
|
|
204
|
+
|
|
205
|
+
// Step 2: parse payment requirements
|
|
206
|
+
// FIX v4.16.11: detect V2 by extra.feePayer presence (Dexter sponsorship marker),
|
|
207
|
+
// not by header. Per-tool endpoints (mcp-alpha-scanner, mcp-btc-regime, etc.) only
|
|
208
|
+
// serve 402 in body, no payment-required header. Header check stays as fast path.
|
|
209
|
+
var payReq = null;
|
|
210
|
+
var prHeader = resp1.headers.get('payment-required');
|
|
211
|
+
if (prHeader) {
|
|
212
|
+
try {
|
|
213
|
+
var arr = JSON.parse(Buffer.from(prHeader, 'base64').toString('utf8'));
|
|
214
|
+
if (arr && arr[0]) payReq = arr[0];
|
|
215
|
+
} catch(_e) {}
|
|
216
|
+
}
|
|
217
|
+
if (!payReq) {
|
|
218
|
+
var b402 = await resp1.json();
|
|
219
|
+
if (b402 && b402.accepts && b402.accepts[0]) payReq = b402.accepts[0];
|
|
220
|
+
}
|
|
221
|
+
if (!payReq) throw new Error('No payment requirements in 402');
|
|
222
|
+
// V2 = Dexter sponsored gas = extra.feePayer field present (independent of transport)
|
|
223
|
+
var useV2 = !!(payReq.extra && payReq.extra.feePayer);
|
|
224
|
+
|
|
225
|
+
var amount = parseInt(payReq.maxAmountRequired || payReq.amount || '10000');
|
|
226
|
+
var hasFeePayer = payReq.extra && payReq.extra.feePayer;
|
|
227
|
+
var paymentHeader = '';
|
|
228
|
+
var headerName = '';
|
|
229
|
+
|
|
230
|
+
// Step 3: Try V2 Dexter (gas-sponsored by Dexter — user only needs USDC)
|
|
231
|
+
if (useV2 && hasFeePayer) {
|
|
232
|
+
console.error('[cryptoiz-mcp] V2 mode: Dexter gas-sponsored, paying ' + (amount/1000000).toFixed(4) + ' USDC');
|
|
233
|
+
try {
|
|
234
|
+
var txB64 = await buildV2PaymentPayload(amount, payReq.extra.feePayer);
|
|
235
|
+
// FIX v4.16.10: x402Version:2 (was 1), add 'accepted' (chosen PaymentRequirements
|
|
236
|
+
// verbatim — Dexter /verify needs this to match amount/asset/payTo). Removed bogus
|
|
237
|
+
// signature field — V2 schema only has payload.transaction.
|
|
238
|
+
var v2Payload = {
|
|
239
|
+
x402Version: 2,
|
|
240
|
+
scheme: 'exact',
|
|
241
|
+
network: payReq.network || 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
242
|
+
accepted: payReq,
|
|
243
|
+
payload: { transaction: txB64 },
|
|
244
|
+
extensions: {}
|
|
245
|
+
};
|
|
246
|
+
paymentHeader = Buffer.from(JSON.stringify(v2Payload)).toString('base64');
|
|
247
|
+
headerName = 'payment-signature';
|
|
248
|
+
} catch(v2Err) {
|
|
249
|
+
console.error('[cryptoiz-mcp] V2 build failed: ' + v2Err.message + ' -> fallback V1');
|
|
250
|
+
useV2 = false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Step 4: V1 fallback (user pays gas — only if V2 failed)
|
|
255
|
+
if (!paymentHeader) {
|
|
256
|
+
console.error('[cryptoiz-mcp] V1 fallback: direct on-chain transfer');
|
|
257
|
+
var sig = await sendUSDC(amount, toolName);
|
|
258
|
+
paymentHeader = Buffer.from(JSON.stringify({ signature: sig })).toString('base64');
|
|
259
|
+
headerName = 'x-payment';
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Step 5: submit payment
|
|
263
|
+
var headers2 = {};
|
|
264
|
+
headers2[headerName] = paymentHeader;
|
|
265
|
+
var resp2 = await fetch(url, { headers: clientHeaders(headers2) });
|
|
266
|
+
|
|
267
|
+
// Step 6: if V2 failed at server, retry with V1
|
|
268
|
+
if (resp2.status !== 200 && useV2) {
|
|
269
|
+
console.error('[cryptoiz-mcp] V2 settle failed, trying V1 fallback...');
|
|
270
|
+
var fallbackSig = await sendUSDC(amount, toolName);
|
|
271
|
+
var v1Header = Buffer.from(JSON.stringify({ signature: fallbackSig })).toString('base64');
|
|
272
|
+
resp2 = await fetch(url, { headers: clientHeaders({ 'x-payment': v1Header }) });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (resp2.status !== 200) throw new Error('Payment failed ' + resp2.status + ': ' + (await resp2.text()).substring(0, 300));
|
|
276
|
+
var data = await resp2.json();
|
|
277
|
+
notifyUpdate(data, resp2.headers);
|
|
278
|
+
return data;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
var TOOLS = [
|
|
282
|
+
{ name: 'get_whale_alpha', description: 'Alpha scanner - early accumulation tokens. Cost: $0.05 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
283
|
+
{ name: 'get_whale_divergence', description: 'Whale divergence signals. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: { timeframe: { type: 'string', enum: ['4h', '1d'] } }, additionalProperties: false } },
|
|
284
|
+
{ name: 'get_whale_accumulation', description: 'Accumulation phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
285
|
+
{ name: 'get_whale_neutral', description: 'Neutral phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
286
|
+
{ name: 'get_whale_distribution', description: 'Distribution phase tokens. Cost: $0.02 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
287
|
+
{ name: 'get_btc_regime', description: 'BTC macro regime. Cost: $0.01 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
288
|
+
{ name: 'get_btc_futures_signal', description: 'BTC futures signal. Cost: $0.03 USDC', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
289
|
+
{ name: 'get_token_ca', description: 'Token contract address. FREE', inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false } },
|
|
290
|
+
{ name: 'get_status', description: 'CryptoIZ MCP status. FREE', inputSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
291
|
+
];
|
|
292
|
+
|
|
293
|
+
var server = new Server({ name: 'cryptoiz-mcp', version: VERSION }, { capabilities: { tools: {} } });
|
|
294
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
295
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
296
|
+
try {
|
|
297
|
+
var result = await callTool(request.params.name, request.params.arguments || {});
|
|
298
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
299
|
+
} catch(e) {
|
|
300
|
+
return { content: [{ type: 'text', text: 'Error: ' + e.message }], isError: true };
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
async function main() {
|
|
305
|
+
var transport = new StdioServerTransport();
|
|
306
|
+
await server.connect(transport);
|
|
307
|
+
console.error('[cryptoiz-mcp] ' + VERSION + ' running (V2 Dexter gas-sponsored + V1 fallback)');
|
|
308
|
+
}
|
|
309
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,49 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cryptoiz-mcp",
|
|
3
|
-
"version": "4.16.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"cryptoiz-mcp
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"@
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "cryptoiz-mcp",
|
|
3
|
+
"version": "4.16.17",
|
|
4
|
+
"mcpName": "io.github.dadang11/cryptoiz",
|
|
5
|
+
"description": "CryptoIZ MCP Server - Solana DEX whale intelligence (alpha, divergence, accumulation, BTC regime). Recommended install: npx agentcash add https://mcp.cryptoiz.org. x402 V2 + Dexter gas-sponsored payments.",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"type": "commonjs",
|
|
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.29.0",
|
|
20
|
+
"@solana/web3.js": "^1.95.8",
|
|
21
|
+
"bs58": "^6.0.0"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
26
|
+
"author": "CryptoIZ",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/dadang11/cryptoiz-mcp.git"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mcp",
|
|
34
|
+
"solana",
|
|
35
|
+
"whale-tracking",
|
|
36
|
+
"alpha-scanner",
|
|
37
|
+
"x402",
|
|
38
|
+
"dexter",
|
|
39
|
+
"agentcash",
|
|
40
|
+
"defi",
|
|
41
|
+
"smart-money",
|
|
42
|
+
"btc-regime",
|
|
43
|
+
"divergence",
|
|
44
|
+
"accumulation"
|
|
45
|
+
],
|
|
46
|
+
"homepage": "https://cryptoiz.org/McpLanding",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/dadang11/cryptoiz-mcp/issues"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/setup.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
var VERSION = 'v4.16.15';
|
|
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
|
-
}
|
|
1
|
+
'use strict';
|
|
2
|
+
var VERSION = 'v4.16.15';
|
|
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
|
+
}
|