Serveur MCP crypto pour agents IA
Un agent IA se connecte, découvre onze outils, lit leurs descriptions pour comprendre quelles données existent, et compose ses propres requêtes. Aucune URL à construire, aucun schéma REST à analyser.
Le serveur parle le protocole MCP sur transport HTTP. Il relaie chaque appel vers l’API avec votre clé, sous les noms, unités et conventions de l’API, et présente le résultat pour un agent IA : lignes compactes, résumé par série, taille bornée.
#Connecter votre IA au serveur MCP crypto
Une URL et un en-tête. Le serveur est fermé par défaut : sans X-API-KEY valide, aucun outil n’est annoncé et toute requête est refusée en 401 (X-Deny-Reason: missing_api_key si l’en-tête est absent, invalid_api_key si la clé est inconnue ou révoquée).
{
"mcpServers": {
"bytnode": {
"type": "http",
"url": "https://api.bytnode.com/mcp",
"headers": { "X-API-KEY": "your_key" }
}
}
}La forme exacte du fichier de configuration dépend de l’agent IA, et le bloc générique ci-dessus ne convient pas à tous : Claude Desktop, ChatGPT et Gemini CLI le lisent autrement. La page du serveur MCP donne la config prête à coller de chaque client : Claude Desktop, Claude Code, ChatGPT, Cursor, Codex, VS Code, LangChain, n8n et d’autres.
Le transport est Streamable HTTP sans session : chaque requête se suffit à elle-même. serverInfo.version est la version de la surface MCP (1.0.0) — ses outils, ses instructions et la forme de ses réponses —, distincte de la version du contrat de l’API (1.0.2) ; chaque réponse la répète dans mcp_version. Certains clients gardent les définitions d’outils reçues à la connexion : quand mcp_version change (une nouvelle version majeure signale un changement auquel s’adapter), reconnectez le connecteur pour charger les nouvelles. Les capacités n’annoncent que ce qui existe — outils et ressources, sans notification listChanged — et une ressource inconnue répond l’erreur JSON-RPC -32002. Le CORS est ouvert sur /mcp : un client MCP qui tourne dans un navigateur peut se connecter. Les connecteurs qui se connectent par OAuth (claude.ai, ChatGPT, Claude Code) n’ont besoin d’aucune clé : une requête sans clé reçoit 401 avec WWW-Authenticate: Bearer resource_metadata=…, qui désigne le serveur d’autorisation, bytnode.com, où vous approuvez la connexion. Sinon, la clé passe dans l’en-tête X-API-KEY, ou en Authorization: Bearer. Sans clé, la fiche du serveur https://api.bytnode.com/.well-known/mcp/server-card.json décrit toute la surface (outils, ressources, version, authentification), et /mcp/server.json est son entrée pour le registre officiel MCP.
#Les onze outils de données du marché crypto
Les onze sont en lecture seule, sans effet de bord et idempotents : un agent IA peut les rejouer sans risque. Les cinq outils de données ont chacun leur cible — une paire, un actif, tout le marché, la macro, l’on-chain — et fonctionnent de la même façon : fields (les noms des champs à rendre), limit, since_ms / until_ms, last, columns, detail et max_tokens (détaillés sous get_pair_data) veulent dire la même chose dans chacun, chaque réponse porte server_time et response_tokens, et leurs conventions communes — modes, fenêtres, résumé, unités, budget de taille — sont dans les instructions du serveur, envoyées une fois à la connexion plutôt que répétées dans chaque description. rank_pairs classe toutes les paires sur une métrique, et read_export lit la suite d’une réponse coupée par son budget.
get_system_info
Votre offre et, à la demande, les paires servies, la fraîcheur des données et les catalogues dont un agent IA a besoin pour cibler un champ. Il rend toujours la santé du service et plan : l’offre de votre clé — ses familles, sa profondeur d’historique par timeframe, son débit et le quota restant —, sans décompte dans votre quota. include ajoute la liste vivante des paires et/ou un résumé de fraîcheur, freshness_fields la fraîcheur de champs précis, catalogs les séries qu’attend get_macro_data ou les capacités d’une paire. Chaque partie demandée compte une requête.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
include | string[] | — | Parmi symbols (la liste vivante des paires servies) et freshness (le résumé de fraîcheur des données : state, stale_fields, stale_feeds). Les deux à la fois. |
freshness_fields | string[] | — | Les noms de champs, de n’importe quel outil de données, dont vous voulez la fraîcheur : par champ, age_s et is_stale. Implique freshness. |
catalogs | string[] | — | Parmi macro_series et macro_intraday_series (les séries de get_macro_data, les secondes avec leurs timeframes), symbol_capabilities. Plusieurs à la fois. |
symbol | string | — | Requis par symbol_capabilities : quels flux sont actifs, quelles métriques sont disponibles ou bloquées, avant de les demander. |
category | string | — | Filtre le catalogue macro_series. |
get_pair_brief
L’état d’une paire en un appel, toujours sous la même forme, sans champ à choisir : price_change (le prix et ses variations glissantes), funding_next, le dernier basis, l’oi (avec oi_usd) et le cvd du dernier bucket 1h clos, les liquidations des dernières 24 heures en un objet (liquidations_24h : from et to, le début du premier et du dernier bucket d’1h, long_usd, short_usd, total_usd, bucket_count) et l’indice Fear & Greed (fear_greed). Chaque valeur est un objet à plat : aucune série à lire, aucun total à chercher dans summary. Elle coûte environ une requête de quota par paire, plus une. Pour tout le reste — d’autres champs, un historique, un autre pas —, get_pair_data. Il lit des valeurs courantes : en Free, qui n’a pas la famille snapshot, il est refusé, et get_pair_data avec last: "1h" donne les derniers points.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
symbol | string[] | — | Requis : une paire, ex. BTCUSDT, ou une liste de 10 paires au plus pour les comparer ; avec plusieurs, chaque clé est précédée de sa paire (BTCUSDT/funding_next), et fear_greed, de tout le marché, vient une fois. |
get_pair_data
Les données de marché d’une paire, ou de dix au plus comparées en un appel : prix et bougies, transactions, carnet et flux d’ordres, dérivés (open interest, funding, basis, liquidations) et tokenomics. Un appel, plusieurs champs, valeur courante ou historique daté. Les champs servis par le snapshot REST partagent une seule requête par paire ; les autres (les gros trades, par exemple) partent sur leur propre route, en parallèle. fields liste les champs à rendre, limit le nombre de derniers points de chaque série.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
symbol | string[] | — | Requis : la paire, ex. BTCUSDT, ou une liste de 10 paires au plus pour les comparer : les requêtes se comptent par paire, chaque clé devient paire/champ (ETHUSDT/funding_next), et une paire refusée n’empêche pas les autres (errors, partial). La liste vivante vient de get_system_info. |
fields | string[] | — | Requis : les champs à rendre, plusieurs par appel, parmi les 24 noms de cet outil (listés plus bas). Un champ d’un autre outil est refusé avec le nom de son outil. |
limit | integer | — | Les N derniers points de chaque série ; par défaut, le dernier (avec un timeframe, les N derniers buckets). Un champ en valeur courante seule comme price_change rend un point ; un limit au-delà du maximum propre d’un champ (1000 pour une série, 10000 pour les trades individuels) est plafonné, et warnings le dit. Avec une fenêtre, un plafond de points par série. describe_fields dit ce que compte N. |
timeframe | string | 1h | Pas des champs marqués timeframe. Absent : 1h en valeur courante ; en historique, un pas qui donne environ 200 points. 1w : klines seulement. |
live | boolean | false | Valeur courante seulement : ajoute la bougie en formation, marquée is_closed: false. |
since_ms / until_ms | string | — | Les bornes d’une fenêtre datée : millisecondes epoch, une date ISO 8601 (2026-10-20T00:00:00Z ; sans fuseau, UTC) ou une durée écoulée ('48h', '30d' ; unités m, h, d, w). Présente : chaque champ demandé rend son historique. |
last | string | — | L’historique sur la durée donnée ('48h', '30d') en buckets clos entiers : since_ms recule au début de son bucket, si bien que last: '7d' en 1h rend 168 bougies, contre 167 avec since_ms: '7d'. Il remplace since_ms (les deux ensemble sont refusés) ; until_ms peut en fixer la fin. |
min_usd | number | — | Seuil USD de trades_large (défaut 100 000, minimum 1 000) et de liquidations_events. |
market | string | all | Marché de cvd, buy_sell_ratio, trades_avg_size et orderbook : all (spot + futures perpétuels), spot ou futures. L’outil le traduit en la route de ce marché. |
columns | string | — | Les colonnes à garder dans chaque ligne, en liste (p. ex. ["close", "volume"] ; une chaîne CSV est acceptée aussi), notation pointée pour les champs imbriqués — l’équivalent de ?fields= dans l’API REST (ici, fields nomme les champs de données). Appliquée champ par champ : une colonne présente dans au moins un champ demandé s’applique là où elle existe, et warnings dit où elle a été ignorée ; une colonne inconnue de tous les champs est refusée, avec une suggestion. Prime sur detail. |
detail | string | compact | compact : les colonnes principales des lignes lourdes, is_closed retiré quand chaque ligne est close, identifiants de trades retirés ; omitted_columns nomme ce qui a été laissé. full : toutes les colonnes. |
max_tokens | integer | 6000 | Budget de la réponse en jetons estimés, de 1 500 à 16 000 (défaut 6 000). Le même paramètre sur chaque outil de données, get_market_indicators, rank_pairs et read_export. |
get_options_data
Les options et les ETF spot d’un actif : résumé des options, open interest, volume, put/call, volatilité implicite, max pain, grecques, OI par strike, et etf_fundamentals (les déclarations trimestrielles à la SEC des ETF spot par émetteur ; pas de flux quotidiens). expiries: true ajoute les échéances actives avec, par échéance, l’OI des calls et des puts, le put/call, le max pain, les principaux strikes et l’IV ATM ; options_summary et options_put_call_ratio sont des totaux sur toutes les échéances.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
asset | string | — | Requis : l’actif seul, ex. BTC, jamais une paire. |
fields | string[] | — | Les champs à rendre, parmi les 11 noms de cet outil (listés plus bas). Le seul outil de données où il est facultatif : expiries: true peut venir seul. |
limit | integer | — | Les N derniers points de chaque série ; par défaut, le dernier (avec un timeframe, les N derniers buckets). Un champ en valeur courante seule comme price_change rend un point ; un limit au-delà du maximum propre d’un champ (1000 pour une série, 10000 pour les trades individuels) est plafonné, et warnings le dit. Avec une fenêtre, un plafond de points par série. describe_fields dit ce que compte N. |
expiries | boolean | false | Ajoute data.expiries : les échéances actives et les chiffres de chacune, en une requête. Leur date est l’expiry des autres champs. Valable seul, sans aucun champ. |
timeframe | string | — | Pas de l’historique des options (champs marqués timeframe). Absent, un pas qui donne environ 200 points. |
expiry | string | — | Une échéance, AAAA-MM-JJ : options_oi_distribution, et options_max_pain en historique, où elle est requise. |
ticker | string | — | Un émetteur d’ETF, ex. IBIT : filtre facultatif de l’historique d’etf_fundamentals. |
get_market_overview
Tout le marché crypto, sans cible : capitalisation totale, volume et dominance BTC/ETH (global_market), deux indices Fear & Greed (fear_greed et celui de CMC, fear_greed_cmc), altcoin_season, et les indices cmc20 et cmc100.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
fields | string[] | — | Requis : les champs à rendre, plusieurs par appel, parmi les 6 noms de cet outil (listés plus bas). Un champ d’un autre outil est refusé avec le nom de son outil. |
limit | integer | — | Les N derniers points de chaque série ; par défaut, le dernier (avec un timeframe, les N derniers buckets). Un champ en valeur courante seule comme price_change rend un point ; un limit au-delà du maximum propre d’un champ (1000 pour une série, 10000 pour les trades individuels) est plafonné, et warnings le dit. Avec une fenêtre, un plafond de points par série. describe_fields dit ce que compte N. |
timeframe | string | — | Pas de global_market seulement (1h, 4h, 1d) ; les indices sont quotidiens. |
get_macro_data
La macro américaine et mondiale. macro lit une série FRED (DGS10, DCOILWTICO…) — sans series, la dernière valeur de chaque série ; macro_intraday lit un instrument intraday de son catalogue (ex. PAXGUSDT), series requise. Quatre champs calculés ne prennent aucune cible : liquidité nette, corrélations crypto-macro, momentum et un score de risque. Les listes de séries viennent des catalogues de get_system_info.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
fields | string[] | — | Requis : les champs à rendre, plusieurs par appel, parmi les 6 noms de cet outil (listés plus bas). Un champ d’un autre outil est refusé avec le nom de son outil. |
limit | integer | — | Les N derniers points de chaque série ; par défaut, le dernier (avec un timeframe, les N derniers buckets). Un champ en valeur courante seule comme price_change rend un point ; un limit au-delà du maximum propre d’un champ (1000 pour une série, 10000 pour les trades individuels) est plafonné, et warnings le dit. Avec une fenêtre, un plafond de points par série. describe_fields dit ce que compte N. |
series | string | — | L’identifiant de série : une série FRED pour macro (ex. DGS10 ; facultative pour sa valeur courante), un instrument pour macro_intraday (ex. PAXGUSDT ; requis). |
timeframe | string | — | Pas de macro_intraday seulement (son catalogue donne les pas de chaque instrument). |
get_onchain_data
L’on-chain de Bitcoin et d’Ethereum, sans cible : huit champs btc_* (réseau, mempool, frais, minage, MVRV, NVT, adresses actives, revenu par difficulté) et huit champs eth_* (offre, gas, staking, déflation, DeFi, momentum du gas, resserrement de l’offre, prix de l’ETH en BTC).
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
fields | string[] | — | Requis : les champs à rendre, plusieurs par appel, parmi les 16 noms de cet outil (listés plus bas). Un champ d’un autre outil est refusé avec le nom de son outil. |
limit | integer | — | Les N derniers points de chaque série ; par défaut, le dernier (avec un timeframe, les N derniers buckets). Un champ en valeur courante seule comme price_change rend un point ; un limit au-delà du maximum propre d’un champ (1000 pour une série, 10000 pour les trades individuels) est plafonné, et warnings le dit. Avec une fenêtre, un plafond de points par série. describe_fields dit ce que compte N. |
timeframe | string | — | Pas de btc_fees seulement (1h, 4h, 1d) ; les autres séries gardent la cadence de leur source. |
dataset | string | — | concentration (défaut), rewards, difficulty ou fee_rates, pour l’historique de btc_mining. |
get_market_indicators
Les dix-neuf indicateurs techniques, calculés à la demande, pour une à dix paires. symbol (une liste, comme dans les autres outils), timeframe et indicators sont obligatoires ; seul limit a un défaut, à 1. Les paramètres, défauts et bornes de chaque type sont dans le schéma JSON et la description de l’outil.
await c.call_tool("get_market_indicators", {
"symbol": "BTCUSDT",
"timeframe": "1h",
"limit": 60,
"indicators": [
{"id": "rsi_7", "type": "rsi", "period": 7},
{"id": "rsi_21", "type": "rsi", "period": 21},
{"id": "macd", "type": "macd", "fast": 12, "slow": 26, "signal": 9},
{"id": "adx_14", "type": "adx", "period": 14},
],
})Les mêmes règles qu’en REST s’appliquent : un id de votre choix pour chaque indicateur, unique dans l’appel, et un plafond de limit + warm-up ≤ 1000. La réponse a la forme de celle des outils de données : data porte une série par id@timeframe (paire/id@timeframe avec plusieurs paires), indicators le type et les paramètres de chacun ; une paire où les indicateurs ne s’appliquent pas (une stablecoin) a ses clés à null, avec not_applicable dans unavailable, et une paire refusée est signalée dans errors. Une requête de quota par paire.
describe_fields
La définition complète des champs des cinq outils de données : ce que rend chacun (colonnes, conventions, datation des lignes), l’unité de chaque colonne (units), les seuils de chaque libellé (labels), son outil et sa cible, ses timeframes, son maximum de points, son historique, ses paramètres annexes et la prise en charge de live. Il décrit aussi les clés de sortie qui ne sont pas des champs : liquidations_24h, oi_usd, cumulative_net_volume et ranking. Aucun appel à l’API, aucun quota : la description de chaque outil porte une ligne par champ, avec les mêmes étiquettes que l’index, et cet outil donne le reste. Les mêmes définitions sont des ressources MCP : bytnode://fields (l’index, avec l’outil de chaque champ) et bytnode://fields/{name}.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
fields | string[] | — | Les noms à décrire, au moins un : des champs de n’importe quel outil de données, ou les clés de sortie liquidations_24h, oi_usd, cumulative_net_volume et ranking. Un nom inconnu est refusé avec une suggestion. |
rank_pairs
Toutes les paires servies classées sur une métrique, les limit premières rendues, pour une requête de quota quel que soit le nombre de paires : oi_usd (open interest en USD), volume_usd_24h (volume spot + futures des 24 dernières heures closes, somme du volume horaire × la clôture), funding_next (le prochain funding estimé : estimated_rate_pct, équivalent 8 h en %, et apr_pct), price_change_pct (la variation glissante sur window) et rsi (RSI 14 sur la dernière bougie close de timeframe). data.ranking donne pour chaque paire son rank, son symbol, sa valeur et son prix. Les valeurs ont au plus 60 secondes (computed_at) ; une paire sans la métrique — paires spot seulement pour oi_usd, funding_next et rsi, flux manquant — est listée dans excluded. La requête de quota est faite avec votre clé sur la route de la famille de la métrique, donc votre offre s’applique : dérivés pour oi_usd et funding_next, prix et volume pour price_change_pct et volume_usd_24h, indicateurs pour rsi. Pour les données complètes d’une paire, get_pair_data.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
metric | string | — | Requis : oi_usd, volume_usd_24h, funding_next, price_change_pct ou rsi. |
order | string | desc | desc (le plus grand d’abord, par défaut) ou asc — le funding le plus négatif, par exemple. |
limit | integer | 10 | Le nombre de paires rendues, de 1 à 100. |
window | string | 1d | price_change_pct seulement : 1h, 4h, 1d (défaut) ou 1w. |
timeframe | string | 4h | rsi seulement : les bougies du RSI, 1h, 4h (défaut) ou 1d. |
max_tokens | integer | 6000 | Budget de la réponse en jetons estimés, de 1 500 à 16 000 (défaut 6 000). Le même paramètre sur chaque outil de données, get_market_indicators, rank_pairs et read_export. |
read_export
La suite d’une réponse coupée par son budget de taille, page par page, dans le même format, sans requête à l’API ni quota. Une réponse coupée porte export.export_id, et le missing de son ranges (ou, pour plusieurs paires, le missing de premier niveau) donne l’appel à faire : read_export(export_id=…, key='klines@1h', offset=N). Chaque page dit row_count, total_row_count et next_offset (null à la fin), et keys liste chaque série de l’export avec son nombre de lignes. Un export vit une heure et se lit avec la clé API qui l’a produit.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
export_id | string | — | Requis : l’export.export_id de la réponse coupée (son URI bytnode:// est aussi acceptée). |
key | string | — | La série à lire, sous sa clé dans le data de la réponse (klines@1h, par exemple) ; par défaut la première. keys les liste. |
offset | integer | 0 | La première ligne à rendre, 0 étant la plus récente ; le row_count du ranges de la réponse coupée la donne. |
max_tokens | integer | 6000 | Budget de la réponse en jetons estimés, de 1 500 à 16 000 (défaut 6 000). Le même paramètre sur chaque outil de données, get_market_indicators, rank_pairs et read_export. |
#Donnée crypto courante ou historique
Le mode ne dépend que d’une chose : la présence d’une fenêtre datée. Sans since_ms, until_ms ni last, un outil de données répond avec la valeur courante ; avec l’un d’eux, chaque champ demandé répond avec son historique sur la fenêtre — plusieurs métriques datées en un seul appel.
| Requête | Ce que rend chaque champ |
|---|---|
| fields : [...] | Le dernier point de chaque champ ; pour une série par buckets, le dernier bucket clos. |
| limit : N | Les N derniers points de chaque série ; pour un champ marqué timeframe, les N derniers buckets du timeframe (1h par défaut) : basis, oi_change et les autres séries à la minute sont alors agrégées par bucket. Un champ en valeur courante seule en rend un. |
| since_ms / until_ms, ou last | Sa série entière sur la période, jamais coupée en silence. Une ligne est rendue quand son instant (le début de son bucket) est ≥ since_ms et ≤ until_ms ; un bucket inachevé n’est jamais rendu. last recule since_ms au début de son bucket : last: '24h' en 1h rend les 24 buckets clos, since_ms: '24h' au plus 23. Sans timeframe, le serveur choisit un pas qui donne environ 200 points pour tout l’appel et le dit dans ranges.note ; un timeframe imposé qui ne tient pas est refusé avant l’appel, avec le motif exact (hors offre, ou trop de points pour un appel) et le pas qui marcherait. |
| live : true | Les champs listés ci-dessous gagnent la bougie en formation, provisoire. Refusé avec une fenêtre, et si aucun champ demandé ne la sert. |
Champs qui servent la bougie en formation
klinescvdspread_interexchangetrades_klinetrades_kline_spottrades_kline_futures
#Cibler les paires et les marchés crypto
Chaque outil de données a sa cible : une paire pour get_pair_data (symbol, requis), un actif pour get_options_data (asset, requis), une série de catalogue pour get_macro_data (series), aucune pour get_market_overview et get_onchain_data. Chaque champ appartient à un seul outil. Ce qui ne colle pas est refusé avant le premier appel réseau, jamais absorbé, et tous les problèmes sont listés dans le même message.
| Cas | Réponse |
|---|---|
| Une cible absente | Une erreur qui nomme le paramètre manquant, avec un exemple : symbol et asset sont requis par le schéma de leur outil, series par macro_intraday et par l’historique de macro. |
| Un champ demandé au mauvais outil | Erreur : 'fear_greed' is a field of get_market_overview: call that tool. Le message nomme l’outil du champ plutôt qu’un champ voisin. |
| series qu’aucun champ demandé n’attend | Erreur : seuls macro et macro_intraday lisent series ; les champs macro calculés n’ont pas de cible. |
| asset rempli avec une paire | Erreur : asset attend l’actif seul. Il n’y a aucune dérivation automatique. |
| Un paramètre que la route choisie n’accepte pas | Erreur : par exemple expiry sur la valeur courante d’options_max_pain, que seul son historique accepte. |
| Un timeframe qu’aucun champ n’utilise | Erreur : le timeframe ne s’applique à aucun champ demandé (chaque outil dit quels champs le prennent : klines, cvd, trades_kline… pour une paire, global_market, macro_intraday, btc_fees). |
| Une fenêtre datée sur un champ qui n’en a pas | Erreur : le champ n’a pas d’historique daté ; demander sa valeur courante, sans fenêtre, ou le champ qui porte son historique, que le message nomme (price_change → klines, funding_next → funding_rate). |
| last avec since_ms | Erreur : last remplace since_ms, en donner un seul. Une borne qui n’est ni des millisecondes epoch, ni une date ISO 8601, ni une durée est refusée avec les formes acceptées. |
| Plus de 10 paires dans symbol | Erreur : 10 paires au plus par appel, avec le nombre reçu. |
#Les 64 champs du marché crypto
Les noms sont ceux de l’API, identiques en valeur courante et en historique, avec ces différences : le marché global s’appelle global_market ici et global dans le snapshot REST (global est un mot réservé de Python, la langue du serveur) ; le marché est un paramètre ici (market: "spot") et un suffixe de chemin en REST (/v1/cvd/spot) ; les chiffres de chaque échéance d’options viennent avec expiries: true de get_options_data (REST : /v1/options/expiry) et les capacités d’une paire avec le catalogue symbol_capabilities (REST : /v1/capabilities?symbol=…) ; et un historique dit le pas que l’outil a retenu dans timeframe_applied, puisqu’il peut le choisir. Le détail de chaque champ — son outil, ce qu’il contient, ses unités, ce que compte N, son plafond, son historique — est donné par describe_fields ; la description de chaque outil en porte une ligne par champ, avec ses étiquettes (timeframe, valeur courante seule, live, limit maximal). Voir aussi le catalogue des données.
get_pair_data : vingt-cinq champs par paire (symbol)
klinesprice_changetrades_spottrades_futurestrades_largetrades_kline_futures_secondsoifunding_nextfunding_ratefunding_cumulativebasisoi_changeliquidations_eventsliquidations_cumulativeliquidations_big_small_ratioorderbookcvdspread_interexchangebuy_sell_ratiotrades_avg_sizetrades_klinetrades_kline_spottrades_kline_futurestokenomics
get_options_data : onze champs par actif (asset)
options_summaryoptions_oioptions_oi_changeoptions_oi_distributionoptions_volumeoptions_put_call_ratiooptions_ivoptions_iv_klinesoptions_max_painoptions_greeksetf_fundamentals
Les champs options et etf_fundamentals. Les échéances actives, avec les chiffres de chacune, viennent avec expiries: true. options_max_pain liste chaque échéance active, la plus proche en premier, et limit: N garde les N plus proches, sans fenêtre ; une fenêtre rend l’historique d’une seule expiry, alors requise.
get_market_overview : six champs de tout le marché (aucune cible)
global_marketfear_greedfear_greed_cmcaltcoin_seasoncmc20cmc100
get_macro_data : six champs macro
macromacro_intradaymacro_net_liquiditymacro_correlationsmacro_momentummacro_risk
macro sans series rend la dernière valeur de chaque série FRED ; avec, cette série seule, et son historique l’exige. macro_intraday l’exige toujours et refuse 30m. Les deux ne portent pas les mêmes instruments : ne pas substituer l’un à l’autre. Les quatre champs calculés (macro_net_liquidity, macro_correlations, macro_momentum, macro_risk) ne prennent pas de series.
get_onchain_data : seize champs on-chain (aucune cible)
btc_networkbtc_mempoolbtc_feesbtc_miningbtc_mvrvbtc_nvtbtc_active_addressesbtc_revenue_per_difficultyeth_supplyeth_gaseth_stakingeth_deflationeth_defieth_gas_momentumeth_squeezeeth_price_btc
Seul btc_fees prend un timeframe ; l’historique de btc_mining prend un dataset ; les valorisations (btc_mvrv, btc_nvt…) sont quotidiennes.
Valeur courante seulement
price_changetrades_spottrades_futurestrades_largetrades_kline_futures_secondsfunding_nextliquidations_eventsmacro_correlationsmacro_momentummacro_riskoptions_summaryoptions_oi_distributionoptions_greeks
Ces champs n’ont pas d’historique daté : ils servent leur valeur courante (un point, ou avec limit les N derniers quand le champ compte des lignes — transactions, événements de liquidation). Une fenêtre since_ms ou until_ms sur eux est refusée plutôt qu’ignorée — un agent IA croirait filtrer une période alors qu’il reçoit les derniers points.
#La réponse : des données de marché crypto lisibles par votre agent IA
Les données gardent les noms, unités et conventions de l’API, sous une clé par champ, mais elles sont présentées pour un agent IA plutôt que rendues telles quelles. Un champ à timeframe a pour clé champ@tf ; avec plusieurs paires, chaque clé est précédée de sa paire (ETHUSDT/funding_next, BTCUSDT/cvd@1h). Une réponse porte mode, data, api_requests, server_time (l’heure du serveur, ISO 8601 UTC), mcp_version (la version de la surface MCP) et response_tokens (sa propre taille, en jetons estimés), plus, quand ils s’appliquent, scopes, summary, ranges, freshness, warnings, errors, partial, unavailable, omitted_columns, missing, truncation, export, timeframe_applied et window ; get_market_indicators et rank_pairs répondent dans la même enveloppe. Une série vide ou sans objet vaut null, et unavailable dit pourquoi. unavailable et out_of_plan_fields sont celles du snapshot. Aucun outil ne déclare d’outputSchema : les clés sont décrites ici, et structuredContent porte le même JSON que le texte.
{
"mode": "latest",
"data": {
"klines@1h": {
"first_time": "2026-10-21T13:00:00.000Z",
"step_s": -3600,
"columns": ["open", "high", "low", "close", "volume"],
"rows": [[…], …]
},
"oi@1h": { "first_time": …, "step_s": -3600, "columns": ["oi", "oi_usd", … ], "rows": [ … ] },
"funding_next": { … },
"price_change": { … }
},
"scopes": {
"symbol:BTCUSDT": ["klines@1h", "oi@1h", "funding_next", "price_change"]
},
"summary": {
"klines@1h": { "column": "close", "latest": …, "min": …, "max": …, "mean": …,
"change_pct": …, "high_max": …, "low_min": …, … }
},
"freshness": { "age_s": { "klines@1h": 4, "funding_next": 2, … }, "stale": [] },
"omitted_columns": { "klines@1h": ["is_closed"] },
"timeframe_applied": "1h",
"unavailable": { … },
"api_requests": 1,
"server_time": "2026-10-21T14:02:31.512Z",
"response_tokens": 1840
}data: une liste de lignes arrive en{columns, rows}, lignes de la plus récente à la plus ancienne ; un point seul, en objet ; une série vide ou sans objet, ennull. Une série à pas régulier n’a pas de colonnetimemaisfirst_timeetstep_s, quel que soit son nombre de lignes, une comprise : la ligne i est datéefirst_time + i × step_s,step_sétant négatif, de la ligne la plus récente vers le passé ; au moindre trou, la colonnetimereste. Les événements (trades, liquidations unitaires) et les tables gardent leurtime, et ce que toutes les lignes partagent est dit une fois sur le bloc :date(chaquetimeest alors l’heure UTC de ce jour,12:54:30.494Z) ou un seultime(toutes les lignes à cet instant, comme une table d’échéances) ;.000disparaît quand aucune ligne n’a de millisecondes. Les flottants gardent 6 chiffres significatifs, sauf les offres et les cumuls, qui gardent leurs unités entières. Avecdetail: "compact"(le défaut), les lignes lourdes gardent leurs colonnes principales,is_closeddisparaît quand chaque ligne est close et les identifiants de trades sont retirés ;omitted_columnsnomme ce qui a été laissé, etdetail: "full"le rend.scopes: la portée réelle de chaque clé —symbol:X,asset:X,series:X, oumarketpour un champ sans cible.macrodemandé sansseriesest étiquetémarket, jamais avec une série. Avec plusieurs paires, le préfixe de la clé nomme déjà sa paire : seules restent les portées des autres cibles (market…).mode:latestouhistory; en historique,windowrappelle les bornes etrangesdit, par série, ce qui est réellement couvert :timeframe,row_count,frometto(le début du premier et du dernier bucket, comme letimede chaque ligne),noteettruncated; quand une série est coupée,missingdit comment obtenir la suite — unlimitplus bas, une fenêtre plus ancienne qui finit ànext_until_ms, ouread_exportà partir de l’offset qu’il donne.summary: par série, sur sa colonne principale, la dernière et la plus ancienne valeur, le min et le max avec leur instant, et la moyenne ; la somme pour un flux (liquidations, volume net…), avec danssumscelle de ses composantes (long_usdetshort_usd,buy_volumeetsell_volume), la variation (etchange_pctquand elle a un sens) pour un état ; les bougies ajoutenthigh_maxetlow_minavec leur instant. Les trades et liquidations unitaires ajoutentby_side(nombre, quantité et USD par côté).freshness(valeur courante) :age_s, les secondes écoulées depuis la dernière livraison du flux source de chaque clé (la date d’une ligne est sontime), etstale, les clés dont le flux est en retard, selon le moniteur des flux ;warningsnomme chaque champ en retard — sa valeur n’est pas courante — et chaque colonne de projection qu’un champ a ignorée.- Taille : une réponse est bornée à 6 000 jetons estimés par défaut ; le paramètre
max_tokensdes outils de données, deget_market_indicators, derank_pairset deread_exportla règle de 1 500 à 16 000, etresponse_tokensdonne la taille de chaque réponse. Au-delà du budget, les séries les plus lourdes gardent leurs lignes les plus récentes, la coupe est dite une fois, dans lerangesde chaque série (row_countlignes servies surtotal_row_count, etmissing: comment avoir la suite, souvent lemax_tokensqui suffit à la réponse entière ; le même champ coupé pour plusieurs paires porte une seule consigne, dans lemissingde premier niveau ;truncationseulement pour ce qui n’a pas deranges), les métadonnées identiques pour plusieurs paires (ranges,omitted_columns,freshness) sont écrites une fois par champ, sous le nom du champ, etexportgarde les données complètes une heure, pour la même clé :read_exportles lit page par page avecexport.export_id, au format des réponses, sans requête à l’API ni quota. C’est aussi la ressource MCPbytnode://exports/{id}, pour les clients qui lisent les ressources, d’un seul bloc, avec 8 chiffres significatifs et letimede chaque ligne. timeframe_applied: le pas réellement appliqué, dès qu’un champ l’a utilisé ;live: présent quand la bougie en formation a été demandée.errorsetpartial: un champ en erreur n’empêche pas les autres, ni une paire refusée les autres paires. Il est signalé souserrors(une paire sous son nom) et la réponse portepartial: true.api_requests: les requêtes que cet appel a décomptées de votre quota — pour chaque paire, une pour les valeurs courantes des champs du snapshot ensemble ; une pour chaque autre champ, chaque historique etexpiries.oi_usd: chaque ligne d’oiporte l’open interest en USD,oi× la clôture de la bougie spot de référence du même bucket (nullsans elle), en valeur courante aussi, sans requête de plus ;get_pair_briefle porte également. De même, chaque ligne decvdportecumulative_net_volume, le cumul denet_volumedepuis la ligne la plus ancienne de la série servie : la courbe de CVD sur la période. La valeur courante deliquidations_cumulativeest son dernier bucket clos (1h par défaut), daté à son début comme toute ligne.
#Erreurs sur les appels de données de marché crypto
Toute erreur commence par Error (HTTP NNN): message. Quand l’API a répondu, elle se termine par [code: …], l’error.code stable de l’API. Un appel d’outil en échec est signalé comme une erreur MCP (isError), jamais rendu comme une donnée, et porte la même erreur en champs dans structuredContent.error : {status, code, message, param?, hint?, retry_after_s?}. code est celui de l’API quand elle en a donné un (invalid_symbol, plan_family, history_depth, rate_limited, quota_exceeded…), sinon il suit le statut (invalid_request pour un 422, unauthorized pour un 401…) ; un champ demandé au mauvais outil donne wrong_tool, avec le bon outil dans hint (call get_market_overview), un champ ou une colonne inconnus unknown_field, un paramètre inconnu unknown_parameter, avec did you mean … dans hint ; retry_after_s est le délai à attendre quand le message en donne un.
| Situation | Comportement |
|---|---|
| Requête sans clé valide | 401, X-Deny-Reason: missing_api_key (ou invalid_api_key), avant qu’un seul outil soit annoncé. |
| Requête invalide | Error (HTTP 422) listant chaque problème, avant tout appel réseau. |
| Famille hors offre | Error (HTTP 403): The 'options' data family is not included in your plan. GET /v1/limits lists the families of your key; https://bytnode.com/pricing lists the plans that open it. [code: plan_family] — la donnée existe, simplement pas dans votre offre. |
| Snapshot hors offre (Free) | Un refus explicite, Error (HTTP 403), sur les valeurs courantes (les champs du snapshot, get_pair_brief), qui nomme l’offre qui les ouvre ; les autres champs restent servis, et un court historique (last: '1h') donne les derniers points. |
| Une période au-delà de la profondeur de l’offre | Refusée avant l’appel, avec la profondeur de l’offre à ce pas et le pas qui servirait la période ; à la frontière, l’Error (HTTP 403) de l’API [code: history_depth]. |
| Débit ou quota | Error (HTTP 429) avec le detail de l’API : débit par minute, ou quota mensuel. |
| Un champ en erreur | Signalé sous errors, les autres servis, partial: true ; une erreur identique sur plusieurs champs n’est écrite qu’une fois (same error as '…'). L’appel n’échoue que si aucun champ n’aboutit. |
| Une paire refusée parmi plusieurs | Signalée sous errors avec son nom (un symbol invalide, par exemple), les autres paires servies, partial: true. L’appel n’échoue que si aucune paire n’aboutit. |
| Un symbol invalide | L’Error (HTTP 422) de l’API, terminée par [code: invalid_symbol], qui liste les valeurs acceptées ; la liste vivante vient de get_system_info. |
| Un export expiré ou inconnu | Error (HTTP 404) de read_export, terminée par [code: not_found] : un export vit une heure et se lit avec la clé qui l’a produit ; rappeler l’outil. |
| Amont qui ne répond pas | Une relance sur 502, 503, 504 ou panne réseau. Un 500 n’est pas rejoué : chaque requête compte dans votre quota. |
| Délai dépassé | Error (HTTP 504) après trente secondes sans réponse. |
| Erreur interne du serveur | Error (HTTP 500) avec le seul type de l’erreur ; le détail reste dans le journal du serveur. |