> ## 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.

# AI tools FAQ

> Common questions about the WhiteBIT MCP server and CLI — API key safety, supported clients, account setup, and automation.

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 />

Answers to common questions about the WhiteBIT MCP server and CLI.

## MCP server and CLI capabilities

The MCP server provides 115 tools covering market data, spot trading, collateral trading, wallet operations, lending, sub-accounts, mining pool, and currency conversion. All tools are available to any connected AI client using natural language.

The CLI provides 110+ commands covering the same API surface, designed for terminal use, scripting, and CI/CD pipelines.

See [MCP server](/guides/mcp-server) and [CLI](/guides/cli) for the full tool and command listings.

## Supported AI clients

The MCP server works with any client that supports the Model Context Protocol. Supported clients include:

* **Claude Code** — global or project-scoped registration via `claude mcp add`
* **Cursor** — configuration via `~/.cursor/mcp.json`
* **Claude Desktop** — configuration via the application config file
* **Codex** — configuration via `~/.codex/config.toml`
* **OpenClaw** — configuration via the agent config file

See [MCP server — Connect an AI client](/guides/mcp-server#connect-an-ai-client) for setup instructions for each client.

## API key security

API keys are passed as parameters in each tool call and are used only to sign outgoing WhiteBIT API requests. The MCP server does not store, log, or cache credentials. All processing happens locally — no data is sent to external services beyond WhiteBIT.

For public market data tools (tickers, order book, market info), pass `"public"` for both `api_key` and `secret_key`. No account credentials are required for public endpoints.

See [Authentication](/api-reference/authentication) for instructions on generating and managing API keys.

## Trading MCP server vs documentation MCP

The WhiteBIT documentation portal has two separate MCP integrations that serve different purposes:

| MCP                          | Purpose                                       | Endpoint                                  |
| ---------------------------- | --------------------------------------------- | ----------------------------------------- |
| Trading MCP (`whitebit-mcp`) | Execute trades, query balances, manage orders | `http://localhost:8080/mcp` (self-hosted) |
| Documentation MCP            | Search the WhiteBIT API documentation         | `https://docs.whitebit.com/mcp` (hosted)  |

The trading MCP is a self-hosted server that requires cloning the [whitebit-mcp](https://github.com/whitebit-exchange/whitebit-mcp) repository and starting a local Docker container. See [MCP server](/guides/mcp-server).

The documentation MCP is a Mintlify-hosted service. See [Docs search via MCP](/guides/ai-ide-setup).

## Public market data without API keys

Public market data tools do not require a WhiteBIT account. Pass `"public"` for both `api_key` and `secret_key` parameters, then ask questions like:

* "What is the current BTC\_USDT price?"
* "Show the order book for ETH\_USDT"
* "List all available trading pairs"

The CLI market module also requires no authentication:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
whitebit market list
whitebit market ticker BTC_USDT
```

## CLI use in automation

The CLI is designed for scripting and automation:

* `--json` flag on every command outputs machine-readable JSON, compatible with `jq` and any data pipeline.
* `--dry-run` flag previews the exact API request payload without sending it — useful for validating scripts.
* Exit codes (`0` success, `2` auth error, `5` rate limit, etc.) allow precise error handling in shell scripts.
* Multi-profile support enables switching between API keys with `--profile`.

See [CLI — JSON output and scripting](/guides/cli#examples) for examples.

## Safe account practices

Before connecting AI tools to 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 permissions required — read-only keys are sufficient for balance and order queries.
* Enable IP whitelisting on the API key to restrict access to the machine running the MCP server.
* Test with small amounts before executing larger trades.
* Never provide API keys in the AI conversation — pass credentials as tool parameters at session start only.

See [MCP server — Safe account practices](/guides/mcp-server#safe-account-practices) for the full checklist.

## Report an issue

Report bugs or request features by opening an issue on the relevant GitHub repository:

* [whitebit-mcp issues](https://github.com/whitebit-exchange/whitebit-mcp/issues) — MCP server bugs and feature requests
* [whitebit-cli issues](https://github.com/whitebit-exchange/whitebit-cli/issues) — CLI bugs and feature requests

Include the full error output when reporting a bug. For MCP errors, include the structured error block from the AI client. For CLI errors, include the full stderr output.

## Related resources

* [MCP server](/guides/mcp-server) — Full setup guide for the WhiteBIT trading MCP server
* [CLI](/guides/cli) — Full setup and command reference for the WhiteBIT CLI
* [Docs search via MCP](/guides/ai-ide-setup) — Connect Cursor, VS Code, or Claude Desktop to the documentation search MCP
* [Authentication](/api-reference/authentication) — How to generate and manage WhiteBIT API keys
