> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whitebit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Connect Claude Code, Cursor, Claude Desktop, Codex, or OpenClaw to 115 WhiteBIT trading tools using the Model Context Protocol.

export const RegionBaseUrl = ({className = "", showBaseUrl = true}) => {
  const [region, setRegionState] = useState(() => {
    if (typeof window !== 'undefined') {
      return localStorage.getItem("api-region-preference") || "com";
    }
    return "com";
  });
  const [mounted, setMounted] = useState(false);
  const observerRef = useRef(null);
  const isSyncingRef = useRef(false);
  const updateAllContentOnPage = targetRegion => {
    try {
      const domainFrom = targetRegion === "eu" ? "whitebit.com" : "whitebit.eu";
      const domainTo = targetRegion === "eu" ? "whitebit.eu" : "whitebit.com";
      const links = document.querySelectorAll('a');
      links.forEach(link => {
        let href = link.getAttribute('href');
        if (href && href.includes(domainFrom)) {
          link.setAttribute('href', href.replace(domainFrom, domainTo));
        }
      });
      const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
        acceptNode: node => {
          if (node.parentElement?.closest('.region-toggle-component')) {
            return NodeFilter.FILTER_REJECT;
          }
          return node.textContent.includes(domainFrom) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
        }
      });
      let currentNode;
      while (currentNode = walker.nextNode()) {
        currentNode.textContent = currentNode.textContent.replace(new RegExp(domainFrom, 'g'), domainTo);
      }
      console.log(`[RegionSync] Global content updated to ${domainTo}`);
    } catch (e) {
      console.error("[RegionSync] Error updating content:", e);
    }
  };
  const updateRegion = (newRegion, source) => {
    if (region === newRegion) return;
    console.log(`[RegionBaseUrl] Updating to "${newRegion}" (Source: ${source})`);
    if (source === 'observer') {
      isSyncingRef.current = true;
      setTimeout(() => isSyncingRef.current = false, 1000);
    }
    setRegionState(newRegion);
    localStorage.setItem("api-region-preference", newRegion);
    updateAllContentOnPage(newRegion);
    if (source === 'user-click') {
      window.dispatchEvent(new CustomEvent("regionChange", {
        detail: newRegion
      }));
      attemptToUpdateNativeDropdown(newRegion, 0);
      setTimeout(() => attemptToUpdateNativeDropdown(newRegion, 1), 500);
      setTimeout(() => attemptToUpdateNativeDropdown(newRegion, 2), 1500);
    }
  };
  const attemptToUpdateNativeDropdown = (targetRegion, attempt) => {
    if (isSyncingRef.current) return;
    try {
      const targetUrl = targetRegion === "eu" ? "https://whitebit.eu" : "https://whitebit.com";
      const targetDesc = targetRegion === "eu" ? "EU Server" : "Production Server";
      const selects = document.querySelectorAll('select');
      for (const select of selects) {
        if (select.innerHTML.includes('whitebit.com') || select.innerHTML.includes('whitebit.eu')) {
          select.value = targetUrl;
          select.dispatchEvent(new Event('change', {
            bubbles: true
          }));
          return;
        }
      }
      const buttons = Array.from(document.querySelectorAll('button, [role="combobox"]'));
      const serverSelector = buttons.find(btn => {
        if (btn.closest('a') || btn.closest('[class*="card"]') || btn.closest('nav')) {
          return false;
        }
        const txt = btn.textContent || "";
        const isServerDropdown = (txt.includes('Production Server') || txt.includes('EU Server') || txt.includes('WhiteBIT Global Server') || txt.includes('WhiteBIT EU Server')) && !txt.includes('Run') && !txt.includes('Send') || btn.getAttribute('role') === 'combobox';
        return isServerDropdown;
      });
      if (serverSelector) {
        const currentText = serverSelector.textContent || "";
        if (currentText.includes(targetDesc)) return;
        serverSelector.click();
        setTimeout(() => {
          const options = document.querySelectorAll('[role="option"], li, button');
          for (const opt of options) {
            const optText = opt.textContent || "";
            if (optText.includes(targetDesc) || optText.includes(targetUrl)) {
              opt.click();
              return;
            }
          }
        }, 100);
      }
    } catch (e) {
      console.error("[Sync] Error:", e);
    }
  };
  useEffect(() => {
    setMounted(true);
    updateAllContentOnPage(region);
    const handleStorageChange = e => {
      if (e.key === "api-region-preference" && e.newValue) {
        updateRegion(e.newValue, 'storage');
      }
    };
    const handleRegionChange = e => {
      if (e.detail !== region) {
        updateRegion(e.detail, 'event');
      }
    };
    window.addEventListener("storage", handleStorageChange);
    window.addEventListener("regionChange", handleRegionChange);
    observerRef.current = new MutationObserver(mutations => {
      if (isSyncingRef.current) return;
      updateAllContentOnPage(region);
      for (const mutation of mutations) {
        if (mutation.type !== 'childList' && mutation.type !== 'characterData') continue;
        const target = mutation.target;
        const el = target.nodeType === Node.TEXT_NODE ? target.parentElement : target;
        if (el && (el.getAttribute('role') === 'option' || el.closest('[role="listbox"]'))) continue;
        const text = target.textContent || "";
        if (text.includes('WhiteBIT EU Server') || text.includes('https://whitebit.eu') && text.includes('Server')) {
          if (el && el.tagName !== 'A' && !el.closest('.region-toggle-component')) {
            if (region !== 'eu') updateRegion('eu', 'observer');
          }
        } else if (text.includes('WhiteBIT Global Server') || text.includes('https://whitebit.com') && text.includes('Server')) {
          if (el && el.tagName !== 'A' && !el.closest('.region-toggle-component')) {
            if (region !== 'com') updateRegion('com', 'observer');
          }
        }
      }
    });
    observerRef.current.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true
    });
    if (typeof window !== 'undefined') {
      const current = localStorage.getItem("api-region-preference");
      if (current) attemptToUpdateNativeDropdown(current, 'init');
    }
    return () => {
      window.removeEventListener("storage", handleStorageChange);
      window.removeEventListener("regionChange", handleRegionChange);
      if (observerRef.current) observerRef.current.disconnect();
    };
  }, [region]);
  const apiBaseUrl = region === "eu" ? "https://whitebit.eu" : "https://whitebit.com";
  if (!mounted) return null;
  return <div className={`flex items-center gap-2 flex-wrap my-4 region-toggle-component ${className}`}>
            <span className="text-sm text-gray-500 dark:text-gray-400 font-mono">
                Base URL
            </span>
            <span className="text-sm text-gray-400">(</span>
            <div className="inline-flex bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5 border border-gray-200 dark:border-gray-700">
                <button onClick={() => updateRegion("com", "user-click")} className={`px-2 py-0.5 text-xs font-medium rounded-md transition-all ${region === "com" ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm" : "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200"}`}>
                    .com
                </button>
                <button onClick={() => updateRegion("eu", "user-click")} className={`px-2 py-0.5 text-xs font-medium rounded-md transition-all ${region === "eu" ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm" : "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200"}`}>
                    .eu
                </button>
            </div>
            <span className="text-sm text-gray-400">)</span>
            {showBaseUrl && <>
                    <span className="text-sm text-gray-400">:</span>
                    <a href={apiBaseUrl} target="_blank" rel="noopener noreferrer" className="text-sm font-mono text-primary dark:text-primary-light hover:underline">
                        {apiBaseUrl}
                    </a>
                </>}
        </div>;
};

<RegionBaseUrl />

The WhiteBIT MCP server exposes the full WhiteBIT API as AI tools over the Model Context Protocol. Connect a supported AI client and interact with markets, trading, balances, wallets, and sub-accounts using natural language.

* **115 tools** across market data, spot trading, collateral trading, wallet, lending, sub-accounts, mining pool, and currency conversion
* Runs locally — API keys never leave the machine
* Credentials are passed per tool call and are not stored or logged by the server

<Note>
  The MCP server documented on this page enables **trading** via AI clients. For documentation search via MCP (searching the WhiteBIT API docs in Cursor or VS Code), see [Docs search via MCP](/guides/ai-ide-setup).
</Note>

## Prerequisites

* A WhiteBIT account with an API key (for trading tools) — see [API key generation](/api-reference/authentication)
* A supported AI client: Claude Code, Cursor, Claude Desktop, Codex, or OpenClaw
* [uv](https://docs.astral.sh/uv/getting-started/installation/) **or** [Docker](https://docs.docker.com/get-docker/)

## Quick start

<Tabs>
  <Tab title="Auto-setup (recommended)">
    One command configures the MCP server for every supported AI client at once. No Docker, no manual config editing.

    <Steps>
      <Step title="Install uv">
        `uv` is a Python package manager that provides the `uvx` command used to run the server.

        <Tabs>
          <Tab title="macOS / Linux">
            ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
            curl -LsSf https://astral.sh/uv/install.sh | sh
            source $HOME/.local/bin/env
            ```
          </Tab>

          <Tab title="Windows">
            ```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
            powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
            ```
          </Tab>
        </Tabs>
      </Step>

      <Step title="Run the setup command">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        uvx whitebit-mcp-setup --public=YOUR_API_KEY --secret=YOUR_SECRET_KEY
        ```

        The script writes the server configuration and credentials into the config of each AI tool it finds:

        | AI tool        | Config file                                                                                                |
        | -------------- | ---------------------------------------------------------------------------------------------------------- |
        | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\…` (Windows) |
        | Claude Code    | `~/.claude/mcp.json`                                                                                       |
        | Cursor         | `~/.cursor/mcp.json`                                                                                       |
        | OpenAI Codex   | `~/.codex/config.toml`                                                                                     |
        | OpenClaw       | `~/.openclaw/openclaw.json`                                                                                |

        Existing configs are updated in place — other MCP servers you have configured are not affected.
      </Step>

      <Step title="Start the MCP server">
        The MCP server is started automatically by your AI client — there is no separate server process to run manually. Under the hood, the setup command registered the following as the server entry in each config:

        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        uvx whitebit-mcp
        ```

        Your AI client will execute this command on startup and keep the server running in the background as long as the client is open.
      </Step>

      <Step title="Restart your AI client">
        Restart the AI client so it picks up the new config and launches the server.

        * **Claude Desktop** — quit and reopen the app
        * **Claude Code** — run `claude mcp list` to reload, or start a new session
        * **Cursor** — open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and run **MCP: Reload Servers**
        * **Codex** — start a new Codex session
        * **OpenClaw** — restart the agent
      </Step>

      <Step title="Verify the connection">
        Ask your AI client something like:

        ```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
        What is the current BTC_USDT price?
        ```

        If the WhiteBIT MCP server is connected, the AI client will call the tool and return live data.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Docker">
    <Steps>
      <Step title="Clone the repository">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        git clone https://github.com/whitebit-exchange/whitebit-mcp
        cd whitebit-mcp
        ```
      </Step>

      <Step title="Start the server">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        docker compose up -d
        ```

        The MCP endpoint is available at `http://localhost:8080/mcp`.
      </Step>

      <Step title="Verify the server is running">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        docker compose ps
        ```

        The `whitebit-mcp` container status shows `Up`.
      </Step>
    </Steps>

    Stop the server at any time:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    docker compose down
    ```

    Then follow the [Connect an AI client](#connect-an-ai-client) section below to register the server in your AI tool.
  </Tab>

  <Tab title="Without Docker">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    pip install mcp whitebit-python-sdk
    mcp run server.py
    ```

    The server listens on `http://0.0.0.0:8000`. Use port `8000` in place of `8080` in all client configurations below.

    Then follow the [Connect an AI client](#connect-an-ai-client) section below to register the server in your AI tool.
  </Tab>
</Tabs>

## Connect an AI client

Skip this section if you used the auto-setup tab above — your AI clients are already configured.

<Tabs>
  <Tab title="Claude Code">
    **Global registration (all projects):**

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    claude mcp add --transport http --scope user whitebit http://localhost:8080/mcp
    ```

    Verify the connection:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    claude mcp list
    # whitebit: http://localhost:8080/mcp (http)
    ```

    **Project-scoped registration:**

    The repository includes a `.mcp.json` file at the project root. Running `claude` from inside the cloned `whitebit-mcp` directory registers the server automatically at project scope.

    Use `/mcp` inside a Claude Code session to see live server status and available tools.
  </Tab>

  <Tab title="Cursor">
    Create or edit `~/.cursor/mcp.json`:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "mcpServers": {
        "whitebit": {
          "url": "http://localhost:8080/mcp"
        }
      }
    }
    ```

    Open the Command Palette (`Cmd+Shift+P` on macOS, `Ctrl+Shift+P` on Windows/Linux) and run **MCP: Reload Servers**.
  </Tab>

  <Tab title="Claude Desktop">
    Edit the Claude Desktop configuration file:

    * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
    * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "mcpServers": {
        "whitebit": {
          "type": "http",
          "url": "http://localhost:8080/mcp"
        }
      }
    }
    ```

    Restart Claude Desktop.
  </Tab>

  <Tab title="Codex">
    Add to `~/.codex/config.toml`:

    ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
    [mcp_servers.whitebit]
    url = "http://localhost:8080/mcp"
    ```

    Start a Codex session — the server connects automatically.
  </Tab>

  <Tab title="OpenClaw">
    Add to the OpenClaw agent configuration:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "mcp_servers": {
        "whitebit": {
          "url": "http://localhost:8080/mcp"
        }
      }
    }
    ```
  </Tab>
</Tabs>

## API keys

Generate API keys at [whitebit.com](https://whitebit.com) → **Profile** → **API Keys**. Use the minimum permissions required for the intended use case — read-only keys are sufficient for balance and order queries.

<Warning>
  Never paste API keys directly into the AI conversation. Pass credentials as tool parameters at the start of a session. The server uses keys only to sign outgoing WhiteBIT API requests — keys are not stored, logged, or cached.
</Warning>

**How credentials work:** API keys are passed as parameters in each tool call. The AI client sends the credentials on behalf of the account holder when provided at the start of the conversation.

**Public market data tools** (market info, tickers, order book) query public endpoints. Pass `"public"` for both `api_key` and `secret_key` when only public data is needed.

### Example: provide credentials at session start

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
API key is YOUR_API_KEY and secret is YOUR_SECRET. Show the spot balance.
```

The AI client passes credentials as tool parameters for the duration of the session.

## Example prompts

### Market data — no API key required

Pass `"public"` for both key fields when querying public endpoints.

* "What is the current BTC\_USDT price?"
* "Show the order book for ETH\_USDT"
* "List all available markets"
* "What are the deposit fees for USDT?"
* "What is the funding rate history for BTC\_USDT?"
* "Is WhiteBIT in maintenance mode?"

### Spot trading — API key required

* "Show the spot balance"
* "List open orders on BTC\_USDT"
* "Place a limit buy order for 0.001 BTC at 90000 on BTC\_USDT"
* "Cancel all open orders on ETH\_USDT"
* "Show order history for the last 30 days"

### Wallet — API key required

* "What is the deposit address for USDT on TRC20?"
* "Show recent deposits and withdrawals"
* "Transfer 100 USDT from the main account to spot trading"
* "Create a WhiteBIT code for 50 USDT"

### Collateral trading — API key required

* "List open collateral positions"
* "Place a collateral limit buy for 0.01 BTC on BTC\_USDT"
* "What is the current leverage?"
* "Close the BTC\_USDT position"

### Sub-accounts — API key required

* "List all sub-accounts"
* "Show the balance of sub-account ID 123"
* "Transfer 200 USDT to sub-account ID 456"

## Configuration reference

| Variable            | Default                | Description                                    |
| ------------------- | ---------------------- | ---------------------------------------------- |
| `WHITEBIT_BASE_URL` | `https://whitebit.com` | API base URL — override for custom deployments |

Set in `docker-compose.yml` or as a shell variable:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
WHITEBIT_BASE_URL=https://whitebit.com docker compose up
```

## Safe account practices

Before using the MCP server with a live account:

* Create a dedicated sub-account with a separate API key for AI tool access.
* Fund the sub-account with only the amount allocated for AI-assisted trading.
* Generate API keys with the minimum required permissions — use read-only keys for monitoring.
* Use IP whitelisting on the API key to restrict access to the machine running the server.
* Test with a small amount before executing larger trades.

## What's next

* [CLI](/guides/cli) — Trade and query account data directly from the terminal without an AI client
* [AI tools FAQ](/guides/ai-faq) — Answers to common questions about API key safety, supported clients, and account practices
* [AI tools overview](/guides/use-with-ai) — All WhiteBIT AI tools in one place
* [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys
* [API Reference Overview](/api-reference/overview) — Full REST API endpoint listing
