Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Connect AI agents to the Bitquery MCP server

Vendor MCP
Open markdown

The Bitquery MCP connector routes your AI agent's tool calls to Bitquery's own MCP server through Scalekit. Each user signs in to Bitquery once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 123 tools.

Tools
123
What they doRead · write · destructive
123 · 0 · 0123 read0 write0 destructive
Users sign in with
OAuth app
Scalekit's or your own

Setup

  1. Install the SDK

    Terminal window
    npm install @scalekit-sdk/node dotenv
  2. Set your credentials

    Add your Scalekit credentials to your .env file. Find values in app.scalekit.com > Developers > API Credentials.

    .env
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
    SCALEKIT_CLIENT_ID=<your-client-id>
    SCALEKIT_CLIENT_SECRET=<your-client-secret>
  3. Create the Bitquery MCP connection

    In AgentKit > Connections, create a Bitquery MCP connection. The name you give it is the connection_name your code passes. See Configure connections.

    Scalekit credentials are available for Bitquery MCP server, so you don't need to register an OAuth app.

  4. Authorize a user and make your first call

    quickstart.mts
    import { ScalekitClient } from '@scalekit-sdk/node'
    import 'dotenv/config'
    import { createInterface } from 'node:readline/promises'
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET,
    )
    const actions = scalekit.actions
    const connector = 'bitquerymcp'
    const identifier = 'user_123'
    // Generate an authorization link for the user
    const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
    console.log('Authorize Bitquery MCP:', link)
    const rl = createInterface({ input: process.stdin, output: process.stdout })
    await rl.question('Press Enter after authorizing...')
    rl.close()
    // Make your first call
    const result = await actions.executeTool({
    connector,
    identifier,
    toolName: 'bitquerymcp_chain_capabilities',
    toolInput: {},
    })
    console.log(result)
    Terminal window
    npx tsx quickstart.mts

    Each user signs in once. See Authorize a user for the full flow and statuses.

Tools

Pass the exact name to execute_tool
Try in PlaygroundRequest a tool
  • bitquerymcp_accumulating_traders_by_tokenFind wallets with the highest net buy volume for a token over a given time window.Read-only

    Accumulating Traders By Token

    Find wallets with the highest net buy volume for a token over a given time window.

    Inputs

    addressstringrequired
    Token contract address. Lowercase 0x-hex for EVM; base58 for Solana/Tron.
    blockchainstringrequired
    Token_Network — Ethereum, Arbitrum, Base, Matic, Optimism, Binance Smart Chain, Tron, or Solana.
    limitinteger
    Max traders to return.default 50
    min_net_buy_usdinteger
    Filter out traders whose net accumulation is below this USD threshold.default 0
    window_hoursinteger
    Look-back window in hours. Max 720 (30 days).default 24
  • bitquerymcp_address_labelsLook up all known LABELS for a blockchain ADDRESS — entity, category, CEX deposit/hot wallet, mixer, gambling, scam, token-clone, contract type, NFT collection, ENS, … Works for both wallets and token/contract addresses.Read-only

    Address Labels

    Look up all known LABELS for a blockchain ADDRESS — entity, category, CEX deposit/hot wallet, mixer, gambling, scam, token-clone, contract type, NFT collection, ENS, … Works for both wallets and token/contract addresses. Use for "what / who is this address", "is this token a scam or a clone", "is this wallet a CEX or mixer". To rank a token's traders by label use `labeled_traders_of_token`; to list every address carrying a label use `addresses_by_label`; to resolve a human name to a stored value use `find_label_values`. Backed by the Bitquery address-label directory (directory.labels). Coverage: token/contract labels are dense on EVM (Ethereum, BSC, Polygon); wallet (EOA) labels are densest on Tron and Bitcoin. Pass chain='' to search every chain. Tracing note: call this ONLY when the inline label already on a *_flow_edges / *_transfers row is empty, or to refine the type. An empty result while find_label_values shows rich coverage (e.g. 'binance') is a meaningful NEGATIVE signal, not missing data.

    Inputs

    addressstringrequired
    Address to look up. Lowercase 0x-hex for EVM (case is normalized); base58 as-is for Solana/Tron/Bitcoin.
    chainstring
    Restrict to one chain — network name or slug (Ethereum/ethereum, Matic/polygon, Binance Smart Chain/bsc, Tron, Solana, bitcoin, …). Empty string = all chains.default
  • bitquerymcp_addresses_by_labelList blockchain ADDRESSES that carry a specific label — e.g.Read-only

    Addresses By Label

    List blockchain ADDRESSES that carry a specific label — e.g. every `cex-deposit-address` = 'binance-deposit', every `category` = 'DEX', every `scam` / `mixer` / `sanctioned` address. Use for "give me every address tagged X" or to build an address set to cross-reference with trading via `execute_sql` (join `trading_rt.*` on the returned addresses). Discover valid label_type / label_value pairs first with `find_label_values`. Backed by directory.labels (indexed by label_type + label_value, so this is fast). label_value is matched exactly. Pass chain='' for all chains.

    Inputs

    label_typestringrequired
    Exact label key — e.g. cex-deposit-address, cex-hot-wallet, mixer, gambling, scam, token-clone, token-contract, darknet-market, category, entity.
    label_valuestringrequired
    Exact (case-sensitive) label value to match, e.g. "binance-deposit", "DEX". Use find_label_values to discover valid values.
    chainstring
    Restrict to one chain (network name or slug). Empty string = all chains.default
    limitinteger
    Max addresses to return.default 100
  • bitquerymcp_arbitrum_address_flow_summaryONE-CALL triage of an Arbitrum (arb, ARB, Arbitrum One, L2) address — profile (sent/received transfer counts, distinct receivers/senders) + TOP receivers AND TOP senders.Read-only

    Arbitrum Address Flow Summary

    ONE-CALL triage of an Arbitrum (arb, ARB, Arbitrum One, L2) address — profile (sent/received transfer counts, distinct receivers/senders) + TOP receivers AND TOP senders. Collapses address_profile + trace_next_hop(out) + an incoming convergence into a single call — call this FIRST when triaging a hop. Returns a computed Role: consolidator (senders ≫ receivers) / distributor (receivers ≫ senders) / hub (thousands of both — don't trace deeper) / relay. Profile counts are all-currency; the top arrays honor the currency filter. Pass the returned counterparties to labels_for_addresses to identify them. For raw rows use arbitrum_transfers_in/out; for one direction's full ranking use arbitrum_trace_next_hop. READING THE TOP ARRAYS: one entry per (counterparty, TOKEN) — the same address repeats once per token it moved. Symbols are not unique; identify a token by `contract`.

    Inputs

    addressstringrequired
    Wallet/contract address, 0x-hex (case-insensitive).
    contractstring
    Restrict to ONE exact token by its contract address (0x-hex, case-insensitive) — the reliable way to pin a token, since a currency symbol also matches clone tokens. Empty = no token filter.default
    currencystring
    Restrict the top receiver/sender arrays to one currency symbol (e.g. "USDT"). Empty = all. A symbol is NOT unique — clone/scam tokens reuse "USDC"/"USDT" and their broken decimals can make a fake token outrank the real one, so check the returned contract before trusting the ranking.default
    top_ninteger
    How many top receivers and top senders to return (each).default 5
  • bitquerymcp_arbitrum_address_profileArbitrum (arb, ARB, Arbitrum One, L2) address STATISTICS — successful transfer counts out/in and distinct counterparties (receivers/senders), across all tokens.Read-only

    Arbitrum Address Profile

    Arbitrum (arb, ARB, Arbitrum One, L2) address STATISTICS — successful transfer counts out/in and distinct counterparties (receivers/senders), across all tokens. Fast triage of an address during tracing. For one-call triage that ALSO returns the top counterparties, prefer arbitrum_address_flow_summary. Role from the ratio (cheap triage before flow_edges): senders ≫ receivers = consolidator / sweep; receivers ≫ senders = distributor; ~1↔1 = relay (layering); thousands of both = mega-hub (exchange / treasury — don't trace deeper).

    Inputs

    addressstringrequired
    Address, 0x-hex (case-insensitive).
  • bitquerymcp_arbitrum_find_callsFIND SMART-CONTRACT CALLS of a specific (possibly rare) method on ONE Arbitrum (arb, ARB, Arbitrum One, L2) contract — "who called method X on contract Y, when, did it succeed" in a single filtered query.Read-only

    Arbitrum Find Calls

    FIND SMART-CONTRACT CALLS of a specific (possibly rare) method on ONE Arbitrum (arb, ARB, Arbitrum One, L2) contract — "who called method X on contract Y, when, did it succeed" in a single filtered query. Match by method NAME (e.g. "transfer"), full SIGNATURE (e.g. "transfer(address,uint256)"), or raw 4-byte SELECTOR (e.g. "a9059cbb"). Includes internal calls, reverts and error text. Searches the LAST 7 DAYS by default — set after_time to widen or shift the window; page back by passing the oldest Time of the previous page as before_time (the 7-day window follows it). Wide windows on very busy contracts can be slow — narrow the window or retry. For value movements use arbitrum_transfers_out / arbitrum_transfers_in; for event logs use arbitrum_find_events.

    Inputs

    contractstringrequired
    Contract address being called, 0x-hex (case-insensitive).
    after_timestring
    Only calls at/after this UTC time. Empty = the last 7 days (measured back from before_time when set).default
    before_timestring
    Only calls strictly before this UTC time — page back by passing the oldest Time of the previous page. Empty = no upper bound.default
    callerstring
    Only calls made by this address, 0x-hex (case-insensitive). Empty = any caller.default
    limitinteger
    Max calls to return (newest first).default 20
    methodstring
    Method name (e.g. "transfer") or full signature (e.g. "transfer(address,uint256)"), case-insensitive. Empty = all methods.default
    only_successfulinteger
    1 = only successful calls in successful transactions; 0 = include reverted/failed calls.default 1
    selectorstring
    Raw 4-byte method selector, hex with or without 0x (e.g. "a9059cbb"). Use when the method name is unknown or unparsed. Empty = ignore.default
  • bitquerymcp_arbitrum_find_eventsFIND EVENT LOGS of a specific event on ONE Arbitrum (arb, ARB, Arbitrum One, L2) contract — "which X events involved contract Y, when, in which tx" in a single filtered query.Read-only

    Arbitrum Find Events

    FIND EVENT LOGS of a specific event on ONE Arbitrum (arb, ARB, Arbitrum One, L2) contract — "which X events involved contract Y, when, in which tx" in a single filtered query. Match by event NAME (e.g. "Transfer") or full SIGNATURE (e.g. "Transfer(address,address,uint256)"), case-insensitive. The contract matches both the called contract and the log emitter, so proxy tokens are found by their public address. Searches the LAST 7 DAYS by default — set after_time to widen or shift the window; page back by passing the oldest Time of the previous page as before_time (the 7-day window follows it). Wide windows on very busy contracts can be slow — narrow the window or retry. For decoded asset movements use arbitrum_transfers_out / arbitrum_transfers_in; for the calls themselves use arbitrum_find_calls.

    Inputs

    contractstringrequired
    Contract address, 0x-hex (case-insensitive).
    after_timestring
    Only events at/after this UTC time. Empty = the last 7 days (measured back from before_time when set).default
    before_timestring
    Only events strictly before this UTC time — page back by passing the oldest Time of the previous page. Empty = no upper bound.default
    emitterstring
    Only logs emitted by this address, 0x-hex — useful when the call fans out to other contracts. Empty = any emitter.default
    eventstring
    Event name (e.g. "Transfer") or full signature (e.g. "Transfer(address,address,uint256)"), case-insensitive. Empty = all events.default
    limitinteger
    Max events to return (newest first).default 20
    only_successfulinteger
    1 = only events from successful transactions; 0 = include failed ones.default 1
  • bitquerymcp_arbitrum_flow_edgesMONEYFLOW GRAPH EDGES out of an Arbitrum (arb, ARB, Arbitrum One, L2) address: one row per counterparty — Source → Target, total Amount, Currency.Read-only

    Arbitrum Flow Edges

    MONEYFLOW GRAPH EDGES out of an Arbitrum (arb, ARB, Arbitrum One, L2) address: one row per counterparty — Source → Target, total Amount, Currency. Building block for a MoneyFlow DIAGRAM. HOW TO DRAW: call this per address/hop, collect the edges, and emit a Mermaid `graph LR` (one node per address; each edge labeled with Amount+Currency). Pass the Target addresses to labels_for_addresses to flag CEX / mixer / bridge nodes and STOP expanding those branches. Pass a currency to avoid spam-token noise; call WITHOUT a currency filter to spot a token → USDT off-ramp at the edge. For raw per-transfer rows use arbitrum_transfers_out. Each edge carries the token Contract — pin one exact token with the contract param.

    Inputs

    addressstringrequired
    Source address, 0x-hex (case-insensitive).
    contractstring
    Restrict to ONE exact token by its contract address (0x-hex, case-insensitive) — the reliable way to pin a token, since a currency symbol also matches clone tokens. Empty = no token filter.default
    currencystring
    Restrict to one currency symbol (e.g. "ETH", "USDT") — recommended. Empty = all.default
    limitinteger
    Max edges (largest amount first).default 20