binance-futures-mcp 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- binance_futures_mcp-1.0.0.dist-info/METADATA +437 -0
- binance_futures_mcp-1.0.0.dist-info/RECORD +9 -0
- binance_futures_mcp-1.0.0.dist-info/WHEEL +5 -0
- binance_futures_mcp-1.0.0.dist-info/entry_points.txt +2 -0
- binance_futures_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
- binance_futures_mcp-1.0.0.dist-info/top_level.txt +1 -0
- binance_mcp/__init__.py +3 -0
- binance_mcp/__main__.py +7 -0
- binance_mcp/server.py +760 -0
@@ -0,0 +1,437 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: binance-futures-mcp
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: A Model Context Protocol server for Binance Futures API
|
5
|
+
Author: Binance MCP Server
|
6
|
+
License: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/bin-mcp/binance-mcp-server
|
8
|
+
Project-URL: Repository, https://github.com/bin-mcp/binance-mcp-server.git
|
9
|
+
Project-URL: Issues, https://github.com/bin-mcp/binance-mcp-server/issues
|
10
|
+
Keywords: mcp,binance,trading,futures,api,model-context-protocol
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
20
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
21
|
+
Requires-Python: >=3.8
|
22
|
+
Description-Content-Type: text/markdown
|
23
|
+
License-File: LICENSE
|
24
|
+
Requires-Dist: mcp>=1.0.0
|
25
|
+
Requires-Dist: aiohttp>=3.8.0
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
27
|
+
Provides-Extra: dev
|
28
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
29
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
30
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
31
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
33
|
+
Dynamic: license-file
|
34
|
+
|
35
|
+
# Binance MCP Server
|
36
|
+
|
37
|
+
A Model Context Protocol (MCP) server that provides comprehensive access to Binance Futures API endpoints. This server implements all major trading, account management, and market data functionality as documented in the Binance Futures API.
|
38
|
+
|
39
|
+
## Features
|
40
|
+
|
41
|
+
### Account Information Tools
|
42
|
+
- Get account info, balance, and position information
|
43
|
+
- Query position mode and commission rates
|
44
|
+
- Access risk management data (ADL quantile, leverage brackets, force orders)
|
45
|
+
|
46
|
+
### Order Management Tools
|
47
|
+
- Place orders (MARKET, LIMIT, STOP, STOP_MARKET, TRAILING_STOP_MARKET)
|
48
|
+
- Place multiple orders in batch
|
49
|
+
- Cancel orders (single, multiple, or all)
|
50
|
+
- Query order status and history
|
51
|
+
- Auto-cancel functionality
|
52
|
+
|
53
|
+
### Trading Configuration Tools
|
54
|
+
- Change leverage and margin type
|
55
|
+
- Switch between hedge and one-way position modes
|
56
|
+
- Modify position margins
|
57
|
+
|
58
|
+
### Market Data Tools
|
59
|
+
- Get exchange information and trading rules
|
60
|
+
- Access real-time price data and order books
|
61
|
+
- Retrieve candlestick/kline data
|
62
|
+
- Get mark prices and funding rates
|
63
|
+
- Access aggregate trade data
|
64
|
+
|
65
|
+
### Trading History Tools
|
66
|
+
- Get account trade history
|
67
|
+
- Access income history (funding fees, PnL, etc.)
|
68
|
+
- Retrieve funding rate history
|
69
|
+
|
70
|
+
## Installation
|
71
|
+
|
72
|
+
### Prerequisites
|
73
|
+
- Python 3.8 or higher
|
74
|
+
- Binance Futures API credentials
|
75
|
+
|
76
|
+
### Method 1: Install via uvx (Recommended)
|
77
|
+
|
78
|
+
```bash
|
79
|
+
uvx --from git+https://github.com/alexcandrabersiva/bin-mcp binance-mcp-server
|
80
|
+
```
|
81
|
+
|
82
|
+
### Method 2: Local Installation
|
83
|
+
|
84
|
+
```bash
|
85
|
+
cd binance-mcp-server
|
86
|
+
pip install -e .
|
87
|
+
```
|
88
|
+
|
89
|
+
Or install development dependencies:
|
90
|
+
|
91
|
+
```bash
|
92
|
+
pip install -e ".[dev]"
|
93
|
+
```
|
94
|
+
|
95
|
+
## MCP Client Configuration
|
96
|
+
|
97
|
+
This server can be integrated with various MCP clients. Here are configuration examples for popular clients:
|
98
|
+
|
99
|
+
### VS Code
|
100
|
+
|
101
|
+
Add to your VS Code `settings.json`:
|
102
|
+
|
103
|
+
```json
|
104
|
+
{
|
105
|
+
"mcp.servers": {
|
106
|
+
"binance": {
|
107
|
+
"command": "uvx",
|
108
|
+
"args": ["binance-mcp-server"],
|
109
|
+
"env": {
|
110
|
+
"BINANCE_API_KEY": "your_api_key_here",
|
111
|
+
"BINANCE_SECRET_KEY": "your_secret_key_here"
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
```
|
117
|
+
|
118
|
+
### Cursor
|
119
|
+
|
120
|
+
Add to your Cursor configuration file (`.cursor/mcp.json`):
|
121
|
+
|
122
|
+
```json
|
123
|
+
{
|
124
|
+
"servers": {
|
125
|
+
"binance": {
|
126
|
+
"command": "uvx",
|
127
|
+
"args": ["binance-mcp-server"],
|
128
|
+
"env": {
|
129
|
+
"BINANCE_API_KEY": "your_api_key_here",
|
130
|
+
"BINANCE_SECRET_KEY": "your_secret_key_here"
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
### Windsurf
|
138
|
+
|
139
|
+
Add to your Windsurf configuration (`.windsurf/mcp.json`):
|
140
|
+
|
141
|
+
```json
|
142
|
+
{
|
143
|
+
"mcpServers": {
|
144
|
+
"binance": {
|
145
|
+
"command": "uvx",
|
146
|
+
"args": ["binance-mcp-server"],
|
147
|
+
"env": {
|
148
|
+
"BINANCE_API_KEY": "your_api_key_here",
|
149
|
+
"BINANCE_SECRET_KEY": "your_secret_key_here"
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
154
|
+
```
|
155
|
+
|
156
|
+
### Claude Desktop
|
157
|
+
|
158
|
+
Add to your Claude Desktop configuration file:
|
159
|
+
|
160
|
+
**On macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
161
|
+
**On Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
|
162
|
+
|
163
|
+
```json
|
164
|
+
{
|
165
|
+
"mcpServers": {
|
166
|
+
"binance": {
|
167
|
+
"command": "uvx",
|
168
|
+
"args": ["binance-mcp-server"],
|
169
|
+
"env": {
|
170
|
+
"BINANCE_API_KEY": "your_api_key_here",
|
171
|
+
"BINANCE_SECRET_KEY": "your_secret_key_here"
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
```
|
177
|
+
|
178
|
+
### Configuration Notes
|
179
|
+
|
180
|
+
1. **No path needed**: With PyPI installation, you don't need to specify paths or working directories.
|
181
|
+
|
182
|
+
2. **Set API credentials**: Replace `your_api_key_here` and `your_secret_key_here` with your actual Binance API credentials.
|
183
|
+
|
184
|
+
3. **Alternative commands**: You can also use:
|
185
|
+
- `pip install binance-mcp-server && python -m binance_mcp`
|
186
|
+
- `binance-mcp-server` (if installed globally)
|
187
|
+
|
188
|
+
4. **Python environment**: Using `uvx` automatically handles the Python environment.
|
189
|
+
|
190
|
+
5. **Security**: For production use, consider storing credentials in your system's environment variables instead of directly in configuration files.
|
191
|
+
|
192
|
+
## Installation
|
193
|
+
|
194
|
+
### Prerequisites
|
195
|
+
- Python 3.8 or higher
|
196
|
+
- Binance Futures API credentials
|
197
|
+
|
198
|
+
### Method 1: Install via uvx (Recommended)
|
199
|
+
|
200
|
+
```bash
|
201
|
+
uvx --from git+https://github.com/alexcandrabersiva/bin-mcp binance-mcp-server
|
202
|
+
```
|
203
|
+
|
204
|
+
### Method 2: Local Installation
|
205
|
+
|
206
|
+
```bash
|
207
|
+
cd binance-mcp-server
|
208
|
+
pip install -e .
|
209
|
+
```
|
210
|
+
|
211
|
+
Or install development dependencies:
|
212
|
+
|
213
|
+
```bash
|
214
|
+
pip install -e ".[dev]"
|
215
|
+
```
|
216
|
+
|
217
|
+
## Configuration
|
218
|
+
|
219
|
+
### Environment Variables
|
220
|
+
|
221
|
+
Set your Binance API credentials as environment variables:
|
222
|
+
|
223
|
+
```bash
|
224
|
+
export BINANCE_API_KEY="your_api_key_here"
|
225
|
+
export BINANCE_SECRET_KEY="your_secret_key_here"
|
226
|
+
```
|
227
|
+
|
228
|
+
### API Permissions
|
229
|
+
|
230
|
+
Your Binance API key needs the following permissions:
|
231
|
+
- **Futures Trading**: For order placement and management
|
232
|
+
- **Futures Reading**: For account and market data access
|
233
|
+
|
234
|
+
**Note**: Market data endpoints (exchange info, prices, order books, etc.) work without authentication.
|
235
|
+
|
236
|
+
## Usage
|
237
|
+
|
238
|
+
### Running the Server
|
239
|
+
|
240
|
+
```bash
|
241
|
+
# Run directly
|
242
|
+
python -m binance_mcp
|
243
|
+
|
244
|
+
# Or using the installed script
|
245
|
+
binance-mcp-server
|
246
|
+
```
|
247
|
+
|
248
|
+
### Available Tools
|
249
|
+
|
250
|
+
The server provides 32 tools organized into categories:
|
251
|
+
|
252
|
+
#### Account Information (5 tools)
|
253
|
+
- `get_account_info` - Get futures account information
|
254
|
+
- `get_balance` - Get account balance for all assets
|
255
|
+
- `get_position_info` - Get current position information
|
256
|
+
- `get_position_mode` - Get position mode (Hedge/One-way)
|
257
|
+
- `get_commission_rate` - Get commission rate for a symbol
|
258
|
+
|
259
|
+
#### Risk Management (4 tools)
|
260
|
+
- `get_adl_quantile` - Get ADL quantile estimation
|
261
|
+
- `get_leverage_brackets` - Get leverage brackets
|
262
|
+
- `get_force_orders` - Get liquidation orders
|
263
|
+
- `get_position_margin_history` - Get margin change history
|
264
|
+
|
265
|
+
#### Order Management (10 tools)
|
266
|
+
- `place_order` - Place a futures order
|
267
|
+
- `place_multiple_orders` - Place multiple orders in batch
|
268
|
+
- `cancel_order` - Cancel an active order
|
269
|
+
- `cancel_multiple_orders` - Cancel multiple orders
|
270
|
+
- `cancel_all_orders` - Cancel all open orders for a symbol
|
271
|
+
- `auto_cancel_all_orders` - Set up auto-cancellation
|
272
|
+
- `get_open_order` - Query specific open order
|
273
|
+
- `get_open_orders` - Get all open orders
|
274
|
+
- `get_all_orders` - Get all orders (filled, canceled, rejected)
|
275
|
+
- `query_order` - Query order status
|
276
|
+
|
277
|
+
#### Trading Configuration (4 tools)
|
278
|
+
- `change_leverage` - Change initial leverage
|
279
|
+
- `change_margin_type` - Change margin type (ISOLATED/CROSSED)
|
280
|
+
- `change_position_mode` - Change position mode
|
281
|
+
- `modify_position_margin` - Modify position margin
|
282
|
+
|
283
|
+
#### Market Data (6 tools)
|
284
|
+
- `get_exchange_info` - Get trading rules and symbol info
|
285
|
+
- `get_book_ticker` - Get best bid/ask prices
|
286
|
+
- `get_price_ticker` - Get latest prices
|
287
|
+
- `get_order_book` - Get order book depth
|
288
|
+
- `get_klines` - Get candlestick data
|
289
|
+
- `get_mark_price` - Get mark price and funding rate
|
290
|
+
- `get_aggregate_trades` - Get aggregate trade data
|
291
|
+
|
292
|
+
#### Trading History (3 tools)
|
293
|
+
- `get_account_trades` - Get account trade history
|
294
|
+
- `get_income_history` - Get income history
|
295
|
+
- `get_funding_rate_history` - Get funding rate history
|
296
|
+
|
297
|
+
## Example Usage
|
298
|
+
|
299
|
+
### Place a Market Order
|
300
|
+
|
301
|
+
```json
|
302
|
+
{
|
303
|
+
"tool": "place_order",
|
304
|
+
"arguments": {
|
305
|
+
"symbol": "BTCUSDT",
|
306
|
+
"side": "BUY",
|
307
|
+
"order_type": "MARKET",
|
308
|
+
"quantity": 0.001
|
309
|
+
}
|
310
|
+
}
|
311
|
+
```
|
312
|
+
|
313
|
+
### Place a Limit Order
|
314
|
+
|
315
|
+
```json
|
316
|
+
{
|
317
|
+
"tool": "place_order",
|
318
|
+
"arguments": {
|
319
|
+
"symbol": "BTCUSDT",
|
320
|
+
"side": "BUY",
|
321
|
+
"order_type": "LIMIT",
|
322
|
+
"quantity": 0.001,
|
323
|
+
"price": 50000.0,
|
324
|
+
"time_in_force": "GTC"
|
325
|
+
}
|
326
|
+
}
|
327
|
+
```
|
328
|
+
|
329
|
+
### Get Account Information
|
330
|
+
|
331
|
+
```json
|
332
|
+
{
|
333
|
+
"tool": "get_account_info",
|
334
|
+
"arguments": {}
|
335
|
+
}
|
336
|
+
```
|
337
|
+
|
338
|
+
### Get Market Data
|
339
|
+
|
340
|
+
```json
|
341
|
+
{
|
342
|
+
"tool": "get_klines",
|
343
|
+
"arguments": {
|
344
|
+
"symbol": "BTCUSDT",
|
345
|
+
"interval": "1h",
|
346
|
+
"limit": 100
|
347
|
+
}
|
348
|
+
}
|
349
|
+
```
|
350
|
+
|
351
|
+
## Security
|
352
|
+
|
353
|
+
### API Key Security
|
354
|
+
- Store API credentials securely using environment variables
|
355
|
+
- Never commit credentials to version control
|
356
|
+
- Use API keys with minimal required permissions
|
357
|
+
- Consider using testnet for development
|
358
|
+
|
359
|
+
### Rate Limiting
|
360
|
+
The server respects Binance's rate limits:
|
361
|
+
- Weight-based limits for different endpoints
|
362
|
+
- Order placement rate limits
|
363
|
+
- Automatic signature generation for authenticated requests
|
364
|
+
|
365
|
+
### Error Handling
|
366
|
+
- Comprehensive error handling for API failures
|
367
|
+
- Clear error messages for common issues
|
368
|
+
- Validation of required parameters
|
369
|
+
|
370
|
+
## API Reference
|
371
|
+
|
372
|
+
This server implements all endpoints documented in the Binance Futures API:
|
373
|
+
|
374
|
+
- **Base URL**: `https://fapi.binance.com`
|
375
|
+
- **API Type**: Binance USD-S Margined Futures
|
376
|
+
- **Authentication**: API Key + HMAC SHA256 Signature
|
377
|
+
|
378
|
+
For detailed parameter specifications, see the [Binance Futures API Documentation](https://binance-docs.github.io/apidocs/futures/en/).
|
379
|
+
|
380
|
+
## Development
|
381
|
+
|
382
|
+
### Project Structure
|
383
|
+
|
384
|
+
```
|
385
|
+
binance-mcp-server/
|
386
|
+
├── src/
|
387
|
+
│ └── binance_mcp/
|
388
|
+
│ ├── __init__.py
|
389
|
+
│ ├── __main__.py
|
390
|
+
│ └── server.py
|
391
|
+
├── pyproject.toml
|
392
|
+
└── README.md
|
393
|
+
```
|
394
|
+
|
395
|
+
### Running Tests
|
396
|
+
|
397
|
+
```bash
|
398
|
+
pytest
|
399
|
+
```
|
400
|
+
|
401
|
+
### Code Formatting
|
402
|
+
|
403
|
+
```bash
|
404
|
+
black src/
|
405
|
+
ruff check src/
|
406
|
+
```
|
407
|
+
|
408
|
+
## Error Codes
|
409
|
+
|
410
|
+
Common Binance API error codes:
|
411
|
+
- `-1121`: Invalid symbol
|
412
|
+
- `-2019`: Margin is insufficient
|
413
|
+
- `-1116`: Invalid orderType
|
414
|
+
- `-1013`: Filter failure (PRICE_FILTER, LOT_SIZE, etc.)
|
415
|
+
|
416
|
+
## Contributing
|
417
|
+
|
418
|
+
1. Fork the repository
|
419
|
+
2. Create a feature branch
|
420
|
+
3. Make your changes
|
421
|
+
4. Add tests if applicable
|
422
|
+
5. Submit a pull request
|
423
|
+
|
424
|
+
## License
|
425
|
+
|
426
|
+
MIT License - see LICENSE file for details.
|
427
|
+
|
428
|
+
## Disclaimer
|
429
|
+
|
430
|
+
This software is for educational and development purposes. Trading cryptocurrencies involves substantial risk. Use at your own risk and never trade with money you cannot afford to lose.
|
431
|
+
|
432
|
+
## Support
|
433
|
+
|
434
|
+
For issues and questions:
|
435
|
+
- Check the [Binance API Documentation](https://binance-docs.github.io/apidocs/futures/en/)
|
436
|
+
- Review the error codes in the API documentation
|
437
|
+
- Ensure your API credentials have the correct permissions
|
@@ -0,0 +1,9 @@
|
|
1
|
+
binance_futures_mcp-1.0.0.dist-info/licenses/LICENSE,sha256=zqfwopvOi7kOx5YVOnehgmRFR-IU3x1n9JEShr3QOYg,1075
|
2
|
+
binance_mcp/__init__.py,sha256=ExUxc1kp3GoSwmEtC7eGgFMZlvSQ4IdW1T5xhw-NT98,106
|
3
|
+
binance_mcp/__main__.py,sha256=arjH5cad7koMZTvXR3u3eLE6I7pdT1zg5ttp7KNjQ6Y,131
|
4
|
+
binance_mcp/server.py,sha256=LW16OetihWrkBLC1X-0Wg6k_Oug6PQ3LRVPkpEa32s0,38221
|
5
|
+
binance_futures_mcp-1.0.0.dist-info/METADATA,sha256=_rOapSOSDn8prUvEifrTocZ4wEMNJm0TJXql2YTkXFk,11017
|
6
|
+
binance_futures_mcp-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
binance_futures_mcp-1.0.0.dist-info/entry_points.txt,sha256=Olf_ctXC2kgUJEg-bfsy90EXuCDM0gW8xJwO_QzraqE,65
|
8
|
+
binance_futures_mcp-1.0.0.dist-info/top_level.txt,sha256=RqGhe1caZUvBF_ezvTiLZD8kVS25eiWVkfJfmoND9m8,12
|
9
|
+
binance_futures_mcp-1.0.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Binance MCP Server
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1 @@
|
|
1
|
+
binance_mcp
|
binance_mcp/__init__.py
ADDED
binance_mcp/__main__.py
ADDED
binance_mcp/server.py
ADDED
@@ -0,0 +1,760 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
import hashlib
|
5
|
+
import hmac
|
6
|
+
import json
|
7
|
+
import time
|
8
|
+
from datetime import datetime
|
9
|
+
from typing import Any, Dict, List, Optional, Union
|
10
|
+
from urllib.parse import urlencode
|
11
|
+
|
12
|
+
import aiohttp
|
13
|
+
from mcp.server import Server
|
14
|
+
from mcp.server.models import InitializationOptions
|
15
|
+
from mcp.server.stdio import stdio_server
|
16
|
+
from mcp.types import TextContent, Tool
|
17
|
+
from pydantic import BaseModel, Field
|
18
|
+
|
19
|
+
|
20
|
+
class BinanceConfig:
|
21
|
+
"""Configuration for Binance API"""
|
22
|
+
BASE_URL = "https://fapi.binance.com"
|
23
|
+
|
24
|
+
def __init__(self, api_key: str = "", secret_key: str = ""):
|
25
|
+
self.api_key = api_key
|
26
|
+
self.secret_key = secret_key
|
27
|
+
|
28
|
+
|
29
|
+
class BinanceClient:
|
30
|
+
"""Binance Futures API client"""
|
31
|
+
|
32
|
+
def __init__(self, config: BinanceConfig):
|
33
|
+
self.config = config
|
34
|
+
self.session: Optional[aiohttp.ClientSession] = None
|
35
|
+
|
36
|
+
async def __aenter__(self):
|
37
|
+
self.session = aiohttp.ClientSession()
|
38
|
+
return self
|
39
|
+
|
40
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
41
|
+
if self.session:
|
42
|
+
await self.session.close()
|
43
|
+
|
44
|
+
def _generate_signature(self, query_string: str) -> str:
|
45
|
+
"""Generate HMAC SHA256 signature"""
|
46
|
+
return hmac.new(
|
47
|
+
self.config.secret_key.encode('utf-8'),
|
48
|
+
query_string.encode('utf-8'),
|
49
|
+
hashlib.sha256
|
50
|
+
).hexdigest()
|
51
|
+
|
52
|
+
async def _make_request(
|
53
|
+
self,
|
54
|
+
method: str,
|
55
|
+
endpoint: str,
|
56
|
+
params: Optional[Dict[str, Any]] = None,
|
57
|
+
security_type: str = "NONE"
|
58
|
+
) -> Dict[str, Any]:
|
59
|
+
"""Make API request to Binance"""
|
60
|
+
|
61
|
+
if params is None:
|
62
|
+
params = {}
|
63
|
+
|
64
|
+
url = self.config.BASE_URL + endpoint
|
65
|
+
headers = {}
|
66
|
+
|
67
|
+
if security_type in ["USER_DATA", "TRADE"]:
|
68
|
+
# Add API key to headers
|
69
|
+
headers["X-MBX-APIKEY"] = self.config.api_key
|
70
|
+
|
71
|
+
# Add timestamp
|
72
|
+
params["timestamp"] = int(time.time() * 1000)
|
73
|
+
|
74
|
+
# Generate signature
|
75
|
+
query_string = urlencode(params)
|
76
|
+
signature = self._generate_signature(query_string)
|
77
|
+
params["signature"] = signature
|
78
|
+
|
79
|
+
try:
|
80
|
+
if method == "GET":
|
81
|
+
async with self.session.get(url, params=params, headers=headers) as response:
|
82
|
+
return await response.json()
|
83
|
+
elif method == "POST":
|
84
|
+
async with self.session.post(url, data=params, headers=headers) as response:
|
85
|
+
return await response.json()
|
86
|
+
elif method == "DELETE":
|
87
|
+
async with self.session.delete(url, data=params, headers=headers) as response:
|
88
|
+
return await response.json()
|
89
|
+
else:
|
90
|
+
raise ValueError(f"Unsupported HTTP method: {method}")
|
91
|
+
|
92
|
+
except Exception as e:
|
93
|
+
raise Exception(f"Request failed: {str(e)}")
|
94
|
+
|
95
|
+
|
96
|
+
class BinanceMCPServer:
|
97
|
+
"""Binance MCP Server implementation"""
|
98
|
+
|
99
|
+
def __init__(self, api_key: str = "", secret_key: str = ""):
|
100
|
+
self.server = Server("binance-futures-mcp-server")
|
101
|
+
self.config = BinanceConfig(api_key, secret_key)
|
102
|
+
self._setup_tools()
|
103
|
+
|
104
|
+
def _setup_tools(self):
|
105
|
+
"""Setup all MCP tools"""
|
106
|
+
|
107
|
+
@self.server.list_tools()
|
108
|
+
async def handle_list_tools() -> List[Tool]:
|
109
|
+
"""Handle tools/list requests"""
|
110
|
+
return [
|
111
|
+
# Account Information Tools
|
112
|
+
Tool(
|
113
|
+
name="get_account_info",
|
114
|
+
description="Get futures account information V2",
|
115
|
+
inputSchema={
|
116
|
+
"type": "object",
|
117
|
+
"properties": {},
|
118
|
+
"required": []
|
119
|
+
}
|
120
|
+
),
|
121
|
+
Tool(
|
122
|
+
name="get_balance",
|
123
|
+
description="Get futures account balance V2",
|
124
|
+
inputSchema={
|
125
|
+
"type": "object",
|
126
|
+
"properties": {},
|
127
|
+
"required": []
|
128
|
+
}
|
129
|
+
),
|
130
|
+
Tool(
|
131
|
+
name="get_position_info",
|
132
|
+
description="Get current position information V2",
|
133
|
+
inputSchema={
|
134
|
+
"type": "object",
|
135
|
+
"properties": {
|
136
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
137
|
+
},
|
138
|
+
"required": []
|
139
|
+
}
|
140
|
+
),
|
141
|
+
Tool(
|
142
|
+
name="get_position_mode",
|
143
|
+
description="Get user's position mode (Hedge Mode or One-way Mode)",
|
144
|
+
inputSchema={
|
145
|
+
"type": "object",
|
146
|
+
"properties": {},
|
147
|
+
"required": []
|
148
|
+
}
|
149
|
+
),
|
150
|
+
Tool(
|
151
|
+
name="get_commission_rate",
|
152
|
+
description="Get user's commission rate for a symbol",
|
153
|
+
inputSchema={
|
154
|
+
"type": "object",
|
155
|
+
"properties": {
|
156
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
157
|
+
},
|
158
|
+
"required": ["symbol"]
|
159
|
+
}
|
160
|
+
),
|
161
|
+
|
162
|
+
# Risk Management Tools
|
163
|
+
Tool(
|
164
|
+
name="get_adl_quantile",
|
165
|
+
description="Get position ADL quantile estimation",
|
166
|
+
inputSchema={
|
167
|
+
"type": "object",
|
168
|
+
"properties": {
|
169
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
170
|
+
},
|
171
|
+
"required": []
|
172
|
+
}
|
173
|
+
),
|
174
|
+
Tool(
|
175
|
+
name="get_leverage_brackets",
|
176
|
+
description="Get notional and leverage brackets",
|
177
|
+
inputSchema={
|
178
|
+
"type": "object",
|
179
|
+
"properties": {
|
180
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
181
|
+
},
|
182
|
+
"required": []
|
183
|
+
}
|
184
|
+
),
|
185
|
+
Tool(
|
186
|
+
name="get_force_orders",
|
187
|
+
description="Get user's force orders",
|
188
|
+
inputSchema={
|
189
|
+
"type": "object",
|
190
|
+
"properties": {
|
191
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
192
|
+
"auto_close_type": {"type": "string", "description": "Optional filter by auto-close type"},
|
193
|
+
"start_time": {"type": "integer", "description": "Optional start time in ms"},
|
194
|
+
"end_time": {"type": "integer", "description": "Optional end time in ms"},
|
195
|
+
"limit": {"type": "integer", "description": "Maximum number of orders to return (default 50)"}
|
196
|
+
},
|
197
|
+
"required": []
|
198
|
+
}
|
199
|
+
),
|
200
|
+
Tool(
|
201
|
+
name="get_position_margin_history",
|
202
|
+
description="Get position margin modification history",
|
203
|
+
inputSchema={
|
204
|
+
"type": "object",
|
205
|
+
"properties": {
|
206
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
207
|
+
"margin_type": {"type": "integer", "description": "1 for add position margin, 2 for reduce position margin"},
|
208
|
+
"limit": {"type": "integer", "description": "Number of entries to return"}
|
209
|
+
},
|
210
|
+
"required": ["symbol", "margin_type", "limit"]
|
211
|
+
}
|
212
|
+
),
|
213
|
+
|
214
|
+
# Order Management Tools
|
215
|
+
Tool(
|
216
|
+
name="place_order",
|
217
|
+
description="Place a futures order of any type (MARKET, LIMIT, STOP, STOP_MARKET, TRAILING_STOP_MARKET, etc)",
|
218
|
+
inputSchema={
|
219
|
+
"type": "object",
|
220
|
+
"properties": {
|
221
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
222
|
+
"side": {"type": "string", "description": "Order side ('BUY' or 'SELL')"},
|
223
|
+
"order_type": {"type": "string", "description": "Order type ('MARKET', 'LIMIT', 'STOP', 'STOP_MARKET', 'TRAILING_STOP_MARKET', etc)"},
|
224
|
+
"quantity": {"type": "number", "description": "Order quantity"},
|
225
|
+
"price": {"type": "number", "description": "Order price (for LIMIT orders)"},
|
226
|
+
"stop_price": {"type": "number", "description": "Stop price (for STOP orders)"},
|
227
|
+
"time_in_force": {"type": "string", "description": "Time in force (GTC, IOC, FOK)"},
|
228
|
+
"position_side": {"type": "string", "description": "Position side ('BOTH', 'LONG', 'SHORT')"},
|
229
|
+
"reduce_only": {"type": "string", "description": "Reduce only flag"},
|
230
|
+
"new_client_order_id": {"type": "string", "description": "Custom order ID"},
|
231
|
+
"close_position": {"type": "string", "description": "Close position flag"},
|
232
|
+
"activation_price": {"type": "number", "description": "Activation price (for TRAILING_STOP_MARKET)"},
|
233
|
+
"callback_rate": {"type": "number", "description": "Callback rate (for TRAILING_STOP_MARKET)"},
|
234
|
+
"working_type": {"type": "string", "description": "Working type (MARK_PRICE, CONTRACT_PRICE)"},
|
235
|
+
"price_protect": {"type": "string", "description": "Price protection flag"},
|
236
|
+
"new_order_resp_type": {"type": "string", "description": "Response type"},
|
237
|
+
"recv_window": {"type": "integer", "description": "Receive window"},
|
238
|
+
"timestamp": {"type": "integer", "description": "Timestamp"},
|
239
|
+
"quantity_precision": {"type": "integer", "description": "Quantity precision for validation"},
|
240
|
+
"price_precision": {"type": "integer", "description": "Price precision for validation"}
|
241
|
+
},
|
242
|
+
"required": ["symbol", "side", "order_type"]
|
243
|
+
}
|
244
|
+
),
|
245
|
+
Tool(
|
246
|
+
name="place_multiple_orders",
|
247
|
+
description="Place multiple orders at once",
|
248
|
+
inputSchema={
|
249
|
+
"type": "object",
|
250
|
+
"properties": {
|
251
|
+
"orders": {"type": "array", "description": "List of order parameters"},
|
252
|
+
"quantity_precision": {"type": "integer", "description": "Quantity precision for validation"},
|
253
|
+
"price_precision": {"type": "integer", "description": "Price precision for validation"}
|
254
|
+
},
|
255
|
+
"required": ["orders"]
|
256
|
+
}
|
257
|
+
),
|
258
|
+
Tool(
|
259
|
+
name="cancel_order",
|
260
|
+
description="Cancel an active order",
|
261
|
+
inputSchema={
|
262
|
+
"type": "object",
|
263
|
+
"properties": {
|
264
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
265
|
+
"order_id": {"type": "integer", "description": "Order ID to cancel"}
|
266
|
+
},
|
267
|
+
"required": ["symbol", "order_id"]
|
268
|
+
}
|
269
|
+
),
|
270
|
+
Tool(
|
271
|
+
name="cancel_multiple_orders",
|
272
|
+
description="Cancel multiple orders",
|
273
|
+
inputSchema={
|
274
|
+
"type": "object",
|
275
|
+
"properties": {
|
276
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
277
|
+
"order_id_list": {"type": "array", "description": "List of order IDs to cancel (up to 10 orders per batch)"}
|
278
|
+
},
|
279
|
+
"required": ["symbol", "order_id_list"]
|
280
|
+
}
|
281
|
+
),
|
282
|
+
Tool(
|
283
|
+
name="cancel_all_orders",
|
284
|
+
description="Cancel all open orders for a symbol",
|
285
|
+
inputSchema={
|
286
|
+
"type": "object",
|
287
|
+
"properties": {
|
288
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
289
|
+
},
|
290
|
+
"required": ["symbol"]
|
291
|
+
}
|
292
|
+
),
|
293
|
+
Tool(
|
294
|
+
name="auto_cancel_all_orders",
|
295
|
+
description="Set up auto-cancellation of all orders after countdown",
|
296
|
+
inputSchema={
|
297
|
+
"type": "object",
|
298
|
+
"properties": {
|
299
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
300
|
+
"countdown_time": {"type": "integer", "description": "Countdown time in milliseconds"}
|
301
|
+
},
|
302
|
+
"required": ["symbol", "countdown_time"]
|
303
|
+
}
|
304
|
+
),
|
305
|
+
|
306
|
+
# Order Query Tools
|
307
|
+
Tool(
|
308
|
+
name="get_open_order",
|
309
|
+
description="Query current open order by order id",
|
310
|
+
inputSchema={
|
311
|
+
"type": "object",
|
312
|
+
"properties": {
|
313
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
314
|
+
"order_id": {"type": "integer", "description": "Order ID to query"}
|
315
|
+
},
|
316
|
+
"required": ["symbol", "order_id"]
|
317
|
+
}
|
318
|
+
),
|
319
|
+
Tool(
|
320
|
+
name="get_open_orders",
|
321
|
+
description="Get all open futures orders for a specific symbol",
|
322
|
+
inputSchema={
|
323
|
+
"type": "object",
|
324
|
+
"properties": {
|
325
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
326
|
+
},
|
327
|
+
"required": ["symbol"]
|
328
|
+
}
|
329
|
+
),
|
330
|
+
Tool(
|
331
|
+
name="get_all_orders",
|
332
|
+
description="Get all account orders",
|
333
|
+
inputSchema={
|
334
|
+
"type": "object",
|
335
|
+
"properties": {
|
336
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
337
|
+
"order_id": {"type": "integer", "description": "Optional order ID to start from"},
|
338
|
+
"start_time": {"type": "integer", "description": "Optional start time in ms"},
|
339
|
+
"end_time": {"type": "integer", "description": "Optional end time in ms"},
|
340
|
+
"limit": {"type": "integer", "description": "Maximum number of orders to return (default 500)"}
|
341
|
+
},
|
342
|
+
"required": ["symbol"]
|
343
|
+
}
|
344
|
+
),
|
345
|
+
Tool(
|
346
|
+
name="query_order",
|
347
|
+
description="Query a specific order's status",
|
348
|
+
inputSchema={
|
349
|
+
"type": "object",
|
350
|
+
"properties": {
|
351
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
352
|
+
"order_id": {"type": "integer", "description": "Order ID to query"}
|
353
|
+
},
|
354
|
+
"required": ["symbol", "order_id"]
|
355
|
+
}
|
356
|
+
),
|
357
|
+
|
358
|
+
# Trading Configuration Tools
|
359
|
+
Tool(
|
360
|
+
name="change_leverage",
|
361
|
+
description="Change initial leverage for a symbol",
|
362
|
+
inputSchema={
|
363
|
+
"type": "object",
|
364
|
+
"properties": {
|
365
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
366
|
+
"leverage": {"type": "integer", "description": "Target initial leverage (1-125)"}
|
367
|
+
},
|
368
|
+
"required": ["symbol", "leverage"]
|
369
|
+
}
|
370
|
+
),
|
371
|
+
Tool(
|
372
|
+
name="change_margin_type",
|
373
|
+
description="Change margin type between isolated and cross",
|
374
|
+
inputSchema={
|
375
|
+
"type": "object",
|
376
|
+
"properties": {
|
377
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
378
|
+
"margin_type": {"type": "string", "description": "'ISOLATED' or 'CROSSED'"}
|
379
|
+
},
|
380
|
+
"required": ["symbol", "margin_type"]
|
381
|
+
}
|
382
|
+
),
|
383
|
+
Tool(
|
384
|
+
name="change_position_mode",
|
385
|
+
description="Change position mode between Hedge Mode and One-way Mode",
|
386
|
+
inputSchema={
|
387
|
+
"type": "object",
|
388
|
+
"properties": {
|
389
|
+
"dual_side": {"type": "boolean", "description": "\"true\" for Hedge Mode, \"false\" for One-way Mode"}
|
390
|
+
},
|
391
|
+
"required": ["dual_side"]
|
392
|
+
}
|
393
|
+
),
|
394
|
+
Tool(
|
395
|
+
name="modify_position_margin",
|
396
|
+
description="Modify isolated position margin",
|
397
|
+
inputSchema={
|
398
|
+
"type": "object",
|
399
|
+
"properties": {
|
400
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
401
|
+
"amount": {"type": "number", "description": "Amount to modify"},
|
402
|
+
"position_side": {"type": "string", "description": "Position side ('BOTH', 'LONG', or 'SHORT')"},
|
403
|
+
"margin_type": {"type": "integer", "description": "1 for add position margin, 2 for reduce position margin"}
|
404
|
+
},
|
405
|
+
"required": ["symbol", "amount", "position_side", "margin_type"]
|
406
|
+
}
|
407
|
+
),
|
408
|
+
|
409
|
+
# Market Data Tools
|
410
|
+
Tool(
|
411
|
+
name="get_exchange_info",
|
412
|
+
description="Get exchange trading rules and symbol information",
|
413
|
+
inputSchema={
|
414
|
+
"type": "object",
|
415
|
+
"properties": {
|
416
|
+
"symbol": {"type": "string", "description": "Trading pair symbol (optional)"}
|
417
|
+
},
|
418
|
+
"required": []
|
419
|
+
}
|
420
|
+
),
|
421
|
+
Tool(
|
422
|
+
name="get_book_ticker",
|
423
|
+
description="Get best price/qty on the order book for a symbol",
|
424
|
+
inputSchema={
|
425
|
+
"type": "object",
|
426
|
+
"properties": {
|
427
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
428
|
+
},
|
429
|
+
"required": []
|
430
|
+
}
|
431
|
+
),
|
432
|
+
Tool(
|
433
|
+
name="get_price_ticker",
|
434
|
+
description="Get latest price for a symbol",
|
435
|
+
inputSchema={
|
436
|
+
"type": "object",
|
437
|
+
"properties": {
|
438
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
439
|
+
},
|
440
|
+
"required": []
|
441
|
+
}
|
442
|
+
),
|
443
|
+
Tool(
|
444
|
+
name="get_order_book",
|
445
|
+
description="Get order book for a symbol",
|
446
|
+
inputSchema={
|
447
|
+
"type": "object",
|
448
|
+
"properties": {
|
449
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
450
|
+
"limit": {"type": "integer", "description": "Number of bids/asks (5,10,20,50,100,500,1000)"}
|
451
|
+
},
|
452
|
+
"required": ["symbol", "limit"]
|
453
|
+
}
|
454
|
+
),
|
455
|
+
Tool(
|
456
|
+
name="get_klines",
|
457
|
+
description="Get kline/candlestick data for a symbol",
|
458
|
+
inputSchema={
|
459
|
+
"type": "object",
|
460
|
+
"properties": {
|
461
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
462
|
+
"interval": {"type": "string", "description": "Kline interval"},
|
463
|
+
"start_time": {"type": "integer", "description": "Start timestamp in ms"},
|
464
|
+
"end_time": {"type": "integer", "description": "End timestamp in ms"},
|
465
|
+
"limit": {"type": "integer", "description": "Number of klines (max 1500)"}
|
466
|
+
},
|
467
|
+
"required": ["symbol", "interval"]
|
468
|
+
}
|
469
|
+
),
|
470
|
+
Tool(
|
471
|
+
name="get_mark_price",
|
472
|
+
description="Get mark price and funding rate for a symbol",
|
473
|
+
inputSchema={
|
474
|
+
"type": "object",
|
475
|
+
"properties": {
|
476
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"}
|
477
|
+
},
|
478
|
+
"required": []
|
479
|
+
}
|
480
|
+
),
|
481
|
+
Tool(
|
482
|
+
name="get_aggregate_trades",
|
483
|
+
description="Get compressed, aggregate market trades",
|
484
|
+
inputSchema={
|
485
|
+
"type": "object",
|
486
|
+
"properties": {
|
487
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
488
|
+
"from_id": {"type": "integer", "description": "ID to get trades from"},
|
489
|
+
"start_time": {"type": "integer", "description": "Start timestamp in ms"},
|
490
|
+
"end_time": {"type": "integer", "description": "End timestamp in ms"},
|
491
|
+
"limit": {"type": "integer", "description": "Number of trades (max 1000)"}
|
492
|
+
},
|
493
|
+
"required": ["symbol"]
|
494
|
+
}
|
495
|
+
),
|
496
|
+
Tool(
|
497
|
+
name="get_funding_rate_history",
|
498
|
+
description="Get funding rate history for a symbol",
|
499
|
+
inputSchema={
|
500
|
+
"type": "object",
|
501
|
+
"properties": {
|
502
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
503
|
+
"start_time": {"type": "integer", "description": "Start timestamp in ms"},
|
504
|
+
"end_time": {"type": "integer", "description": "End timestamp in ms"},
|
505
|
+
"limit": {"type": "integer", "description": "Number of entries (max 1000)"}
|
506
|
+
},
|
507
|
+
"required": []
|
508
|
+
}
|
509
|
+
),
|
510
|
+
|
511
|
+
# Trading History Tools
|
512
|
+
Tool(
|
513
|
+
name="get_account_trades",
|
514
|
+
description="Get account trade list",
|
515
|
+
inputSchema={
|
516
|
+
"type": "object",
|
517
|
+
"properties": {
|
518
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
519
|
+
"start_time": {"type": "integer", "description": "Optional start time in ms"},
|
520
|
+
"end_time": {"type": "integer", "description": "Optional end time in ms"},
|
521
|
+
"from_id": {"type": "integer", "description": "Optional trade ID to fetch from"},
|
522
|
+
"limit": {"type": "integer", "description": "Maximum number of trades to return (default 500)"}
|
523
|
+
},
|
524
|
+
"required": ["symbol"]
|
525
|
+
}
|
526
|
+
),
|
527
|
+
Tool(
|
528
|
+
name="get_income_history",
|
529
|
+
description="Get income history",
|
530
|
+
inputSchema={
|
531
|
+
"type": "object",
|
532
|
+
"properties": {
|
533
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
534
|
+
"income_type": {"type": "string", "description": "Optional income type filter"},
|
535
|
+
"start_time": {"type": "integer", "description": "Optional start time in ms"},
|
536
|
+
"end_time": {"type": "integer", "description": "Optional end time in ms"},
|
537
|
+
"limit": {"type": "integer", "description": "Maximum number of records to return (default 100)"}
|
538
|
+
},
|
539
|
+
"required": []
|
540
|
+
}
|
541
|
+
)
|
542
|
+
]
|
543
|
+
|
544
|
+
@self.server.call_tool()
|
545
|
+
async def handle_call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]:
|
546
|
+
"""Handle tool calls"""
|
547
|
+
|
548
|
+
# Check if API credentials are configured for authenticated endpoints
|
549
|
+
unauthenticated_tools = [
|
550
|
+
"get_exchange_info", "get_price_ticker", "get_book_ticker",
|
551
|
+
"get_order_book", "get_klines", "get_mark_price",
|
552
|
+
"get_aggregate_trades", "get_funding_rate_history"
|
553
|
+
]
|
554
|
+
|
555
|
+
if not self.config.api_key or not self.config.secret_key:
|
556
|
+
if name not in unauthenticated_tools:
|
557
|
+
return [TextContent(
|
558
|
+
type="text",
|
559
|
+
text="Error: API credentials not configured. Please provide valid API key and secret key."
|
560
|
+
)]
|
561
|
+
|
562
|
+
try:
|
563
|
+
async with BinanceClient(self.config) as client:
|
564
|
+
|
565
|
+
# Account Information Tools
|
566
|
+
if name == "get_account_info":
|
567
|
+
result = await client._make_request("GET", "/fapi/v2/account", security_type="USER_DATA")
|
568
|
+
elif name == "get_balance":
|
569
|
+
result = await client._make_request("GET", "/fapi/v2/balance", security_type="USER_DATA")
|
570
|
+
elif name == "get_position_info":
|
571
|
+
params = {}
|
572
|
+
if "symbol" in arguments:
|
573
|
+
params["symbol"] = arguments["symbol"]
|
574
|
+
result = await client._make_request("GET", "/fapi/v2/positionRisk", params, "USER_DATA")
|
575
|
+
elif name == "get_position_mode":
|
576
|
+
result = await client._make_request("GET", "/fapi/v1/positionSide/dual", security_type="USER_DATA")
|
577
|
+
elif name == "get_commission_rate":
|
578
|
+
params = {"symbol": arguments["symbol"]}
|
579
|
+
result = await client._make_request("GET", "/fapi/v1/commissionRate", params, "USER_DATA")
|
580
|
+
|
581
|
+
# Risk Management Tools
|
582
|
+
elif name == "get_adl_quantile":
|
583
|
+
params = {}
|
584
|
+
if "symbol" in arguments:
|
585
|
+
params["symbol"] = arguments["symbol"]
|
586
|
+
result = await client._make_request("GET", "/fapi/v1/adlQuantile", params, "USER_DATA")
|
587
|
+
elif name == "get_leverage_brackets":
|
588
|
+
params = {}
|
589
|
+
if "symbol" in arguments:
|
590
|
+
params["symbol"] = arguments["symbol"]
|
591
|
+
result = await client._make_request("GET", "/fapi/v1/leverageBracket", params, "USER_DATA")
|
592
|
+
elif name == "get_force_orders":
|
593
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
594
|
+
result = await client._make_request("GET", "/fapi/v1/forceOrders", params, "USER_DATA")
|
595
|
+
elif name == "get_position_margin_history":
|
596
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
597
|
+
result = await client._make_request("GET", "/fapi/v1/positionMargin/history", params, "USER_DATA")
|
598
|
+
|
599
|
+
# Order Management Tools
|
600
|
+
elif name == "place_order":
|
601
|
+
params = {k: v for k, v in arguments.items() if v is not None and k not in ["quantity_precision", "price_precision"]}
|
602
|
+
# Convert order_type to type for API
|
603
|
+
if "order_type" in params:
|
604
|
+
params["type"] = params.pop("order_type")
|
605
|
+
result = await client._make_request("POST", "/fapi/v1/order", params, "TRADE")
|
606
|
+
elif name == "place_multiple_orders":
|
607
|
+
# This requires special handling for batch orders
|
608
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
609
|
+
result = await client._make_request("POST", "/fapi/v1/batchOrders", params, "TRADE")
|
610
|
+
elif name == "cancel_order":
|
611
|
+
params = {"symbol": arguments["symbol"], "orderId": arguments["order_id"]}
|
612
|
+
result = await client._make_request("DELETE", "/fapi/v1/order", params, "TRADE")
|
613
|
+
elif name == "cancel_multiple_orders":
|
614
|
+
params = {
|
615
|
+
"symbol": arguments["symbol"],
|
616
|
+
"orderIdList": arguments["order_id_list"]
|
617
|
+
}
|
618
|
+
result = await client._make_request("DELETE", "/fapi/v1/batchOrders", params, "TRADE")
|
619
|
+
elif name == "cancel_all_orders":
|
620
|
+
params = {"symbol": arguments["symbol"]}
|
621
|
+
result = await client._make_request("DELETE", "/fapi/v1/allOpenOrders", params, "TRADE")
|
622
|
+
elif name == "auto_cancel_all_orders":
|
623
|
+
params = {
|
624
|
+
"symbol": arguments["symbol"],
|
625
|
+
"countdownTime": arguments["countdown_time"]
|
626
|
+
}
|
627
|
+
result = await client._make_request("POST", "/fapi/v1/countdownCancelAll", params, "TRADE")
|
628
|
+
|
629
|
+
# Order Query Tools
|
630
|
+
elif name == "get_open_order":
|
631
|
+
params = {"symbol": arguments["symbol"], "orderId": arguments["order_id"]}
|
632
|
+
result = await client._make_request("GET", "/fapi/v1/openOrder", params, "USER_DATA")
|
633
|
+
elif name == "get_open_orders":
|
634
|
+
params = {"symbol": arguments["symbol"]}
|
635
|
+
result = await client._make_request("GET", "/fapi/v1/openOrders", params, "USER_DATA")
|
636
|
+
elif name == "get_all_orders":
|
637
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
638
|
+
result = await client._make_request("GET", "/fapi/v1/allOrders", params, "USER_DATA")
|
639
|
+
elif name == "query_order":
|
640
|
+
params = {"symbol": arguments["symbol"], "orderId": arguments["order_id"]}
|
641
|
+
result = await client._make_request("GET", "/fapi/v1/order", params, "USER_DATA")
|
642
|
+
|
643
|
+
# Trading Configuration Tools
|
644
|
+
elif name == "change_leverage":
|
645
|
+
params = {
|
646
|
+
"symbol": arguments["symbol"],
|
647
|
+
"leverage": arguments["leverage"]
|
648
|
+
}
|
649
|
+
result = await client._make_request("POST", "/fapi/v1/leverage", params, "TRADE")
|
650
|
+
elif name == "change_margin_type":
|
651
|
+
params = {
|
652
|
+
"symbol": arguments["symbol"],
|
653
|
+
"marginType": arguments["margin_type"]
|
654
|
+
}
|
655
|
+
result = await client._make_request("POST", "/fapi/v1/marginType", params, "TRADE")
|
656
|
+
elif name == "change_position_mode":
|
657
|
+
params = {"dualSidePosition": arguments["dual_side"]}
|
658
|
+
result = await client._make_request("POST", "/fapi/v1/positionSide/dual", params, "TRADE")
|
659
|
+
elif name == "modify_position_margin":
|
660
|
+
params = {
|
661
|
+
"symbol": arguments["symbol"],
|
662
|
+
"positionSide": arguments["position_side"],
|
663
|
+
"amount": arguments["amount"],
|
664
|
+
"type": arguments["margin_type"]
|
665
|
+
}
|
666
|
+
result = await client._make_request("POST", "/fapi/v1/positionMargin", params, "TRADE")
|
667
|
+
|
668
|
+
# Market Data Tools
|
669
|
+
elif name == "get_exchange_info":
|
670
|
+
params = {}
|
671
|
+
if "symbol" in arguments:
|
672
|
+
params["symbol"] = arguments["symbol"]
|
673
|
+
result = await client._make_request("GET", "/fapi/v1/exchangeInfo", params)
|
674
|
+
elif name == "get_book_ticker":
|
675
|
+
params = {}
|
676
|
+
if "symbol" in arguments:
|
677
|
+
params["symbol"] = arguments["symbol"]
|
678
|
+
result = await client._make_request("GET", "/fapi/v1/ticker/bookTicker", params)
|
679
|
+
elif name == "get_price_ticker":
|
680
|
+
params = {}
|
681
|
+
if "symbol" in arguments:
|
682
|
+
params["symbol"] = arguments["symbol"]
|
683
|
+
result = await client._make_request("GET", "/fapi/v1/ticker/price", params)
|
684
|
+
elif name == "get_order_book":
|
685
|
+
params = {
|
686
|
+
"symbol": arguments["symbol"],
|
687
|
+
"limit": arguments["limit"]
|
688
|
+
}
|
689
|
+
result = await client._make_request("GET", "/fapi/v1/depth", params)
|
690
|
+
elif name == "get_klines":
|
691
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
692
|
+
result = await client._make_request("GET", "/fapi/v1/klines", params)
|
693
|
+
elif name == "get_mark_price":
|
694
|
+
params = {}
|
695
|
+
if "symbol" in arguments:
|
696
|
+
params["symbol"] = arguments["symbol"]
|
697
|
+
result = await client._make_request("GET", "/fapi/v1/premiumIndex", params)
|
698
|
+
elif name == "get_aggregate_trades":
|
699
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
700
|
+
result = await client._make_request("GET", "/fapi/v1/aggTrades", params)
|
701
|
+
elif name == "get_funding_rate_history":
|
702
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
703
|
+
result = await client._make_request("GET", "/fapi/v1/fundingRate", params)
|
704
|
+
|
705
|
+
# Trading History Tools
|
706
|
+
elif name == "get_account_trades":
|
707
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
708
|
+
result = await client._make_request("GET", "/fapi/v1/userTrades", params, "USER_DATA")
|
709
|
+
elif name == "get_income_history":
|
710
|
+
params = {k: v for k, v in arguments.items() if v is not None}
|
711
|
+
result = await client._make_request("GET", "/fapi/v1/income", params, "USER_DATA")
|
712
|
+
|
713
|
+
else:
|
714
|
+
raise ValueError(f"Unknown tool: {name}")
|
715
|
+
|
716
|
+
return [TextContent(
|
717
|
+
type="text",
|
718
|
+
text=json.dumps(result, indent=2)
|
719
|
+
)]
|
720
|
+
|
721
|
+
except Exception as e:
|
722
|
+
return [TextContent(
|
723
|
+
type="text",
|
724
|
+
text=f"Error: {str(e)}"
|
725
|
+
)]
|
726
|
+
|
727
|
+
|
728
|
+
async def main():
|
729
|
+
import argparse
|
730
|
+
import os
|
731
|
+
|
732
|
+
# Parse command-line arguments
|
733
|
+
parser = argparse.ArgumentParser(description="Binance Futures MCP Server")
|
734
|
+
parser.add_argument("--binance-api-key",
|
735
|
+
help="Binance API key",
|
736
|
+
default=os.getenv("BINANCE_API_KEY", ""))
|
737
|
+
parser.add_argument("--binance-secret-key",
|
738
|
+
help="Binance secret key",
|
739
|
+
default=os.getenv("BINANCE_SECRET_KEY", ""))
|
740
|
+
|
741
|
+
args = parser.parse_args()
|
742
|
+
|
743
|
+
# Initialize server with credentials
|
744
|
+
server_instance = BinanceMCPServer(args.binance_api_key, args.binance_secret_key)
|
745
|
+
|
746
|
+
# Run server using stdio
|
747
|
+
async with stdio_server() as (read_stream, write_stream):
|
748
|
+
await server_instance.server.run(
|
749
|
+
read_stream,
|
750
|
+
write_stream,
|
751
|
+
InitializationOptions(
|
752
|
+
server_name="binance-futures-mcp-server",
|
753
|
+
server_version="1.0.0",
|
754
|
+
capabilities={}
|
755
|
+
)
|
756
|
+
)
|
757
|
+
|
758
|
+
|
759
|
+
if __name__ == "__main__":
|
760
|
+
asyncio.run(main())
|