提交

Bitkub Trading Mcp

@topcraftcodes

bitkub-trading-mcp is a Model Context Protocol server that exposes the Bitkub cryptocurrency exchange API to AI assistants. Once installed, your AI can: - Fetch real-time prices for any THB trading pair - Check account balances and open orders - Place market and limit orders (with confirmation) - Pull historical OHLC and ticker data - Read deposit/withdrawal history Built on the official @modelcontextprotocol/sdk, distributed as a single npm package. Works with Claude Desktop, Cursor, Cline, Continue, and any other MCP-compatible client. Bitkub is Thailand's largest licensed cryptocurrency exchange.
概览

Bitkub MCP Server

License: MIT Node.js 20.6+ MCP

An MCP server that exposes Bitkub's REST and WebSocket endpoints as tools. Built with Bun + TypeScript and the official @modelcontextprotocol/sdk, served over stdio.

⚠️ READ-ONLY BY DESIGN. This server never places orders, cancels orders, generates addresses, or initiates withdrawals. Only data-retrieval and observation endpoints are exposed. Even if you give it a key with full trading permissions, it cannot move money or submit orders — those endpoints are not implemented in the code.

Install

Requirement: Node.js ≥ 20 (node --version to check). No clone, no build — the MCP client downloads the package on first launch via npx.

One command, no JSON editing.

Public data only (no API key needed)

If you just want market data — prices, order books, candles, public ticker stream — skip the env block entirely:

claude mcp add bitkub-trading-mcp -- npx -y bitkub-trading-mcp

The 9 public REST tools and the 1 public WebSocket ticker tool work immediately. The 12 secure REST tools and 2 private WebSocket tools register but each call returns an auth error explaining how to add keys.

With API key (full features — your wallet or order and match transaction)

Replace the two placeholder values with your real Bitkub key + secret. See Add your API key for how to generate them.

claude mcp add bitkub-trading-mcp \
  -e BITKUB_API_KEY=your_real_key_here \
  -e BITKUB_API_SECRET=your_real_secret_here \
  -- npx -y bitkub-trading-mcp

Make it available across all projects

Add -s user to either command above:

claude mcp add bitkub-trading-mcp -s user -- npx -y bitkub-trading-mcp

After running any of these, /exit and claude again. Verify with /mcp.

Manual install (Claude Desktop or hand-editing config)

If you're using Claude Desktop, or prefer to edit the config file by hand, follow the three steps below.

1. Open your MCP client config file

ClientConfig file path
Claude Code (all platforms)~/.claude.json (Linux/macOS/WSL) or %USERPROFILE%\.claude.json (Windows)
Claude Desktop — macOS~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop — Windows%APPDATA%\Claude\claude_desktop_config.json
Claude Desktop — Linux~/.config/Claude/claude_desktop_config.json

If the file doesn't exist yet, create it with { "mcpServers": {} } as the contents.

2. Add the bitkub-trading-mcp block

Inside the mcpServers object, add this entry. If you already have other MCP servers configured, separate them with a comma — it's a normal JSON object.

{
  "mcpServers": {
    "bitkub-trading-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "bitkub-trading-mcp"],
      "env": {
        "BITKUB_API_KEY": "your_api_key_here",
        "BITKUB_API_SECRET": "your_api_secret_here"
      }
    }
  }
}

Replace the two your_..._here placeholders with your real Bitkub key + secret — see Add your API key below for how to generate them.

3. Restart the client and verify

  • Claude Code: /exit then claude again. Then run /mcp.
  • Claude Desktop: quit the app fully (right-click tray icon → Quit on Windows; Cmd+Q on macOS) and relaunch.

You should see bitkub-trading-mcp connected with 24 tools. The first launch downloads the package from npm (~5–10 seconds); subsequent launches use the cached version.

If BITKUB_API_KEY/BITKUB_API_SECRET are absent, the public tools still work; secure tools register but each call returns an auth error explaining how to add the env block.

Add your API key

Public REST tools and the public ticker WebSocket tool work without a key. The 12 secure REST tools and the 2 private WebSocket tools need a Bitkub API key + secret in your MCP client config's env block — never as tool arguments. The LLM never sees the secret.

1. Generate a key on Bitkub

  1. Go to https://www.bitkub.com/en/api-management and log in if prompted.
  2. Click Create new API key.
  3. Recommended: enable read-only permissions only — uncheck Trade and Withdraw scopes. The server only exposes read-only endpoints, so giving the key write scopes is wasted attack surface.
  4. Copy the API Key and API Secret before closing the dialog (the secret is shown only once).

2. Paste into the env block

Replace the two your_..._here placeholders in whichever Install option you picked above with the real key + secret. Save, restart the MCP client.

3. Verify the key actually works

If you have the source checked out:

cd /path/to/bitkub-trading-mcp
eval "$(bun -e 'const c=await Bun.file(`${process.env.HOME}/.claude.json`).json();const e=c.mcpServers[`bitkub-trading-mcp`].env;console.log(`export BITKUB_API_KEY=${e.BITKUB_API_KEY}\nexport BITKUB_API_SECRET=${e.BITKUB_API_SECRET}`)')" && bun scripts/test-auth.ts

PASS means the key + signing path is working end-to-end against Bitkub.

Otherwise, just ask Claude "What's in my Bitkub wallet?" — if it returns balances, the key works.

Public tools

ToolEndpoint
bitkub_statusGET /api/status
bitkub_servertimeGET /api/v3/servertime (ms)
bitkub_symbolsGET /api/v3/market/symbols
bitkub_tickerGET /api/v3/market/ticker?sym= — omit sym to fetch ALL symbols in one call
bitkub_bidsGET /api/v3/market/bids?sym=&lmt=
bitkub_asksGET /api/v3/market/asks?sym=&lmt=
bitkub_depthGET /api/v3/market/depth?sym=&lmt=
bitkub_tradesGET /api/v3/market/trades?sym=&lmt=
bitkub_tv_historyGET /tradingview/history?symbol=&resolution=&from=&to=

Secure tools (read-only, auth required)

Bitkub v4 is used wherever it has an equivalent; v3 endpoints are kept only where v4 has not yet shipped one. v4 uses GET with query params; v3 mostly used POST with body. Auth signing is identical for v3 and v4.

ToolVerMethodEndpointArgs (zod-validated)
bitkub_balancesv4GET/api/v4/wallet/balancessegment? ("funding")
bitkub_crypto_addressesv4GET/api/v4/crypto/addressespage? (≥1), limit? (1–200), symbol?, network?, memo?
bitkub_crypto_depositsv4GET/api/v4/crypto/depositspage?, limit? (1–200), symbol?, status?, created_start?, created_end? (ISO 8601)
bitkub_crypto_withdrawsv4GET/api/v4/crypto/withdrawssame shape as bitkub_crypto_deposits (read-only history)
bitkub_fiat_accountsv4GET/api/v4/fiat/accountspage? (1–100), limit? (1–100) — must be paired
bitkub_fiat_depositsv4GET/api/v4/fiat/deposit/historypage?, limit? (1–100) — must be paired
bitkub_fiat_withdrawsv4GET/api/v4/fiat/withdraw/historypage?, limit? (1–100) — must be paired (read-only history)
bitkub_my_open_ordersv3GET/api/v3/market/my-open-orderssym
bitkub_my_order_historyv3GET/api/v3/market/my-order-historysym, p?, lmt?, start?, end?
bitkub_order_infov3GET/api/v3/market/order-infosym, id, sd, hash?
bitkub_user_limitsv3POST/api/v3/user/limits(none)
bitkub_user_trading_creditsv3POST/api/v3/user/trading-credits(none)

Auth signing (v3 and v4): X-BTK-APIKEY, X-BTK-TIMESTAMP (Unix ms), X-BTK-SIGN = HMAC-SHA256 of {ts}{METHOD}{path}{?query | body}, hex lowercase. For POSTs the exact JSON bytes sent on the wire are signed.

References: https://github.com/bitkub/bitkub-official-api-docs/blob/master/restful-api.md · https://github.com/bitkub/bitkub-official-api-docs/blob/master/restful-api-v4.md

WebSocket tools (snapshot)

Each call opens a WebSocket, collects events for a bounded duration, then closes. Stateless — no long-lived subscriptions, no MCP notifications.

ToolStreamAuthDefault / max duration
bitkub_ws_ticker_snapshotmarket.ticker.<sym> (public)none10 s / 60 s
bitkub_ws_order_updatesorder_update (private)required30 s / 120 s
bitkub_ws_match_updatesmatch_update (private)required30 s / 120 s

Args (every tool):

  • duration_ms? — int, milliseconds. Defaults and caps as in the table above.
  • bitkub_ws_ticker_snapshot.sym — required (e.g. btc_thb).
  • bitkub_ws_order_updates.sym / bitkub_ws_match_updates.sym — optional post-filter on data.symbol.

Response shape:

{
  "events": [/* raw Bitkub payloads, in receive order */],
  "count": 0,
  "duration_ms_actual": 30000,
  "stream": "order_update",
  "started_at": "2026-05-10T17:00:00.000Z",
  "ended_at":   "2026-05-10T17:00:30.000Z"
}

If the WS closes before the window ends, the response also includes closed_early: true and closed_reason: "...".

Race-condition note: the private streams only deliver events that occur AFTER subscribe is sent. If you want to observe an order's full lifecycle, call bitkub_ws_order_updates in parallel with the order placement — or call bitkub_order_info afterward for the authoritative final state.

Concurrency cap: Bitkub permits at most 5 concurrent private WebSocket connections per API key. The server detects "too many concurrent" closes and surfaces them with a clear message.

Excluded streams (intentional): the public market.trade.* channel (Bitkub deprecates it 2026-05-18) and the public orderbook channel (uses numeric pairing_id instead of symbol; REST bitkub_depth is a better fit).

References: https://github.com/bitkub/bitkub-official-api-docs/blob/master/websocket-api.md · https://github.com/bitkub/bitkub-official-api-docs/blob/master/private-websocket.md

Usage examples

Tools are invoked by Claude based on what you ask in plain English. The "you say" rows show the kind of prompt that triggers the tool; the "tool" rows show what gets called under the hood (you can verify with /mcp → tool history). All examples assume the server is registered and connected.

Public REST — market data (no key needed)

What you sayTool calledNotes
"Is Bitkub's API up right now?"bitkub_statusHealth-check the platform before placing orders manually.
"What's the current BTC/THB price?"bitkub_ticker with sym=btc_thbSingle-shot point-in-time price + 24h change.
"Compare BTC, ETH, ADA, USDT prices" (any multi-symbol query)bitkub_ticker with no args — ONE call returns ALL symbolsDon't loop per-symbol; one batched call is faster and avoids rate limits.
"Show me top 10 buy orders for ETH/THB"bitkub_bids with sym=eth_thb, lmt=10Open buy orders (bids). Use bitkub_asks for sells.
"What's the order book depth for BTC/THB, top 20 levels?"bitkub_depth with sym=btc_thb, lmt=20Aggregated bids/asks — best for spread analysis.
"Last 50 trades on USDT/THB"bitkub_trades with sym=usdt_thb, lmt=50Recent matched trades (timestamp, price, side, amount).
"List all trading pairs available on Bitkub"bitkub_symbolsUseful when you don't know the exact sym string.
"Get BTC/THB hourly candles for the last 24 hours"bitkub_tv_history with symbol=BTC_THB, resolution=60, from=<ts>, to=<ts>OHLCV for charting. Resolutions: 1, 5, 15, 60, 240, 1D.
"What's the server's current time?"bitkub_servertimeSanity-check clock skew if signed requests fail.

Private REST — your account (key required, read-only)

What you sayTool calledNotes
"What's in my Bitkub wallet?"bitkub_balancesv4 endpoint. Returns currency, available, reserved, total per asset.
"List my open orders for BTC/THB"bitkub_my_open_orders with sym=btc_thbCurrently active orders only.
"Show my last 20 BTC/THB orders, including filled/cancelled"bitkub_my_order_history with sym=btc_thb, lmt=20Full history with pagination.
"Tell me the status of order ID 123456 (buy side)"bitkub_order_info with sym=btc_thb, id=123456, sd=buyAuthoritative current state of a specific order.
"What are my user trading limits?"bitkub_user_limitsDaily / monthly THB throughput caps.
"How much trading credit do I have?"bitkub_user_trading_creditsBitkub trading-credit balance (used for fee discounts).
"List my saved crypto deposit addresses"bitkub_crypto_addresses with limit=50v4. Filter by symbol, network, memo.
"Show my crypto deposits in the last 30 days"bitkub_crypto_deposits with created_start=2026-04-10T00:00:00Z, limit=100v4 with date filtering. 90-day max window.
"Show my crypto withdrawals this month"bitkub_crypto_withdraws with created_start=2026-05-01T00:00:00Zv4 same shape as deposits.
"List my registered bank accounts"bitkub_fiat_accounts with page=1, limit=20page+limit must be paired — provide both or neither.
"My fiat deposit history"bitkub_fiat_deposits with page=1, limit=20Same pairing rule.
"My fiat withdrawal history"bitkub_fiat_withdraws with page=1, limit=20Same pairing rule.

Public WebSocket — live ticker (no key)

What you sayTool calledNotes
"Sample BTC/THB price for 10 seconds. Is it trending up or down?"bitkub_ws_ticker_snapshot with sym=btc_thb, duration_ms=10000Returns array of ticker updates; Claude computes first-vs-last delta.
"Watch ETH/THB for 30s and tell me the volatility"bitkub_ws_ticker_snapshot with sym=eth_thb, duration_ms=30000Useful before market-buying so you see actual spread movement.
"Did BTC just spike? Sample for 15 seconds."bitkub_ws_ticker_snapshot with sym=btc_thb, duration_ms=15000Catches micro-movements REST polling would miss.

Caveat: Bitkub sometimes closes the public ticker stream after just a few seconds during low activity. The response will include closed_early: true when that happens — Claude can rerun if needed.

Private WebSocket — order / match streams (key required)

What you sayTool calledNotes
"Watch my account for 60 seconds and report any order events"bitkub_ws_order_updates with duration_ms=60000Captures new → open → partial_filled → filled → canceled transitions.
"Watch only BTC/THB order updates for 90s"bitkub_ws_order_updates with sym=btc_thb, duration_ms=90000sym post-filters events by data.symbol.
"Wait 60 seconds and tell me what trades I executed"bitkub_ws_match_updates with duration_ms=60000Each match = one fill. Aggregates into avg fill price + total fees.
"Compare maker vs taker fill rate over the next 90s"bitkub_ws_match_updates with duration_ms=90000is_maker field on each match.

Race-condition recipe. Private WS only delivers events that occur AFTER subscribe — to capture an order's full lifecycle:

"Place a BTC limit buy at 2.7M for 0.0001 BTC, and IN PARALLEL watch order_updates for 60 seconds. Then call bitkub_order_info to confirm final state."

In one Claude turn, all three tool calls fire in parallel. The WS captures most lifecycle events; the REST order_info call provides the authoritative final state in case any early events were missed.

Note: This server does NOT include order placement — you'd add a separate trading server (or place manually on Bitkub) for the place step. The watch + verify pattern still works against an order placed by other means.

Combined workflows (multiple tools in one prompt)

WorkflowTools used (parallel)
"Show me BTC/THB depth, last 50 trades, and watch ticker for 10s. Tell me if it's a good time to buy."bitkub_depth + bitkub_trades + bitkub_ws_ticker_snapshot
"Audit my last 24h: balances now, all crypto deposits since yesterday, and any open orders."bitkub_balances + bitkub_crypto_deposits (with created_start) + bitkub_my_open_orders (per symbol)
"My order is stuck at 'open' in the UI. Get its REST state AND watch order_updates for 30s to see if anything moves."bitkub_order_info + bitkub_ws_order_updates

Security

  • Read-only by design. This server intentionally does NOT implement order placement, order cancellation, withdrawal initiation, or address generation. Only data-retrieval endpoints are exposed.
  • Use a read-only Bitkub API key. Bitkub's API-key permission model lets you scope a key to read-only operations — please do that. The server will refuse nothing on its own, but a least-privilege key gives you a hard guarantee at the exchange level even if anything misbehaves.
  • Credentials are never accepted as tool arguments. They are read from process.env only, sourced from the MCP client's env block. The LLM cannot see the secret.
  • Secrets aren't logged. Diagnostics on stderr only mention whether creds are present, never their values.
  • Rotate keys by updating the env block in your client config and restarting the MCP client; no server-code change required.

Notes

  • All responses pass Bitkub's JSON through unchanged (no field remapping).
  • Bitkub envelope errors (error != 0) are surfaced as MCP tool errors with the original error code.
  • HTTP non-2xx is surfaced with the status and response body.
  • Diagnostics are written to stderr only — stdout is reserved for the MCP transport.

服务器配置

{
  "mcpServers": {
    "bitkub-trading-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "bitkub-trading-mcp"
      ],
      "env": {
        "BITKUB_API_KEY": "your_real_key_here",
        "BITKUB_API_SECRET": "your_real_secret_here"
      }
    }
  }
}
© 2025 MCP.so. All rights reserved.

Build with ShipAny.