@sharpe-terminal/mcp-server 1.4.0 → 1.6.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/dist/tools.js DELETED
@@ -1,1166 +0,0 @@
1
- import { z } from "zod";
2
- import { FUTURES_CHARTS } from "./resources.js";
3
- import { MAX_ITEMS, paginateRows, paginateSnapshotPayload, rowTimeMs, } from "./tool-runtime.js";
4
- // -- Tool schemas (Zod shapes for McpServer.tool()) --
5
- const FUTURES_CHART_IDS = FUTURES_CHARTS.map((chart) => chart.id);
6
- const pageCursorSchema = z
7
- .string()
8
- .optional()
9
- .describe("Pagination cursor returned by the previous page. Only meaningful alongside limit.");
10
- export const globalOverviewSchema = {
11
- tab: z
12
- .enum(["crypto", "equity", "preipo", "etf", "index", "commodity", "fx"])
13
- .default("crypto")
14
- .describe("Universe to return rows for. 'crypto' = crypto perps; the rest are RWA perp classes. The market-wide metric block is identical on every tab. The 'basket' asset class has no tab and is rejected."),
15
- limit: z
16
- .number()
17
- .int()
18
- .min(1)
19
- .max(1000)
20
- .optional()
21
- .describe("Rows per page (1-1000). A paged response is { data, pagination } holding only the ranked rows; the market-wide metric block comes back on unpaged calls. Responses are additionally capped at 200 items, so pass limit together with cursor to page through every row."),
22
- cursor: pageCursorSchema,
23
- };
24
- export const rwaPerpRatesSchema = {
25
- type: z
26
- .enum(["current", "history", "stats"])
27
- .default("current")
28
- .describe("Type of rwa-perp data. 'current' = latest funding/rollover snapshot per venue market, 'history' = session-tagged settlement time-series for one symbol (Hyperliquid + Kraken), 'stats' = best carry, top cross-venue spread, weekend premium, and tracked open interest."),
29
- symbol: z
30
- .string()
31
- .optional()
32
- .describe("Underlying equity ticker (e.g. TSLA, NVDA, MSTR). Required for type=history. GOOG (Ostium) and GOOGL (Hyperliquid/Kraken) are distinct share classes."),
33
- venue: z
34
- .string()
35
- .optional()
36
- .describe("Filter results to a single venue, e.g. Binance, Bybit, OKX, Bitget, Gate, Kraken, Coinbase, Aster, Lighter, Extended, GRVT, ApeX, Pacifica, Orderly, Ostium, Avantis, or a Hyperliquid HIP-3 builder market (Hyperliquid, Felix, Kinetiq, dreamcash, Paragon, Ventuals). Free-form because the venue list is registry-driven and grows."),
37
- days: z
38
- .number()
39
- .min(1)
40
- .max(90)
41
- .default(7)
42
- .optional()
43
- .describe("Days of settlement history to retrieve (type=history only). Range: 1-90."),
44
- limit: z
45
- .number()
46
- .int()
47
- .min(1)
48
- .max(5000)
49
- .optional()
50
- .describe("Rows per page for type=current and type=history (1-5000); a paged response is { data, pagination }. Responses are additionally capped at 200 items, so pass limit together with cursor to page through every row."),
51
- cursor: pageCursorSchema,
52
- };
53
- export const fundingRatesSchema = {
54
- type: z
55
- .enum(["current", "accumulated", "history"])
56
- .default("current")
57
- .describe("Type of funding rate data. 'current' = latest snapshot across exchanges, 'accumulated' = cumulative rates over 7d/30d/90d/1y, 'history' = time-series for a single coin."),
58
- coin: z
59
- .string()
60
- .optional()
61
- .describe("Coin ticker, lot spelling or full name (e.g. BTC, PEPE, 1000PEPE, kPEPE, bitcoin). Returns every contract of that asset across all exchanges, whatever its base_coin spelling: PEPE also returns the 1000PEPE and KPEPE lot contracts (read lot_multiplier). Required for type=history; optional for current/accumulated."),
62
- exchange: z
63
- .string()
64
- .optional()
65
- .describe("Filter to a single venue. Values are title case exactly as returned in the `exchange` field (e.g. Binance, Bybit, OKX, Gate.io, Hyperliquid, Kraken, Aster, Lighter, dYdX, Crypto.com, edgeX, tradeXYZ); lowercase slugs such as 'gate-io' also resolve. Free-form because the venue list is registry-driven and grows. Read sharpe://exchanges for the current list."),
66
- margin: z
67
- .enum(["linear", "inverse"])
68
- .optional()
69
- .describe("Collateral convention: 'linear' = quote-margined (USDT/USDC), 'inverse' = coin-margined. Unfiltered by default."),
70
- asset_class: z
71
- .enum(["crypto", "equity", "commodity", "fx", "index"])
72
- .optional()
73
- .describe("Underlying category of the perpetual. Unfiltered by default, so tokenized-equity, commodity, index and FX perps are returned alongside crypto; pass 'crypto' to rank crypto only."),
74
- days: z
75
- .number()
76
- .min(1)
77
- .max(1095)
78
- .default(30)
79
- .optional()
80
- .describe("Number of days of history to retrieve (type=history only). Range: 1-1095."),
81
- limit: z
82
- .number()
83
- .int()
84
- .min(1)
85
- .max(5000)
86
- .optional()
87
- .describe("Maximum rows to return. Responses are additionally capped at 200 items to protect the agent context window, so pass limit together with cursor to page through the whole book."),
88
- cursor: z
89
- .string()
90
- .optional()
91
- .describe("Pagination cursor returned by the previous page. Only meaningful alongside limit."),
92
- };
93
- export const fundingSettlementSchema = {
94
- window: z
95
- .enum(["current", "1d", "3d", "7d"])
96
- .default("current")
97
- .describe("Settlement window. 'current' is the next settlement, priced live off open interest and the forward-looking rate (predicted_rate when a venue publishes one, else the in-progress rate) -- always estimated, never realised yet. '1d'/'3d'/'7d' are realised windows; one whose coverage is below 90% carries partial: true in its window value because its history is still accruing, not a completed total."),
98
- class: z
99
- .enum(["all", "crypto", "rwa"])
100
- .default("all")
101
- .describe("Asset universe. 'rwa' = tokenized equity, commodity, FX and index perps. crypto + rwa always equal the all totals."),
102
- coin: z
103
- .string()
104
- .optional()
105
- .describe("Comma-separated base coin tickers (e.g. 'BTC' or 'BTC,ETH,SOL') to filter rows to. `totals` stays scoped to the selected class regardless of this filter -- read a filtered coin's own row for its number, not totals."),
106
- exchange: z
107
- .string()
108
- .optional()
109
- .describe("Keep only coins that have a contract on this venue. Each row's windows and open interest stay all-venue totals, not this venue's own figures. Free-form because the venue list is registry-driven and grows; an unresolvable value is rejected rather than silently returning an empty book."),
110
- limit: z
111
- .number()
112
- .int()
113
- .min(1)
114
- .max(1000)
115
- .optional()
116
- .describe("Maximum rows to return, in market-cap rank order (unranked coins follow alphabetically). Defaults to 100."),
117
- };
118
- export const futuresDataSchema = {
119
- chart: z
120
- .enum(FUTURES_CHART_IDS)
121
- .describe("Chart identifier. See sharpe://charts/futures for the valid IDs and descriptions."),
122
- coin: z
123
- .string()
124
- .default("BTC")
125
- .optional()
126
- .describe("Base coin ticker (e.g. BTC, ETH, SOL)."),
127
- timeframe: z
128
- .enum(["1W", "2W", "1M", "3M", "6M", "1Y", "3Y"])
129
- .default("3M")
130
- .optional()
131
- .describe("Lookback window for the data."),
132
- exchanges: z
133
- .string()
134
- .optional()
135
- .describe("Comma-separated list of exchanges to include (e.g. Binance,Bybit,OKX,Deribit,Hyperliquid)."),
136
- limit: z
137
- .number()
138
- .int()
139
- .min(1)
140
- .max(10000)
141
- .optional()
142
- .describe("Rows per page (1-10000), oldest first, returned with a pagination cursor. Paged rows are raw chart rows, oi-snapshot included. Responses are additionally capped at 200 items, so pass limit together with cursor to page through the full window."),
143
- cursor: pageCursorSchema,
144
- };
145
- export const futuresCoinsSchema = {};
146
- export const correlationMatrixSchema = {
147
- period: z
148
- .enum(["30d", "90d", "1y", "3y"])
149
- .default("30d")
150
- .optional()
151
- .describe("Lookback period for correlation calculation."),
152
- ids: z
153
- .string()
154
- .optional()
155
- .describe("Comma-separated asset IDs. Use CoinGecko IDs for crypto (e.g. bitcoin,ethereum) and Sharpe IDs for TradFi (e.g. sp500,gold,nvda). If omitted, returns the default mixed set."),
156
- };
157
- export const arbitrageSpotPerpSchema = {
158
- exchange: z
159
- .string()
160
- .default("all")
161
- .optional()
162
- .describe('Filter by exchange name (e.g. Binance, Bybit, OKX), or "all" for all exchanges.'),
163
- direction: z
164
- .enum(["all", "long", "short"])
165
- .default("all")
166
- .optional()
167
- .describe("Filter by perpetual-leg direction: short for positive funding capture, long for negative funding capture."),
168
- };
169
- export const arbitrageCrossExchangeSchema = {
170
- exchanges: z
171
- .string()
172
- .optional()
173
- .describe("Comma-separated list of venues to compare (e.g. Binance,Bybit,Hyperliquid). Omit for all 32 funding venues."),
174
- minOiUsd: z
175
- .number()
176
- .min(0)
177
- .optional()
178
- .describe("Minimum open interest in USD on the smaller leg. Legs with unknown OI fail the floor. Default 0 (no floor)."),
179
- minVolUsd: z
180
- .number()
181
- .min(0)
182
- .optional()
183
- .describe("Minimum 24h volume in USD on the smaller leg. Legs with unknown volume fail the floor. Default 0 (no floor)."),
184
- assetClass: z
185
- .enum(["all", "crypto", "rwa"])
186
- .optional()
187
- .describe('Underlying filter: "all" (default), "crypto", or "rwa" (equity, commodity, FX and index perps). Pairs never cross asset classes.'),
188
- };
189
- export const arbitrageScannerSchema = {
190
- coin: z
191
- .string()
192
- .optional()
193
- .describe("Optional base coin ticker, e.g. BTC, ETH, SOL."),
194
- exchanges: z
195
- .string()
196
- .optional()
197
- .describe("Comma-separated exchange filter, e.g. Binance,Bybit,OKX."),
198
- minApr: z
199
- .number()
200
- .optional()
201
- .describe("Minimum product-specific fee-adjusted net APR in percentage points."),
202
- minOiUsd: z
203
- .number()
204
- .min(0)
205
- .optional()
206
- .describe("Minimum open interest in USD."),
207
- minVolumeUsd: z
208
- .number()
209
- .min(0)
210
- .optional()
211
- .describe("Minimum 24-hour volume in USD."),
212
- minDepthUsd: z
213
- .number()
214
- .min(0)
215
- .optional()
216
- .describe("Minimum executable depth in USD when available."),
217
- marginType: z
218
- .enum(["linear", "inverse", "both"])
219
- .optional()
220
- .describe("Futures margin type filter."),
221
- notional: z
222
- .number()
223
- .positive()
224
- .default(10000)
225
- .optional()
226
- .describe("Position notional in USD. Default 10000."),
227
- limit: z
228
- .number()
229
- .int()
230
- .min(1)
231
- .max(1000)
232
- .default(100)
233
- .optional()
234
- .describe("Maximum number of rows to return."),
235
- cursor: z.string().optional().describe("Cursor for the next page."),
236
- };
237
- // The CEX spot-transfer route validates only these 7 fields; minOiUsd is
238
- // silently ignored there, so it is dropped from this dedicated schema.
239
- export const cexSpotTransferScannerSchema = {
240
- coin: arbitrageScannerSchema.coin,
241
- exchanges: arbitrageScannerSchema.exchanges,
242
- minApr: z
243
- .number()
244
- .optional()
245
- .describe("Minimum fee-adjusted transfer profit in percentage points (legacy parameter name)."),
246
- minDepthUsd: arbitrageScannerSchema.minDepthUsd,
247
- notional: arbitrageScannerSchema.notional,
248
- limit: arbitrageScannerSchema.limit,
249
- cursor: arbitrageScannerSchema.cursor,
250
- };
251
- export const heatmapSchema = {
252
- mode: z
253
- .enum(["coins", "narratives", "ecosystems"])
254
- .default("coins")
255
- .optional()
256
- .describe("Heatmap grouping mode."),
257
- category: z
258
- .string()
259
- .default("top-100")
260
- .optional()
261
- .describe("One of 34 category slugs (e.g. top-100, defi, layer-1, memes). The legacy top-100 slug returns the Top 50 universe."),
262
- };
263
- export const tokenScannerSchema = {
264
- mode: z
265
- .enum(["hot", "new-runners", "alpha-drops", "ai-top", "top-new"])
266
- .default("hot")
267
- .optional()
268
- .describe("Token scanner mode."),
269
- chains: z
270
- .string()
271
- .optional()
272
- .describe("Comma-separated Dexscreener chain IDs."),
273
- chain: z.string().optional().describe("Single chain for top-new mode."),
274
- profile: z
275
- .enum(["discovery", "balanced", "strict"])
276
- .optional()
277
- .describe("Scanner profile."),
278
- days: z.number().min(1).optional().describe("Top-new lookback in days."),
279
- limit: z.number().min(1).max(72).default(50).optional(),
280
- minLiquidityUsd: z.number().min(0).optional(),
281
- minVolumeH24: z.number().min(0).optional(),
282
- minTxnsH1: z.number().min(0).optional(),
283
- minTxnsH24: z.number().min(0).optional(),
284
- maxAgeHours: z.number().min(0).optional(),
285
- includeUnknownAge: z.boolean().optional(),
286
- sortBy: z.enum(["score", "readiness", "rs", "volume", "momentum"]).optional(),
287
- minBreakoutReadiness: z.number().min(0).optional(),
288
- minRelativeStrength: z.number().optional(),
289
- maxVolLiqRatio: z.number().min(0).optional(),
290
- minPriceChangeH1: z.number().optional(),
291
- };
292
- export const rugCheckSecuritySchema = {
293
- address: z.string().describe("Token contract address."),
294
- chainId: z
295
- .number()
296
- .int()
297
- .positive()
298
- .describe("EVM chain ID (1 Ethereum, 56 BNB Smart Chain, 8453 Base, 42161 Arbitrum, 137 Polygon, 10 Optimism, 43114 Avalanche, 146 Sonic, 80094 Berachain, and 29 more), or 1399811149 for Solana and 728126428 for Tron. An unsupported chain returns 400."),
299
- };
300
- export const rugCheckTrendingSchema = {
301
- limit: z.number().min(1).max(100).default(50).optional(),
302
- };
303
- export const stablecoinsSchema = {
304
- type: z
305
- .enum(["overview", "detail", "yields"])
306
- .default("overview")
307
- .optional()
308
- .describe("Payload type."),
309
- slug: z.string().optional().describe("Stablecoin slug for detail mode."),
310
- };
311
- export const mindshareSchema = {
312
- tokens: z
313
- .enum(["true", "false"])
314
- .optional()
315
- .describe("Set to true for token rows."),
316
- narrative: z.string().optional().describe("Optional narrative slug."),
317
- historical: z
318
- .enum(["true", "false"])
319
- .optional()
320
- .describe("Set to true for historical snapshots."),
321
- timeframe: z
322
- .enum(["1W", "1M", "3M", "6M", "1Y", "3Y"])
323
- .optional()
324
- .describe("Historical timeframe."),
325
- window: z
326
- .enum(["now", "24h", "7d", "30d"])
327
- .optional()
328
- .describe("Rolling snapshot window."),
329
- };
330
- export const webTrafficSchema = {
331
- type: z
332
- .enum(["exchange", "coin", "narrative"])
333
- .optional()
334
- .describe("Entity type."),
335
- mode: z
336
- .enum(["rankings", "snapshots", "market"])
337
- .optional()
338
- .describe("Payload mode."),
339
- tf: z
340
- .enum(["7d", "30d", "90d", "1y", "3y", "all"])
341
- .optional()
342
- .describe("Lookback window."),
343
- entities: z.string().optional().describe("Comma-separated entity IDs."),
344
- sub: z
345
- .enum(["trending", "categories", "global"])
346
- .optional()
347
- .describe("Market sub-mode when mode=market."),
348
- };
349
- export const narrativesSchema = {
350
- narrative: z
351
- .string()
352
- .optional()
353
- .describe("Narrative to filter by, as the id the API matches (layer-1, layer-2, defi, ai-agents, defai, depin, desci, gaming, dex, cex, lending, memes, nfts, oracles, privacy, rwa, stablecoins, restaking, liquid-staking, modular, socialfi, intent, prediction-markets, perps, bridges, account-abstraction, tap-to-earn, telegram-apps, zk, yield-farming). Page slugs such as dex-tokens or cex-tokens return no coins; use dex or cex. Omit for all narratives."),
354
- correlation: z
355
- .string()
356
- .optional()
357
- .describe('Set to "true" to include correlation data between the narrative\'s tokens.'),
358
- timeframe: z.string().optional().describe("Timeframe for correlation data."),
359
- };
360
- export const ecosystemsSchema = {
361
- ecosystem: z
362
- .string()
363
- .optional()
364
- .describe("Ecosystem to filter by, as the id the API matches (e.g. ethereum, solana, bnb, arbitrum, base, bitcoin, avalanche, optimism, cosmos, polkadot, sui, aptos, ton, tron); read sharpe://ecosystems for all of them. Page slugs such as bnb-chain or toncoin return no coins; use bnb or ton. Omit for all ecosystems."),
365
- excludeNative: z
366
- .string()
367
- .optional()
368
- .describe('Set to "true" to exclude the native token from aggregated metrics (e.g. exclude ETH from Ethereum ecosystem stats).'),
369
- correlation: z
370
- .string()
371
- .optional()
372
- .describe('Set to "true" to include correlation data between the ecosystem\'s tokens.'),
373
- timeframe: z.string().optional().describe("Timeframe for correlation data."),
374
- };
375
- export const memecoinsSchema = {
376
- narrative: z
377
- .string()
378
- .optional()
379
- .describe("Memecoin narrative slug (e.g. dog-coins, cat-coins, frog-coins, ai-memes, trump-coins). Omit for all narratives."),
380
- historical: z
381
- .enum(["24h", "7d", "30d", "1y"])
382
- .optional()
383
- .describe("Include historical time-series data for the specified window."),
384
- coinHistory: z
385
- .enum(["24h", "7d", "1m", "1y"])
386
- .optional()
387
- .describe("In narrative detail mode, include top-coin price history."),
388
- };
389
- export const memecoinLaunchesSchema = {
390
- chains: z
391
- .string()
392
- .optional()
393
- .describe("Comma-separated chain ids, e.g. solana,base,bsc,ethereum."),
394
- days: z.number().min(1).max(30).optional().describe("Launch age window."),
395
- limit: z.number().min(1).max(200).optional().describe("Maximum rows."),
396
- profile: z
397
- .enum(["discovery", "balanced", "strict"])
398
- .optional()
399
- .describe("Screening profile for liquidity, volume, and transaction gates."),
400
- };
401
- export const newsSchema = {
402
- limit: z
403
- .number()
404
- .min(1)
405
- .max(500)
406
- .default(200)
407
- .optional()
408
- .describe("Maximum number of articles to return (1-500)."),
409
- category: z
410
- .string()
411
- .optional()
412
- .describe("Filter by news category. Accepted: all, crypto, tradfi, macro, geopolitics, research, ai."),
413
- coin: z
414
- .string()
415
- .optional()
416
- .describe("Filter by canonical coin slug (e.g. bitcoin, ethereum, solana)."),
417
- since: z
418
- .string()
419
- .optional()
420
- .describe("ISO 8601 timestamp. Only return articles published after this time."),
421
- q: z
422
- .string()
423
- .trim()
424
- .min(1)
425
- .max(200)
426
- .optional()
427
- .describe("Search article titles across the stored news corpus."),
428
- offset: z
429
- .number()
430
- .int()
431
- .min(0)
432
- .optional()
433
- .describe("Offset for pagination; skip this many articles before returning results."),
434
- };
435
- export const marketOverviewSchema = {};
436
- export const pricePredictionSchema = {
437
- coin: z
438
- .string()
439
- .optional()
440
- .describe("Ticker or canonical coin slug (e.g. BTC, bitcoin, solana). Omit for all coins."),
441
- };
442
- export const searchMarketCapSchema = {
443
- q: z
444
- .string()
445
- .min(2)
446
- .max(100)
447
- .describe("Crypto or supported TradFi asset name/symbol (2-100 characters)."),
448
- };
449
- export const gemFinderSchema = {
450
- limit: z
451
- .number()
452
- .min(1)
453
- .max(1000)
454
- .default(100)
455
- .optional()
456
- .describe("Maximum number of tokens to return (1-1000)."),
457
- cursor: z
458
- .string()
459
- .optional()
460
- .describe("Snapshot-bound pagination cursor returned by the previous Gem Finder page."),
461
- };
462
- export const derivativesOverviewSchema = {};
463
- export const apiCoverageSchema = {};
464
- const listingExchangeIds = [
465
- "binance",
466
- "okx",
467
- "bybit",
468
- "gateio",
469
- "mexc",
470
- "bitget",
471
- "kucoin",
472
- "bingx",
473
- "bitmart",
474
- "deepcoin",
475
- "coinbase",
476
- "kraken",
477
- "crypto_com",
478
- "upbit",
479
- "bithumb",
480
- "htx",
481
- "bitfinex",
482
- "bitstamp",
483
- "gemini",
484
- "bitmex",
485
- "deribit",
486
- "phemex",
487
- "lbank",
488
- "bitrue",
489
- "coinex",
490
- "backpack",
491
- "hashkey",
492
- "whitebit",
493
- "toobit",
494
- "hyperliquid",
495
- "aster",
496
- "dydx",
497
- "aevo",
498
- ];
499
- // /listings/data validates only the legacy compatibility venues
500
- // (legacyListingExchangeIds in src/lib/api/schemas.ts) and 400s the rest;
501
- // the recent/events feeds accept every id in listingExchangeIds.
502
- const legacyListingExchangeIds = [
503
- "binance",
504
- "okx",
505
- "bybit",
506
- "gateio",
507
- "mexc",
508
- ];
509
- export const listingsDataSchema = {
510
- narrative: z
511
- .string()
512
- .optional()
513
- .describe("Filter to a single narrative slug (e.g. 'ai-agents', 'memes', 'layer-1', 'rwa', 'defi'). Uses the Sharpe narrative taxonomy."),
514
- exchange: z
515
- .enum(legacyListingExchangeIds)
516
- .optional()
517
- .describe("Filter to a single exchange. The aggregate hub covers the compatibility venues only; use get_recent_listings or get_listing_events for the other venues."),
518
- };
519
- export const listingsRecentSchema = {
520
- narrative: z
521
- .string()
522
- .optional()
523
- .describe("Filter to a single narrative slug."),
524
- exchange: z
525
- .enum(listingExchangeIds)
526
- .optional()
527
- .describe("Filter to a single exchange."),
528
- venue_type: z
529
- .enum(["cex", "perp_dex", "dex"])
530
- .optional()
531
- .describe("Optional event-feed venue filter."),
532
- market_type: z
533
- .enum(["spot", "perp", "futures", "options", "margin"])
534
- .optional()
535
- .describe("Optional event-feed market filter."),
536
- event_type: z
537
- .enum(["listing", "delisting", "suspension", "resumption", "prelaunch"])
538
- .optional()
539
- .describe("Optional event type filter. Defaults remain recent listings."),
540
- asset_class: z
541
- .enum([
542
- "token",
543
- "spot_pair",
544
- "perp_contract",
545
- "futures_contract",
546
- "options_contract",
547
- ])
548
- .optional()
549
- .describe("Optional event-feed asset-class filter."),
550
- status: z
551
- .enum([
552
- "announced",
553
- "scheduled",
554
- "live",
555
- "completed",
556
- "cancelled",
557
- "needs_review",
558
- ])
559
- .optional()
560
- .describe("Optional event status filter."),
561
- confidence: z
562
- .enum(["authoritative", "high", "medium", "low", "proxy", "manual"])
563
- .optional()
564
- .describe("Optional source confidence filter."),
565
- from: z.string().optional().describe("ISO date/datetime lower bound."),
566
- to: z.string().optional().describe("ISO date/datetime upper bound."),
567
- days: z
568
- .number()
569
- .int()
570
- .min(1)
571
- .max(365)
572
- .default(90)
573
- .optional()
574
- .describe("Lookback window in days. Default 90."),
575
- limit: z
576
- .number()
577
- .int()
578
- .min(1)
579
- .max(1000)
580
- .default(200)
581
- .optional()
582
- .describe("Max rows returned. Default 200."),
583
- cursor: z
584
- .string()
585
- .optional()
586
- .describe("Cursor returned by event feed pages."),
587
- };
588
- export const listingsEventsSchema = {
589
- exchange: z
590
- .enum(listingExchangeIds)
591
- .optional()
592
- .describe("Filter to a single exchange or perp DEX."),
593
- venue_type: z
594
- .enum(["cex", "perp_dex", "dex"])
595
- .optional()
596
- .describe("Filter by venue type."),
597
- market_type: z
598
- .enum(["spot", "perp", "futures", "options", "margin"])
599
- .optional()
600
- .describe("Filter by market type."),
601
- event_type: z
602
- .enum(["listing", "delisting", "suspension", "resumption", "prelaunch"])
603
- .optional()
604
- .describe("Filter by listing lifecycle event type."),
605
- asset_class: z
606
- .enum([
607
- "token",
608
- "spot_pair",
609
- "perp_contract",
610
- "futures_contract",
611
- "options_contract",
612
- ])
613
- .optional()
614
- .describe("Filter by listed instrument class."),
615
- status: z
616
- .enum([
617
- "announced",
618
- "scheduled",
619
- "live",
620
- "completed",
621
- "cancelled",
622
- "needs_review",
623
- ])
624
- .optional()
625
- .describe("Filter by event status."),
626
- narrative: z.string().optional().describe("Filter by Sharpe narrative slug."),
627
- confidence: z
628
- .enum(["authoritative", "high", "medium", "low", "proxy", "manual"])
629
- .optional()
630
- .describe("Filter by source confidence."),
631
- from: z.string().optional().describe("ISO date/datetime lower bound."),
632
- to: z.string().optional().describe("ISO date/datetime upper bound."),
633
- days: z
634
- .number()
635
- .int()
636
- .min(1)
637
- .max(365)
638
- .default(90)
639
- .optional()
640
- .describe("Lookback window in days. Default 90."),
641
- limit: z
642
- .number()
643
- .int()
644
- .min(1)
645
- .max(1000)
646
- .default(200)
647
- .optional()
648
- .describe("Max rows returned. Default 200."),
649
- cursor: z.string().optional().describe("Cursor for the next page."),
650
- };
651
- export const listingsExchangesSchema = {
652
- venue_type: z
653
- .enum(["cex", "perp_dex", "dex"])
654
- .optional()
655
- .describe("Filter exchange coverage by venue type."),
656
- market_type: z
657
- .enum(["spot", "perp", "futures", "options", "margin"])
658
- .optional()
659
- .describe("Filter exchange coverage by supported market type."),
660
- enabled: z
661
- .enum(["true", "false"])
662
- .optional()
663
- .describe("Filter to enabled or disabled connectors."),
664
- };
665
- export const signalScoreSchema = {
666
- limit: z
667
- .number()
668
- .int()
669
- .min(1)
670
- .max(500)
671
- .default(100)
672
- .optional()
673
- .describe("Maximum number of scored coins to return. Default 100."),
674
- min_score: z
675
- .number()
676
- .min(0)
677
- .max(10)
678
- .default(0)
679
- .optional()
680
- .describe("Minimum 0-10 risk/pressure score to include."),
681
- };
682
- // get_pump_dump adds a manipulation-lifecycle phase filter on top of the shared
683
- // signal-score params. get_insider_selling stays on signalScoreSchema (no phase).
684
- // Fields are listed explicitly (not spread from signalScoreSchema) so the docs and
685
- // closed-loop schema-field parsers can see limit/min_score/phase.
686
- export const pumpDumpSchema = {
687
- limit: z
688
- .number()
689
- .int()
690
- .min(1)
691
- .max(500)
692
- .default(100)
693
- .optional()
694
- .describe("Maximum number of scored coins to return. Default 100."),
695
- min_score: z
696
- .number()
697
- .min(0)
698
- .max(10)
699
- .default(0)
700
- .optional()
701
- .describe("Minimum 0-10 risk/pressure score to include."),
702
- phase: z
703
- .enum(["setup", "markup", "distribution", "dump", "dumping"])
704
- .optional()
705
- .describe("Filter to one manipulation lifecycle phase."),
706
- };
707
- // -- Keyless-path post-processing helpers --
708
- function isRecord(value) {
709
- return value !== null && typeof value === "object" && !Array.isArray(value);
710
- }
711
- function cursorArg(args) {
712
- return typeof args.cursor === "string" && args.cursor
713
- ? args.cursor
714
- : undefined;
715
- }
716
- /**
717
- * The stored `manipulation_phase` values a public phase param selects.
718
- * Mirrors resolvePhaseFilter in src/app/api/v1/pump-dump/data/route.ts.
719
- */
720
- function resolvePhaseFilter(phase) {
721
- if (!phase)
722
- return null;
723
- if (phase === "dumping")
724
- return ["distribution", "dump-risk"];
725
- if (phase === "dump")
726
- return ["dump-risk"];
727
- return [phase];
728
- }
729
- /**
730
- * The free pump-dump and insider-selling routes are statically cached and
731
- * read no query params, so limit, min_score and phase only ever reached v1
732
- * (2026-09-24 audit). Re-apply them to the keyless `{ scores, meta }` payload
733
- * the way the v1 routes do: score floor, phase mapping, then limit over the
734
- * score-ordered rows. The v1 payload (`{ coins, ... }`) is already filtered.
735
- */
736
- export function filterSignalScores(data, args) {
737
- if (!isRecord(data) || !Array.isArray(data.scores))
738
- return data;
739
- const minScore = typeof args.min_score === "number" ? args.min_score : 0;
740
- const limit = typeof args.limit === "number" ? args.limit : 100;
741
- const phases = resolvePhaseFilter(typeof args.phase === "string" ? args.phase : undefined);
742
- const scores = data.scores
743
- .filter((row) => {
744
- if (!isRecord(row) || typeof row.score !== "number")
745
- return false;
746
- if (row.score < minScore)
747
- return false;
748
- return phases === null || phases.includes(String(row.manipulation_phase));
749
- })
750
- .slice(0, limit);
751
- return { ...data, scores };
752
- }
753
- /**
754
- * oi-snapshot is documented as current open interest by exchange, but both
755
- * routes return the whole ascending window (up to 5,000 raw rows). Keep each
756
- * exchange's newest reading, largest first, so "current" means current.
757
- */
758
- export function latestRowPerExchange(rows) {
759
- const latest = new Map();
760
- for (const row of rows) {
761
- const at = rowTimeMs(row);
762
- if (!isRecord(row) || at == null)
763
- continue;
764
- const exchange = String(row.exchange ?? "");
765
- const prev = latest.get(exchange);
766
- if (!prev || at >= prev.at)
767
- latest.set(exchange, { row, at });
768
- }
769
- const oiOf = (row) => {
770
- const value = Number(row.open_interest_value);
771
- return Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
772
- };
773
- return [...latest.values()]
774
- .map((entry) => entry.row)
775
- .sort((a, b) => oiOf(b) - oiOf(a));
776
- }
777
- /**
778
- * The rows of a funding response that belong to `coin`. The funding API
779
- * resolves `coin` to an asset and returns every contract of it, so `PEPE`
780
- * also returns the 1000PEPE and KPEPE lot contracts, whose base_coin differs.
781
- * A row is kept when its base_coin, asset_symbol or asset_id names the coin,
782
- * or when it is a contract of the same asset as a row that does
783
- * (`coin=1000PEPE` keeps the PEPE-spelled contracts too). Rows from an API
784
- * without the asset fields, or with them null (no instrument master to read),
785
- * match on base_coin exactly as before.
786
- */
787
- export function rowsForFundingCoin(rows, coin) {
788
- const needle = coin.trim().toUpperCase();
789
- const text = (row, key) => {
790
- const value = row !== null && typeof row === "object"
791
- ? row[key]
792
- : undefined;
793
- return typeof value === "string" ? value : null;
794
- };
795
- const names = (row) => [
796
- text(row, "base_coin") ?? text(row, "coin"),
797
- text(row, "asset_symbol"),
798
- text(row, "asset_id"),
799
- ].some((value) => value?.toUpperCase() === needle);
800
- const assets = new Set(rows
801
- .filter(names)
802
- .map((row) => text(row, "asset_id"))
803
- .filter((assetId) => assetId !== null));
804
- return rows.filter((row) => {
805
- const assetId = text(row, "asset_id");
806
- return names(row) || (assetId !== null && assets.has(assetId));
807
- });
808
- }
809
- export const TOOL_DEFS = [
810
- {
811
- name: "get_global_overview",
812
- description: "Get the whole-market derivatives board in one call: total open interest with its crypto-versus-RWA split, 24h liquidations, average Wilder RSI(14) across the top 100 crypto perps by market cap, the Altcoin Season Index (share of the top 50 by market cap beating BTC over 90 days, excluding stablecoins and wrapped/staked derivatives), open interest broken down by asset class, and a ranked per-asset row table. The tab parameter selects the universe: crypto, equity, preipo, etf, index, commodity or fx. Rows carry price, 24h price change, funding rate (interval-true, never assumed 8h), 24h volume, market cap, open interest with 1h and 24h changes, plus liquidations on crypto or a venue count on RWA tabs. Ranks are by open interest descending. Liquidations are crypto-only because no RWA venue publishes a liquidation feed. Use this for 'what is the market doing' questions; use get_funding_rates for per-venue crypto funding detail and get_rwa_perp_funding for RWA carry and cross-venue spreads.",
813
- schema: globalOverviewSchema,
814
- apiPath: "/api/v1/global/overview",
815
- fallbackPath: "/api/global/overview",
816
- // The free route ignores limit/cursor and always returns every row with
817
- // the metric block. Page its rows into the v1 paged shape ({ data,
818
- // pagination }, rows only) so a keyless caller can reach all of them.
819
- postProcess: (data, args, context) => {
820
- if (context?.paginated || typeof args.limit !== "number")
821
- return data;
822
- if (!isRecord(data) || !Array.isArray(data.rows))
823
- return data;
824
- return paginateRows(data.rows, args.limit, cursorArg(args));
825
- },
826
- },
827
- {
828
- name: "get_rwa_perp_funding",
829
- description: "Get funding and carry for real-world-asset perpetuals (RWA perps: stocks, pre-IPO, ETFs, indices, commodities, FX) across 19 venues: CEXs (Binance, Bybit, OKX, Bitget, Gate, Kraken xStocks, Coinbase INTX), perp DEXs (Aster, Lighter, Extended, GRVT, ApeX, Pacifica, Orderly), Hyperliquid HIP-3 builder markets, and the rollover venues Ostium and Avantis. Rates are interval-true and mechanism-true: funding_apr annualizes each venue's own settlement interval (never an assumed 8h), and a both-sides rollover is reported separately as borrow_apr_annual (a cost, never mixed into funding spreads). Marks more than 2% off the cross-venue median are flagged is_price_suspect and excluded from stats and spreads. type=history returns session-tagged settlements (market/after_hours/weekend/holiday); type=stats returns best carry, top cross-venue spread, weekend premium, and open interest.",
830
- schema: rwaPerpRatesSchema,
831
- apiPath: "/api/v1/rwa-perps/rates",
832
- fallbackPath: "/api/rwa-perps/rates",
833
- // The free route returns current/history rows as a bare array and
834
- // ignores limit/cursor; page it the way v1 does. type=stats is an object
835
- // and passes through.
836
- postProcess: (data, args, context) => {
837
- if (context?.paginated || typeof args.limit !== "number")
838
- return data;
839
- if (!Array.isArray(data))
840
- return data;
841
- return paginateRows(data, args.limit, cursorArg(args));
842
- },
843
- },
844
- {
845
- name: "get_funding_rates",
846
- description: "Get perpetual funding rates across every supported venue (see sharpe://exchanges for the current list). Returns current snapshots, accumulated rates over multiple windows, or per-coin historical rates. Units: `rate` is a decimal fraction settled over that row's own `interval_hours` (1h, 2h, 4h, 8h or 24h depending on venue and market). It is not a percent and never implicitly 8h, so annualize with rate * (8760 / interval_hours) before comparing or ranking venues. Accumulated rows carry realized sums (acc_1d/acc_7d/acc_30d/acc_90d/acc_1y) instead of a per-interval rate. Filter with coin, exchange, margin (linear/inverse) and asset_class; asset_class is unfiltered by default, so tokenized-equity, commodity, index and FX perps are included alongside crypto. `coin` names an asset: PEPE returns every PEPE contract, the 1000PEPE and KPEPE lot contracts included. Current and accumulated rows carry asset_id, asset_symbol, lot_multiplier (asset units per contract unit, e.g. 1000 on 1000PEPEUSDT), instrument_status (the venue's own status) and is_live (null = unknown). Page the full book with limit and cursor.",
847
- schema: fundingRatesSchema,
848
- apiPath: "/api/v1/funding/rates",
849
- fallbackPath: "/api/funding/rates",
850
- // The unpaged book is ~13,000 rows (6MB) of which MAX_ITEMS survive
851
- // truncation: page it server-side instead, so the rows come with a cursor
852
- // (0.3s instead of 1.8s, 2026-09-26). A coin filter or history is small.
853
- prepareArgs: (args) => args.limit == null && args.coin == null && args.type !== "history"
854
- ? { ...args, limit: MAX_ITEMS }
855
- : args,
856
- // Both funding endpoints narrow by `coin` server-side. This client-side
857
- // pass is a belt-and-braces guard so a coin-scoped request can never be
858
- // reduced to an arbitrary alphabetical prefix by MAX_ITEMS truncation.
859
- postProcess: (data, args) => {
860
- const coin = args.coin;
861
- const type = args.type;
862
- if (typeof coin !== "string" || coin === "" || type === "history") {
863
- return data;
864
- }
865
- if (!Array.isArray(data)) {
866
- return data;
867
- }
868
- return rowsForFundingCoin(data, coin);
869
- },
870
- },
871
- {
872
- name: "get_funding_settlement",
873
- description: "Get the dollar value of funding actually paid at each settlement -- not just the rate -- and which side, longs or shorts, paid it. Every response carries both the per-coin row breakdown and a totals block (net/long_paid/short_paid) for the requested window and class, so 'who paid funding today' is read directly from totals rather than summed from a page of rows; totals always reflects the full requested class regardless of any coin/exchange filter on the rows. window=current (the default) is the next settlement, priced live off open interest and the forward-looking rate -- always estimated, never realised. 1d/3d/7d are realised windows; one whose coverage is below 90% carries partial: true because its history is still accruing, not a completed total. Sign convention: a window's net = long_paid - short_paid; positive means longs paid more than they received (a cost to longs), negative means shorts paid more. Both long_paid and short_paid are always non-negative magnitudes. Missing is null, never 0. class splits crypto perps from RWA perps (tokenized equity, commodity, FX, index); crypto + rwa totals always equal the all totals.",
874
- schema: fundingSettlementSchema,
875
- apiPath: "/api/v1/funding/settlement",
876
- fallbackPath: "/api/funding/settlement",
877
- // The v1 payload nests rows/totals/settlementMeta inside the envelope's
878
- // `data` field; the free fallback puts the row array directly under
879
- // `data` with `totals` riding alongside it (api-client.ts preserves that
880
- // sibling instead of discarding it). Normalize both shapes into one
881
- // `{ rows, totals, meta }` result so callers never branch on which tier
882
- // answered, and `totals` is always the API's own aggregate -- never
883
- // recomputed from a possibly-truncated page of rows.
884
- postProcess: (data) => {
885
- if (!data || typeof data !== "object" || Array.isArray(data)) {
886
- return data;
887
- }
888
- const obj = data;
889
- const result = {
890
- rows: obj.rows ?? obj.data,
891
- totals: obj.totals,
892
- };
893
- const meta = obj.settlementMeta ?? obj.meta;
894
- if (meta !== undefined)
895
- result.meta = meta;
896
- return result;
897
- },
898
- },
899
- {
900
- name: "get_futures_data",
901
- description: "Get futures chart data including open interest, volume, funding rate history, liquidations, long/short ratios, basis, term structure, and OHLCV. Time series are oldest-first; when one exceeds the response cap its newest rows are kept (truncated_fields marks kept: latest). Without limit, oi-snapshot returns each exchange's latest reading; pass limit/cursor to page raw rows oldest-first.",
902
- schema: futuresDataSchema,
903
- apiPath: "/api/v1/futures/data",
904
- fallbackPath: "/api/futures/data",
905
- postProcess: (data, args, context) => {
906
- if (context?.paginated || !isRecord(data) || !Array.isArray(data.data)) {
907
- return data;
908
- }
909
- if (typeof args.limit === "number") {
910
- // The free route ignores limit/cursor: page the same oldest-first
911
- // rows v1 pages.
912
- return {
913
- ...data,
914
- ...paginateRows(data.data, args.limit, cursorArg(args)),
915
- };
916
- }
917
- if (args.chart === "oi-snapshot") {
918
- return { ...data, data: latestRowPerExchange(data.data) };
919
- }
920
- return data;
921
- },
922
- },
923
- {
924
- name: "get_futures_coins",
925
- description: "Get up to 1,000 coins with futures data, including funding, open-interest, liquidation, long/short, CVD, and dated-basis capability flags plus observed venue coverage and market-cap rank.",
926
- schema: futuresCoinsSchema,
927
- apiPath: "/api/v1/futures/coins",
928
- fallbackPath: "/api/futures/coins",
929
- },
930
- {
931
- name: "get_correlation_matrix",
932
- description: "Get a price correlation matrix for crypto and supported TradFi assets over a specified calendar period. Useful for portfolio analysis and diversification.",
933
- schema: correlationMatrixSchema,
934
- apiPath: "/api/v1/correlation/matrix",
935
- fallbackPath: "/api/correlation/matrix",
936
- },
937
- {
938
- name: "get_arbitrage_spot_perp",
939
- description: "Get structurally executable spot-perpetual funding-capture rows with live funding, verified spot or margin availability, diagnostic basis, gross APR, and fee-adjusted net APR.",
940
- schema: arbitrageSpotPerpSchema,
941
- apiPath: "/api/v1/arbitrage/spot-perp",
942
- fallbackPath: "/api/arbitrage/spot-perp",
943
- },
944
- {
945
- name: "get_arbitrage_cross_exchange",
946
- description: "Get cross-exchange funding arbitrage across every funding venue and asset class (crypto plus RWA perps: equity, commodity, FX, index — pairs never cross classes), ranked with executable rows (book-priced netApr) first by netApr, then indicative rows by gross annualized funding differential (apr); pairs whose two legs' prices differ by more than 20% are indicative (likely different instruments). Spread uses real books where available (spreadSource: book) or reference prices (reference); netApr is present only on book-priced rows; unknown spread/OI/volume are null, never zero.",
947
- schema: arbitrageCrossExchangeSchema,
948
- apiPath: "/api/v1/arbitrage/cross-exchange",
949
- fallbackPath: "/api/arbitrage/cross-exchange",
950
- },
951
- {
952
- name: "get_arbitrage_dated_futures_basis",
953
- description: "Get cash-and-carry arbitrage rows for buying spot and selling dated futures, ranked by net annualized basis after fees.",
954
- schema: arbitrageScannerSchema,
955
- apiPath: "/api/v1/arbitrage/dated-futures-basis",
956
- fallbackPath: "/api/arbitrage/dated-futures-basis",
957
- },
958
- {
959
- name: "get_arbitrage_futures_calendar_spread",
960
- description: "Get near-versus-far dated futures calendar spread rows with forward yield, curve direction, and net roll APY.",
961
- schema: arbitrageScannerSchema,
962
- apiPath: "/api/v1/arbitrage/futures-calendar-spread",
963
- fallbackPath: "/api/arbitrage/futures-calendar-spread",
964
- },
965
- {
966
- name: "get_arbitrage_perp_dated_carry",
967
- description: "Get perp funding versus dated futures basis carry rows, comparing expected funding to expiry against locked dated basis.",
968
- schema: arbitrageScannerSchema,
969
- apiPath: "/api/v1/arbitrage/perp-dated-carry",
970
- fallbackPath: "/api/arbitrage/perp-dated-carry",
971
- },
972
- {
973
- name: "get_arbitrage_cex_spot_transfer",
974
- description: "Get live CEX spot-transfer arbitrage rows after common network and token-contract matching, fee, status, depth, slippage, and spread-lifetime checks.",
975
- schema: cexSpotTransferScannerSchema,
976
- apiPath: "/api/v1/arbitrage/cex-spot-transfer",
977
- fallbackPath: "/api/arbitrage/cex-spot-transfer",
978
- },
979
- {
980
- name: "get_heatmap",
981
- description: "Get market heatmap data for coins, narratives, or ecosystems. The legacy top-100 slug returns the Top 50 universe; aggregate modes expose complete or partial category coverage.",
982
- schema: heatmapSchema,
983
- apiPath: "/api/v1/heatmap/data",
984
- fallbackPath: "/api/heatmap/data",
985
- },
986
- {
987
- name: "get_token_scanner",
988
- description: "Run read-only token scanner modes for hot tokens, new runners, alpha drops, AI tokens, and top-new pairs. Responses expose source coverage; valuation and risk fields stay null when unavailable. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
989
- schema: tokenScannerSchema,
990
- apiPath: "/api/v1/token-scanner/scan",
991
- fallbackPath: "/api/v1/token-scanner/scan",
992
- },
993
- {
994
- name: "get_rug_check_security",
995
- description: "Get rug-check token contract security and liquidity risk signals.",
996
- schema: rugCheckSecuritySchema,
997
- apiPath: "/api/v1/rug-check/security",
998
- fallbackPath: "/api/rug-check/security",
999
- },
1000
- {
1001
- name: "get_rug_check_trending",
1002
- description: "Get trending tokens suitable for rug-check review.",
1003
- schema: rugCheckTrendingSchema,
1004
- apiPath: "/api/v1/rug-check/trending",
1005
- fallbackPath: "/api/rug-check/trending",
1006
- },
1007
- {
1008
- name: "get_narratives",
1009
- description: "Get narrative-level market data (L1, L2, DeFi, AI Agents, DePIN, RWA, Gaming, etc.) including market cap, volume, performance, and social metrics.",
1010
- schema: narrativesSchema,
1011
- apiPath: "/api/v1/narratives/data",
1012
- fallbackPath: "/api/narratives/data",
1013
- },
1014
- {
1015
- name: "get_ecosystems",
1016
- description: "Get ecosystem-level market data (Ethereum, Solana, BNB, Arbitrum, Base, etc.) including market cap, volume, TVL, and performance metrics.",
1017
- schema: ecosystemsSchema,
1018
- apiPath: "/api/v1/ecosystems/data",
1019
- fallbackPath: "/api/ecosystems/data",
1020
- },
1021
- {
1022
- name: "get_memecoins",
1023
- description: "Get memecoin narrative data across grouped categories (Dog, Cat, Frog, AI, Solana, Base, Pump.fun, etc.) with market cap, market share, volume, performance, and freshness fields.",
1024
- schema: memecoinsSchema,
1025
- apiPath: "/api/v1/memecoins/data",
1026
- fallbackPath: "/api/memecoins/data",
1027
- },
1028
- {
1029
- name: "get_memecoin_launches",
1030
- description: "Get recently launched tokens from recognized memecoin launchpads, screened by age, liquidity, volume, and transactions. Generic new DEX pairs are excluded; response includes complete/partial chain coverage.",
1031
- schema: memecoinLaunchesSchema,
1032
- apiPath: "/api/v1/memecoins/launches",
1033
- fallbackPath: "/api/memecoins/launches",
1034
- },
1035
- {
1036
- name: "get_stablecoins",
1037
- description: "Get stablecoin overview, detail, or yield data including nominal supply at peg, marked value, nullable peg metrics, mechanism mix, chain supply, velocity coverage, freshness, and APY risk flags. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
1038
- schema: stablecoinsSchema,
1039
- apiPath: "/api/v1/stablecoins/data",
1040
- fallbackPath: "/api/v1/stablecoins/data",
1041
- },
1042
- {
1043
- name: "get_mindshare",
1044
- description: "Get narrative mindshare rankings, token-level attention rows, rolling windows, or historical mindshare snapshots.",
1045
- schema: mindshareSchema,
1046
- apiPath: "/api/v1/mindshare/data",
1047
- fallbackPath: "/api/mindshare/data",
1048
- },
1049
- {
1050
- name: "get_web_traffic",
1051
- description: "Get attention rankings, social snapshots, or market-level signals for coins and narratives, plus CoinGecko trust-score rankings for exchanges.",
1052
- schema: webTrafficSchema,
1053
- apiPath: "/api/v1/web-traffic/data",
1054
- fallbackPath: "/api/web-traffic/data",
1055
- },
1056
- {
1057
- name: "get_news",
1058
- description: "Get aggregated crypto news articles from multiple sources, with optional title search and filtering by category or coin. Articles are deduplicated so only the best source per story is shown.",
1059
- schema: newsSchema,
1060
- apiPath: "/api/v1/news/feed",
1061
- fallbackPath: "/api/news/feed",
1062
- },
1063
- {
1064
- name: "get_market_overview",
1065
- description: "Get BTC and ETH price/change, total crypto market cap and 24h volume, BTC dominance, market-cap change, and the Fear & Greed Index. Auxiliary source fields may be null when unavailable.",
1066
- schema: marketOverviewSchema,
1067
- apiPath: "/api/v1/tracker/market-overview",
1068
- fallbackPath: "/api/tracker/market-overview",
1069
- },
1070
- {
1071
- name: "get_price_prediction",
1072
- description: "Get deterministic directional scores and sub-signal breakdowns for a coin. Optional 7D/30D values are volatility-scaled heuristic scenarios, not calibrated targets or probabilities.",
1073
- schema: pricePredictionSchema,
1074
- apiPath: "/api/v1/price-prediction/data",
1075
- fallbackPath: "/api/price-prediction/data",
1076
- },
1077
- {
1078
- name: "search_market_cap",
1079
- description: "Search crypto and supported TradFi assets by name or ticker. Returns matching assets with asset class, market cap, and nullable price, 24h change, FDV, ATH, and estimated ATH market cap fields.",
1080
- schema: searchMarketCapSchema,
1081
- apiPath: "/api/v1/market-cap/search",
1082
- fallbackPath: "/api/market-cap/search",
1083
- },
1084
- {
1085
- name: "get_gem_finder",
1086
- description: "Get market-ranked token rows with market cap, volume, price and market-cap change, circulating supply, ATH and ATL history, nullable FDV/MCap, the preferred chain plus every supported chain the asset is deployed on (chainSlugs), observed exchange availability, quote freshness, and enrichment coverage. Delisted or halted markets whose upstream quote is over 24 hours old are excluded rather than reporting a weeks-old price change as current. Ambiguous same-ticker assets do not receive symbol-only exchange attribution. No wallet signal or proprietary score is returned.",
1087
- schema: gemFinderSchema,
1088
- apiPath: "/api/v1/gem-finder/data",
1089
- fallbackPath: "/api/gem-finder/data",
1090
- postProcess: (data, args) => {
1091
- // Authenticated v1 calls are already an array with pagination reattached
1092
- // by the runtime. The free fallback returns the complete cache payload,
1093
- // so apply the same snapshot-bound paging semantics client-side.
1094
- if (!data ||
1095
- typeof data !== "object" ||
1096
- Array.isArray(data) ||
1097
- !Array.isArray(data.coins)) {
1098
- return data;
1099
- }
1100
- const limit = typeof args.limit === "number" && Number.isInteger(args.limit)
1101
- ? args.limit
1102
- : 100;
1103
- const cursor = typeof args.cursor === "string" ? args.cursor : undefined;
1104
- return paginateSnapshotPayload(data, limit, cursor);
1105
- },
1106
- },
1107
- {
1108
- name: "get_derivatives_overview",
1109
- description: "Get a derivatives market overview including aggregated open interest, 8-hour-equivalent funding rates, top coins by open interest, and exchange/coin counts. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
1110
- schema: derivativesOverviewSchema,
1111
- apiPath: "/api/v1/market/derivatives-overview",
1112
- fallbackPath: "/api/v1/market/derivatives-overview",
1113
- },
1114
- {
1115
- name: "get_api_coverage",
1116
- description: "Get public metadata about what data is available across all Sharpe Terminal products, including supported exchanges, coins, timeframes, and chart types. This coverage endpoint does not require an API key.",
1117
- schema: apiCoverageSchema,
1118
- apiPath: "/api/v1/meta/coverage",
1119
- fallbackPath: "/api/v1/meta/coverage",
1120
- },
1121
- {
1122
- name: "get_exchange_listings",
1123
- description: "Get the New Listings hub payload: weekly + monthly aggregated counts by narrative and exchange, plus the last-90-day recent listings. Optionally filter by narrative slug or single exchange. Useful for tracking where venues are adding listing slots.",
1124
- schema: listingsDataSchema,
1125
- apiPath: "/api/v1/listings/data",
1126
- fallbackPath: "/api/listings/data",
1127
- },
1128
- {
1129
- name: "get_recent_listings",
1130
- description: "Get a flat feed of recent token listings. Defaults remain backward-compatible with the legacy spot listing feed. Event filters add source-observation freshness, partial status, and provider coverage so agents can reject incomplete opportunity scans.",
1131
- schema: listingsRecentSchema,
1132
- apiPath: "/api/v1/listings/recent",
1133
- fallbackPath: "/api/listings/recent",
1134
- },
1135
- {
1136
- name: "get_listing_events",
1137
- description: "Get canonical listing lifecycle events across CEXs and Perp DEXs, including source URLs, confidence, real source-observation freshness, partial status, and per-provider coverage. Pass the opaque cursor through unchanged.",
1138
- schema: listingsEventsSchema,
1139
- apiPath: "/api/v1/listings/events",
1140
- fallbackPath: "/api/listings/events",
1141
- },
1142
- {
1143
- name: "get_listing_exchanges",
1144
- description: "Get the typed listing connector registry, including supported exchanges, venue types, market coverage, source documentation URLs, enabled status, polling group, and parser confidence.",
1145
- schema: listingsExchangesSchema,
1146
- apiPath: "/api/v1/listings/exchanges",
1147
- fallbackPath: "/api/listings/exchanges",
1148
- },
1149
- {
1150
- name: "get_insider_selling",
1151
- description: "Get insider selling pressure signals across crypto assets. Scores require cross-venue negative funding and combine OI, basis, CVD, sell-side flow, and supporting wallet/supply context; read signal_coverage_pct because partial-input scores are conservative lower bounds.",
1152
- schema: signalScoreSchema,
1153
- apiPath: "/api/v1/insider-selling/data",
1154
- fallbackPath: "/api/insider-selling/data",
1155
- postProcess: filterSignalScores,
1156
- },
1157
- {
1158
- name: "get_pump_dump",
1159
- description: "Get pump-and-dump manipulation risk signals across crypto assets. Scores combine derivatives pressure, holder concentration, liquidity quality, DEX flow, and price behavior; read signal_coverage_pct because partial-input scores are conservative lower bounds.",
1160
- schema: pumpDumpSchema,
1161
- apiPath: "/api/v1/pump-dump/data",
1162
- fallbackPath: "/api/pump-dump/data",
1163
- postProcess: filterSignalScores,
1164
- },
1165
- ];
1166
- //# sourceMappingURL=tools.js.map