kainext-binance-mcp
Let an AI assistant read Binance spot markets, analyze them, and propose real-money trades — while a separate, human-gated process is the only thing that can ever execute. The model never holds a trade key, and nothing moves without a physical click.
The gate. Every order renders exactly what will execute — and the default button is Cancel.
kainext-binance-mcp is a Model Context Protocol server
that connects any MCP client (Claude Code, Claude Desktop, …) to a Binance spot account.
It exposes 18 tools spanning live market data, technical indicators, news & sentiment,
transparent trading signals, and two-phase order execution with a human in the loop.
It is built around one uncompromising idea: treat the language model as untrusted. Even a fully prompt-injected or malfunctioning model cannot move your funds, because it has neither the credential nor the authority to do so. See SECURITY.md for the full threat model.
⚠️ Real money. On
mainnet, every order moves actual funds. Always start on testnet and switch to mainnet only once everything is verified. ⚠️ Execution currently requires macOS. The confirmer usesosascriptfor the native confirmation dialog. Read/analysis tools are cross-platform; execution on other OSes is on the roadmap.
Why this exists
LLM agents are great at reasoning about markets and terrible at being trusted with irreversible, money-moving actions. Most "AI trading" tooling hands the model an API key and hopes for the best. This project takes the opposite stance: the AI gets rich, read-only context and a way to propose an action, but a human holds the trigger and a separate process holds the key. You get the upside of an AI co-pilot for spot trading without surrendering custody or control.
Security model — the headline feature
Two processes, least privilege, human-in-the-loop:
| Process | Launched by | Key | Role |
|---|---|---|---|
MCP server kainext-binance-mcp |
your MCP client (stdio) | read-only (BINANCE_READ_*) |
reads, pre-validates, and proposes orders. Never executes, holds no trade key. |
Confirmer kainext-binance-mcp-confirmer |
you, in a separate terminal | trade (BINANCE_TRADE_*) |
the sole authority: receives canonical fields, renders the dialog, re-validates, and executes only on your click. |
sequenceDiagram
participant AI as AI model (untrusted)
participant S as MCP server<br/>(read-only key)
participant C as Confirmer<br/>(trade key)
participant H as You (human)
participant B as Binance
AI->>S: binance_spot_order_propose(...)
S->>S: pre-validate vs symbol filters
S->>C: canonical fields (local IPC socket)
S-->>AI: intent_id (no order placed yet)
C->>H: native dialog with exact fields ⚠️
H-->>C: physical click: Confirm / Cancel
C->>C: re-validate
C->>B: execute (only if confirmed)
AI->>S: binance_spot_order_status(intent_id)
S-->>AI: pending → executed / rejected / expired
To execute one order you need both the trade key (isolated in the confirmer) and your physical click. The model has neither. Defense in depth on top of that:
- On mainnet, the server aborts at startup if its read key can trade.
- The confirmer aborts at startup if the trade key has withdrawals/transfer/margin/futures permissions or no IP whitelist.
- Withdrawals and transfers are permanently out of scope — no key enables them.
- Single-tenant: one server+confirmer pair serves exactly one account; run separate pairs for separate accounts.
Tools (18)
Read (5 · read key · no gate)
| Tool | What it does | Params |
|---|---|---|
binance_get_balance |
Spot balances (free/locked), non-zero only | — |
binance_get_price |
Current price/ticker for a symbol | symbol |
binance_get_open_orders |
Open spot orders + status | symbol? |
binance_get_order_history |
Closed spot order history | symbol, limit? |
binance_get_account_info |
Flags + fees; key permissions (mainnet) | — |
Market data — layer 2 (4 · read key · 100% read-only)
| Tool | What it does | Params |
|---|---|---|
binance_get_klines |
OHLCV candles (Decimal). last_n returns only the newest N to keep responses small |
symbol, interval, limit? (≤1000), last_n? |
binance_get_ticker_24h |
Rolling 24h stats (% change, high/low, volume) | symbol |
binance_compute_indicators |
RSI / MACD / EMA / Bollinger / ATR. Returns only the latest value per series by default (last_n=1) to keep responses small; raise last_n for recent history |
symbol, interval, indicators, limit?, last_n? |
binance_backtest |
Lightweight, no-lookahead backtest of a simple rule | symbol, interval, strategy (ema_cross/rsi_threshold), limit? |
News & sentiment — layer 3 (2 · public RSS · no API key · 100% read-only)
| Tool | What it does | Params |
|---|---|---|
binance_get_news |
Crypto headlines from RSS (CoinDesk, crypto.news) | asset?, sources?, limit? |
binance_get_sentiment |
Aggregated raw sentiment (lexicon, not a prediction) | asset, window_hours? |
Signals — layer 4 (3 · read key · propose, never execute)
| Tool | What it does | Params |
|---|---|---|
binance_generate_signal |
Composite, transparent signal: direction + score + per-factor rationale + ATR risk levels | symbol, interval?, threshold? |
binance_scan_signals |
Signals for a watchlist, ranked by score | symbols, interval? |
binance_backtest_signal |
Backtest the composite technical signal (no lookahead, sentiment=0) | symbol, interval?, limit?, threshold? |
Write — two-phase (4 · spot only · the server never executes)
| Tool | What it does | Params |
|---|---|---|
binance_spot_order_propose |
Proposes an order; does not execute. Returns intent_id |
symbol, side, type, env, quantity?, quote_quantity?, price?, time_in_force? |
binance_spot_order_status |
Polls the outcome of a proposal | intent_id |
binance_cancel_order_propose |
Proposes a cancellation (re-checks state); does not cancel | symbol, order_id, env |
binance_cancel_order_status |
Polls the outcome of a cancellation | intent_id |
The read, market-data, news, and signal tools work without the confirmer. The *_propose
tools require the confirmer to be running.
Quickstart
Prerequisites: Python 3.12+, uv, and (for execution) macOS.
1. Create the API key(s) on Binance
Go to Binance → API Management. The design uses two keys for least privilege:
- Read-only (used by the server):
Enable ReadingON; everything else OFF. - Trade (used by the confirmer):
Enable Spot & Margin TradingON; withdrawals, universal/internal transfer, margin, futures OFF; IP whitelist mandatory. The confirmer aborts on mainnet if any dangerous permission is on or the IP restriction is off.
On testnet (testnet.binance.vision), a single key serves both roles — there are no granular permissions or IP whitelist there.
2. Set environment variables
| Variable | Process | Where it goes |
|---|---|---|
BINANCE_ENV |
both | testnet or mainnet (no default → aborts if missing/invalid) |
BINANCE_READ_API_KEY / BINANCE_READ_API_SECRET |
server | .mcp.json (via ${VAR}) or the server's shell |
BINANCE_TRADE_API_KEY / BINANCE_TRADE_API_SECRET |
confirmer | only the shell where you launch the confirmer |
🔒 Hard rule: the trade key never goes in
.mcp.jsonor any environment your AI client inherits. It lives only in the confirmer's shell.
3. Add the server to your MCP client
.mcp.json (Claude Code style). Only the read key + BINANCE_ENV:
{
"mcpServers": {
"binance": {
"command": "uvx",
"args": ["kainext-binance-mcp"],
"env": {
"BINANCE_ENV": "${BINANCE_ENV}",
"BINANCE_READ_API_KEY": "${BINANCE_READ_API_KEY}",
"BINANCE_READ_API_SECRET": "${BINANCE_READ_API_SECRET}"
}
}
}
}
${VAR} placeholders are resolved from your shell. If a variable arrives unexpanded, the
server aborts with a clear message — export the variables before launching your client.
Installing from git instead of PyPI? Use "args": ["--from", "git+https://github.com/Alejandrehl/kainext-binance-mcp@v1.0.0", "kainext-binance-mcp"]
(pin a tag; git+https works without any GitHub credentials).
4. Run the confirmer (required to execute)
In a separate terminal, with the trade key exported:
export BINANCE_ENV=testnet
export BINANCE_TRADE_API_KEY="...your trade key..."
export BINANCE_TRADE_API_SECRET="...your trade secret..."
uvx kainext-binance-mcp-confirmer # or: uvx --from "git+https://github.com/Alejandrehl/kainext-binance-mcp@v1.0.0" kainext-binance-mcp-confirmer
It listens on a local Unix socket. When the AI proposes an order, a native dialog appears
with the exact fields (symbol, side, type, effective quantity, price, timeInForce, estimated
notional, and a TESTNET / ⚠️ REAL MONEY banner). The default button is Cancel; the
order executes only when you click Confirm.
Testnet-first (recommended)
- Generate keys at testnet.binance.vision (login with GitHub → Generate HMAC_SHA256 Key) and request faucet funds.
- Export
BINANCE_ENV=testnetand the testnet keys. - Exercise the full flow with fake money before touching mainnet.
Mainnet = real money + macOS
On mainnet, the confirmer re-validates against live symbol filters, shows the
⚠️ REAL MONEY banner, and waits for your click. Start with minimal order sizes. Execution
requires macOS (the dialog uses osascript).
Development
Requires Python 3.12+ and uv. See CONTRIBUTING.md for details.
uv venv --python 3.12
uv pip install -e ".[dev]"
uv run ruff check src/ tests/ examples/ # lint (the release gate)
uv run mypy # strict type checking
uv run pytest -q # tests + coverage (hard gate: 90% min)
The unit suite runs fully offline. Integration tests (-m integration) hit Binance testnet
and skip cleanly without keys; the news test hits live RSS only with RUN_NETWORK_TESTS=1.
CI runs lint + types + tests on ubuntu and macOS (the confirmer's target OS) across
Python 3.12/3.13, plus pip-audit and CodeQL, on every push and PR. pre-commit install
gets you the same ruff check locally.
Roadmap
- Migrate to MCP SDK 2.x (v1.0.0 pins
mcp==1.29.0; 2.0 is a breaking API change). - Headless / non-macOS confirmation (today the dialog is macOS-only via
osascript). - Additional order types and exchange surfaces beyond spot.
- Optional notification channels for proposal/execution events.
Research: is there an edge?
We backtested our own composite signal the hard way — out-of-sample walk-forward over ~51,000 real candles (4 pairs x 3 timeframes x 3 strategies, grid search on train windows, measured on unseen test windows, triple anti-lookahead). Result: 0 of 36 configurations showed a robust out-of-sample edge; in-sample "edges" were overfitting.
That is why every signal tool ships with a disclaimer: the signals are context, not alpha.
Full write-ups and reproducible scripts: docs/research/ + examples/.
Disclaimer
This software is not financial advice and comes with no warranty (MIT). Trading cryptocurrencies can result in the loss of your entire capital. Signals, indicators, and backtests are informational; past performance does not predict future results. You are solely responsible for every order you confirm — that is exactly why the human gate exists.
Author
Built by Alejandro Exequiel Hernández Lara — founder of KaiNext. Part of KaiNext's MCP product line.
License
MIT © 2026 Alejandro Exequiel Hernández Lara (KaiNext)
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kainext_binance_mcp-1.0.0.tar.gz.
File metadata
- Download URL: kainext_binance_mcp-1.0.0.tar.gz
- Upload date:
- Size: 207.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
245a2ed25d8811d81871f9f9ff881d9e35b0fe07fe1515bd1ce638e7049cfeb4
|
|
| MD5 |
e7e99747230be05d0cee11dab2a138f9
|
|
| BLAKE2b-256 |
1e71212e99fbd5080e03751b0ef1720687f009f74ca243b69b5417b92c1bc527
|
Provenance
The following attestation bundles were made for kainext_binance_mcp-1.0.0.tar.gz:
Publisher:
release.yml on Alejandrehl/kainext-binance-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kainext_binance_mcp-1.0.0.tar.gz -
Subject digest:
245a2ed25d8811d81871f9f9ff881d9e35b0fe07fe1515bd1ce638e7049cfeb4 - Sigstore transparency entry: 2567735857
- Sigstore integration time:
-
Permalink:
Alejandrehl/kainext-binance-mcp@87dae821e8d3b0708fb93e2c2036e47848384f35 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Alejandrehl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@87dae821e8d3b0708fb93e2c2036e47848384f35 -
Trigger Event:
push
-
Statement type:
File details
Details for the file kainext_binance_mcp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: kainext_binance_mcp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 65.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
698c445fcd2669b4e78ef5a8be0a10fb68211b6cec7e934f7793961f36d560b1
|
|
| MD5 |
e2ba26b6dc1909ed26812f592ce60fac
|
|
| BLAKE2b-256 |
7d4b4487c425da5075e632bf09e4bb025bc4bc9f47c8707f37a66988f0a2eb0d
|
Provenance
The following attestation bundles were made for kainext_binance_mcp-1.0.0-py3-none-any.whl:
Publisher:
release.yml on Alejandrehl/kainext-binance-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kainext_binance_mcp-1.0.0-py3-none-any.whl -
Subject digest:
698c445fcd2669b4e78ef5a8be0a10fb68211b6cec7e934f7793961f36d560b1 - Sigstore transparency entry: 2567735884
- Sigstore integration time:
-
Permalink:
Alejandrehl/kainext-binance-mcp@87dae821e8d3b0708fb93e2c2036e47848384f35 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Alejandrehl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@87dae821e8d3b0708fb93e2c2036e47848384f35 -
Trigger Event:
push
-
Statement type: