bykaranteli-mcp 0.7.2 → 0.8.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 +14 -1
- package/dist/tools.d.ts +7 -2
- package/dist/tools.js +60 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
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.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
20 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 and BingX).
|
|
6
|
+
|
|
7
|
+
## Hosted endpoint (no install)
|
|
8
|
+
|
|
9
|
+
Paste `https://mcp.bykaranteli.com` as a custom connector in any MCP-capable
|
|
10
|
+
assistant. Same 20 tools, nothing to install, no key.
|
|
6
11
|
|
|
7
12
|
## Quick start
|
|
8
13
|
|
|
@@ -83,3 +88,11 @@ node dist/index.js # speaks MCP over stdio
|
|
|
83
88
|
## License
|
|
84
89
|
|
|
85
90
|
MIT. Attribution appreciated: "ByKaranteli (bykaranteli.com)".
|
|
91
|
+
|
|
92
|
+
## Paid depth (optional)
|
|
93
|
+
|
|
94
|
+
The 20 tools above are free and stay free. For recorded history and raw records
|
|
95
|
+
beyond the live snapshots, bykaranteli.com also exposes pay-per-call x402
|
|
96
|
+
endpoints (USDC on Solana or Base, priced per call, no account):
|
|
97
|
+
<https://bykaranteli.com/developers#x402> · machine catalog:
|
|
98
|
+
<https://bykaranteli.com/api/x402>
|
package/dist/tools.d.ts
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
* Tool registrations for the ByKaranteli MCP server, transport-agnostic.
|
|
3
3
|
* The stdio bin (index.ts) and the hosted Streamable HTTP endpoint on
|
|
4
4
|
* bykaranteli.com both call registerByKaranteliTools on their own server
|
|
5
|
-
* instance, so
|
|
5
|
+
* instance, so all 20 tools have exactly one definition.
|
|
6
6
|
*/
|
|
7
7
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
export type RegisterOptions = {
|
|
9
|
-
/** Override the
|
|
9
|
+
/** Override the API origin used for OUTBOUND fetches (the hosted endpoint
|
|
10
|
+
* points this at the container-internal origin). */
|
|
10
11
|
baseUrl?: string;
|
|
12
|
+
/** Origin used in citations returned to the caller. Defaults to baseUrl.
|
|
13
|
+
* The hosted endpoint must set this, otherwise every response cites the
|
|
14
|
+
* container-internal address, which is useless to the agent reading it. */
|
|
15
|
+
publicUrl?: string;
|
|
11
16
|
/** Version string for the outbound user-agent. */
|
|
12
17
|
version?: string;
|
|
13
18
|
};
|
package/dist/tools.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* Tool registrations for the ByKaranteli MCP server, transport-agnostic.
|
|
3
3
|
* The stdio bin (index.ts) and the hosted Streamable HTTP endpoint on
|
|
4
4
|
* bykaranteli.com both call registerByKaranteliTools on their own server
|
|
5
|
-
* instance, so
|
|
5
|
+
* instance, so all 20 tools have exactly one definition.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod/v4";
|
|
8
8
|
export function registerByKaranteliTools(server, options) {
|
|
9
9
|
const BASE_URL = (options?.baseUrl ?? process.env.BYKARANTELI_BASE_URL ?? "https://bykaranteli.com").replace(/\/+$/, "");
|
|
10
|
+
const PUBLIC_URL = (options?.publicUrl ?? process.env.BYKARANTELI_PUBLIC_URL ?? "https://bykaranteli.com").replace(/\/+$/, "");
|
|
10
11
|
const USER_AGENT = `bykaranteli-mcp/${options?.version ?? "dev"} (+https://github.com/bykarantelicom/bykaranteli-mcp)`;
|
|
11
12
|
const TIMEOUT_MS = 15_000;
|
|
12
13
|
// Read-only GET tools over an open-world public API, all of them.
|
|
@@ -78,7 +79,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
78
79
|
explainer: euphoria.explainer,
|
|
79
80
|
}
|
|
80
81
|
: undefined,
|
|
81
|
-
source: `${
|
|
82
|
+
source: `${PUBLIC_URL}/indices`,
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
catch (err) {
|
|
@@ -109,8 +110,8 @@ export function registerByKaranteliTools(server, options) {
|
|
|
109
110
|
const filtered = rows.filter((r) => dateSet.has(String(r.date)) && (!symbol || String(r.symbol).toUpperCase() === symbol));
|
|
110
111
|
return ok({
|
|
111
112
|
rows: filtered.slice(0, 400),
|
|
112
|
-
note: "Recorded from public exchange streams; totals are a floor (Binance throttles its stream). Live 24h view: " +
|
|
113
|
-
source: `${
|
|
113
|
+
note: "Recorded from public exchange streams; totals are a floor (Binance throttles its stream). Live 24h view: " + PUBLIC_URL + "/liquidations",
|
|
114
|
+
source: `${PUBLIC_URL}/liquidations`,
|
|
114
115
|
});
|
|
115
116
|
}
|
|
116
117
|
catch (err) {
|
|
@@ -133,7 +134,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
133
134
|
return ok({
|
|
134
135
|
rows: filtered.slice(0, (days ?? 10) * (asset ? 1 : 2)),
|
|
135
136
|
note: "Finalized US trading days only; a positive net_inflow_usd means the funds bought more of the asset than they sold that day.",
|
|
136
|
-
source: `${
|
|
137
|
+
source: `${PUBLIC_URL}/etf`,
|
|
137
138
|
});
|
|
138
139
|
}
|
|
139
140
|
catch (err) {
|
|
@@ -162,9 +163,9 @@ export function registerByKaranteliTools(server, options) {
|
|
|
162
163
|
note: `${want} is not in the top-30 heatmap set. Tracked symbols: ${d.rows.map((r) => r.symbol).join(", ")}`,
|
|
163
164
|
});
|
|
164
165
|
}
|
|
165
|
-
return ok({ generatedAt: d.generatedAt, row, source: `${
|
|
166
|
+
return ok({ generatedAt: d.generatedAt, row, source: `${PUBLIC_URL}/heatmap` });
|
|
166
167
|
}
|
|
167
|
-
return ok({ ...d, source: `${
|
|
168
|
+
return ok({ ...d, source: `${PUBLIC_URL}/heatmap` });
|
|
168
169
|
}
|
|
169
170
|
catch (err) {
|
|
170
171
|
return fail(err);
|
|
@@ -178,7 +179,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
178
179
|
}, async () => {
|
|
179
180
|
try {
|
|
180
181
|
const d = (await fetchJson("/api/public/funding-arb"));
|
|
181
|
-
return ok({ ...d, source: `${
|
|
182
|
+
return ok({ ...d, source: `${PUBLIC_URL}/funding-arb` });
|
|
182
183
|
}
|
|
183
184
|
catch (err) {
|
|
184
185
|
return fail(err);
|
|
@@ -221,13 +222,13 @@ export function registerByKaranteliTools(server, options) {
|
|
|
221
222
|
note: `${want} is not in the tracked pressure universe right now.`,
|
|
222
223
|
});
|
|
223
224
|
}
|
|
224
|
-
return ok({ generatedAt: d.generatedAt, item: slim(item), source: `${
|
|
225
|
+
return ok({ generatedAt: d.generatedAt, item: slim(item), source: `${PUBLIC_URL}/pressure` });
|
|
225
226
|
}
|
|
226
227
|
return ok({
|
|
227
228
|
generatedAt: d.generatedAt,
|
|
228
229
|
items: d.items.slice(0, limit ?? 20).map(slim),
|
|
229
230
|
totalTracked: d.items.length,
|
|
230
|
-
source: `${
|
|
231
|
+
source: `${PUBLIC_URL}/pressure`,
|
|
231
232
|
});
|
|
232
233
|
}
|
|
233
234
|
catch (err) {
|
|
@@ -242,7 +243,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
242
243
|
}, async () => {
|
|
243
244
|
try {
|
|
244
245
|
const d = (await fetchJson("/api/public/top-movers"));
|
|
245
|
-
return ok({ ...d, source: `${
|
|
246
|
+
return ok({ ...d, source: `${PUBLIC_URL}/top-movers` });
|
|
246
247
|
}
|
|
247
248
|
catch (err) {
|
|
248
249
|
return fail(err);
|
|
@@ -256,7 +257,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
256
257
|
}, async () => {
|
|
257
258
|
try {
|
|
258
259
|
const d = (await fetchJson("/api/public/recent"));
|
|
259
|
-
return ok({ ...d, source: `${
|
|
260
|
+
return ok({ ...d, source: `${PUBLIC_URL}/signals` });
|
|
260
261
|
}
|
|
261
262
|
catch (err) {
|
|
262
263
|
return fail(err);
|
|
@@ -288,7 +289,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
288
289
|
return ok({
|
|
289
290
|
symbol: want,
|
|
290
291
|
window_days: w,
|
|
291
|
-
note: `No closed signals recorded for ${want} in the last ${w} days (or the symbol is not tracked). Try window_days: 180, or check ${
|
|
292
|
+
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}.`,
|
|
292
293
|
});
|
|
293
294
|
}
|
|
294
295
|
throw err;
|
|
@@ -298,7 +299,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
298
299
|
return ok({
|
|
299
300
|
...d,
|
|
300
301
|
daily_points: Array.isArray(daily) ? daily.slice(-30) : daily,
|
|
301
|
-
source: `${
|
|
302
|
+
source: `${PUBLIC_URL}/symbols/${want}`,
|
|
302
303
|
});
|
|
303
304
|
}
|
|
304
305
|
catch (err) {
|
|
@@ -313,7 +314,7 @@ export function registerByKaranteliTools(server, options) {
|
|
|
313
314
|
}, async () => {
|
|
314
315
|
try {
|
|
315
316
|
const d = (await fetchJson("/api/v1/public/leaderboard"));
|
|
316
|
-
return ok({ ...d, source: `${
|
|
317
|
+
return ok({ ...d, source: `${PUBLIC_URL}/leaderboard` });
|
|
317
318
|
}
|
|
318
319
|
catch (err) {
|
|
319
320
|
return fail(err);
|
|
@@ -449,4 +450,48 @@ export function registerByKaranteliTools(server, options) {
|
|
|
449
450
|
return fail(err);
|
|
450
451
|
}
|
|
451
452
|
});
|
|
453
|
+
server.registerTool("get_altseason", {
|
|
454
|
+
title: "Altcoin Season Index (live + recorded history)",
|
|
455
|
+
description: "Call this when the user asks whether it is altseason, how altcoins are doing against Bitcoin, or about market rotation. Returns the live Altcoin Season Index (share of the top 50 Binance perpetual altcoins beating BTC over the trailing 90 days; >=75 altseason, <=25 bitcoin season), the strongest and weakest large alts, and the recorded daily history (never reconstructed).",
|
|
456
|
+
inputSchema: {},
|
|
457
|
+
annotations: READ_ONLY,
|
|
458
|
+
}, async () => {
|
|
459
|
+
try {
|
|
460
|
+
return ok(await fetchJson("/api/public/altseason"));
|
|
461
|
+
}
|
|
462
|
+
catch (err) {
|
|
463
|
+
return fail(err);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
server.registerTool("get_quantum_exposure", {
|
|
467
|
+
title: "Quantum-exposed Bitcoin (daily first-party measurement)",
|
|
468
|
+
description: "Call this when the user asks how much Bitcoin is vulnerable to a quantum computer, about quantum-exposed supply, P2PK coins, or Satoshi-era exposure. Returns the latest daily measurement from ByKaranteli's own Bitcoin Core node: exposed BTC and its share of held value and UTXO count, composition by script family, dormancy cohorts, the dormant-P2PK watch set, and provenance hashes (base_height, base_hash, txoutset_hash) so any figure can be re-verified against any node.",
|
|
469
|
+
inputSchema: {},
|
|
470
|
+
annotations: READ_ONLY,
|
|
471
|
+
}, async () => {
|
|
472
|
+
try {
|
|
473
|
+
return ok(await fetchJson("/api/public/quantum"));
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
return fail(err);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
server.registerTool("get_metric_context", {
|
|
480
|
+
title: "Historical context for any recorded metric (conditional distribution)",
|
|
481
|
+
description: "Call this when the user asks whether a metric's current reading is high or low, or what happened after similar readings. Buckets today's value against the metric's own recorded daily history and returns the median forward BTC return and up-share per bucket at +1/+3/+7 days, with the all-days base rate alongside. Honesty rules: buckets under 30 days are suppressed, and most metrics do NOT separate from the base rate; the interpretation says so plainly. History, not a forecast. Metrics include coinbase_premium_pct, kraken_btc_premium_pct, dvol_btc, fear_greed, funding_btc_daily_pct, etf_btc_net_flow_usd, vpin_btc, altseason_index, stablecoin_total_mcap_busd, fred_dff, fred_dgs10, fred_walcl_busd, fred_rrp_busd and the btc_* network series.",
|
|
482
|
+
inputSchema: {
|
|
483
|
+
metric: z
|
|
484
|
+
.string()
|
|
485
|
+
.regex(/^[a-z0-9_]{2,50}$/)
|
|
486
|
+
.describe("Metric key, e.g. coinbase_premium_pct, fear_greed, altseason_index, stablecoin_total_mcap_busd."),
|
|
487
|
+
},
|
|
488
|
+
annotations: READ_ONLY,
|
|
489
|
+
}, async ({ metric }) => {
|
|
490
|
+
try {
|
|
491
|
+
return ok(await fetchJson(`/api/public/context?metric=${encodeURIComponent(metric)}`));
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
return fail(err);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
452
497
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bykaranteli-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
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": {
|