bykaranteli-mcp 0.35.0 → 0.35.1
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/CHANGELOG.md +10 -0
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +21 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to the `bykaranteli-mcp` package. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Dates are UTC and come from the git tag of each release (the version commit where no tag exists). The tool count is the number of tools the server registers in that release.
|
|
4
4
|
|
|
5
|
+
## [0.35.1] - 2026-10-11
|
|
6
|
+
|
|
7
|
+
67 tools.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Every tool carries `annotations.title`, the same text as its top-level `title`: directory portals (the Claude Connectors Directory among them) read the display name there. The read-only, destructive, idempotent and open-world hints are unchanged.
|
|
12
|
+
- Descriptions name plans, not keys: depth and limits follow the account's plan whether the client signed in with OAuth or sends an account key (`get_liqmap`, `get_series`, `get_options_chain`, `get_solana_perps`, the account tools).
|
|
13
|
+
- `get_series` returns the newest 300 bars when neither `from` nor `limit` is given (Builder and higher plans received 1,000 by default, 64,700 characters for price); `limit` and `from`/`to` still return up to 5,000.
|
|
14
|
+
|
|
5
15
|
## [0.35.0] - 2026-10-11
|
|
6
16
|
|
|
7
17
|
67 tools.
|
package/dist/tools.d.ts
CHANGED
|
@@ -25,4 +25,4 @@ export type RegisterOptions = {
|
|
|
25
25
|
* (the hosted endpoint). Takes precedence over apiKey when it returns one. */
|
|
26
26
|
authorizationProvider?: () => string | undefined;
|
|
27
27
|
};
|
|
28
|
-
export declare function registerByKaranteliTools(
|
|
28
|
+
export declare function registerByKaranteliTools(target: McpServer, options?: RegisterOptions): void;
|
package/dist/tools.js
CHANGED
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod/v4";
|
|
8
8
|
import { buildProvenance, pageForApiPath } from "./provenance.js";
|
|
9
|
-
export function registerByKaranteliTools(
|
|
9
|
+
export function registerByKaranteliTools(target, options) {
|
|
10
|
+
const withTitle = (def) => def.title && !(def.annotations && "title" in def.annotations) ? { ...def, annotations: { ...(def.annotations ?? {}), title: def.title } } : def;
|
|
11
|
+
const server = {
|
|
12
|
+
registerTool: (name, def, handler) => target.registerTool.call(target, name, withTitle(def), handler),
|
|
13
|
+
};
|
|
10
14
|
const BASE_URL = (options?.baseUrl ?? process.env.BYKARANTELI_BASE_URL ?? "https://bykaranteli.com").replace(/\/+$/, "");
|
|
11
15
|
const PUBLIC_URL = (options?.publicUrl ?? process.env.BYKARANTELI_PUBLIC_URL ?? "https://bykaranteli.com").replace(/\/+$/, "");
|
|
12
16
|
const USER_AGENT = `bykaranteli-mcp/${options?.version ?? "dev"} (+https://github.com/bykarantelicom/bykaranteli-mcp)`;
|
|
@@ -1152,7 +1156,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1152
1156
|
});
|
|
1153
1157
|
server.registerTool("get_liqmap", {
|
|
1154
1158
|
title: "LiqMap: estimated liquidation clusters with real prints overlaid",
|
|
1155
|
-
description: "Call this when the user asks where liquidation clusters or liquidity pools sit for a perpetual, where leveraged longs/shorts would get liquidated, or for a liquidation heatmap reading. Returns the LiqMap snapshot for one symbol: modeled liquidation levels by price, zone aggregates and real liquidation prints from every liquidation venue ByKaranteli counts (listed on bykaranteli.com/coverage).
|
|
1159
|
+
description: "Call this when the user asks where liquidation clusters or liquidity pools sit for a perpetual, where leveraged longs/shorts would get liquidated, or for a liquidation heatmap reading. Returns the LiqMap snapshot for one symbol: modeled liquidation levels by price, zone aggregates and real liquidation prints from every liquidation venue ByKaranteli counts (listed on bykaranteli.com/coverage). On the Free plan the 24h view; on Builder and higher plans every timeframe from 1h to 30d. By default the 30 real levels nearest the price and the 30 newest real prints; pass detail=true for all of them.",
|
|
1156
1160
|
inputSchema: {
|
|
1157
1161
|
symbol: z
|
|
1158
1162
|
.string()
|
|
@@ -1164,7 +1168,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1164
1168
|
timeframe: z
|
|
1165
1169
|
.enum(["1h", "4h", "12h", "24h", "3d", "1w", "30d"])
|
|
1166
1170
|
.optional()
|
|
1167
|
-
.describe("Model window. Default 24h, the only one
|
|
1171
|
+
.describe("Model window. Default 24h, the only one on the Free plan; Builder and higher plans get every window."),
|
|
1168
1172
|
detail: z.boolean().optional().describe("Optional. true: every real level and every real print (default false: the 30 nearest levels, the 30 newest prints)."),
|
|
1169
1173
|
},
|
|
1170
1174
|
annotations: READ_ONLY,
|
|
@@ -1484,12 +1488,12 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1484
1488
|
});
|
|
1485
1489
|
server.registerTool("get_options_chain", {
|
|
1486
1490
|
title: "Options chain hour by hour: open interest and IV per expiry and strike, the change over 1h and 24h, the ATM IV path",
|
|
1487
|
-
description: "Call this when the user asks how the BTC or ETH option chain moved today or over the last day: open interest and mark IV per expiry and strike from ByKaranteli's own hourly capture of every listed venue, the change over the last hour and the last 24 hours, and the front expiry's ATM IV hour by hour.
|
|
1491
|
+
description: "Call this when the user asks how the BTC or ETH option chain moved today or over the last day: open interest and mark IV per expiry and strike from ByKaranteli's own hourly capture of every listed venue, the change over the last hour and the last 24 hours, and the front expiry's ATM IV hour by hour. The Free plan lists the largest strikes; Builder and higher plans list every strike. Recorded from 2026-09-30, so the first days carry a short history.",
|
|
1488
1492
|
inputSchema: {
|
|
1489
1493
|
currency: z.enum(["BTC", "ETH"]).optional().describe("BTC or ETH (default BTC)"),
|
|
1490
1494
|
venue: z.enum(["all", "deribit", "bybit", "binance", "okx", "delta"]).optional().describe("One venue or all (default all)"),
|
|
1491
1495
|
expiry: z.string().trim().toUpperCase().regex(/^\d{1,2}[A-Z]{3}\d{2}$/).optional().describe("Expiry as DDMONYY, e.g. 31OCT26 (default: every expiry)"),
|
|
1492
|
-
strikes: z.enum(["top", "all"]).optional().describe("top (largest strikes) or all (
|
|
1496
|
+
strikes: z.enum(["top", "all"]).optional().describe("top (largest strikes) or all (Builder and higher plans)"),
|
|
1493
1497
|
},
|
|
1494
1498
|
annotations: READ_ONLY,
|
|
1495
1499
|
}, async ({ currency, venue, expiry, strikes }) => {
|
|
@@ -1588,7 +1592,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1588
1592
|
});
|
|
1589
1593
|
server.registerTool("get_solana_perps", {
|
|
1590
1594
|
title: "Solana Perps board: open interest, 24h volume and hourly rates across six Solana perpetual venues (Jupiter, Pacifica, Phoenix, GM Trade, Velocity, Bullet)",
|
|
1591
|
-
description: "Call this when the user asks about perpetuals on Solana as a whole, which Solana perp DEX has the most open interest or volume, a market on Pacifica, Phoenix, GM Trade (GMX on Solana), Velocity (the Drift relaunch) or Bullet (funding, open interest, 24h volume, mark), or how Jupiter compares with the order-book venues. Returns the board read every 10 minutes: per-venue totals (one-sided open interest, both sides on pool venues, 24h volume, market count, median hourly rate, as_of), every market of every venue largest first with instrument type (perpetual, equity, index, commodity, fx), and optional hourly history of one market on any venue but Jupiter (7 days
|
|
1595
|
+
description: "Call this when the user asks about perpetuals on Solana as a whole, which Solana perp DEX has the most open interest or volume, a market on Pacifica, Phoenix, GM Trade (GMX on Solana), Velocity (the Drift relaunch) or Bullet (funding, open interest, 24h volume, mark), or how Jupiter compares with the order-book venues. Returns the board read every 10 minutes: per-venue totals (one-sided open interest, both sides on pool venues, 24h volume, market count, median hourly rate, as_of), every market of every venue largest first with instrument type (perpetual, equity, index, commodity, fx), and optional hourly history of one market on any venue but Jupiter (7 days on the Free plan, 30 on Builder and higher plans; Jupiter history is get_jupiter_perps). Without venue, the 30 largest markets; pass venue, or limit (up to 300) for more.",
|
|
1592
1596
|
inputSchema: {
|
|
1593
1597
|
venue: z.string().trim().toLowerCase().regex(/^(jupiter|pacifica|phoenix|gmtrade|velocity|bullet)$/).optional().describe("Venue filter: jupiter, pacifica, phoenix, gmtrade, velocity or bullet"),
|
|
1594
1598
|
/* Passed as typed: Pacifica and Phoenix list mixed-case markets (kBONK, kPEPE, kSHIB) and the route matches the
|
|
@@ -1779,7 +1783,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1779
1783
|
/* ---- 0.31.0: recorded series, alert text, alert recipes, watchlists ---- */
|
|
1780
1784
|
server.registerTool("get_series", {
|
|
1781
1785
|
title: "Recorded series: bars or points of one metric for one perpetual (price, OI, funding, CVD, liquidations, long/short, RSI and more)",
|
|
1782
|
-
description: `Call this when the user wants the history of one recorded metric for one perpetual as a time series: price candles, volume, perp or spot CVD, open interest, funding (one venue, or OI-weighted across every venue as funding_agg), liquidations, long/short ratios, RSI, the Coinbase premium, US spot ETF flows, borrow rates or Hyperliquid whale net flow, for charting, backtesting or "what did X do over the last N days". Returns the /api/series answer (points as [t, v], or [t, o, h, l, c, v] for price, with unit, kind, source and source_kind, the bars served and whether member depth applied) plus provenance. metric is one of: ${SERIES_METRIC_KEYS.join(", ")} (unit, finest period and venue support of each: https://bykaranteli.com/api/series/metrics).
|
|
1786
|
+
description: `Call this when the user wants the history of one recorded metric for one perpetual as a time series: price candles, volume, perp or spot CVD, open interest, funding (one venue, or OI-weighted across every venue as funding_agg), liquidations, long/short ratios, RSI, the Coinbase premium, US spot ETF flows, borrow rates or Hyperliquid whale net flow, for charting, backtesting or "what did X do over the last N days". Returns the /api/series answer (points as [t, v], or [t, o, h, l, c, v] for price, with unit, kind, source and source_kind, the bars served and whether member depth applied) plus provenance. metric is one of: ${SERIES_METRIC_KEYS.join(", ")} (unit, finest period and venue support of each: https://bykaranteli.com/api/series/metrics). The Free plan gets public depth: fewer bars and no bars under 15 minutes (1m, 3m, 5m, 10m); Builder and higher plans get member depth; the bar limits are in the same list. The answer names the venue it was read from (venue) and every venue a market-wide series sums (venues). Without from or limit, the newest 300 bars; pass from and to (ISO) for a window, or limit for more of the newest bars.`,
|
|
1783
1787
|
inputSchema: {
|
|
1784
1788
|
metric: z.string().describe("string, metric key, e.g. price, oi, funding, liquidations (list: /api/series/metrics)"),
|
|
1785
1789
|
symbol: z.string().optional().describe("string, optional Binance USDT-M perp or coin, e.g. BTCUSDT or BTC (default BTCUSDT)"),
|
|
@@ -1787,7 +1791,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1787
1791
|
venue: z.string().optional().describe("string, optional venue id for price, oi, funding or borrow, e.g. okx (default binance)"),
|
|
1788
1792
|
from: z.string().optional().describe("string, optional ISO start, e.g. 2026-09-01T00:00:00Z"),
|
|
1789
1793
|
to: z.string().optional().describe("string, optional ISO end (default now)"),
|
|
1790
|
-
limit: z.number().optional().describe(`number, optional newest bars, 10..${SERIES_MEMBER_BAR_LIMIT}; the
|
|
1794
|
+
limit: z.number().optional().describe(`number, optional newest bars, 10..${SERIES_MEMBER_BAR_LIMIT}; the plan's depth caps it (default 300 without from)`),
|
|
1791
1795
|
},
|
|
1792
1796
|
annotations: READ_ONLY,
|
|
1793
1797
|
}, async (args = {}) => {
|
|
@@ -1809,6 +1813,9 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1809
1813
|
const bars = from ? Math.ceil((end.getTime() - from.getTime()) / PERIOD_MS[period]) : undefined;
|
|
1810
1814
|
if (bars !== undefined)
|
|
1811
1815
|
limit = Math.min(limit ?? bars, bars);
|
|
1816
|
+
/* 0.35.1: the newest 300 bars when neither from nor limit is given (the route gives members 1000 by default). */
|
|
1817
|
+
if (limit === undefined)
|
|
1818
|
+
limit = 300;
|
|
1812
1819
|
if (limit !== undefined)
|
|
1813
1820
|
limit = Math.max(10, Math.min(SERIES_MEMBER_BAR_LIMIT, limit));
|
|
1814
1821
|
const q = new URLSearchParams({ metric, symbol, period });
|
|
@@ -1839,7 +1846,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1839
1846
|
});
|
|
1840
1847
|
server.registerTool("list_alert_recipes", {
|
|
1841
1848
|
title: "Your alert recipes: every alert on your account with its conditions, scope, channels and when it last fired",
|
|
1842
|
-
description: "Call this when the user asks which alerts they have, whether an alert fired, or before deleting or changing one. Returns the account's alert recipes (id, name, scope, symbols, conditions, cooldown in hours, enabled, last fired, fire count, channels). Needs
|
|
1849
|
+
description: "Call this when the user asks which alerts they have, whether an alert fired, or before deleting or changing one. Returns the account's alert recipes (id, name, scope, symbols, conditions, cooldown in hours, enabled, last fired, fire count, channels). Needs a signed-in account (OAuth sign-in or account key); reads nothing but this account.",
|
|
1843
1850
|
inputSchema: {},
|
|
1844
1851
|
annotations: ACCOUNT_READ,
|
|
1845
1852
|
}, async () => {
|
|
@@ -1848,7 +1855,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1848
1855
|
});
|
|
1849
1856
|
server.registerTool("create_alert_recipe", {
|
|
1850
1857
|
title: "Create an alert recipe (writes to your account)",
|
|
1851
|
-
description: `Call this when the user asks to be alerted when a metric crosses a threshold and has agreed to the exact condition (parse_alert_text turns their words into one). Saves an alert recipe on the account: it fires when every condition holds, delivers by Telegram first with email as fallback unless channels says otherwise, and waits cooldown_hours before it fires again for the same symbol. field is one of: ${RECIPE_FIELD_KEYS.join(", ")}; op is one of ${RECIPE_OPS.join(" ")}; percent fields take percent values (0.05 means 0.05%). Pass field, op and threshold for one condition, or conditions for up to ${RECIPE_LIMITS.MAX_CONDITIONS}. scope: watchlist (default), any, or symbols with symbols. The plan sets how many recipes an account keeps; past it the tool answers with the limit. Writes are rate limited per key and each one is recorded on the account.`,
|
|
1858
|
+
description: `Call this when the user asks to be alerted when a metric crosses a threshold and has agreed to the exact condition (parse_alert_text turns their words into one). Saves an alert recipe on the account: it fires when every condition holds, delivers by Telegram first with email as fallback unless channels says otherwise, and waits cooldown_hours before it fires again for the same symbol. field is one of: ${RECIPE_FIELD_KEYS.join(", ")}; op is one of ${RECIPE_OPS.join(" ")}; percent fields take percent values (0.05 means 0.05%). Pass field, op and threshold for one condition, or conditions for up to ${RECIPE_LIMITS.MAX_CONDITIONS}. scope: watchlist (default), any, or symbols with symbols. The plan sets how many recipes an account keeps; past it the tool answers with the limit. Writes are rate limited per connection (sign-in or key) and each one is recorded on the account.`,
|
|
1852
1859
|
inputSchema: {
|
|
1853
1860
|
field: z.string().optional().describe("string, one condition's metric, e.g. funding_rate_pct"),
|
|
1854
1861
|
op: z.enum(RECIPE_OPS).optional().describe(`string, one condition's comparison: ${RECIPE_OPS.join(" | ")}`),
|
|
@@ -1910,7 +1917,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1910
1917
|
});
|
|
1911
1918
|
server.registerTool("delete_alert_recipe", {
|
|
1912
1919
|
title: "Delete one of your alert recipes (writes to your account)",
|
|
1913
|
-
description: "Call this when the user asks to remove an alert. Deletes the alert recipe with this id from the account (list_alert_recipes shows the ids); an id that is not one of the account's recipes changes nothing and says so. Writes are rate limited per key and each one is recorded on the account.",
|
|
1920
|
+
description: "Call this when the user asks to remove an alert. Deletes the alert recipe with this id from the account (list_alert_recipes shows the ids); an id that is not one of the account's recipes changes nothing and says so. Writes are rate limited per connection (sign-in or key) and each one is recorded on the account.",
|
|
1914
1921
|
inputSchema: {
|
|
1915
1922
|
id: z.string().describe("string, the recipe id from list_alert_recipes"),
|
|
1916
1923
|
},
|
|
@@ -1928,7 +1935,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1928
1935
|
});
|
|
1929
1936
|
server.registerTool("list_watchlists", {
|
|
1930
1937
|
title: "Your watchlists and the symbols on each",
|
|
1931
|
-
description: "Call this when the user asks what is on their watchlist, which lists they have, or before adding or removing a symbol. Returns the account's watchlists (id, name, symbol count) and, unless include_symbols is false, the symbols on each list in order. Needs
|
|
1938
|
+
description: "Call this when the user asks what is on their watchlist, which lists they have, or before adding or removing a symbol. Returns the account's watchlists (id, name, symbol count) and, unless include_symbols is false, the symbols on each list in order. Needs a signed-in account (OAuth sign-in or account key); reads nothing but this account.",
|
|
1932
1939
|
inputSchema: {
|
|
1933
1940
|
include_symbols: z.boolean().optional().describe("boolean, optional: include each list's symbols (default true)"),
|
|
1934
1941
|
},
|
|
@@ -1951,7 +1958,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1951
1958
|
});
|
|
1952
1959
|
server.registerTool("add_watchlist_symbol", {
|
|
1953
1960
|
title: "Add a symbol to your watchlist (writes to your account)",
|
|
1954
|
-
description: "Call this when the user asks to watch, follow or add a coin to their watchlist. Adds the symbol to the list named by watchlist_id, else to the default list (or the only list the account has); a symbol already on the list stays once. Returns the list's symbols after the change. Writes are rate limited per key and each one is recorded on the account.",
|
|
1961
|
+
description: "Call this when the user asks to watch, follow or add a coin to their watchlist. Adds the symbol to the list named by watchlist_id, else to the default list (or the only list the account has); a symbol already on the list stays once. Returns the list's symbols after the change. Writes are rate limited per connection (sign-in or key) and each one is recorded on the account.",
|
|
1955
1962
|
inputSchema: {
|
|
1956
1963
|
symbol: z.string().describe("string, a Binance USDT-M perp or coin, e.g. SOLUSDT or SOL"),
|
|
1957
1964
|
watchlist_id: z.string().optional().describe("string, optional list id from list_watchlists (default: the default list)"),
|
|
@@ -1971,7 +1978,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
1971
1978
|
});
|
|
1972
1979
|
server.registerTool("remove_watchlist_symbol", {
|
|
1973
1980
|
title: "Remove a symbol from your watchlist (writes to your account)",
|
|
1974
|
-
description: "Call this when the user asks to stop watching a coin or remove it from their watchlist. Removes the symbol from the list named by watchlist_id, else from the default list (or the only list the account has); a symbol that is not on the list changes nothing. Returns the list's symbols after the change. Writes are rate limited per key and each one is recorded on the account.",
|
|
1981
|
+
description: "Call this when the user asks to stop watching a coin or remove it from their watchlist. Removes the symbol from the list named by watchlist_id, else from the default list (or the only list the account has); a symbol that is not on the list changes nothing. Returns the list's symbols after the change. Writes are rate limited per connection (sign-in or key) and each one is recorded on the account.",
|
|
1975
1982
|
inputSchema: {
|
|
1976
1983
|
symbol: z.string().describe("string, the symbol to remove, e.g. SOLUSDT or SOL"),
|
|
1977
1984
|
watchlist_id: z.string().optional().describe("string, optional list id from list_watchlists (default: the default list)"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bykaranteli-mcp",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.1",
|
|
4
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. 67 read-only and account tools (the alert and watchlist tools act on your own account), free account key, paid depth via plans or x402.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|