asrai-mcp 0.5.4 → 0.5.6
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/README.md +16 -16
- package/package.json +1 -1
- package/src/server.js +6 -192
- package/src/tool-endpoints.js +174 -0
- package/src/tools-definitions.js +201 -0
- package/src/tools.js +17 -146
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ PRIVATE_KEY=0x<your_base_wallet_private_key>
|
|
|
47
47
|
|
|
48
48
|
**Step 2** — Restart Claude Desktop. Done.
|
|
49
49
|
|
|
50
|
-
Each API call costs **$0.
|
|
50
|
+
Each API call costs **$0.005 USDC** from your wallet on Base mainnet. Make sure your wallet has a small USDC balance (~$1–2 to start).
|
|
51
51
|
|
|
52
52
|
## What you get
|
|
53
53
|
|
|
@@ -55,21 +55,21 @@ Each API call costs **$0.001 USDC** from your wallet on Base mainnet. Make sure
|
|
|
55
55
|
|
|
56
56
|
| Tool | What it does | Cost |
|
|
57
57
|
|---|---|---|
|
|
58
|
-
| `market_overview` | Trending, gainers/losers, RSI
|
|
59
|
-
| `technical_analysis` | ALSAT, SuperALSAT, PSAR, MACD-DEMA, AlphaTrend | $0.
|
|
60
|
-
| `sentiment` | CBBI, CMC sentiment, AI insights | $0.
|
|
61
|
-
| `forecast` | AI 3-7 day price prediction | $0.
|
|
62
|
-
| `screener` | Find coins by criteria | $0.
|
|
63
|
-
| `smart_money` | Order blocks, FVGs, support/resistance | $0.
|
|
64
|
-
| `elliott_wave` | Elliott Wave analysis | $0.
|
|
65
|
-
| `ichimoku` | Ichimoku cloud | $0.
|
|
66
|
-
| `cashflow` | Capital flow data | $0.
|
|
67
|
-
| `coin_info` | Stats, info, price, tags | $0.
|
|
68
|
-
| `dexscreener` | DEX trading data | $0.
|
|
69
|
-
| `chain_tokens` | Low-cap tokens on chain | $0.
|
|
70
|
-
| `portfolio` |
|
|
71
|
-
| `channel_summary` | Latest crypto narratives | $0.
|
|
72
|
-
| `ask_ai` | AI analyst freeform answer | $0.
|
|
58
|
+
| `market_overview` | Trending, gainers/losers, RSI, screeners, sentiment, narratives, cashflow | $0.095 |
|
|
59
|
+
| `technical_analysis` | ALSAT, SuperALSAT, PSAR, MACD-DEMA, AlphaTrend, TD, forecast, SMC, S/R, Elliott Wave, Ichimoku | $0.06 |
|
|
60
|
+
| `sentiment` | CBBI, CMC sentiment, AI insights | $0.015 |
|
|
61
|
+
| `forecast` | AI 3-7 day price prediction | $0.005 |
|
|
62
|
+
| `screener` | Find coins by criteria | $0.005 |
|
|
63
|
+
| `smart_money` | Order blocks, FVGs, support/resistance | $0.01 |
|
|
64
|
+
| `elliott_wave` | Elliott Wave analysis | $0.005 |
|
|
65
|
+
| `ichimoku` | Ichimoku cloud | $0.005 |
|
|
66
|
+
| `cashflow` | Capital flow data | $0.005 |
|
|
67
|
+
| `coin_info` | Stats, info, price, tags, CMC AI + auto DEX data | $0.025–$0.03 |
|
|
68
|
+
| `dexscreener` | DEX trading data | $0.005 |
|
|
69
|
+
| `chain_tokens` | Low-cap tokens on chain | $0.005 |
|
|
70
|
+
| `portfolio` | Model portfolio — investment reference | $0.005 |
|
|
71
|
+
| `channel_summary` | Latest crypto narratives | $0.005 |
|
|
72
|
+
| `ask_ai` | AI analyst freeform answer | $0.01 |
|
|
73
73
|
| `indicator_guide` | Asrai indicator reference | FREE |
|
|
74
74
|
|
|
75
75
|
## Spend limit
|
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Asrai MCP server — tool definitions and request handlers.
|
|
3
|
+
* TOOLS imported from tools-definitions.js (synced from asrai-shared/).
|
|
4
|
+
* Do NOT edit shared TOOLS here — edit in asrai-shared/tools-definitions.js and run sync.py.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -11,180 +13,12 @@ import {
|
|
|
11
13
|
|
|
12
14
|
import * as tools from "./tools.js";
|
|
13
15
|
import { indicator_guide } from "./indicator_guide.js";
|
|
16
|
+
import { TOOLS as BASE_TOOLS } from "./tools-definitions.js";
|
|
14
17
|
|
|
15
|
-
// ──
|
|
18
|
+
// ── x402-only tools (added on top of shared TOOLS) ───────────────────────────
|
|
16
19
|
|
|
17
20
|
const TOOLS = [
|
|
18
|
-
|
|
19
|
-
name: "market_overview",
|
|
20
|
-
description:
|
|
21
|
-
"Get current crypto market pulse: trending coins, gainers/losers, RSI extremes, top/bottom signals. " +
|
|
22
|
-
"Use for general market questions like 'what's moving today' or 'give me a market brief'.",
|
|
23
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
name: "technical_analysis",
|
|
27
|
-
description:
|
|
28
|
-
"Get full technical analysis for a specific coin: signal, ALSAT, SuperALSAT, PSAR, MACD-DEMA, AlphaTrend. " +
|
|
29
|
-
"Use when asked about TA, buy/sell signals, or indicators for a coin.",
|
|
30
|
-
inputSchema: {
|
|
31
|
-
type: "object",
|
|
32
|
-
properties: {
|
|
33
|
-
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH, SOL" },
|
|
34
|
-
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Timeframe. Default: 1D" },
|
|
35
|
-
},
|
|
36
|
-
required: ["symbol"],
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: "sentiment",
|
|
41
|
-
description:
|
|
42
|
-
"Get market sentiment: CBBI (crypto bull/bear index), CMC sentiment, CMC AI insights. " +
|
|
43
|
-
"Use for questions about market mood, fear/greed, or cycle position.",
|
|
44
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "forecast",
|
|
48
|
-
description: "Get AI-powered 3-7 day price forecast for a coin: direction, confidence, price targets.",
|
|
49
|
-
inputSchema: {
|
|
50
|
-
type: "object",
|
|
51
|
-
properties: { symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" } },
|
|
52
|
-
required: ["symbol"],
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "screener",
|
|
57
|
-
description:
|
|
58
|
-
"Run a market screener to find coins matching specific criteria. " +
|
|
59
|
-
"Types: ichimoku-trend, sar-coins, macd-coins, emacross, techrating, vwap, volume, " +
|
|
60
|
-
"highvolumelowcap, bounce-dip, galaxyscore, socialdominance, late-unlocked-coins, ath, rsi, rsi-heatmap, ao.",
|
|
61
|
-
inputSchema: {
|
|
62
|
-
type: "object",
|
|
63
|
-
properties: {
|
|
64
|
-
screener_type: {
|
|
65
|
-
type: "string",
|
|
66
|
-
enum: [
|
|
67
|
-
"ichimoku-trend", "sar-coins", "macd-coins", "emacross",
|
|
68
|
-
"techrating", "vwap", "volume", "highvolumelowcap",
|
|
69
|
-
"bounce-dip", "galaxyscore", "socialdominance", "late-unlocked-coins",
|
|
70
|
-
"ath", "rsi", "rsi-heatmap", "ao",
|
|
71
|
-
],
|
|
72
|
-
description: "Type of screener to run",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
required: ["screener_type"],
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: "smart_money",
|
|
80
|
-
description:
|
|
81
|
-
"Get Smart Money Concepts (SMC): order blocks, fair value gaps, liquidity zones, BOS/CHoCH, " +
|
|
82
|
-
"plus support/resistance levels.",
|
|
83
|
-
inputSchema: {
|
|
84
|
-
type: "object",
|
|
85
|
-
properties: {
|
|
86
|
-
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
87
|
-
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
88
|
-
},
|
|
89
|
-
required: ["symbol"],
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
name: "elliott_wave",
|
|
94
|
-
description: "Get Elliott Wave analysis: current wave position, impulse/corrective structure, price targets.",
|
|
95
|
-
inputSchema: {
|
|
96
|
-
type: "object",
|
|
97
|
-
properties: {
|
|
98
|
-
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
99
|
-
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
100
|
-
},
|
|
101
|
-
required: ["symbol"],
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
name: "ichimoku",
|
|
106
|
-
description: "Get Ichimoku cloud analysis: cloud position, Tenkan/Kijun cross, kumo twist, trend bias for a coin.",
|
|
107
|
-
inputSchema: {
|
|
108
|
-
type: "object",
|
|
109
|
-
properties: {
|
|
110
|
-
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
111
|
-
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
112
|
-
},
|
|
113
|
-
required: ["symbol"],
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: "cashflow",
|
|
118
|
-
description:
|
|
119
|
-
"Get capital flow data showing where money is moving. " +
|
|
120
|
-
"Modes: 'market' (overall), 'coin' (single coin), 'group' (comma-separated coins).",
|
|
121
|
-
inputSchema: {
|
|
122
|
-
type: "object",
|
|
123
|
-
properties: {
|
|
124
|
-
mode: {
|
|
125
|
-
type: "string",
|
|
126
|
-
enum: ["market", "coin", "group"],
|
|
127
|
-
description: "Scope of cashflow data",
|
|
128
|
-
},
|
|
129
|
-
symbol: {
|
|
130
|
-
type: "string",
|
|
131
|
-
description: "Coin symbol (required for coin/group modes)",
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
required: ["mode"],
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
name: "coin_info",
|
|
139
|
-
description: "Get detailed info for a coin: market cap, volume, supply, social stats, tokenomics.",
|
|
140
|
-
inputSchema: {
|
|
141
|
-
type: "object",
|
|
142
|
-
properties: { symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH, SOL" } },
|
|
143
|
-
required: ["symbol"],
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
name: "dexscreener",
|
|
148
|
-
description: "Get DEX trading data for a token: liquidity, volume, buys/sells, price change. Use contract_address alone for symbol search, or provide chain + contract_address for a specific token.",
|
|
149
|
-
inputSchema: {
|
|
150
|
-
type: "object",
|
|
151
|
-
properties: {
|
|
152
|
-
contract_address: { type: "string", description: "Token contract address or symbol" },
|
|
153
|
-
chain: { type: "string", description: "Optional chain e.g. ethereum, bsc, base, solana" },
|
|
154
|
-
},
|
|
155
|
-
required: ["contract_address"],
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: "chain_tokens",
|
|
160
|
-
description: "Get low-cap tokens on a specific blockchain filtered by max market cap.",
|
|
161
|
-
inputSchema: {
|
|
162
|
-
type: "object",
|
|
163
|
-
properties: {
|
|
164
|
-
chain: { type: "string", description: "Chain e.g. ethereum, bsc, base, solana, avax" },
|
|
165
|
-
max_mcap: { type: "string", description: "Max market cap e.g. 10000000 (10M)" },
|
|
166
|
-
},
|
|
167
|
-
required: ["chain", "max_mcap"],
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: "portfolio",
|
|
172
|
-
description:
|
|
173
|
-
"Get Abu's curated crypto portfolio — a model portfolio of carefully selected holdings. " +
|
|
174
|
-
"Use when users ask 'what should I invest in?', 'build me a portfolio', 'what coins to buy', " +
|
|
175
|
-
"or 'give me investment advice'. No symbol = full portfolio overview. " +
|
|
176
|
-
"Symbol provided = Abu's position and analysis for that specific coin.",
|
|
177
|
-
inputSchema: {
|
|
178
|
-
type: "object",
|
|
179
|
-
properties: { symbol: { type: "string", description: "Optional coin symbol to filter" } },
|
|
180
|
-
required: [],
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
name: "channel_summary",
|
|
185
|
-
description: "Get a summary of latest crypto narratives and discussions from monitored channels.",
|
|
186
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
187
|
-
},
|
|
21
|
+
...BASE_TOOLS,
|
|
188
22
|
{
|
|
189
23
|
name: "ask_ai",
|
|
190
24
|
description:
|
|
@@ -196,26 +30,6 @@ const TOOLS = [
|
|
|
196
30
|
required: ["question"],
|
|
197
31
|
},
|
|
198
32
|
},
|
|
199
|
-
{
|
|
200
|
-
name: "indicator_guide",
|
|
201
|
-
description:
|
|
202
|
-
"Reference guide for Asrai-specific indicators. FREE — no payment. " +
|
|
203
|
-
"WHEN TO CALL: only when you encounter an unfamiliar indicator name in tool output " +
|
|
204
|
-
"(e.g. ALSAT, SuperALSAT, AlphaTrend, PMax, MavilimW). " +
|
|
205
|
-
"Standard indicators (RSI, MACD, Ichimoku, Elliott Wave, BB) are well-known — skip them. " +
|
|
206
|
-
"indicator='' or 'list' → compact 1-line summary of all. " +
|
|
207
|
-
"indicator='ALSAT' → full detail. indicator='all' → everything (avoid unless needed).",
|
|
208
|
-
inputSchema: {
|
|
209
|
-
type: "object",
|
|
210
|
-
properties: {
|
|
211
|
-
indicator: {
|
|
212
|
-
type: "string",
|
|
213
|
-
description: "Indicator name e.g. 'ALSAT', 'SuperALSAT', 'PMax'. Empty = compact list.",
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
required: [],
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
33
|
];
|
|
220
34
|
|
|
221
35
|
// ── Request handlers ─────────────────────────────────────────────────────────
|
|
@@ -256,7 +70,7 @@ async function handleTool(name, args) {
|
|
|
256
70
|
|
|
257
71
|
export function createServer() {
|
|
258
72
|
const server = new Server(
|
|
259
|
-
{ name: "asrai", version: "0.5.
|
|
73
|
+
{ name: "asrai", version: "0.5.5" },
|
|
260
74
|
{ capabilities: { tools: {} } }
|
|
261
75
|
);
|
|
262
76
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared endpoint lists and tool handlers for asrai-mcp and asrai-mcp-apikey.
|
|
3
|
+
* SOURCE OF TRUTH — edit here, then run sync.py to propagate.
|
|
4
|
+
*
|
|
5
|
+
* Add/remove endpoints here → sync.py copies to both projects.
|
|
6
|
+
* pricing.json call counts must match the arrays here.
|
|
7
|
+
* Add new tool handlers to createHandlers() below — auto-available in both projects.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ── Static endpoint arrays ────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
export const MARKET_OVERVIEW_ENDPOINTS = [
|
|
13
|
+
"/api/trending/",
|
|
14
|
+
"/api/gainers-losers/",
|
|
15
|
+
"/api/rsi/",
|
|
16
|
+
"/api/top-bottom/",
|
|
17
|
+
"/api/cmcai/",
|
|
18
|
+
"/api/cbbi/",
|
|
19
|
+
"/api/channel-summary/",
|
|
20
|
+
"/api/cashflow/market",
|
|
21
|
+
"/api/cmc-sentiment/",
|
|
22
|
+
"/api/socialdominance/",
|
|
23
|
+
"/api/ath/",
|
|
24
|
+
"/api/ichimoku-trend/",
|
|
25
|
+
"/api/bounce-dip/",
|
|
26
|
+
"/api/sar-coins/",
|
|
27
|
+
"/api/macd-coins/",
|
|
28
|
+
"/api/emacross/",
|
|
29
|
+
"/api/techrating/",
|
|
30
|
+
"/api/volume/",
|
|
31
|
+
"/api/highvolumelowcap/",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const SENTIMENT_ENDPOINTS = [
|
|
35
|
+
"/api/cbbi/",
|
|
36
|
+
"/api/cmc-sentiment/",
|
|
37
|
+
"/api/cmcai/",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// ── Dynamic endpoint builders (return arrays) ─────────────────────────────────
|
|
41
|
+
|
|
42
|
+
export function technicalAnalysisEndpoints(s, tf) {
|
|
43
|
+
return [
|
|
44
|
+
`/api/signal/${s}usdt/${tf}`,
|
|
45
|
+
`/api/alsat/${s}usdt/${tf}`,
|
|
46
|
+
`/api/superalsat/${s}usdt`,
|
|
47
|
+
`/api/psar/${s}usdt/${tf}`,
|
|
48
|
+
`/api/macd-dema/${s}usdt/${tf}`,
|
|
49
|
+
`/api/alphatrend/${s}usdt/${tf}`,
|
|
50
|
+
`/api/td/${s}usdt/${tf}`,
|
|
51
|
+
`/api/forecasting/${s}usdt`,
|
|
52
|
+
`/api/smartmoney/${s}usdt/${tf}`,
|
|
53
|
+
`/api/support-resistance/${s}usdt/${tf}`,
|
|
54
|
+
`/api/ew/${s}usdt/${tf}`,
|
|
55
|
+
`/api/ichimoku/${s}usdt/${tf}`,
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function smartMoneyEndpoints(s, tf) {
|
|
60
|
+
return [
|
|
61
|
+
`/api/smartmoney/${s}usdt/${tf}`,
|
|
62
|
+
`/api/support-resistance/${s}usdt/${tf}`,
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function coinInfoEndpoints(s) {
|
|
67
|
+
return [
|
|
68
|
+
`/api/coinstats/${s}`,
|
|
69
|
+
`/api/info/${s}`,
|
|
70
|
+
`/api/price/${s}`,
|
|
71
|
+
`/api/tags/${s}`,
|
|
72
|
+
`/api/cmcai/${s}`,
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ── Screener valid types ──────────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
export const SCREENER_TYPES = [
|
|
79
|
+
"ichimoku-trend", "sar-coins", "macd-coins", "emacross",
|
|
80
|
+
"techrating", "vwap", "volume", "highvolumelowcap",
|
|
81
|
+
"bounce-dip", "galaxyscore", "socialdominance", "late-unlocked-coins",
|
|
82
|
+
"ath", "rsi", "rsi-heatmap", "ao",
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// ── Symbol normalisation ──────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
function sym(symbol) {
|
|
88
|
+
return symbol.toLowerCase().replace(/usdt$/, "");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Shared tool handlers ──────────────────────────────────────────────────────
|
|
92
|
+
// _get and _gather are injected per-project (x402 vs apikey transport differs).
|
|
93
|
+
// Add new tools here — sync.py copies this file to both projects automatically.
|
|
94
|
+
|
|
95
|
+
export function createHandlers(_get, _gather) {
|
|
96
|
+
return {
|
|
97
|
+
async market_overview() {
|
|
98
|
+
return JSON.stringify(await _gather(...MARKET_OVERVIEW_ENDPOINTS), null, 2);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
async technical_analysis(symbol, timeframe = "1D") {
|
|
102
|
+
const s = sym(symbol);
|
|
103
|
+
return JSON.stringify(await _gather(...technicalAnalysisEndpoints(s, timeframe)), null, 2);
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
async sentiment() {
|
|
107
|
+
return JSON.stringify(await _gather(...SENTIMENT_ENDPOINTS), null, 2);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
async forecast(symbol) {
|
|
111
|
+
return JSON.stringify(await _get(`/api/forecasting/${sym(symbol)}usdt`), null, 2);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
async screener(screener_type) {
|
|
115
|
+
if (!SCREENER_TYPES.includes(screener_type)) {
|
|
116
|
+
return JSON.stringify({ error: `Invalid screener. Choose from: ${SCREENER_TYPES.join(", ")}` });
|
|
117
|
+
}
|
|
118
|
+
return JSON.stringify(await _get(`/api/${screener_type}/`), null, 2);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
async smart_money(symbol, timeframe = "1D") {
|
|
122
|
+
const s = sym(symbol);
|
|
123
|
+
return JSON.stringify(await _gather(...smartMoneyEndpoints(s, timeframe)), null, 2);
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
async elliott_wave(symbol, timeframe = "1D") {
|
|
127
|
+
return JSON.stringify(await _get(`/api/ew/${sym(symbol)}usdt/${timeframe}`), null, 2);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
async ichimoku(symbol, timeframe = "1D") {
|
|
131
|
+
return JSON.stringify(await _get(`/api/ichimoku/${sym(symbol)}usdt/${timeframe}`), null, 2);
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
async cashflow(mode, symbol = "") {
|
|
135
|
+
if (mode === "market") {
|
|
136
|
+
return JSON.stringify(await _get("/api/cashflow/market"), null, 2);
|
|
137
|
+
}
|
|
138
|
+
if ((mode === "coin" || mode === "group") && symbol) {
|
|
139
|
+
return JSON.stringify(await _get(`/api/cashflow/${mode}/${symbol.toLowerCase()}`), null, 2);
|
|
140
|
+
}
|
|
141
|
+
return JSON.stringify({ error: "mode must be 'market', 'coin', or 'group'. coin/group require symbol." });
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
async coin_info(symbol) {
|
|
145
|
+
const s = symbol.toLowerCase();
|
|
146
|
+
const data = await _gather(...coinInfoEndpoints(s));
|
|
147
|
+
const contractAddress = data[`/api/info/${s}`]?.info_data?.contract_address;
|
|
148
|
+
if (contractAddress) {
|
|
149
|
+
data[`/api/dexscreener/${contractAddress}`] = await _get(`/api/dexscreener/${contractAddress}`);
|
|
150
|
+
}
|
|
151
|
+
return JSON.stringify(data, null, 2);
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
async dexscreener(contract_address, chain = "") {
|
|
155
|
+
const path = chain
|
|
156
|
+
? `/api/dexscreener/${chain}/${contract_address}`
|
|
157
|
+
: `/api/dexscreener/${contract_address}`;
|
|
158
|
+
return JSON.stringify(await _get(path), null, 2);
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
async chain_tokens(chain, max_mcap) {
|
|
162
|
+
return JSON.stringify(await _get(`/api/chain/${chain}/${max_mcap}`), null, 2);
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
async portfolio(symbol = "") {
|
|
166
|
+
const path = symbol ? `/api/portfolio/${symbol.toLowerCase()}` : "/api/portfolio/";
|
|
167
|
+
return JSON.stringify(await _get(path), null, 2);
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
async channel_summary() {
|
|
171
|
+
return JSON.stringify(await _get("/api/channel-summary/"), null, 2);
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared tool definitions for asrai-mcp and asrai-mcp-apikey.
|
|
3
|
+
* SOURCE OF TRUTH — edit here, then run sync.py to propagate.
|
|
4
|
+
*
|
|
5
|
+
* Note: ask_ai is x402-only and is added in asrai-mcp/src/server.js directly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const TOOLS = [
|
|
9
|
+
{
|
|
10
|
+
name: "market_overview",
|
|
11
|
+
description:
|
|
12
|
+
"Get current crypto market pulse: trending coins, gainers/losers, RSI extremes, top/bottom signals. " +
|
|
13
|
+
"Use for general market questions like 'what's moving today' or 'give me a market brief'.",
|
|
14
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "technical_analysis",
|
|
18
|
+
description:
|
|
19
|
+
"Get full technical analysis for a specific coin: signal, ALSAT, SuperALSAT, PSAR, MACD-DEMA, AlphaTrend. " +
|
|
20
|
+
"Use when asked about TA, buy/sell signals, or indicators for a coin.",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH, SOL" },
|
|
25
|
+
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Timeframe. Default: 1D" },
|
|
26
|
+
},
|
|
27
|
+
required: ["symbol"],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "sentiment",
|
|
32
|
+
description:
|
|
33
|
+
"Get market sentiment: CBBI (crypto bull/bear index), CMC sentiment, CMC AI insights. " +
|
|
34
|
+
"Use for questions about market mood, fear/greed, or cycle position.",
|
|
35
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "forecast",
|
|
39
|
+
description: "Get AI-powered 3-7 day price forecast for a coin: direction, confidence, price targets.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: { symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" } },
|
|
43
|
+
required: ["symbol"],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "screener",
|
|
48
|
+
description:
|
|
49
|
+
"Run a market screener to find coins matching specific criteria. " +
|
|
50
|
+
"Types: ichimoku-trend, sar-coins, macd-coins, emacross, techrating, vwap, volume, " +
|
|
51
|
+
"highvolumelowcap, bounce-dip, galaxyscore, socialdominance, late-unlocked-coins, ath, rsi, rsi-heatmap, ao.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
screener_type: {
|
|
56
|
+
type: "string",
|
|
57
|
+
enum: [
|
|
58
|
+
"ichimoku-trend", "sar-coins", "macd-coins", "emacross",
|
|
59
|
+
"techrating", "vwap", "volume", "highvolumelowcap",
|
|
60
|
+
"bounce-dip", "galaxyscore", "socialdominance", "late-unlocked-coins",
|
|
61
|
+
"ath", "rsi", "rsi-heatmap", "ao",
|
|
62
|
+
],
|
|
63
|
+
description: "Type of screener to run",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ["screener_type"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "smart_money",
|
|
71
|
+
description:
|
|
72
|
+
"Get Smart Money Concepts (SMC): order blocks, fair value gaps, liquidity zones, BOS/CHoCH, " +
|
|
73
|
+
"plus support/resistance levels.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {
|
|
77
|
+
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
78
|
+
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
79
|
+
},
|
|
80
|
+
required: ["symbol"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "elliott_wave",
|
|
85
|
+
description: "Get Elliott Wave analysis: current wave position, impulse/corrective structure, price targets.",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
90
|
+
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
91
|
+
},
|
|
92
|
+
required: ["symbol"],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "ichimoku",
|
|
97
|
+
description: "Get Ichimoku cloud analysis: cloud position, Tenkan/Kijun cross, kumo twist, trend bias for a coin.",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH" },
|
|
102
|
+
timeframe: { type: "string", enum: ["1D", "4H", "1W"], description: "Default: 1D" },
|
|
103
|
+
},
|
|
104
|
+
required: ["symbol"],
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "cashflow",
|
|
109
|
+
description:
|
|
110
|
+
"Get capital flow data showing where money is moving. " +
|
|
111
|
+
"Modes: 'market' (overall), 'coin' (single coin), 'group' (comma-separated coins).",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
properties: {
|
|
115
|
+
mode: {
|
|
116
|
+
type: "string",
|
|
117
|
+
enum: ["market", "coin", "group"],
|
|
118
|
+
description: "Scope of cashflow data",
|
|
119
|
+
},
|
|
120
|
+
symbol: {
|
|
121
|
+
type: "string",
|
|
122
|
+
description: "Coin symbol (required for coin/group modes)",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
required: ["mode"],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "coin_info",
|
|
130
|
+
description: "Get detailed info for a coin: market cap, volume, supply, social stats, tokenomics.",
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: "object",
|
|
133
|
+
properties: { symbol: { type: "string", description: "Coin symbol e.g. BTC, ETH, SOL" } },
|
|
134
|
+
required: ["symbol"],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "dexscreener",
|
|
139
|
+
description:
|
|
140
|
+
"Get DEX trading data for a token: liquidity, volume, buys/sells, price change. " +
|
|
141
|
+
"Use contract_address alone for symbol search, or provide chain + contract_address for a specific token.",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {
|
|
145
|
+
contract_address: { type: "string", description: "Token contract address or symbol" },
|
|
146
|
+
chain: { type: "string", description: "Optional chain e.g. ethereum, bsc, base, solana" },
|
|
147
|
+
},
|
|
148
|
+
required: ["contract_address"],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "chain_tokens",
|
|
153
|
+
description: "Get low-cap tokens on a specific blockchain filtered by max market cap.",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
chain: { type: "string", description: "Chain e.g. ethereum, bsc, base, solana, avax" },
|
|
158
|
+
max_mcap: { type: "string", description: "Max market cap e.g. 10000000 (10M)" },
|
|
159
|
+
},
|
|
160
|
+
required: ["chain", "max_mcap"],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "portfolio",
|
|
165
|
+
description:
|
|
166
|
+
"Get Abu's curated crypto portfolio — a model portfolio of carefully selected holdings. " +
|
|
167
|
+
"Use when users ask 'what should I invest in?', 'build me a portfolio', 'what coins to buy', " +
|
|
168
|
+
"or 'give me investment advice'. No symbol = full portfolio overview. " +
|
|
169
|
+
"Symbol provided = Abu's position and analysis for that specific coin.",
|
|
170
|
+
inputSchema: {
|
|
171
|
+
type: "object",
|
|
172
|
+
properties: { symbol: { type: "string", description: "Optional coin symbol to filter" } },
|
|
173
|
+
required: [],
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "channel_summary",
|
|
178
|
+
description: "Get a summary of latest crypto narratives and discussions from monitored channels.",
|
|
179
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "indicator_guide",
|
|
183
|
+
description:
|
|
184
|
+
"Reference guide for Asrai-specific indicators. FREE — no payment required. " +
|
|
185
|
+
"WHEN TO CALL: only when you encounter an unfamiliar indicator name in tool output " +
|
|
186
|
+
"(e.g. ALSAT, SuperALSAT, AlphaTrend, PMax, MavilimW). " +
|
|
187
|
+
"Standard indicators (RSI, MACD, Ichimoku, Elliott Wave, BB) are well-known — skip them. " +
|
|
188
|
+
"indicator='' or 'list' → compact 1-line summary of all. " +
|
|
189
|
+
"indicator='ALSAT' → full detail. indicator='all' → everything (avoid unless needed).",
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
indicator: {
|
|
194
|
+
type: "string",
|
|
195
|
+
description: "Indicator name e.g. 'ALSAT', 'SuperALSAT', 'PMax'. Empty = compact list.",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: [],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
package/src/tools.js
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Asrai API calls via x402 payment protocol.
|
|
3
|
-
* Each call costs
|
|
3
|
+
* Each call costs PRICE_PER_CALL USDC from the user's wallet on Base mainnet.
|
|
4
4
|
*
|
|
5
5
|
* Supports two modes:
|
|
6
6
|
* - stdio (Claude Desktop): reads PRIVATE_KEY from env
|
|
7
7
|
* - SSE (Docker/n8n): key injected per-connection via AsyncLocalStorage
|
|
8
|
+
*
|
|
9
|
+
* Endpoints and tool handlers imported from tool-endpoints.js (synced from asrai-shared/).
|
|
10
|
+
* Do NOT edit tool handlers here — edit in asrai-shared/tool-endpoints.js and run sync.py.
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
13
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
14
|
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
|
|
12
15
|
import { registerExactEvmScheme } from "@x402/evm/exact/client";
|
|
13
16
|
import { privateKeyToAccount } from "viem/accounts";
|
|
17
|
+
import { createHandlers } from "./tool-endpoints.js";
|
|
14
18
|
|
|
15
19
|
const BASE_URL = "https://x402.asrai.me";
|
|
16
20
|
const X402_HEADERS = { "x-coinbase-402": "true", "x-payment-token": "usdc" };
|
|
17
21
|
|
|
18
22
|
// Per-connection state — works for both stdio and multi-user SSE
|
|
19
|
-
// In stdio mode: nothing set here, falls back to PRIVATE_KEY env var
|
|
20
|
-
// In SSE mode: each connection runs inside connectionStorage.run({ key, spend: 0 }, ...)
|
|
21
23
|
export const connectionStorage = new AsyncLocalStorage();
|
|
22
24
|
|
|
23
25
|
function getMaxSpend() {
|
|
24
26
|
return parseFloat(process.env.ASRAI_MAX_SPEND ?? "2.0");
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
// PRICE_PER_CALL — updated by sync.py when pricing.json changes
|
|
30
|
+
const PRICE_PER_CALL = 0.005;
|
|
31
|
+
|
|
27
32
|
function checkSpend(amount) {
|
|
28
33
|
const store = connectionStorage.getStore();
|
|
29
34
|
if (store) {
|
|
@@ -38,8 +43,6 @@ function checkSpend(amount) {
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
function buildFetch() {
|
|
41
|
-
// SSE mode: key from per-connection storage
|
|
42
|
-
// stdio mode: key from env var
|
|
43
46
|
const store = connectionStorage.getStore();
|
|
44
47
|
const key = store?.key ?? process.env.PRIVATE_KEY;
|
|
45
48
|
if (!key) throw new Error("PRIVATE_KEY environment variable is required");
|
|
@@ -51,7 +54,7 @@ function buildFetch() {
|
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
async function _get(path) {
|
|
54
|
-
checkSpend(
|
|
57
|
+
checkSpend(PRICE_PER_CALL);
|
|
55
58
|
const fetchWithPayment = buildFetch();
|
|
56
59
|
const res = await fetchWithPayment(`${BASE_URL}${path}`, {
|
|
57
60
|
headers: X402_HEADERS,
|
|
@@ -62,7 +65,7 @@ async function _get(path) {
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
async function _post(path, body) {
|
|
65
|
-
checkSpend(
|
|
68
|
+
checkSpend(PRICE_PER_CALL);
|
|
66
69
|
const fetchWithPayment = buildFetch();
|
|
67
70
|
const res = await fetchWithPayment(`${BASE_URL}${path}`, {
|
|
68
71
|
method: "POST",
|
|
@@ -84,147 +87,15 @@ async function _gather(...paths) {
|
|
|
84
87
|
return results;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
|
-
// ──
|
|
88
|
-
|
|
89
|
-
function sym(symbol) {
|
|
90
|
-
return symbol.toLowerCase().replace(/usdt$/, "");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ── Tool handlers ───────────────────────────────────────────────────────────
|
|
94
|
-
|
|
95
|
-
export async function market_overview() {
|
|
96
|
-
return JSON.stringify(await _gather(
|
|
97
|
-
"/api/trending/",
|
|
98
|
-
"/api/gainers-losers/",
|
|
99
|
-
"/api/rsi/",
|
|
100
|
-
"/api/top-bottom/",
|
|
101
|
-
"/api/cmcai/",
|
|
102
|
-
"/api/cbbi/",
|
|
103
|
-
"/api/channel-summary/",
|
|
104
|
-
"/api/cashflow/market",
|
|
105
|
-
"/api/cmc-sentiment/",
|
|
106
|
-
"/api/socialdominance/",
|
|
107
|
-
"/api/ath/",
|
|
108
|
-
"/api/ichimoku-trend/",
|
|
109
|
-
"/api/bounce-dip/",
|
|
110
|
-
"/api/sar-coins/",
|
|
111
|
-
"/api/macd-coins/",
|
|
112
|
-
"/api/emacross/",
|
|
113
|
-
"/api/techrating/",
|
|
114
|
-
"/api/volume/",
|
|
115
|
-
"/api/highvolumelowcap/",
|
|
116
|
-
), null, 2);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function technical_analysis(symbol, timeframe = "1D") {
|
|
120
|
-
const s = sym(symbol);
|
|
121
|
-
return JSON.stringify(await _gather(
|
|
122
|
-
`/api/signal/${s}usdt/${timeframe}`,
|
|
123
|
-
`/api/alsat/${s}usdt/${timeframe}`,
|
|
124
|
-
`/api/superalsat/${s}usdt`,
|
|
125
|
-
`/api/psar/${s}usdt/${timeframe}`,
|
|
126
|
-
`/api/macd-dema/${s}usdt/${timeframe}`,
|
|
127
|
-
`/api/alphatrend/${s}usdt/${timeframe}`,
|
|
128
|
-
`/api/td/${s}usdt/${timeframe}`,
|
|
129
|
-
`/api/forecasting/${s}usdt`,
|
|
130
|
-
`/api/smartmoney/${s}usdt/${timeframe}`,
|
|
131
|
-
`/api/support-resistance/${s}usdt/${timeframe}`,
|
|
132
|
-
`/api/ew/${s}usdt/${timeframe}`,
|
|
133
|
-
`/api/ichimoku/${s}usdt/${timeframe}`,
|
|
134
|
-
), null, 2);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export async function sentiment() {
|
|
138
|
-
return JSON.stringify(await _gather(
|
|
139
|
-
"/api/cbbi/",
|
|
140
|
-
"/api/cmc-sentiment/",
|
|
141
|
-
"/api/cmcai/",
|
|
142
|
-
), null, 2);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export async function forecast(symbol) {
|
|
146
|
-
return JSON.stringify(await _get(`/api/forecasting/${sym(symbol)}usdt`), null, 2);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export async function screener(screener_type) {
|
|
150
|
-
const valid = [
|
|
151
|
-
"ichimoku-trend", "sar-coins", "macd-coins", "emacross",
|
|
152
|
-
"techrating", "vwap", "volume", "highvolumelowcap",
|
|
153
|
-
"bounce-dip", "galaxyscore", "socialdominance", "late-unlocked-coins",
|
|
154
|
-
"ath", "rsi", "rsi-heatmap", "ao",
|
|
155
|
-
];
|
|
156
|
-
if (!valid.includes(screener_type)) {
|
|
157
|
-
return JSON.stringify({ error: `Invalid screener. Choose from: ${valid.join(", ")}` });
|
|
158
|
-
}
|
|
159
|
-
return JSON.stringify(await _get(`/api/${screener_type}/`), null, 2);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function smart_money(symbol, timeframe = "1D") {
|
|
163
|
-
const s = sym(symbol);
|
|
164
|
-
return JSON.stringify(await _gather(
|
|
165
|
-
`/api/smartmoney/${s}usdt/${timeframe}`,
|
|
166
|
-
`/api/support-resistance/${s}usdt/${timeframe}`,
|
|
167
|
-
), null, 2);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export async function elliott_wave(symbol, timeframe = "1D") {
|
|
171
|
-
return JSON.stringify(await _get(`/api/ew/${sym(symbol)}usdt/${timeframe}`), null, 2);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export async function ichimoku(symbol, timeframe = "1D") {
|
|
175
|
-
return JSON.stringify(await _get(`/api/ichimoku/${sym(symbol)}usdt/${timeframe}`), null, 2);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export async function cashflow(mode, symbol = "") {
|
|
179
|
-
if (mode === "market") {
|
|
180
|
-
return JSON.stringify(await _get("/api/cashflow/market"), null, 2);
|
|
181
|
-
}
|
|
182
|
-
if ((mode === "coin" || mode === "group") && symbol) {
|
|
183
|
-
return JSON.stringify(await _get(`/api/cashflow/${mode}/${symbol.toLowerCase()}`), null, 2);
|
|
184
|
-
}
|
|
185
|
-
return JSON.stringify({ error: "mode must be 'market', 'coin', or 'group'. coin/group require symbol." });
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export async function coin_info(symbol) {
|
|
189
|
-
const s = symbol.toLowerCase();
|
|
90
|
+
// ── Shared handlers (from tool-endpoints.js) ──────────────────────────────────
|
|
190
91
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
`/api/tags/${s}`,
|
|
197
|
-
`/api/cmcai/${s}`,
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
// Phase 2: dexscreener via contract_address if available
|
|
201
|
-
const contractAddress = data[`/api/info/${s}`]?.info_data?.contract_address;
|
|
202
|
-
if (contractAddress) {
|
|
203
|
-
data[`/api/dexscreener/${contractAddress}`] = await _get(`/api/dexscreener/${contractAddress}`);
|
|
204
|
-
}
|
|
92
|
+
export const {
|
|
93
|
+
market_overview, technical_analysis, sentiment, forecast, screener,
|
|
94
|
+
smart_money, elliott_wave, ichimoku, cashflow, coin_info,
|
|
95
|
+
dexscreener, chain_tokens, portfolio, channel_summary,
|
|
96
|
+
} = createHandlers(_get, _gather);
|
|
205
97
|
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export async function dexscreener(contract_address, chain = "") {
|
|
210
|
-
const path = chain
|
|
211
|
-
? `/api/dexscreener/${chain}/${contract_address}`
|
|
212
|
-
: `/api/dexscreener/${contract_address}`;
|
|
213
|
-
return JSON.stringify(await _get(path), null, 2);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export async function chain_tokens(chain, max_mcap) {
|
|
217
|
-
return JSON.stringify(await _get(`/api/chain/${chain}/${max_mcap}`), null, 2);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export async function portfolio(symbol = "") {
|
|
221
|
-
const path = symbol ? `/api/portfolio/${symbol.toLowerCase()}` : "/api/portfolio/";
|
|
222
|
-
return JSON.stringify(await _get(path), null, 2);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export async function channel_summary() {
|
|
226
|
-
return JSON.stringify(await _get("/api/channel-summary/"), null, 2);
|
|
227
|
-
}
|
|
98
|
+
// ── x402-only tools ───────────────────────────────────────────────────────────
|
|
228
99
|
|
|
229
100
|
export async function ask_ai(question) {
|
|
230
101
|
return JSON.stringify(await _post("/ai", { message: question }), null, 2);
|