bykaranteli-mcp 0.24.1 → 0.26.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/README.md CHANGED
@@ -1,20 +1,22 @@
1
1
  # bykaranteli-mcp
2
2
 
3
- MCP (Model Context Protocol) server for **live crypto derivatives data**: funding rates, cross-exchange funding arbitrage, open interest pressure, Fear & Greed, BTC dominance and a verified signal track record.
3
+ MCP (Model Context Protocol) server for **live crypto derivatives data**: funding rates, cross-exchange funding arbitrage, open interest pressure, liquidations, options, ETF flows, Fear & Greed and BTC dominance.
4
4
 
5
- 48 read-only tools over the free, no-auth public JSON API of [bykaranteli.com](https://bykaranteli.com/developers). No API key, no account, no rate-limit registration. Data covers Binance USDT-M perpetuals (funding arbitrage additionally compares OKX, Bybit, Gate, HTX, BingX, Kraken, MEXC and Bitget).
5
+ 45 read-only tools over the public JSON API of [bykaranteli.com](https://bykaranteli.com/developers). Since 2026-09-17 the API asks programs for an account key: a **free key** comes with any verified account at <https://bykaranteli.com/dashboard/api> (30 requests a minute, public depth), and the Builder, Business and Scale plans raise the rate and unlock member depth (LiqMap on seven timeframes, 5-minute series, the x402 catalog included). Set it as `BYKARANTELI_API_KEY`. Data covers Binance USDT-M perpetuals (funding arbitrage additionally compares OKX, Bybit, Gate, HTX, BingX, Kraken, MEXC and Bitget).
6
6
 
7
7
  ## Hosted endpoint (no install)
8
8
 
9
9
  Paste `https://mcp.bykaranteli.com` as a custom connector in any MCP-capable
10
- assistant. Same 48 tools, nothing to install, no key.
10
+ assistant. Same 45 tools, nothing to install. Without a key it runs on the
11
+ shared Free pool; a connector header `Authorization: Bearer bk_...` (Builder
12
+ and above) brings your own rate limit and member depth.
11
13
 
12
14
  ## Quick start
13
15
 
14
16
  ### Claude Code
15
17
 
16
18
  ```bash
17
- claude mcp add bykaranteli -- npx -y bykaranteli-mcp
19
+ claude mcp add bykaranteli -e BYKARANTELI_API_KEY=bk_... -- npx -y bykaranteli-mcp
18
20
  ```
19
21
 
20
22
  ### Claude Desktop
@@ -26,7 +28,8 @@ Add to `claude_desktop_config.json`:
26
28
  "mcpServers": {
27
29
  "bykaranteli": {
28
30
  "command": "npx",
29
- "args": ["-y", "bykaranteli-mcp"]
31
+ "args": ["-y", "bykaranteli-mcp"],
32
+ "env": { "BYKARANTELI_API_KEY": "bk_..." }
30
33
  }
31
34
  }
32
35
  }
@@ -34,7 +37,7 @@ Add to `claude_desktop_config.json`:
34
37
 
35
38
  ### Cursor / other MCP clients
36
39
 
37
- Any stdio MCP client works: command `npx`, args `["-y", "bykaranteli-mcp"]`.
40
+ Any stdio MCP client works: command `npx`, args `["-y", "bykaranteli-mcp"]`, env `BYKARANTELI_API_KEY`.
38
41
 
39
42
  Requires Node.js 18 or newer.
40
43
 
@@ -47,9 +50,6 @@ Requires Node.js 18 or newer.
47
50
  | `get_funding_arbitrage` | "Any funding arb opportunities?", "Best venue to long/short BTC for carry?" |
48
51
  | `get_pressure_scores` | "Which coins are over-leveraged / crowded right now?" |
49
52
  | `get_top_movers` | "Biggest OI spikes today?", "Most extreme funding right now?" |
50
- | `get_recent_signals` | "How did the signals do in the last 24h?" |
51
- | `get_symbol_performance` | "Win rate on ETHUSDT over 90 days?" |
52
- | `get_strategy_leaderboard` | "Which strategies are performing best?" |
53
53
  | `get_liquidations` | "How much was liquidated today?", "Did longs or shorts get flushed this week?" |
54
54
  | `get_etf_flows` | "Did the Bitcoin ETFs buy or sell yesterday?", "Cumulative ETH ETF inflow?" |
55
55
  | `get_cot_positioning` | "Are hedge funds long or short Bitcoin?", "What did the COT report show?" |
@@ -97,11 +97,12 @@ All responses are JSON and carry a `generatedAt` timestamp plus a `source` URL t
97
97
 
98
98
  | Env var | Default | Purpose |
99
99
  |---|---|---|
100
+ | `BYKARANTELI_API_KEY` | none | Account key (`bk_...`) sent as `Authorization: Bearer`. Free at <https://bykaranteli.com/dashboard/api>; required for programs from 2026-09-17 |
100
101
  | `BYKARANTELI_BASE_URL` | `https://bykaranteli.com` | Override the API host (testing only) |
101
102
 
102
103
  ## Data notes
103
104
 
104
- - Signal performance is a **live-only** track record: real published signals with SHA-256 receipts, evaluated net of fees, slippage and funding. Never backtests. Verify any signal at [bykaranteli.com/verify](https://bykaranteli.com/verify).
105
+ - The signal engine was retired in September 2026; this server publishes recorded market data only, no trading signals or performance claims.
105
106
  - Funding, OI and pressure data refresh every 15 to 30 minutes; indices every 30 minutes.
106
107
  - Nothing here is financial advice. See [bykaranteli.com/risk-guide](https://bykaranteli.com/risk-guide).
107
108
 
@@ -115,12 +116,20 @@ node dist/index.js # speaks MCP over stdio
115
116
 
116
117
  ## License
117
118
 
118
- MIT. Attribution appreciated: "ByKaranteli (bykaranteli.com)".
119
+ Server: MIT. Data: personal and research use with attribution "ByKaranteli (bykaranteli.com)"; commercial use with the Business plan. Licence text: <https://bykaranteli.com/data#license>.
119
120
 
120
- ## Paid depth (optional)
121
+ ## Plans and paid depth
121
122
 
122
- The 48 tools above are free and stay free. For recorded history and raw records
123
- beyond the live snapshots, bykaranteli.com also exposes pay-per-call x402
124
- endpoints (USDC on Solana or Base, priced per call, no account):
125
- <https://bykaranteli.com/developers#x402> · machine catalog:
126
- <https://bykaranteli.com/api/x402>
123
+ | Plan | Price | Rate | Depth |
124
+ |---|---|---|---|
125
+ | Free API | $0 | 30 / min | public pages |
126
+ | Builder | $49 / mo | 300 / min | member depth, x402 catalog included |
127
+ | Business | $149 / mo | 1,200 / min | member depth, commercial licence, monthly bulk |
128
+ | Scale | $399 / mo | 3,000 / min | member depth, derived redistribution, daily raw |
129
+
130
+ Full table: <https://bykaranteli.com/developers#tiers>. For recorded history and
131
+ raw records beyond the live snapshots, bykaranteli.com also exposes pay-per-call
132
+ x402 endpoints for anonymous agents (USDC on Solana or Base, priced per call,
133
+ no account): <https://bykaranteli.com/developers#x402> · machine catalog:
134
+ <https://bykaranteli.com/api/x402>. Builder and higher keys call those routes
135
+ unpaid within their plan limits.
package/dist/tools.d.ts CHANGED
@@ -15,5 +15,14 @@ export type RegisterOptions = {
15
15
  publicUrl?: string;
16
16
  /** Version string for the outbound user-agent. */
17
17
  version?: string;
18
+ /** Account API key (bk_...) sent as Authorization: Bearer on every fetch.
19
+ * Since 2026-09-17 the public API asks programs for one; a free key comes
20
+ * with any verified account (https://bykaranteli.com/dashboard/api) and paid
21
+ * plans raise the rate and unlock member depth. Falls back to the
22
+ * BYKARANTELI_API_KEY environment variable. */
23
+ apiKey?: string;
24
+ /** Per-call Authorization value, for hosts that forward their caller's key
25
+ * (the hosted endpoint). Takes precedence over apiKey when it returns one. */
26
+ authorizationProvider?: () => string | undefined;
18
27
  };
19
28
  export declare function registerByKaranteliTools(server: McpServer, options?: RegisterOptions): void;
package/dist/tools.js CHANGED
@@ -10,6 +10,13 @@ export function registerByKaranteliTools(server, options) {
10
10
  const PUBLIC_URL = (options?.publicUrl ?? process.env.BYKARANTELI_PUBLIC_URL ?? "https://bykaranteli.com").replace(/\/+$/, "");
11
11
  const USER_AGENT = `bykaranteli-mcp/${options?.version ?? "dev"} (+https://github.com/bykarantelicom/bykaranteli-mcp)`;
12
12
  const TIMEOUT_MS = 15_000;
13
+ const STATIC_KEY = (options?.apiKey ?? process.env.BYKARANTELI_API_KEY ?? "").trim();
14
+ const authorizationFor = () => {
15
+ const forwarded = options?.authorizationProvider?.();
16
+ if (forwarded)
17
+ return forwarded;
18
+ return STATIC_KEY ? `Bearer ${STATIC_KEY}` : undefined;
19
+ };
13
20
  // Read-only GET tools over an open-world public API, all of them.
14
21
  const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
15
22
  /** Invalid tool input (not a network problem): no retry hint in the error. */
@@ -19,9 +26,14 @@ export function registerByKaranteliTools(server, options) {
19
26
  const controller = new AbortController();
20
27
  const timer = setTimeout(() => controller.abort(new Error(`${path} timed out after ${TIMEOUT_MS / 1000}s`)), TIMEOUT_MS);
21
28
  try {
29
+ const authorization = authorizationFor();
22
30
  const res = await fetch(`${BASE_URL}${path}`, {
23
31
  signal: controller.signal,
24
- headers: { accept: "application/json", "user-agent": USER_AGENT },
32
+ headers: {
33
+ accept: "application/json",
34
+ "user-agent": USER_AGENT,
35
+ ...(authorization ? { authorization } : {}),
36
+ },
25
37
  });
26
38
  if (!res.ok) {
27
39
  /* Carry the route's own error body (audit P3 #412): "HTTP 400" alone
@@ -43,8 +55,6 @@ export function registerByKaranteliTools(server, options) {
43
55
  const PAGE_FOR_STEM = {
44
56
  "/borrow-rates": "/borrow",
45
57
  "/oi": "/oi-leaderboard",
46
- "/recent": "/signals",
47
- "/leaderboard": "/strategies",
48
58
  "/venues/markets": "/venues",
49
59
  "/venues/lead-lag": "/venues",
50
60
  "/venues/profile": "/venues",
@@ -379,78 +389,6 @@ export function registerByKaranteliTools(server, options) {
379
389
  return fail(err);
380
390
  }
381
391
  });
382
- server.registerTool("get_recent_signals", {
383
- title: "Recent closed trading signals with verified outcomes",
384
- description: "Call this when the user asks how the ByKaranteli signal engine is doing today, or wants recent closed LONG/SHORT signals with real outcomes (TP1, SL or TIMEOUT) and net basis-point results. Includes a 24h summary (wins, losses, net bps). Every signal is published with a SHA-256 receipt and results are net of fees, slippage and funding; live signals only, never backtests.",
385
- inputSchema: {},
386
- annotations: READ_ONLY,
387
- }, async () => {
388
- try {
389
- const d = (await fetchJson("/api/public/recent"));
390
- return ok({ ...d, source: `${PUBLIC_URL}/signals` });
391
- }
392
- catch (err) {
393
- return fail(err);
394
- }
395
- });
396
- server.registerTool("get_symbol_performance", {
397
- title: "Per-symbol signal performance and recent trades",
398
- description: "Call this when the user asks how signals performed on a specific coin (win rate, profit factor, net PnL, best/worst trade) or wants that coin's recent closed signals. Data is the live verified track record for one Binance USDT-M perp over a 30, 90 or 180 day window.",
399
- inputSchema: {
400
- symbol: z.string().describe("The symbol, e.g. BTCUSDT, or a coin name like BTC."),
401
- window_days: z
402
- .preprocess((v) => (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : v), z.number().int().min(1).max(365))
403
- .optional()
404
- .describe("Optional lookback window in days, 1 to 365 (the API accepts any integer in that range). Default 90."),
405
- },
406
- annotations: READ_ONLY,
407
- }, async ({ symbol, window_days }) => {
408
- try {
409
- const want = normalizeSymbol(symbol);
410
- const w = window_days ?? 90;
411
- let d;
412
- try {
413
- d = (await fetchJson(`/api/v1/public/symbols/${want}?window=${w}`));
414
- }
415
- catch (err) {
416
- // The API 404s when the symbol has no closed signals in the chosen
417
- // window (data-dependent, not an invalid request). Say so plainly.
418
- if (err instanceof Error && err.message.includes("HTTP 404")) {
419
- return ok({
420
- symbol: want,
421
- window_days: w,
422
- note: `No closed signals recorded for ${want} in the last ${w} days (or the symbol is not tracked). Try window_days: 180, or check ${PUBLIC_URL}/symbols/${want}.`,
423
- });
424
- }
425
- throw err;
426
- }
427
- // daily_points can be long; the stats + recent signals carry the answer.
428
- const daily = d.daily_points;
429
- return ok({
430
- ...d,
431
- daily_points: Array.isArray(daily) ? daily.slice(-30) : daily,
432
- daily_points_truncated: Array.isArray(daily) ? daily.length > 30 : false,
433
- source: `${PUBLIC_URL}/symbols/${want}`,
434
- });
435
- }
436
- catch (err) {
437
- return fail(err);
438
- }
439
- });
440
- server.registerTool("get_strategy_leaderboard", {
441
- title: "Strategy leaderboard with verified live results",
442
- description: "Call this when the user asks which trading strategies are performing best, or wants win rate, profit factor, drawdown and Sharpe per strategy. Rankings are computed from live closed signals only (no backtests), net of fees.",
443
- inputSchema: {},
444
- annotations: READ_ONLY,
445
- }, async () => {
446
- try {
447
- const d = (await fetchJson("/api/v1/public/leaderboard"));
448
- return ok({ ...d, source: `${PUBLIC_URL}/leaderboard` });
449
- }
450
- catch (err) {
451
- return fail(err);
452
- }
453
- });
454
392
  server.registerTool("get_cot_positioning", {
455
393
  title: "CME futures positioning (weekly COT report, BTC + ETH)",
456
394
  description: "Call this when the user asks how hedge funds or institutions are positioned in Bitcoin or Ethereum, or about the CFTC Commitments of Traders report. Returns net positions in contracts, week-over-week changes, open interest and notable extremes/streaks, from official CFTC data updated every Friday. Note: a large share of hedge fund shorts is the market-neutral basis trade, so the weekly change carries more signal than the level.",
@@ -823,7 +761,7 @@ export function registerByKaranteliTools(server, options) {
823
761
  server.registerTool("get_new_listings", {
824
762
  title: "New and delisted perpetual contracts",
825
763
  description: "Call this when the user asks what new perpetuals were listed, which exchange listed a coin first, or about delistings. Returns listings and delistings across six exchanges from the hourly scan.",
826
- inputSchema: { days: z.number().int().min(1).max(30).optional().describe("Window in days, 1-30 (default 30). Longer listing history is the paid x402 dataset.") },
764
+ inputSchema: { days: z.number().int().min(1).max(30).optional().describe("Window in days, 1-30 (default 30). Longer listing history is the listings dataset at bykaranteli.com/data.") },
827
765
  annotations: READ_ONLY,
828
766
  }, async (args) => {
829
767
  try {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bykaranteli-mcp",
3
- "version": "0.24.1",
4
- "description": "MCP server for live crypto derivatives data from bykaranteli.com: funding rates, funding arbitrage, open interest pressure, Fear & Greed, BTC dominance and verified signal performance. Free, no API key.",
3
+ "version": "0.26.0",
4
+ "description": "MCP server for live crypto derivatives data from bykaranteli.com: funding rates, funding arbitrage, open interest pressure, liquidations, options, ETF flows, Fear & Greed and BTC dominance. Free, no API key.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "bykaranteli-mcp": "dist/index.js"