@aicoin/opendata-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/README.md +228 -0
- package/build/index.js +2086 -0
- package/package.json +44 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,2086 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
|
|
7
|
+
// src/tools/coins.ts
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
// src/client/signature.ts
|
|
11
|
+
import { createHmac, randomBytes } from "crypto";
|
|
12
|
+
function generateSignature(accessKeyId, accessSecret) {
|
|
13
|
+
const nonce = randomBytes(4).toString("hex");
|
|
14
|
+
const ts = Math.floor(Date.now() / 1e3).toString();
|
|
15
|
+
const str = `AccessKeyId=${accessKeyId}&SignatureNonce=${nonce}&Timestamp=${ts}`;
|
|
16
|
+
const hex = createHmac("sha1", accessSecret).update(str).digest("hex");
|
|
17
|
+
const signature = Buffer.from(hex, "binary").toString(
|
|
18
|
+
"base64"
|
|
19
|
+
);
|
|
20
|
+
return {
|
|
21
|
+
AccessKeyId: accessKeyId,
|
|
22
|
+
SignatureNonce: nonce,
|
|
23
|
+
Timestamp: ts,
|
|
24
|
+
Signature: signature
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/client/api.ts
|
|
29
|
+
var DOMAIN = process.env.AICOIN_BASE_URL || "https://open.aicoin.com";
|
|
30
|
+
function getCredentials() {
|
|
31
|
+
const key = process.env.AICOIN_ACCESS_KEY;
|
|
32
|
+
const secret = process.env.AICOIN_ACCESS_SECRET;
|
|
33
|
+
if (!key || !secret) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"Missing AICOIN_ACCESS_KEY or AICOIN_ACCESS_SECRET"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return { key, secret };
|
|
39
|
+
}
|
|
40
|
+
async function apiGet(path, params = {}) {
|
|
41
|
+
const { key, secret } = getCredentials();
|
|
42
|
+
const auth = generateSignature(key, secret);
|
|
43
|
+
const qs = new URLSearchParams({
|
|
44
|
+
...params,
|
|
45
|
+
...auth
|
|
46
|
+
});
|
|
47
|
+
const url = `${DOMAIN}${path}?${qs.toString()}`;
|
|
48
|
+
const res = await fetch(url);
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const body = await res.text();
|
|
51
|
+
throw new Error(`API ${res.status}: ${body}`);
|
|
52
|
+
}
|
|
53
|
+
return res.json();
|
|
54
|
+
}
|
|
55
|
+
async function apiPost(path, body = {}) {
|
|
56
|
+
const { key, secret } = getCredentials();
|
|
57
|
+
const auth = generateSignature(key, secret);
|
|
58
|
+
const url = `${DOMAIN}${path}`;
|
|
59
|
+
const res = await fetch(url, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "Content-Type": "application/json" },
|
|
62
|
+
body: JSON.stringify({ ...body, ...auth })
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const text = await res.text();
|
|
66
|
+
throw new Error(`API ${res.status}: ${text}`);
|
|
67
|
+
}
|
|
68
|
+
return res.json();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/tools/coins.ts
|
|
72
|
+
function ok(data) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function err(e) {
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{ type: "text", text: `Error: ${e.message}` }
|
|
81
|
+
],
|
|
82
|
+
isError: true
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function registerCoinTools(server2) {
|
|
86
|
+
server2.tool(
|
|
87
|
+
"get_coin_list",
|
|
88
|
+
"Get list of all supported coins with basic info",
|
|
89
|
+
{},
|
|
90
|
+
async () => {
|
|
91
|
+
try {
|
|
92
|
+
return ok(await apiGet("/api/v2/coin"));
|
|
93
|
+
} catch (e) {
|
|
94
|
+
return err(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
server2.tool(
|
|
99
|
+
"get_coin_ticker",
|
|
100
|
+
"Get real-time ticker data for coins (price, change, volume)",
|
|
101
|
+
{
|
|
102
|
+
coin_list: z.string().describe("Coin keys, comma-separated, e.g. bitcoin,ethereum")
|
|
103
|
+
},
|
|
104
|
+
async ({ coin_list }) => {
|
|
105
|
+
try {
|
|
106
|
+
return ok(
|
|
107
|
+
await apiGet("/api/v2/coin/ticker", { coin_list })
|
|
108
|
+
);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
return err(e);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
server2.tool(
|
|
115
|
+
"get_coin_config",
|
|
116
|
+
"Get coin profile/description data",
|
|
117
|
+
{
|
|
118
|
+
coin_key: z.string().describe("Coin key, e.g. bitcoin")
|
|
119
|
+
},
|
|
120
|
+
async ({ coin_key }) => {
|
|
121
|
+
try {
|
|
122
|
+
return ok(
|
|
123
|
+
await apiGet("/api/v2/coin/config", { coin_key })
|
|
124
|
+
);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
return err(e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
server2.tool(
|
|
131
|
+
"get_ai_coin_analysis",
|
|
132
|
+
"Get AI interpretation and prediction for coins",
|
|
133
|
+
{
|
|
134
|
+
coin_keys: z.string().describe('Coin keys JSON array, e.g. ["bitcoin","ethereum"]'),
|
|
135
|
+
language: z.enum(["CN", "EN", "TC"]).optional().describe("Language: CN/EN/TC, default CN")
|
|
136
|
+
},
|
|
137
|
+
async ({ coin_keys, language }) => {
|
|
138
|
+
try {
|
|
139
|
+
const body = {
|
|
140
|
+
coinKeys: JSON.parse(coin_keys)
|
|
141
|
+
};
|
|
142
|
+
if (language) body.language = language;
|
|
143
|
+
return ok(
|
|
144
|
+
await apiPost("/api/v2/content/ai-coins", body)
|
|
145
|
+
);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
return err(e);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
server2.tool(
|
|
152
|
+
"get_funding_rate_history",
|
|
153
|
+
"Get funding rate history for a coin",
|
|
154
|
+
{
|
|
155
|
+
coin: z.string().describe("Coin key, e.g. bitcoin"),
|
|
156
|
+
interval: z.string().optional().describe("Interval, e.g. 8h")
|
|
157
|
+
},
|
|
158
|
+
async ({ coin, interval }) => {
|
|
159
|
+
try {
|
|
160
|
+
const params = { coin };
|
|
161
|
+
if (interval) params.interval = interval;
|
|
162
|
+
return ok(
|
|
163
|
+
await apiGet(
|
|
164
|
+
"/api/upgrade/v2/futures/funding-rate/history",
|
|
165
|
+
params
|
|
166
|
+
)
|
|
167
|
+
);
|
|
168
|
+
} catch (e) {
|
|
169
|
+
return err(e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
server2.tool(
|
|
174
|
+
"get_liquidation_map",
|
|
175
|
+
"Get liquidation heatmap data for a coin",
|
|
176
|
+
{
|
|
177
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
178
|
+
},
|
|
179
|
+
async ({ coin }) => {
|
|
180
|
+
try {
|
|
181
|
+
return ok(
|
|
182
|
+
await apiGet(
|
|
183
|
+
"/api/upgrade/v2/futures/liquidation/map",
|
|
184
|
+
{ coin }
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
} catch (e) {
|
|
188
|
+
return err(e);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
server2.tool(
|
|
193
|
+
"get_weighted_funding_rate_history",
|
|
194
|
+
"Get volume-weighted funding rate history",
|
|
195
|
+
{
|
|
196
|
+
coin: z.string().describe("Coin key, e.g. bitcoin"),
|
|
197
|
+
interval: z.string().optional().describe("Interval, e.g. 8h")
|
|
198
|
+
},
|
|
199
|
+
async ({ coin, interval }) => {
|
|
200
|
+
try {
|
|
201
|
+
const params = { coin };
|
|
202
|
+
if (interval) params.interval = interval;
|
|
203
|
+
return ok(
|
|
204
|
+
await apiGet(
|
|
205
|
+
"/api/upgrade/v2/futures/funding-rate/vol-weight-history",
|
|
206
|
+
params
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
return err(e);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
server2.tool(
|
|
215
|
+
"get_aggregated_stablecoin_oi_history",
|
|
216
|
+
"Get aggregated stablecoin-margined open interest history",
|
|
217
|
+
{
|
|
218
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
219
|
+
},
|
|
220
|
+
async ({ coin }) => {
|
|
221
|
+
try {
|
|
222
|
+
return ok(
|
|
223
|
+
await apiGet(
|
|
224
|
+
"/api/upgrade/v2/futures/open-interest/aggregated-stablecoin-history",
|
|
225
|
+
{ coin }
|
|
226
|
+
)
|
|
227
|
+
);
|
|
228
|
+
} catch (e) {
|
|
229
|
+
return err(e);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
server2.tool(
|
|
234
|
+
"get_aggregated_coin_margin_oi_history",
|
|
235
|
+
"Get aggregated coin-margined open interest history",
|
|
236
|
+
{
|
|
237
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
238
|
+
},
|
|
239
|
+
async ({ coin }) => {
|
|
240
|
+
try {
|
|
241
|
+
return ok(
|
|
242
|
+
await apiGet(
|
|
243
|
+
"/api/upgrade/v2/futures/open-interest/aggregated-coin-margin-history",
|
|
244
|
+
{ coin }
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
} catch (e) {
|
|
248
|
+
return err(e);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
server2.tool(
|
|
253
|
+
"get_liquidation_history",
|
|
254
|
+
"Get liquidation order history",
|
|
255
|
+
{
|
|
256
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
257
|
+
},
|
|
258
|
+
async ({ coin }) => {
|
|
259
|
+
try {
|
|
260
|
+
return ok(
|
|
261
|
+
await apiGet(
|
|
262
|
+
"/api/upgrade/v2/futures/liquidation/history",
|
|
263
|
+
{ coin }
|
|
264
|
+
)
|
|
265
|
+
);
|
|
266
|
+
} catch (e) {
|
|
267
|
+
return err(e);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
server2.tool(
|
|
272
|
+
"get_estimated_liquidation_history",
|
|
273
|
+
"Get historical estimated liquidation chart data",
|
|
274
|
+
{
|
|
275
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
276
|
+
},
|
|
277
|
+
async ({ coin }) => {
|
|
278
|
+
try {
|
|
279
|
+
return ok(
|
|
280
|
+
await apiGet(
|
|
281
|
+
"/api/upgrade/v2/futures/estimated-liquidation/history",
|
|
282
|
+
{ coin }
|
|
283
|
+
)
|
|
284
|
+
);
|
|
285
|
+
} catch (e) {
|
|
286
|
+
return err(e);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
server2.tool(
|
|
291
|
+
"get_historical_depth",
|
|
292
|
+
"Get historical order book depth data",
|
|
293
|
+
{
|
|
294
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
295
|
+
},
|
|
296
|
+
async ({ coin }) => {
|
|
297
|
+
try {
|
|
298
|
+
return ok(
|
|
299
|
+
await apiGet(
|
|
300
|
+
"/api/upgrade/v2/futures/historical-depth",
|
|
301
|
+
{ coin }
|
|
302
|
+
)
|
|
303
|
+
);
|
|
304
|
+
} catch (e) {
|
|
305
|
+
return err(e);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
server2.tool(
|
|
310
|
+
"get_super_depth_history",
|
|
311
|
+
"Get large order depth history",
|
|
312
|
+
{
|
|
313
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
314
|
+
},
|
|
315
|
+
async ({ coin }) => {
|
|
316
|
+
try {
|
|
317
|
+
return ok(
|
|
318
|
+
await apiGet(
|
|
319
|
+
"/api/upgrade/v2/futures/super-depth/history",
|
|
320
|
+
{ coin }
|
|
321
|
+
)
|
|
322
|
+
);
|
|
323
|
+
} catch (e) {
|
|
324
|
+
return err(e);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
server2.tool(
|
|
329
|
+
"get_trade_data",
|
|
330
|
+
"Get latest trade data for futures",
|
|
331
|
+
{
|
|
332
|
+
coin: z.string().describe("Coin key, e.g. bitcoin")
|
|
333
|
+
},
|
|
334
|
+
async ({ coin }) => {
|
|
335
|
+
try {
|
|
336
|
+
return ok(
|
|
337
|
+
await apiGet(
|
|
338
|
+
"/api/upgrade/v2/futures/trade-data",
|
|
339
|
+
{ coin }
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
} catch (e) {
|
|
343
|
+
return err(e);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/tools/contents.ts
|
|
350
|
+
import { z as z2 } from "zod";
|
|
351
|
+
function ok2(data) {
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function err2(e) {
|
|
357
|
+
return {
|
|
358
|
+
content: [
|
|
359
|
+
{ type: "text", text: `Error: ${e.message}` }
|
|
360
|
+
],
|
|
361
|
+
isError: true
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function registerContentTools(server2) {
|
|
365
|
+
server2.tool(
|
|
366
|
+
"get_newsflash",
|
|
367
|
+
"Get latest crypto flash news (kuaixun)",
|
|
368
|
+
{
|
|
369
|
+
page: z2.string().optional().describe("Page number, default 1"),
|
|
370
|
+
limit: z2.string().optional().describe("Items per page, default 20")
|
|
371
|
+
},
|
|
372
|
+
async ({ page, limit }) => {
|
|
373
|
+
try {
|
|
374
|
+
const params = {};
|
|
375
|
+
if (page) params.page = page;
|
|
376
|
+
if (limit) params.limit = limit;
|
|
377
|
+
return ok2(
|
|
378
|
+
await apiGet("/api/v2/content/newsflash", params)
|
|
379
|
+
);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
return err2(e);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
server2.tool(
|
|
386
|
+
"get_news_list",
|
|
387
|
+
"Get news article list",
|
|
388
|
+
{
|
|
389
|
+
page: z2.string().optional().describe("Page number"),
|
|
390
|
+
limit: z2.string().optional().describe("Items per page")
|
|
391
|
+
},
|
|
392
|
+
async ({ page, limit }) => {
|
|
393
|
+
try {
|
|
394
|
+
const params = {};
|
|
395
|
+
if (page) params.page = page;
|
|
396
|
+
if (limit) params.limit = limit;
|
|
397
|
+
return ok2(
|
|
398
|
+
await apiGet("/api/v2/content/news-list", params)
|
|
399
|
+
);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
return err2(e);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
server2.tool(
|
|
406
|
+
"get_news_detail",
|
|
407
|
+
"Get full content of a news article",
|
|
408
|
+
{
|
|
409
|
+
id: z2.string().describe("News article ID")
|
|
410
|
+
},
|
|
411
|
+
async ({ id }) => {
|
|
412
|
+
try {
|
|
413
|
+
return ok2(
|
|
414
|
+
await apiGet("/api/v2/content/news-detail", { id })
|
|
415
|
+
);
|
|
416
|
+
} catch (e) {
|
|
417
|
+
return err2(e);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
server2.tool(
|
|
422
|
+
"get_rss_news_list",
|
|
423
|
+
"Get RSS news list (dedicated RSS feed)",
|
|
424
|
+
{
|
|
425
|
+
page: z2.string().optional().describe("Page number"),
|
|
426
|
+
pageSize: z2.string().optional().describe("Page size, max 20")
|
|
427
|
+
},
|
|
428
|
+
async ({ page, pageSize }) => {
|
|
429
|
+
try {
|
|
430
|
+
const params = {};
|
|
431
|
+
if (page) params.page = page;
|
|
432
|
+
if (pageSize) params.pageSize = pageSize;
|
|
433
|
+
return ok2(
|
|
434
|
+
await apiGet(
|
|
435
|
+
"/api/v2/content/square/market/news-list",
|
|
436
|
+
params
|
|
437
|
+
)
|
|
438
|
+
);
|
|
439
|
+
} catch (e) {
|
|
440
|
+
return err2(e);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
);
|
|
444
|
+
server2.tool(
|
|
445
|
+
"get_flash_list",
|
|
446
|
+
"Get industry flash news (with flash type classification)",
|
|
447
|
+
{
|
|
448
|
+
language: z2.string().optional().describe("Language: cn, tc, en"),
|
|
449
|
+
createtime: z2.string().optional().describe("Filter by create time")
|
|
450
|
+
},
|
|
451
|
+
async ({ language, createtime }) => {
|
|
452
|
+
try {
|
|
453
|
+
const params = {};
|
|
454
|
+
if (language) params.language = language;
|
|
455
|
+
if (createtime) params.createtime = createtime;
|
|
456
|
+
return ok2(
|
|
457
|
+
await apiGet(
|
|
458
|
+
"/api/v2/content/flashList",
|
|
459
|
+
params
|
|
460
|
+
)
|
|
461
|
+
);
|
|
462
|
+
} catch (e) {
|
|
463
|
+
return err2(e);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
);
|
|
467
|
+
server2.tool(
|
|
468
|
+
"get_exchange_listing_flash",
|
|
469
|
+
"Get exchange coin listing/delisting news",
|
|
470
|
+
{
|
|
471
|
+
page: z2.string().optional().describe("Page number"),
|
|
472
|
+
limit: z2.string().optional().describe("Items per page")
|
|
473
|
+
},
|
|
474
|
+
async ({ page, limit }) => {
|
|
475
|
+
try {
|
|
476
|
+
const params = {};
|
|
477
|
+
if (page) params.page = page;
|
|
478
|
+
if (limit) params.limit = limit;
|
|
479
|
+
return ok2(
|
|
480
|
+
await apiGet(
|
|
481
|
+
"/api/v2/content/exchange-listing-flash",
|
|
482
|
+
params
|
|
483
|
+
)
|
|
484
|
+
);
|
|
485
|
+
} catch (e) {
|
|
486
|
+
return err2(e);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// src/tools/markets.ts
|
|
493
|
+
import { z as z3 } from "zod";
|
|
494
|
+
function ok3(data) {
|
|
495
|
+
return {
|
|
496
|
+
content: [
|
|
497
|
+
{ type: "text", text: JSON.stringify(data) }
|
|
498
|
+
]
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function err3(e) {
|
|
502
|
+
return {
|
|
503
|
+
content: [
|
|
504
|
+
{
|
|
505
|
+
type: "text",
|
|
506
|
+
text: `Error: ${e.message}`
|
|
507
|
+
}
|
|
508
|
+
],
|
|
509
|
+
isError: true
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function registerMarketTools(server2) {
|
|
513
|
+
server2.tool(
|
|
514
|
+
"get_kline_data",
|
|
515
|
+
"Get K-line (candlestick) data for a trading pair",
|
|
516
|
+
{
|
|
517
|
+
trading_pair: z3.string().describe("Trading pair key"),
|
|
518
|
+
period: z3.string().optional().describe("Period: 1min,5min,15min,1hour,4hour,1day,1week"),
|
|
519
|
+
limit: z3.string().optional().describe("Number of candles")
|
|
520
|
+
},
|
|
521
|
+
async ({ trading_pair, period, limit }) => {
|
|
522
|
+
try {
|
|
523
|
+
const params = {
|
|
524
|
+
trading_pair
|
|
525
|
+
};
|
|
526
|
+
if (period) params.period = period;
|
|
527
|
+
if (limit) params.limit = limit;
|
|
528
|
+
return ok3(
|
|
529
|
+
await apiGet(
|
|
530
|
+
"/api/v2/commonKline/dataRecords",
|
|
531
|
+
params
|
|
532
|
+
)
|
|
533
|
+
);
|
|
534
|
+
} catch (e) {
|
|
535
|
+
return err3(e);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
);
|
|
539
|
+
server2.tool(
|
|
540
|
+
"get_market_ticker",
|
|
541
|
+
"Get ticker data for a specific exchange platform",
|
|
542
|
+
{
|
|
543
|
+
platform: z3.string().describe("Exchange platform key, e.g. binance"),
|
|
544
|
+
type: z3.string().optional().describe("Market type filter")
|
|
545
|
+
},
|
|
546
|
+
async ({ platform, type }) => {
|
|
547
|
+
try {
|
|
548
|
+
const params = { platform };
|
|
549
|
+
if (type) params.type = type;
|
|
550
|
+
return ok3(
|
|
551
|
+
await apiGet("/api/v2/market/ticker", params)
|
|
552
|
+
);
|
|
553
|
+
} catch (e) {
|
|
554
|
+
return err3(e);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
);
|
|
558
|
+
server2.tool(
|
|
559
|
+
"get_markets",
|
|
560
|
+
"Get list of all supported exchange platforms",
|
|
561
|
+
{},
|
|
562
|
+
async () => {
|
|
563
|
+
try {
|
|
564
|
+
return ok3(await apiGet("/api/v2/market"));
|
|
565
|
+
} catch (e) {
|
|
566
|
+
return err3(e);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
server2.tool(
|
|
571
|
+
"get_futures_interest",
|
|
572
|
+
"Get futures open interest data",
|
|
573
|
+
{
|
|
574
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
575
|
+
},
|
|
576
|
+
async ({ coin }) => {
|
|
577
|
+
try {
|
|
578
|
+
return ok3(
|
|
579
|
+
await apiGet("/api/v2/futures/interest", { coin })
|
|
580
|
+
);
|
|
581
|
+
} catch (e) {
|
|
582
|
+
return err3(e);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
server2.tool(
|
|
587
|
+
"get_crypto_stock_quotes",
|
|
588
|
+
"Get crypto-related stock quotes (MSTR, COIN, etc.)",
|
|
589
|
+
{
|
|
590
|
+
tickers: z3.string().optional().describe(
|
|
591
|
+
"Stock tickers, e.g. i:mstr:nasdaq,i:coin:nasdaq"
|
|
592
|
+
)
|
|
593
|
+
},
|
|
594
|
+
async ({ tickers }) => {
|
|
595
|
+
try {
|
|
596
|
+
const params = {};
|
|
597
|
+
if (tickers) params.tickers = tickers;
|
|
598
|
+
return ok3(
|
|
599
|
+
await apiGet(
|
|
600
|
+
"/api/upgrade/v2/crypto_stock/quotes",
|
|
601
|
+
params
|
|
602
|
+
)
|
|
603
|
+
);
|
|
604
|
+
} catch (e) {
|
|
605
|
+
return err3(e);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
);
|
|
609
|
+
server2.tool(
|
|
610
|
+
"get_index_price",
|
|
611
|
+
"Get index price data",
|
|
612
|
+
{
|
|
613
|
+
index_key: z3.string().describe("Index key")
|
|
614
|
+
},
|
|
615
|
+
async ({ index_key }) => {
|
|
616
|
+
try {
|
|
617
|
+
return ok3(
|
|
618
|
+
await apiGet("/api/v2/index/indexPrice", {
|
|
619
|
+
index_key
|
|
620
|
+
})
|
|
621
|
+
);
|
|
622
|
+
} catch (e) {
|
|
623
|
+
return err3(e);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
);
|
|
627
|
+
server2.tool(
|
|
628
|
+
"get_hot_tab_coins",
|
|
629
|
+
"Get trending/hot coins list by category",
|
|
630
|
+
{
|
|
631
|
+
tab: z3.string().optional().describe("Tab/category filter")
|
|
632
|
+
},
|
|
633
|
+
async ({ tab }) => {
|
|
634
|
+
try {
|
|
635
|
+
const params = {};
|
|
636
|
+
if (tab) params.tab = tab;
|
|
637
|
+
return ok3(
|
|
638
|
+
await apiGet(
|
|
639
|
+
"/api/v2/market/hotTabCoins",
|
|
640
|
+
params
|
|
641
|
+
)
|
|
642
|
+
);
|
|
643
|
+
} catch (e) {
|
|
644
|
+
return err3(e);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
server2.tool(
|
|
649
|
+
"get_crypto_company_info",
|
|
650
|
+
"Get crypto-related company details by stock symbol",
|
|
651
|
+
{
|
|
652
|
+
symbol: z3.string().describe("Stock symbol, e.g. mstr, coin")
|
|
653
|
+
},
|
|
654
|
+
async ({ symbol }) => {
|
|
655
|
+
try {
|
|
656
|
+
return ok3(
|
|
657
|
+
await apiGet(
|
|
658
|
+
`/api/upgrade/v2/crypto_stock/company/${symbol}`
|
|
659
|
+
)
|
|
660
|
+
);
|
|
661
|
+
} catch (e) {
|
|
662
|
+
return err3(e);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
server2.tool(
|
|
667
|
+
"get_index_info",
|
|
668
|
+
"Get index detail information",
|
|
669
|
+
{
|
|
670
|
+
index_key: z3.string().describe("Index key")
|
|
671
|
+
},
|
|
672
|
+
async ({ index_key }) => {
|
|
673
|
+
try {
|
|
674
|
+
return ok3(
|
|
675
|
+
await apiGet("/api/v2/index/indexInfo", {
|
|
676
|
+
index_key
|
|
677
|
+
})
|
|
678
|
+
);
|
|
679
|
+
} catch (e) {
|
|
680
|
+
return err3(e);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
server2.tool(
|
|
685
|
+
"get_index_list",
|
|
686
|
+
"Get list of all available indexes",
|
|
687
|
+
{},
|
|
688
|
+
async () => {
|
|
689
|
+
try {
|
|
690
|
+
return ok3(
|
|
691
|
+
await apiGet("/api/v2/index/getIndex")
|
|
692
|
+
);
|
|
693
|
+
} catch (e) {
|
|
694
|
+
return err3(e);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
);
|
|
698
|
+
server2.tool(
|
|
699
|
+
"get_indicator_kline_trading_pair",
|
|
700
|
+
"Get trading pairs for indicator K-line",
|
|
701
|
+
{
|
|
702
|
+
indicator: z3.string().optional().describe("Indicator name filter")
|
|
703
|
+
},
|
|
704
|
+
async ({ indicator }) => {
|
|
705
|
+
try {
|
|
706
|
+
const params = {};
|
|
707
|
+
if (indicator) params.indicator = indicator;
|
|
708
|
+
return ok3(
|
|
709
|
+
await apiGet(
|
|
710
|
+
"/api/v2/indicatorKline/getTradingPair",
|
|
711
|
+
params
|
|
712
|
+
)
|
|
713
|
+
);
|
|
714
|
+
} catch (e) {
|
|
715
|
+
return err3(e);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
server2.tool(
|
|
720
|
+
"get_indicator_kline_data",
|
|
721
|
+
"Get indicator K-line data records",
|
|
722
|
+
{
|
|
723
|
+
trading_pair: z3.string().describe("Trading pair key"),
|
|
724
|
+
indicator: z3.string().describe("Indicator name"),
|
|
725
|
+
period: z3.string().optional().describe("Period: 1min,5min,15min,1hour,4hour,1day"),
|
|
726
|
+
limit: z3.string().optional().describe("Number of records")
|
|
727
|
+
},
|
|
728
|
+
async ({ trading_pair, indicator, period, limit }) => {
|
|
729
|
+
try {
|
|
730
|
+
const params = {
|
|
731
|
+
trading_pair,
|
|
732
|
+
indicator
|
|
733
|
+
};
|
|
734
|
+
if (period) params.period = period;
|
|
735
|
+
if (limit) params.limit = limit;
|
|
736
|
+
return ok3(
|
|
737
|
+
await apiGet(
|
|
738
|
+
"/api/v2/indicatorKline/dataRecords",
|
|
739
|
+
params
|
|
740
|
+
)
|
|
741
|
+
);
|
|
742
|
+
} catch (e) {
|
|
743
|
+
return err3(e);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
);
|
|
747
|
+
server2.tool(
|
|
748
|
+
"get_coin_treasury_entities",
|
|
749
|
+
"Get coin treasury entity data (e.g. MicroStrategy BTC holdings)",
|
|
750
|
+
{
|
|
751
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin"),
|
|
752
|
+
entity_type: z3.string().optional().describe("Entity type filter")
|
|
753
|
+
},
|
|
754
|
+
async ({ coin, entity_type }) => {
|
|
755
|
+
try {
|
|
756
|
+
const body = { coin };
|
|
757
|
+
if (entity_type) body.entity_type = entity_type;
|
|
758
|
+
return ok3(
|
|
759
|
+
await apiPost(
|
|
760
|
+
"/api/upgrade/v2/coin-treasuries/entities",
|
|
761
|
+
body
|
|
762
|
+
)
|
|
763
|
+
);
|
|
764
|
+
} catch (e) {
|
|
765
|
+
return err3(e);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
server2.tool(
|
|
770
|
+
"get_coin_treasury_history",
|
|
771
|
+
"Get coin treasury historical data",
|
|
772
|
+
{
|
|
773
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin"),
|
|
774
|
+
entity_id: z3.string().optional().describe("Entity ID filter")
|
|
775
|
+
},
|
|
776
|
+
async ({ coin, entity_id }) => {
|
|
777
|
+
try {
|
|
778
|
+
const body = { coin };
|
|
779
|
+
if (entity_id) body.entity_id = entity_id;
|
|
780
|
+
return ok3(
|
|
781
|
+
await apiPost(
|
|
782
|
+
"/api/upgrade/v2/coin-treasuries/history",
|
|
783
|
+
body
|
|
784
|
+
)
|
|
785
|
+
);
|
|
786
|
+
} catch (e) {
|
|
787
|
+
return err3(e);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
);
|
|
791
|
+
server2.tool(
|
|
792
|
+
"get_coin_treasury_accumulated",
|
|
793
|
+
"Get accumulated coin treasury historical data",
|
|
794
|
+
{
|
|
795
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin"),
|
|
796
|
+
entity_id: z3.string().optional().describe("Entity ID filter")
|
|
797
|
+
},
|
|
798
|
+
async ({ coin, entity_id }) => {
|
|
799
|
+
try {
|
|
800
|
+
const body = { coin };
|
|
801
|
+
if (entity_id) body.entity_id = entity_id;
|
|
802
|
+
return ok3(
|
|
803
|
+
await apiPost(
|
|
804
|
+
"/api/upgrade/v2/coin-treasuries/history/accumulated",
|
|
805
|
+
body
|
|
806
|
+
)
|
|
807
|
+
);
|
|
808
|
+
} catch (e) {
|
|
809
|
+
return err3(e);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
);
|
|
813
|
+
server2.tool(
|
|
814
|
+
"get_latest_coin_treasury_entities",
|
|
815
|
+
"Get latest coin treasury entity data",
|
|
816
|
+
{
|
|
817
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
818
|
+
},
|
|
819
|
+
async ({ coin }) => {
|
|
820
|
+
try {
|
|
821
|
+
return ok3(
|
|
822
|
+
await apiGet(
|
|
823
|
+
"/api/upgrade/v2/coin-treasuries/latest/entities",
|
|
824
|
+
{ coin }
|
|
825
|
+
)
|
|
826
|
+
);
|
|
827
|
+
} catch (e) {
|
|
828
|
+
return err3(e);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
);
|
|
832
|
+
server2.tool(
|
|
833
|
+
"get_latest_coin_treasury_history",
|
|
834
|
+
"Get latest coin treasury history data",
|
|
835
|
+
{
|
|
836
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
837
|
+
},
|
|
838
|
+
async ({ coin }) => {
|
|
839
|
+
try {
|
|
840
|
+
return ok3(
|
|
841
|
+
await apiGet(
|
|
842
|
+
"/api/upgrade/v2/coin-treasuries/latest/history",
|
|
843
|
+
{ coin }
|
|
844
|
+
)
|
|
845
|
+
);
|
|
846
|
+
} catch (e) {
|
|
847
|
+
return err3(e);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
);
|
|
851
|
+
server2.tool(
|
|
852
|
+
"get_coin_treasury_summary",
|
|
853
|
+
"Get coin treasury data summary",
|
|
854
|
+
{
|
|
855
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
856
|
+
},
|
|
857
|
+
async ({ coin }) => {
|
|
858
|
+
try {
|
|
859
|
+
return ok3(
|
|
860
|
+
await apiGet(
|
|
861
|
+
"/api/upgrade/v2/coin-treasuries/summary",
|
|
862
|
+
{ coin }
|
|
863
|
+
)
|
|
864
|
+
);
|
|
865
|
+
} catch (e) {
|
|
866
|
+
return err3(e);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
);
|
|
870
|
+
server2.tool(
|
|
871
|
+
"get_latest_depth",
|
|
872
|
+
"Get latest order book depth data for futures",
|
|
873
|
+
{
|
|
874
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
875
|
+
},
|
|
876
|
+
async ({ coin }) => {
|
|
877
|
+
try {
|
|
878
|
+
return ok3(
|
|
879
|
+
await apiGet(
|
|
880
|
+
"/api/upgrade/v2/futures/latest-depth",
|
|
881
|
+
{ coin }
|
|
882
|
+
)
|
|
883
|
+
);
|
|
884
|
+
} catch (e) {
|
|
885
|
+
return err3(e);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
);
|
|
889
|
+
server2.tool(
|
|
890
|
+
"get_full_depth",
|
|
891
|
+
"Get full order book depth data for futures",
|
|
892
|
+
{
|
|
893
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
894
|
+
},
|
|
895
|
+
async ({ coin }) => {
|
|
896
|
+
try {
|
|
897
|
+
return ok3(
|
|
898
|
+
await apiGet(
|
|
899
|
+
"/api/upgrade/v2/futures/full-depth",
|
|
900
|
+
{ coin }
|
|
901
|
+
)
|
|
902
|
+
);
|
|
903
|
+
} catch (e) {
|
|
904
|
+
return err3(e);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
);
|
|
908
|
+
server2.tool(
|
|
909
|
+
"get_full_depth_grouped",
|
|
910
|
+
"Get full depth data grouped by price level",
|
|
911
|
+
{
|
|
912
|
+
coin: z3.string().describe("Coin key, e.g. bitcoin")
|
|
913
|
+
},
|
|
914
|
+
async ({ coin }) => {
|
|
915
|
+
try {
|
|
916
|
+
return ok3(
|
|
917
|
+
await apiGet(
|
|
918
|
+
"/api/upgrade/v2/futures/full-depth/grouped",
|
|
919
|
+
{ coin }
|
|
920
|
+
)
|
|
921
|
+
);
|
|
922
|
+
} catch (e) {
|
|
923
|
+
return err3(e);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// src/tools/features.ts
|
|
930
|
+
import { z as z4 } from "zod";
|
|
931
|
+
function ok4(data) {
|
|
932
|
+
return {
|
|
933
|
+
content: [
|
|
934
|
+
{ type: "text", text: JSON.stringify(data) }
|
|
935
|
+
]
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
function err4(e) {
|
|
939
|
+
return {
|
|
940
|
+
content: [
|
|
941
|
+
{
|
|
942
|
+
type: "text",
|
|
943
|
+
text: `Error: ${e.message}`
|
|
944
|
+
}
|
|
945
|
+
],
|
|
946
|
+
isError: true
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
function registerFeatureTools(server2) {
|
|
950
|
+
server2.tool(
|
|
951
|
+
"get_ls_ratio",
|
|
952
|
+
"Get long/short ratio data",
|
|
953
|
+
{
|
|
954
|
+
coin: z4.string().describe("Coin key, e.g. bitcoin"),
|
|
955
|
+
period: z4.string().optional().describe("Period filter")
|
|
956
|
+
},
|
|
957
|
+
async ({ coin, period }) => {
|
|
958
|
+
try {
|
|
959
|
+
const params = { coin };
|
|
960
|
+
if (period) params.period = period;
|
|
961
|
+
return ok4(
|
|
962
|
+
await apiGet("/api/v2/mix/ls-ratio", params)
|
|
963
|
+
);
|
|
964
|
+
} catch (e) {
|
|
965
|
+
return err4(e);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
);
|
|
969
|
+
server2.tool(
|
|
970
|
+
"get_liquidation_data",
|
|
971
|
+
"Get liquidation/forced-close data",
|
|
972
|
+
{
|
|
973
|
+
coin: z4.string().optional().describe("Coin key filter"),
|
|
974
|
+
period: z4.string().optional().describe("Period filter")
|
|
975
|
+
},
|
|
976
|
+
async ({ coin, period }) => {
|
|
977
|
+
try {
|
|
978
|
+
const params = {};
|
|
979
|
+
if (coin) params.coin = coin;
|
|
980
|
+
if (period) params.period = period;
|
|
981
|
+
return ok4(
|
|
982
|
+
await apiGet("/api/v2/mix/liq", params)
|
|
983
|
+
);
|
|
984
|
+
} catch (e) {
|
|
985
|
+
return err4(e);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
);
|
|
989
|
+
server2.tool(
|
|
990
|
+
"get_big_orders",
|
|
991
|
+
"Get whale/large order tracking data",
|
|
992
|
+
{
|
|
993
|
+
coin: z4.string().optional().describe("Coin key filter"),
|
|
994
|
+
platform: z4.string().optional().describe("Exchange platform filter"),
|
|
995
|
+
page: z4.string().optional().describe("Page number")
|
|
996
|
+
},
|
|
997
|
+
async ({ coin, platform, page }) => {
|
|
998
|
+
try {
|
|
999
|
+
const params = {};
|
|
1000
|
+
if (coin) params.coin = coin;
|
|
1001
|
+
if (platform) params.platform = platform;
|
|
1002
|
+
if (page) params.page = page;
|
|
1003
|
+
return ok4(
|
|
1004
|
+
await apiGet("/api/v2/order/bigOrder", params)
|
|
1005
|
+
);
|
|
1006
|
+
} catch (e) {
|
|
1007
|
+
return err4(e);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
);
|
|
1011
|
+
server2.tool(
|
|
1012
|
+
"get_agg_trades",
|
|
1013
|
+
"Get aggregated large trades data",
|
|
1014
|
+
{
|
|
1015
|
+
coin: z4.string().optional().describe("Coin key filter"),
|
|
1016
|
+
platform: z4.string().optional().describe("Exchange platform filter")
|
|
1017
|
+
},
|
|
1018
|
+
async ({ coin, platform }) => {
|
|
1019
|
+
try {
|
|
1020
|
+
const params = {};
|
|
1021
|
+
if (coin) params.coin = coin;
|
|
1022
|
+
if (platform) params.platform = platform;
|
|
1023
|
+
return ok4(
|
|
1024
|
+
await apiGet("/api/v2/order/aggTrade", params)
|
|
1025
|
+
);
|
|
1026
|
+
} catch (e) {
|
|
1027
|
+
return err4(e);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
);
|
|
1031
|
+
server2.tool(
|
|
1032
|
+
"get_trading_pair_ticker",
|
|
1033
|
+
"Get ticker data for specific trading pairs",
|
|
1034
|
+
{
|
|
1035
|
+
trading_pairs: z4.string().describe(
|
|
1036
|
+
"Trading pair keys, comma-separated"
|
|
1037
|
+
)
|
|
1038
|
+
},
|
|
1039
|
+
async ({ trading_pairs }) => {
|
|
1040
|
+
try {
|
|
1041
|
+
return ok4(
|
|
1042
|
+
await apiGet("/api/v2/trading-pair/ticker", {
|
|
1043
|
+
trading_pairs
|
|
1044
|
+
})
|
|
1045
|
+
);
|
|
1046
|
+
} catch (e) {
|
|
1047
|
+
return err4(e);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
);
|
|
1051
|
+
server2.tool(
|
|
1052
|
+
"get_strategy_signal",
|
|
1053
|
+
"Get indicator win-rate signal data",
|
|
1054
|
+
{
|
|
1055
|
+
coin: z4.string().optional().describe("Coin key filter")
|
|
1056
|
+
},
|
|
1057
|
+
async ({ coin }) => {
|
|
1058
|
+
try {
|
|
1059
|
+
const params = {};
|
|
1060
|
+
if (coin) params.coin = coin;
|
|
1061
|
+
return ok4(
|
|
1062
|
+
await apiGet(
|
|
1063
|
+
"/api/v2/signal/strategySignal",
|
|
1064
|
+
params
|
|
1065
|
+
)
|
|
1066
|
+
);
|
|
1067
|
+
} catch (e) {
|
|
1068
|
+
return err4(e);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
);
|
|
1072
|
+
server2.tool(
|
|
1073
|
+
"get_nav",
|
|
1074
|
+
"Get navigation bar data (market overview)",
|
|
1075
|
+
{},
|
|
1076
|
+
async () => {
|
|
1077
|
+
try {
|
|
1078
|
+
return ok4(await apiGet("/api/v2/mix/nav"));
|
|
1079
|
+
} catch (e) {
|
|
1080
|
+
return err4(e);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
server2.tool(
|
|
1085
|
+
"get_grayscale_trust",
|
|
1086
|
+
"Get Grayscale trust fund data",
|
|
1087
|
+
{},
|
|
1088
|
+
async () => {
|
|
1089
|
+
try {
|
|
1090
|
+
return ok4(
|
|
1091
|
+
await apiGet("/api/v2/mix/grayscale-trust")
|
|
1092
|
+
);
|
|
1093
|
+
} catch (e) {
|
|
1094
|
+
return err4(e);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
);
|
|
1098
|
+
server2.tool(
|
|
1099
|
+
"get_gray_scale",
|
|
1100
|
+
"Get Grayscale holdings data",
|
|
1101
|
+
{},
|
|
1102
|
+
async () => {
|
|
1103
|
+
try {
|
|
1104
|
+
return ok4(
|
|
1105
|
+
await apiGet("/api/v2/mix/gray-scale")
|
|
1106
|
+
);
|
|
1107
|
+
} catch (e) {
|
|
1108
|
+
return err4(e);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
);
|
|
1112
|
+
server2.tool(
|
|
1113
|
+
"get_stock_market",
|
|
1114
|
+
"Get stock market data (crypto-related)",
|
|
1115
|
+
{},
|
|
1116
|
+
async () => {
|
|
1117
|
+
try {
|
|
1118
|
+
return ok4(
|
|
1119
|
+
await apiGet("/api/v2/mix/stock-market")
|
|
1120
|
+
);
|
|
1121
|
+
} catch (e) {
|
|
1122
|
+
return err4(e);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
);
|
|
1126
|
+
server2.tool(
|
|
1127
|
+
"get_signal_alert",
|
|
1128
|
+
"Get signal alert data",
|
|
1129
|
+
{
|
|
1130
|
+
coin: z4.string().optional().describe("Coin key filter")
|
|
1131
|
+
},
|
|
1132
|
+
async ({ coin }) => {
|
|
1133
|
+
try {
|
|
1134
|
+
const params = {};
|
|
1135
|
+
if (coin) params.coin = coin;
|
|
1136
|
+
return ok4(
|
|
1137
|
+
await apiGet(
|
|
1138
|
+
"/api/v2/signal/signalAlert",
|
|
1139
|
+
params
|
|
1140
|
+
)
|
|
1141
|
+
);
|
|
1142
|
+
} catch (e) {
|
|
1143
|
+
return err4(e);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
);
|
|
1147
|
+
server2.tool(
|
|
1148
|
+
"get_signal_alert_config",
|
|
1149
|
+
"Get signal alert configuration options",
|
|
1150
|
+
{},
|
|
1151
|
+
async () => {
|
|
1152
|
+
try {
|
|
1153
|
+
return ok4(
|
|
1154
|
+
await apiGet("/api/v2/signal/signalAlertConf")
|
|
1155
|
+
);
|
|
1156
|
+
} catch (e) {
|
|
1157
|
+
return err4(e);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
);
|
|
1161
|
+
server2.tool(
|
|
1162
|
+
"delete_signal_alert",
|
|
1163
|
+
"Delete a signal alert by ID",
|
|
1164
|
+
{
|
|
1165
|
+
id: z4.string().describe("Signal alert ID")
|
|
1166
|
+
},
|
|
1167
|
+
async ({ id }) => {
|
|
1168
|
+
try {
|
|
1169
|
+
return ok4(
|
|
1170
|
+
await apiGet(
|
|
1171
|
+
"/api/v2/signal/delSignalAlert",
|
|
1172
|
+
{ id }
|
|
1173
|
+
)
|
|
1174
|
+
);
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
return err4(e);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
);
|
|
1180
|
+
server2.tool(
|
|
1181
|
+
"add_signal_alert",
|
|
1182
|
+
"Add a new signal alert",
|
|
1183
|
+
{
|
|
1184
|
+
params_json: z4.string().describe("Alert params as JSON string")
|
|
1185
|
+
},
|
|
1186
|
+
async ({ params_json }) => {
|
|
1187
|
+
try {
|
|
1188
|
+
const params = JSON.parse(params_json);
|
|
1189
|
+
return ok4(
|
|
1190
|
+
await apiGet(
|
|
1191
|
+
"/api/v2/signal/addSignalAlert",
|
|
1192
|
+
params
|
|
1193
|
+
)
|
|
1194
|
+
);
|
|
1195
|
+
} catch (e) {
|
|
1196
|
+
return err4(e);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
);
|
|
1200
|
+
server2.tool(
|
|
1201
|
+
"get_signal_alert_list",
|
|
1202
|
+
"Get signal alert settings list",
|
|
1203
|
+
{},
|
|
1204
|
+
async () => {
|
|
1205
|
+
try {
|
|
1206
|
+
return ok4(
|
|
1207
|
+
await apiGet(
|
|
1208
|
+
"/api/v2/signal/getSignalAlertSetList"
|
|
1209
|
+
)
|
|
1210
|
+
);
|
|
1211
|
+
} catch (e) {
|
|
1212
|
+
return err4(e);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
);
|
|
1216
|
+
server2.tool(
|
|
1217
|
+
"get_change_signal",
|
|
1218
|
+
"Get abnormal movement signal data",
|
|
1219
|
+
{
|
|
1220
|
+
coin: z4.string().optional().describe("Coin key filter")
|
|
1221
|
+
},
|
|
1222
|
+
async ({ coin }) => {
|
|
1223
|
+
try {
|
|
1224
|
+
const params = {};
|
|
1225
|
+
if (coin) params.coin = coin;
|
|
1226
|
+
return ok4(
|
|
1227
|
+
await apiGet(
|
|
1228
|
+
"/api/v2/signal/changeSignal",
|
|
1229
|
+
params
|
|
1230
|
+
)
|
|
1231
|
+
);
|
|
1232
|
+
} catch (e) {
|
|
1233
|
+
return err4(e);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
);
|
|
1237
|
+
server2.tool(
|
|
1238
|
+
"get_trading_pair",
|
|
1239
|
+
"Get trading pair info by key",
|
|
1240
|
+
{
|
|
1241
|
+
trading_pair: z4.string().describe("Trading pair key")
|
|
1242
|
+
},
|
|
1243
|
+
async ({ trading_pair }) => {
|
|
1244
|
+
try {
|
|
1245
|
+
return ok4(
|
|
1246
|
+
await apiGet(
|
|
1247
|
+
"/api/v2/trading-pair/getTradingPair",
|
|
1248
|
+
{ trading_pair }
|
|
1249
|
+
)
|
|
1250
|
+
);
|
|
1251
|
+
} catch (e) {
|
|
1252
|
+
return err4(e);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
);
|
|
1256
|
+
server2.tool(
|
|
1257
|
+
"get_trading_pairs",
|
|
1258
|
+
"Get trading pair list for a platform",
|
|
1259
|
+
{
|
|
1260
|
+
platform: z4.string().describe("Platform key, e.g. binance"),
|
|
1261
|
+
type: z4.string().optional().describe("Market type filter")
|
|
1262
|
+
},
|
|
1263
|
+
async ({ platform, type }) => {
|
|
1264
|
+
try {
|
|
1265
|
+
const params = {
|
|
1266
|
+
platform
|
|
1267
|
+
};
|
|
1268
|
+
if (type) params.type = type;
|
|
1269
|
+
return ok4(
|
|
1270
|
+
await apiGet("/api/v2/trading-pair", params)
|
|
1271
|
+
);
|
|
1272
|
+
} catch (e) {
|
|
1273
|
+
return err4(e);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// src/tools/hyperliquid.ts
|
|
1280
|
+
import { z as z5 } from "zod";
|
|
1281
|
+
function ok5(data) {
|
|
1282
|
+
return {
|
|
1283
|
+
content: [
|
|
1284
|
+
{ type: "text", text: JSON.stringify(data) }
|
|
1285
|
+
]
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
function err5(e) {
|
|
1289
|
+
return {
|
|
1290
|
+
content: [
|
|
1291
|
+
{
|
|
1292
|
+
type: "text",
|
|
1293
|
+
text: `Error: ${e.message}`
|
|
1294
|
+
}
|
|
1295
|
+
],
|
|
1296
|
+
isError: true
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
function registerHyperliquidTools(server2) {
|
|
1300
|
+
server2.tool(
|
|
1301
|
+
"hl_get_tickers",
|
|
1302
|
+
"Get all Hyperliquid ticker data",
|
|
1303
|
+
{},
|
|
1304
|
+
async () => {
|
|
1305
|
+
try {
|
|
1306
|
+
return ok5(await apiGet("/api/v2/hl/tickers"));
|
|
1307
|
+
} catch (e) {
|
|
1308
|
+
return err5(e);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
);
|
|
1312
|
+
server2.tool(
|
|
1313
|
+
"hl_get_ticker_by_coin",
|
|
1314
|
+
"Get Hyperliquid ticker for a specific coin",
|
|
1315
|
+
{
|
|
1316
|
+
coin: z5.string().describe("Coin symbol, e.g. BTC, ETH")
|
|
1317
|
+
},
|
|
1318
|
+
async ({ coin }) => {
|
|
1319
|
+
try {
|
|
1320
|
+
return ok5(
|
|
1321
|
+
await apiGet(`/api/v2/hl/tickers/coin/${coin}`)
|
|
1322
|
+
);
|
|
1323
|
+
} catch (e) {
|
|
1324
|
+
return err5(e);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
);
|
|
1328
|
+
server2.tool(
|
|
1329
|
+
"hl_get_whale_positions",
|
|
1330
|
+
"Get Hyperliquid whale open positions",
|
|
1331
|
+
{
|
|
1332
|
+
coin: z5.string().optional().describe("Coin filter, e.g. BTC"),
|
|
1333
|
+
min_usd: z5.string().optional().describe("Min position size in USD")
|
|
1334
|
+
},
|
|
1335
|
+
async ({ coin, min_usd }) => {
|
|
1336
|
+
try {
|
|
1337
|
+
const params = {};
|
|
1338
|
+
if (coin) params.coin = coin;
|
|
1339
|
+
if (min_usd) params.min_usd = min_usd;
|
|
1340
|
+
return ok5(
|
|
1341
|
+
await apiGet(
|
|
1342
|
+
"/api/v2/hl/whales/open-positions",
|
|
1343
|
+
params
|
|
1344
|
+
)
|
|
1345
|
+
);
|
|
1346
|
+
} catch (e) {
|
|
1347
|
+
return err5(e);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
);
|
|
1351
|
+
server2.tool(
|
|
1352
|
+
"hl_get_liquidations",
|
|
1353
|
+
"Get Hyperliquid liquidation history",
|
|
1354
|
+
{
|
|
1355
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1356
|
+
},
|
|
1357
|
+
async ({ coin }) => {
|
|
1358
|
+
try {
|
|
1359
|
+
const params = {};
|
|
1360
|
+
if (coin) params.coin = coin;
|
|
1361
|
+
return ok5(
|
|
1362
|
+
await apiGet(
|
|
1363
|
+
"/api/v2/hl/liquidations/history",
|
|
1364
|
+
params
|
|
1365
|
+
)
|
|
1366
|
+
);
|
|
1367
|
+
} catch (e) {
|
|
1368
|
+
return err5(e);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
);
|
|
1372
|
+
server2.tool(
|
|
1373
|
+
"hl_get_trader_stats",
|
|
1374
|
+
"Get Hyperliquid trader statistics by address",
|
|
1375
|
+
{
|
|
1376
|
+
address: z5.string().describe("Wallet address, e.g. 0x...")
|
|
1377
|
+
},
|
|
1378
|
+
async ({ address }) => {
|
|
1379
|
+
try {
|
|
1380
|
+
return ok5(
|
|
1381
|
+
await apiGet(
|
|
1382
|
+
`/api/v2/hl/traders/${address}/addr-stat`
|
|
1383
|
+
)
|
|
1384
|
+
);
|
|
1385
|
+
} catch (e) {
|
|
1386
|
+
return err5(e);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
);
|
|
1390
|
+
server2.tool(
|
|
1391
|
+
"hl_info",
|
|
1392
|
+
"Generic Hyperliquid Info API (supports all info types)",
|
|
1393
|
+
{
|
|
1394
|
+
type: z5.string().describe(
|
|
1395
|
+
"Info type, e.g. metaAndAssetCtxs, clearinghouseState, spotMeta, allMids, l2Book, openOrders, userFills, candleSnapshot"
|
|
1396
|
+
),
|
|
1397
|
+
user: z5.string().optional().describe("User wallet address (for user-specific queries)"),
|
|
1398
|
+
extra_params: z5.string().optional().describe('Extra params as JSON string, e.g. {"coin":"BTC"}')
|
|
1399
|
+
},
|
|
1400
|
+
async ({ type, user, extra_params }) => {
|
|
1401
|
+
try {
|
|
1402
|
+
const body = { type };
|
|
1403
|
+
if (user) body.user = user;
|
|
1404
|
+
if (extra_params) {
|
|
1405
|
+
Object.assign(body, JSON.parse(extra_params));
|
|
1406
|
+
}
|
|
1407
|
+
return ok5(
|
|
1408
|
+
await apiPost("/api/v2/hl/info", body)
|
|
1409
|
+
);
|
|
1410
|
+
} catch (e) {
|
|
1411
|
+
return err5(e);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
);
|
|
1415
|
+
server2.tool(
|
|
1416
|
+
"hl_get_fills_by_address",
|
|
1417
|
+
"Get Hyperliquid user trade fills by wallet address",
|
|
1418
|
+
{
|
|
1419
|
+
address: z5.string().describe("Wallet address, e.g. 0x...")
|
|
1420
|
+
},
|
|
1421
|
+
async ({ address }) => {
|
|
1422
|
+
try {
|
|
1423
|
+
return ok5(
|
|
1424
|
+
await apiGet(`/api/v2/hl/fills/${address}`)
|
|
1425
|
+
);
|
|
1426
|
+
} catch (e) {
|
|
1427
|
+
return err5(e);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
);
|
|
1431
|
+
server2.tool(
|
|
1432
|
+
"hl_get_fills_by_oid",
|
|
1433
|
+
"Get Hyperliquid trade fills by order ID",
|
|
1434
|
+
{
|
|
1435
|
+
oid: z5.string().describe("Order ID")
|
|
1436
|
+
},
|
|
1437
|
+
async ({ oid }) => {
|
|
1438
|
+
try {
|
|
1439
|
+
return ok5(
|
|
1440
|
+
await apiGet(`/api/v2/hl/fills/oid/${oid}`)
|
|
1441
|
+
);
|
|
1442
|
+
} catch (e) {
|
|
1443
|
+
return err5(e);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
);
|
|
1447
|
+
server2.tool(
|
|
1448
|
+
"hl_get_fills_by_twapid",
|
|
1449
|
+
"Get Hyperliquid trade fills by TWAP ID",
|
|
1450
|
+
{
|
|
1451
|
+
twapid: z5.string().describe("TWAP ID")
|
|
1452
|
+
},
|
|
1453
|
+
async ({ twapid }) => {
|
|
1454
|
+
try {
|
|
1455
|
+
return ok5(
|
|
1456
|
+
await apiGet(
|
|
1457
|
+
`/api/v2/hl/fills/twapid/${twapid}`
|
|
1458
|
+
)
|
|
1459
|
+
);
|
|
1460
|
+
} catch (e) {
|
|
1461
|
+
return err5(e);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
);
|
|
1465
|
+
server2.tool(
|
|
1466
|
+
"hl_get_top_trades",
|
|
1467
|
+
"Get Hyperliquid top trades",
|
|
1468
|
+
{
|
|
1469
|
+
coin: z5.string().optional().describe("Coin filter, e.g. BTC")
|
|
1470
|
+
},
|
|
1471
|
+
async ({ coin }) => {
|
|
1472
|
+
try {
|
|
1473
|
+
const params = {};
|
|
1474
|
+
if (coin) params.coin = coin;
|
|
1475
|
+
return ok5(
|
|
1476
|
+
await apiGet(
|
|
1477
|
+
"/api/v2/hl/fills/top-trades",
|
|
1478
|
+
params
|
|
1479
|
+
)
|
|
1480
|
+
);
|
|
1481
|
+
} catch (e) {
|
|
1482
|
+
return err5(e);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
);
|
|
1486
|
+
server2.tool(
|
|
1487
|
+
"hl_get_filled_orders",
|
|
1488
|
+
"Get filled orders by wallet address",
|
|
1489
|
+
{
|
|
1490
|
+
address: z5.string().describe("Wallet address")
|
|
1491
|
+
},
|
|
1492
|
+
async ({ address }) => {
|
|
1493
|
+
try {
|
|
1494
|
+
return ok5(
|
|
1495
|
+
await apiGet(
|
|
1496
|
+
`/api/v2/hl/filled-orders/${address}/latest`
|
|
1497
|
+
)
|
|
1498
|
+
);
|
|
1499
|
+
} catch (e) {
|
|
1500
|
+
return err5(e);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
);
|
|
1504
|
+
server2.tool(
|
|
1505
|
+
"hl_get_filled_order_by_oid",
|
|
1506
|
+
"Get filled order by order ID",
|
|
1507
|
+
{
|
|
1508
|
+
oid: z5.string().describe("Order ID")
|
|
1509
|
+
},
|
|
1510
|
+
async ({ oid }) => {
|
|
1511
|
+
try {
|
|
1512
|
+
return ok5(
|
|
1513
|
+
await apiGet(
|
|
1514
|
+
`/api/v2/hl/filled-orders/oid/${oid}`
|
|
1515
|
+
)
|
|
1516
|
+
);
|
|
1517
|
+
} catch (e) {
|
|
1518
|
+
return err5(e);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
);
|
|
1522
|
+
server2.tool(
|
|
1523
|
+
"hl_get_orders",
|
|
1524
|
+
"Get latest orders by wallet address",
|
|
1525
|
+
{
|
|
1526
|
+
address: z5.string().describe("Wallet address")
|
|
1527
|
+
},
|
|
1528
|
+
async ({ address }) => {
|
|
1529
|
+
try {
|
|
1530
|
+
return ok5(
|
|
1531
|
+
await apiGet(
|
|
1532
|
+
`/api/v2/hl/orders/${address}/latest`
|
|
1533
|
+
)
|
|
1534
|
+
);
|
|
1535
|
+
} catch (e) {
|
|
1536
|
+
return err5(e);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
);
|
|
1540
|
+
server2.tool(
|
|
1541
|
+
"hl_get_order_by_oid",
|
|
1542
|
+
"Get order by order ID",
|
|
1543
|
+
{
|
|
1544
|
+
oid: z5.string().describe("Order ID")
|
|
1545
|
+
},
|
|
1546
|
+
async ({ oid }) => {
|
|
1547
|
+
try {
|
|
1548
|
+
return ok5(
|
|
1549
|
+
await apiGet(`/api/v2/hl/orders/oid/${oid}`)
|
|
1550
|
+
);
|
|
1551
|
+
} catch (e) {
|
|
1552
|
+
return err5(e);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
1556
|
+
server2.tool(
|
|
1557
|
+
"hl_get_top_open_orders",
|
|
1558
|
+
"Get top open orders on Hyperliquid",
|
|
1559
|
+
{
|
|
1560
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1561
|
+
},
|
|
1562
|
+
async ({ coin }) => {
|
|
1563
|
+
try {
|
|
1564
|
+
const params = {};
|
|
1565
|
+
if (coin) params.coin = coin;
|
|
1566
|
+
return ok5(
|
|
1567
|
+
await apiGet(
|
|
1568
|
+
"/api/v2/hl/orders/top-open-orders",
|
|
1569
|
+
params
|
|
1570
|
+
)
|
|
1571
|
+
);
|
|
1572
|
+
} catch (e) {
|
|
1573
|
+
return err5(e);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
);
|
|
1577
|
+
server2.tool(
|
|
1578
|
+
"hl_get_active_stats",
|
|
1579
|
+
"Get active order statistics",
|
|
1580
|
+
{
|
|
1581
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1582
|
+
},
|
|
1583
|
+
async ({ coin }) => {
|
|
1584
|
+
try {
|
|
1585
|
+
const params = {};
|
|
1586
|
+
if (coin) params.coin = coin;
|
|
1587
|
+
return ok5(
|
|
1588
|
+
await apiGet(
|
|
1589
|
+
"/api/v2/hl/orders/active-stats",
|
|
1590
|
+
params
|
|
1591
|
+
)
|
|
1592
|
+
);
|
|
1593
|
+
} catch (e) {
|
|
1594
|
+
return err5(e);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
);
|
|
1598
|
+
server2.tool(
|
|
1599
|
+
"hl_get_portfolio",
|
|
1600
|
+
"Get account value and PNL curves",
|
|
1601
|
+
{
|
|
1602
|
+
address: z5.string().describe("Wallet address"),
|
|
1603
|
+
window: z5.string().describe("Time window, e.g. 1d, 7d, 30d")
|
|
1604
|
+
},
|
|
1605
|
+
async ({ address, window: win }) => {
|
|
1606
|
+
try {
|
|
1607
|
+
return ok5(
|
|
1608
|
+
await apiGet(
|
|
1609
|
+
`/api/v2/hl/portfolio/${address}/${win}`
|
|
1610
|
+
)
|
|
1611
|
+
);
|
|
1612
|
+
} catch (e) {
|
|
1613
|
+
return err5(e);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
);
|
|
1617
|
+
server2.tool(
|
|
1618
|
+
"hl_get_pnls",
|
|
1619
|
+
"Get PNL curve data by address",
|
|
1620
|
+
{
|
|
1621
|
+
address: z5.string().describe("Wallet address")
|
|
1622
|
+
},
|
|
1623
|
+
async ({ address }) => {
|
|
1624
|
+
try {
|
|
1625
|
+
return ok5(
|
|
1626
|
+
await apiGet(`/api/v2/hl/pnls/${address}`)
|
|
1627
|
+
);
|
|
1628
|
+
} catch (e) {
|
|
1629
|
+
return err5(e);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
);
|
|
1633
|
+
server2.tool(
|
|
1634
|
+
"hl_get_best_trades",
|
|
1635
|
+
"Get most profitable trades by address",
|
|
1636
|
+
{
|
|
1637
|
+
address: z5.string().describe("Wallet address")
|
|
1638
|
+
},
|
|
1639
|
+
async ({ address }) => {
|
|
1640
|
+
try {
|
|
1641
|
+
return ok5(
|
|
1642
|
+
await apiGet(
|
|
1643
|
+
`/api/v2/hl/traders/${address}/best-trades`
|
|
1644
|
+
)
|
|
1645
|
+
);
|
|
1646
|
+
} catch (e) {
|
|
1647
|
+
return err5(e);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
);
|
|
1651
|
+
server2.tool(
|
|
1652
|
+
"hl_get_performance_by_coin",
|
|
1653
|
+
"Get per-coin trading performance stats",
|
|
1654
|
+
{
|
|
1655
|
+
address: z5.string().describe("Wallet address")
|
|
1656
|
+
},
|
|
1657
|
+
async ({ address }) => {
|
|
1658
|
+
try {
|
|
1659
|
+
return ok5(
|
|
1660
|
+
await apiGet(
|
|
1661
|
+
`/api/v2/hl/traders/${address}/performance-by-coin`
|
|
1662
|
+
)
|
|
1663
|
+
);
|
|
1664
|
+
} catch (e) {
|
|
1665
|
+
return err5(e);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
);
|
|
1669
|
+
server2.tool(
|
|
1670
|
+
"hl_get_completed_trades",
|
|
1671
|
+
"Get completed trades list by address",
|
|
1672
|
+
{
|
|
1673
|
+
address: z5.string().describe("Wallet address")
|
|
1674
|
+
},
|
|
1675
|
+
async ({ address }) => {
|
|
1676
|
+
try {
|
|
1677
|
+
return ok5(
|
|
1678
|
+
await apiGet(
|
|
1679
|
+
`/api/v2/hl/traders/${address}/completed-trades`
|
|
1680
|
+
)
|
|
1681
|
+
);
|
|
1682
|
+
} catch (e) {
|
|
1683
|
+
return err5(e);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
);
|
|
1687
|
+
server2.tool(
|
|
1688
|
+
"hl_get_current_position_history",
|
|
1689
|
+
"Get current position history for a coin",
|
|
1690
|
+
{
|
|
1691
|
+
address: z5.string().describe("Wallet address"),
|
|
1692
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1693
|
+
},
|
|
1694
|
+
async ({ address, coin }) => {
|
|
1695
|
+
try {
|
|
1696
|
+
return ok5(
|
|
1697
|
+
await apiGet(
|
|
1698
|
+
`/api/v2/hl/traders/${address}/current-position-history/${coin}`
|
|
1699
|
+
)
|
|
1700
|
+
);
|
|
1701
|
+
} catch (e) {
|
|
1702
|
+
return err5(e);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
server2.tool(
|
|
1707
|
+
"hl_get_completed_position_history",
|
|
1708
|
+
"Get completed position history for a coin",
|
|
1709
|
+
{
|
|
1710
|
+
address: z5.string().describe("Wallet address"),
|
|
1711
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1712
|
+
},
|
|
1713
|
+
async ({ address, coin }) => {
|
|
1714
|
+
try {
|
|
1715
|
+
return ok5(
|
|
1716
|
+
await apiGet(
|
|
1717
|
+
`/api/v2/hl/traders/${address}/completed-position-history/${coin}`
|
|
1718
|
+
)
|
|
1719
|
+
);
|
|
1720
|
+
} catch (e) {
|
|
1721
|
+
return err5(e);
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
);
|
|
1725
|
+
server2.tool(
|
|
1726
|
+
"hl_get_current_position_pnl",
|
|
1727
|
+
"Get current position PnL for a coin",
|
|
1728
|
+
{
|
|
1729
|
+
address: z5.string().describe("Wallet address"),
|
|
1730
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1731
|
+
},
|
|
1732
|
+
async ({ address, coin }) => {
|
|
1733
|
+
try {
|
|
1734
|
+
return ok5(
|
|
1735
|
+
await apiGet(
|
|
1736
|
+
`/api/v2/hl/traders/${address}/current-position-pnl/${coin}`
|
|
1737
|
+
)
|
|
1738
|
+
);
|
|
1739
|
+
} catch (e) {
|
|
1740
|
+
return err5(e);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
);
|
|
1744
|
+
server2.tool(
|
|
1745
|
+
"hl_get_completed_position_pnl",
|
|
1746
|
+
"Get completed position PnL for a coin",
|
|
1747
|
+
{
|
|
1748
|
+
address: z5.string().describe("Wallet address"),
|
|
1749
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1750
|
+
},
|
|
1751
|
+
async ({ address, coin }) => {
|
|
1752
|
+
try {
|
|
1753
|
+
return ok5(
|
|
1754
|
+
await apiGet(
|
|
1755
|
+
`/api/v2/hl/traders/${address}/completed-position-pnl/${coin}`
|
|
1756
|
+
)
|
|
1757
|
+
);
|
|
1758
|
+
} catch (e) {
|
|
1759
|
+
return err5(e);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
);
|
|
1763
|
+
server2.tool(
|
|
1764
|
+
"hl_get_current_position_executions",
|
|
1765
|
+
"Get current position execution trace",
|
|
1766
|
+
{
|
|
1767
|
+
address: z5.string().describe("Wallet address"),
|
|
1768
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1769
|
+
},
|
|
1770
|
+
async ({ address, coin }) => {
|
|
1771
|
+
try {
|
|
1772
|
+
return ok5(
|
|
1773
|
+
await apiGet(
|
|
1774
|
+
`/api/v2/hl/traders/${address}/current-position-executions/${coin}`
|
|
1775
|
+
)
|
|
1776
|
+
);
|
|
1777
|
+
} catch (e) {
|
|
1778
|
+
return err5(e);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
);
|
|
1782
|
+
server2.tool(
|
|
1783
|
+
"hl_get_completed_position_executions",
|
|
1784
|
+
"Get completed position execution trace",
|
|
1785
|
+
{
|
|
1786
|
+
address: z5.string().describe("Wallet address"),
|
|
1787
|
+
coin: z5.string().describe("Coin, e.g. BTC")
|
|
1788
|
+
},
|
|
1789
|
+
async ({ address, coin }) => {
|
|
1790
|
+
try {
|
|
1791
|
+
return ok5(
|
|
1792
|
+
await apiGet(
|
|
1793
|
+
`/api/v2/hl/traders/${address}/completed-position-executions/${coin}`
|
|
1794
|
+
)
|
|
1795
|
+
);
|
|
1796
|
+
} catch (e) {
|
|
1797
|
+
return err5(e);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
);
|
|
1801
|
+
server2.tool(
|
|
1802
|
+
"hl_get_traders_accounts",
|
|
1803
|
+
"Batch query trader account info",
|
|
1804
|
+
{
|
|
1805
|
+
addresses: z5.string().describe("Addresses as JSON array string")
|
|
1806
|
+
},
|
|
1807
|
+
async ({ addresses }) => {
|
|
1808
|
+
try {
|
|
1809
|
+
return ok5(
|
|
1810
|
+
await apiPost("/api/v2/hl/traders/accounts", {
|
|
1811
|
+
addresses: JSON.parse(addresses)
|
|
1812
|
+
})
|
|
1813
|
+
);
|
|
1814
|
+
} catch (e) {
|
|
1815
|
+
return err5(e);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
);
|
|
1819
|
+
server2.tool(
|
|
1820
|
+
"hl_get_traders_statistics",
|
|
1821
|
+
"Batch query trader statistics",
|
|
1822
|
+
{
|
|
1823
|
+
addresses: z5.string().describe("Addresses as JSON array string")
|
|
1824
|
+
},
|
|
1825
|
+
async ({ addresses }) => {
|
|
1826
|
+
try {
|
|
1827
|
+
return ok5(
|
|
1828
|
+
await apiPost(
|
|
1829
|
+
"/api/v2/hl/traders/statistics",
|
|
1830
|
+
{ addresses: JSON.parse(addresses) }
|
|
1831
|
+
)
|
|
1832
|
+
);
|
|
1833
|
+
} catch (e) {
|
|
1834
|
+
return err5(e);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
);
|
|
1838
|
+
server2.tool(
|
|
1839
|
+
"hl_get_whale_events",
|
|
1840
|
+
"Get latest whale position events",
|
|
1841
|
+
{
|
|
1842
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1843
|
+
},
|
|
1844
|
+
async ({ coin }) => {
|
|
1845
|
+
try {
|
|
1846
|
+
const params = {};
|
|
1847
|
+
if (coin) params.coin = coin;
|
|
1848
|
+
return ok5(
|
|
1849
|
+
await apiGet(
|
|
1850
|
+
"/api/v2/hl/whales/latest-events",
|
|
1851
|
+
params
|
|
1852
|
+
)
|
|
1853
|
+
);
|
|
1854
|
+
} catch (e) {
|
|
1855
|
+
return err5(e);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
);
|
|
1859
|
+
server2.tool(
|
|
1860
|
+
"hl_get_whale_directions",
|
|
1861
|
+
"Get whale position long/short counts",
|
|
1862
|
+
{
|
|
1863
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1864
|
+
},
|
|
1865
|
+
async ({ coin }) => {
|
|
1866
|
+
try {
|
|
1867
|
+
const params = {};
|
|
1868
|
+
if (coin) params.coin = coin;
|
|
1869
|
+
return ok5(
|
|
1870
|
+
await apiGet(
|
|
1871
|
+
"/api/v2/hl/whales/directions",
|
|
1872
|
+
params
|
|
1873
|
+
)
|
|
1874
|
+
);
|
|
1875
|
+
} catch (e) {
|
|
1876
|
+
return err5(e);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
);
|
|
1880
|
+
server2.tool(
|
|
1881
|
+
"hl_get_whale_history_long_ratio",
|
|
1882
|
+
"Get historical whale long/short ratio",
|
|
1883
|
+
{
|
|
1884
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1885
|
+
},
|
|
1886
|
+
async ({ coin }) => {
|
|
1887
|
+
try {
|
|
1888
|
+
const params = {};
|
|
1889
|
+
if (coin) params.coin = coin;
|
|
1890
|
+
return ok5(
|
|
1891
|
+
await apiGet(
|
|
1892
|
+
"/api/v2/hl/whales/history-long-ratio",
|
|
1893
|
+
params
|
|
1894
|
+
)
|
|
1895
|
+
);
|
|
1896
|
+
} catch (e) {
|
|
1897
|
+
return err5(e);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
);
|
|
1901
|
+
server2.tool(
|
|
1902
|
+
"hl_get_liquidation_stats",
|
|
1903
|
+
"Get Hyperliquid liquidation statistics",
|
|
1904
|
+
{},
|
|
1905
|
+
async () => {
|
|
1906
|
+
try {
|
|
1907
|
+
return ok5(
|
|
1908
|
+
await apiGet("/api/v2/hl/liquidations/stat")
|
|
1909
|
+
);
|
|
1910
|
+
} catch (e) {
|
|
1911
|
+
return err5(e);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
);
|
|
1915
|
+
server2.tool(
|
|
1916
|
+
"hl_get_liquidation_stats_by_coin",
|
|
1917
|
+
"Get liquidation statistics by coin",
|
|
1918
|
+
{
|
|
1919
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1920
|
+
},
|
|
1921
|
+
async ({ coin }) => {
|
|
1922
|
+
try {
|
|
1923
|
+
const params = {};
|
|
1924
|
+
if (coin) params.coin = coin;
|
|
1925
|
+
return ok5(
|
|
1926
|
+
await apiGet(
|
|
1927
|
+
"/api/v2/hl/liquidations/stat-by-coin",
|
|
1928
|
+
params
|
|
1929
|
+
)
|
|
1930
|
+
);
|
|
1931
|
+
} catch (e) {
|
|
1932
|
+
return err5(e);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
);
|
|
1936
|
+
server2.tool(
|
|
1937
|
+
"hl_get_liquidation_top_positions",
|
|
1938
|
+
"Get top liquidated positions",
|
|
1939
|
+
{
|
|
1940
|
+
coin: z5.string().optional().describe("Coin filter")
|
|
1941
|
+
},
|
|
1942
|
+
async ({ coin }) => {
|
|
1943
|
+
try {
|
|
1944
|
+
const params = {};
|
|
1945
|
+
if (coin) params.coin = coin;
|
|
1946
|
+
return ok5(
|
|
1947
|
+
await apiGet(
|
|
1948
|
+
"/api/v2/hl/liquidations/top-positions",
|
|
1949
|
+
params
|
|
1950
|
+
)
|
|
1951
|
+
);
|
|
1952
|
+
} catch (e) {
|
|
1953
|
+
return err5(e);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
);
|
|
1957
|
+
server2.tool(
|
|
1958
|
+
"hl_smart_find",
|
|
1959
|
+
"Discover smart money addresses on Hyperliquid",
|
|
1960
|
+
{
|
|
1961
|
+
params_json: z5.string().describe("Search params as JSON string")
|
|
1962
|
+
},
|
|
1963
|
+
async ({ params_json }) => {
|
|
1964
|
+
try {
|
|
1965
|
+
return ok5(
|
|
1966
|
+
await apiPost(
|
|
1967
|
+
"/api/v2/hl/smart/find",
|
|
1968
|
+
JSON.parse(params_json)
|
|
1969
|
+
)
|
|
1970
|
+
);
|
|
1971
|
+
} catch (e) {
|
|
1972
|
+
return err5(e);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
server2.tool(
|
|
1977
|
+
"hl_discover_traders",
|
|
1978
|
+
"Discover traders by criteria",
|
|
1979
|
+
{
|
|
1980
|
+
params_json: z5.string().describe("Discovery params as JSON string")
|
|
1981
|
+
},
|
|
1982
|
+
async ({ params_json }) => {
|
|
1983
|
+
try {
|
|
1984
|
+
return ok5(
|
|
1985
|
+
await apiPost(
|
|
1986
|
+
"/api/v2/hl/traders/discover",
|
|
1987
|
+
JSON.parse(params_json)
|
|
1988
|
+
)
|
|
1989
|
+
);
|
|
1990
|
+
} catch (e) {
|
|
1991
|
+
return err5(e);
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
);
|
|
1995
|
+
server2.tool(
|
|
1996
|
+
"hl_get_twap_states",
|
|
1997
|
+
"Get TWAP order states by address",
|
|
1998
|
+
{
|
|
1999
|
+
address: z5.string().describe("Wallet address")
|
|
2000
|
+
},
|
|
2001
|
+
async ({ address }) => {
|
|
2002
|
+
try {
|
|
2003
|
+
return ok5(
|
|
2004
|
+
await apiGet(
|
|
2005
|
+
`/api/v2/hl/twap-states/${address}/latest`
|
|
2006
|
+
)
|
|
2007
|
+
);
|
|
2008
|
+
} catch (e) {
|
|
2009
|
+
return err5(e);
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
);
|
|
2013
|
+
server2.tool(
|
|
2014
|
+
"hl_get_max_drawdown",
|
|
2015
|
+
"Get max drawdown data by address",
|
|
2016
|
+
{
|
|
2017
|
+
address: z5.string().describe("Wallet address")
|
|
2018
|
+
},
|
|
2019
|
+
async ({ address }) => {
|
|
2020
|
+
try {
|
|
2021
|
+
return ok5(
|
|
2022
|
+
await apiGet(
|
|
2023
|
+
`/api/v2/hl/max-drawdown/${address}`
|
|
2024
|
+
)
|
|
2025
|
+
);
|
|
2026
|
+
} catch (e) {
|
|
2027
|
+
return err5(e);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
);
|
|
2031
|
+
server2.tool(
|
|
2032
|
+
"hl_get_net_flow",
|
|
2033
|
+
"Get ledger net flow by address",
|
|
2034
|
+
{
|
|
2035
|
+
address: z5.string().describe("Wallet address")
|
|
2036
|
+
},
|
|
2037
|
+
async ({ address }) => {
|
|
2038
|
+
try {
|
|
2039
|
+
return ok5(
|
|
2040
|
+
await apiGet(
|
|
2041
|
+
`/api/v2/hl/ledger-updates/net-flow/${address}`
|
|
2042
|
+
)
|
|
2043
|
+
);
|
|
2044
|
+
} catch (e) {
|
|
2045
|
+
return err5(e);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
);
|
|
2049
|
+
server2.tool(
|
|
2050
|
+
"hl_get_klines_with_taker_vol",
|
|
2051
|
+
"Get K-line data with taker volume",
|
|
2052
|
+
{
|
|
2053
|
+
coin: z5.string().describe("Coin, e.g. BTC"),
|
|
2054
|
+
interval: z5.string().describe("Interval, e.g. 1h, 4h, 1d")
|
|
2055
|
+
},
|
|
2056
|
+
async ({ coin, interval }) => {
|
|
2057
|
+
try {
|
|
2058
|
+
return ok5(
|
|
2059
|
+
await apiGet(
|
|
2060
|
+
`/api/v2/hl/klines-with-taker-vol/${coin}/${interval}`
|
|
2061
|
+
)
|
|
2062
|
+
);
|
|
2063
|
+
} catch (e) {
|
|
2064
|
+
return err5(e);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
// src/tools/index.ts
|
|
2071
|
+
function registerAllTools(server2) {
|
|
2072
|
+
registerCoinTools(server2);
|
|
2073
|
+
registerContentTools(server2);
|
|
2074
|
+
registerMarketTools(server2);
|
|
2075
|
+
registerFeatureTools(server2);
|
|
2076
|
+
registerHyperliquidTools(server2);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
// src/index.ts
|
|
2080
|
+
var server = new McpServer({
|
|
2081
|
+
name: "aicoin-opendata",
|
|
2082
|
+
version: "1.0.0"
|
|
2083
|
+
});
|
|
2084
|
+
registerAllTools(server);
|
|
2085
|
+
var transport = new StdioServerTransport();
|
|
2086
|
+
await server.connect(transport);
|