bykaranteli-mcp 0.23.1 → 0.24.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.
Files changed (2) hide show
  1. package/dist/tools.js +26 -7
  2. package/package.json +1 -1
package/dist/tools.js CHANGED
@@ -65,8 +65,27 @@ export function registerByKaranteliTools(server, options) {
65
65
  source: typeof record.source === "string" ? record.source : `${PUBLIC_URL}${pageForApiPath(path)}`,
66
66
  };
67
67
  }
68
+ /* Compact JSON (pretty-printing cost ~35% of the budget) and a hard ceiling:
69
+ * a few argument combinations produced 400k+ characters, more than an LLM
70
+ * context window, with no signal that anything was cut (audit 2026-09-04
71
+ * #41). Above the ceiling the tool answers with guidance instead of a
72
+ * payload the caller could not use anyway. */
73
+ const MAX_RESULT_CHARS = 240_000;
68
74
  function ok(data) {
69
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
75
+ const text = JSON.stringify(data);
76
+ if (text.length <= MAX_RESULT_CHARS)
77
+ return { content: [{ type: "text", text }] };
78
+ return {
79
+ content: [{
80
+ type: "text",
81
+ text: JSON.stringify({
82
+ truncated: true,
83
+ chars: text.length,
84
+ limit: MAX_RESULT_CHARS,
85
+ note: "Result too large for one context window. Narrow the call: fewer hours or days, a single symbol, or include_points=false, then call again.",
86
+ }),
87
+ }],
88
+ };
70
89
  }
71
90
  function fail(err) {
72
91
  const message = err instanceof Error ? err.message : String(err);
@@ -380,9 +399,9 @@ export function registerByKaranteliTools(server, options) {
380
399
  inputSchema: {
381
400
  symbol: z.string().describe("The symbol, e.g. BTCUSDT, or a coin name like BTC."),
382
401
  window_days: z
383
- .preprocess((v) => (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : v), z.union([z.literal(30), z.literal(90), z.literal(180)]))
402
+ .preprocess((v) => (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : v), z.number().int().min(1).max(365))
384
403
  .optional()
385
- .describe("Optional lookback window in days (30, 90 or 180). Default 90."),
404
+ .describe("Optional lookback window in days, 1 to 365 (the API accepts any integer in that range). Default 90."),
386
405
  },
387
406
  annotations: READ_ONLY,
388
407
  }, async ({ symbol, window_days }) => {
@@ -764,11 +783,11 @@ export function registerByKaranteliTools(server, options) {
764
783
  server.registerTool("get_iv_surface", {
765
784
  title: "Options implied-volatility surface and 25-delta skew",
766
785
  description: "Call this when the user asks about implied volatility by strike or expiry, skew, put versus call IV, term structure of IV, or whether downside protection is expensive. Returns the IV surface (expiry x moneyness), per-expiry ATM / 25-delta put and call IV, skew and butterfly, and the constant-30d history, from the daily Deribit chain.",
767
- inputSchema: { currency: z.string().optional().describe("BTC or ETH, default BTC") },
786
+ inputSchema: { currency: z.enum(["BTC", "ETH"]).optional().describe("BTC or ETH, default BTC") },
768
787
  annotations: READ_ONLY,
769
788
  }, async (args) => {
770
789
  try {
771
- const path = `/api/public/options/surface?currency=${(args.currency ?? "BTC").toUpperCase() === "ETH" ? "ETH" : "BTC"}`;
790
+ const path = `/api/public/options/surface?currency=${args.currency ?? "BTC"}`;
772
791
  return ok(withProvenance(await fetchJson(path), path));
773
792
  }
774
793
  catch (err) {
@@ -831,7 +850,7 @@ export function registerByKaranteliTools(server, options) {
831
850
  });
832
851
  server.registerTool("get_network_health", {
833
852
  title: "Bitcoin network health from our own node",
834
- description: "Call this when the user asks about Bitcoin hashrate, difficulty, fees or mempool congestion. Returns the recorded daily series and latest values measured on ByKaranteli's own node.",
853
+ description: "Call this when the user asks about Bitcoin hashrate, difficulty or block fees (our node runs blocksonly, so there is no mempool series). Returns the recorded daily series and latest values measured on ByKaranteli's own node.",
835
854
  inputSchema: { days: z.number().int().min(1).max(730).optional().describe("Window in days, 1-730 (default 365).") },
836
855
  annotations: READ_ONLY,
837
856
  }, async (args) => {
@@ -1010,7 +1029,7 @@ export function registerByKaranteliTools(server, options) {
1010
1029
  });
1011
1030
  server.registerTool("get_coverage", {
1012
1031
  title: "Coverage registry: which venues and data types we collect, how, and how fresh",
1013
- description: "Call this when the user asks which exchanges sit behind a ByKaranteli number, whether a feed is complete or sampled, since when a venue is collected, or how fresh the data is. Returns the live coverage registry: liquidation feeds per venue with kind and last record, snapshot feeds per venue and market, funding arbitrage legs, positioning sources, whale tape, spot minutes and the Hyperliquid whale scan with freshness.",
1032
+ description: "Call this when the user asks which exchanges sit behind a ByKaranteli number, whether a feed is complete or sampled, since when a venue is collected, or how fresh the data is. Returns the live coverage registry: liquidation feeds per venue with kind and last record, snapshot feeds per venue and market, funding arbitrage legs, positioning sources, whale tape, spot minutes and the Hyperliquid whale scan with freshness. snapshots[].country is the jurisdiction only when the venue states one; it is null for most venues, so do not read null as unknown risk.",
1014
1033
  inputSchema: {},
1015
1034
  annotations: READ_ONLY,
1016
1035
  }, async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bykaranteli-mcp",
3
- "version": "0.23.1",
3
+ "version": "0.24.1",
4
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.",
5
5
  "type": "module",
6
6
  "bin": {