binance-futures-mcp 1.0.7__py3-none-any.whl → 1.0.9__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.7.dist-info → binance_futures_mcp-1.0.9.dist-info}/METADATA +19 -8
- binance_futures_mcp-1.0.9.dist-info/RECORD +9 -0
- {binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info}/WHEEL +1 -1
- binance_mcp/server.py +353 -20
- binance_futures_mcp-1.0.7.dist-info/RECORD +0 -9
- {binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info}/entry_points.txt +0 -0
- {binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info/licenses}/LICENSE +0 -0
- {binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,14 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: binance-futures-mcp
|
3
|
-
Version: 1.0.
|
4
|
-
Summary: A Model Context Protocol server for Binance Futures API
|
3
|
+
Version: 1.0.9
|
4
|
+
Summary: A Model Context Protocol server for Binance Futures API with comprehensive trading tools including TP/SL management
|
5
5
|
Home-page: https://github.com/alexcandrabersiva/bin-mcp
|
6
6
|
Author: Binance MCP Server
|
7
|
-
|
7
|
+
License-Expression: MIT
|
8
|
+
Project-URL: Homepage, https://github.com/alexcandrabersiva/bin-mcp
|
8
9
|
Project-URL: Repository, https://github.com/alexcandrabersiva/bin-mcp.git
|
9
|
-
|
10
|
+
Project-URL: Issues, https://github.com/alexcandrabersiva/bin-mcp/issues
|
11
|
+
Keywords: mcp,binance,trading,futures,api,model-context-protocol
|
10
12
|
Classifier: Development Status :: 4 - Beta
|
11
13
|
Classifier: Intended Audience :: Developers
|
12
14
|
Classifier: Programming Language :: Python :: 3
|
@@ -20,9 +22,18 @@ Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
20
22
|
Requires-Python: >=3.8
|
21
23
|
Description-Content-Type: text/markdown
|
22
24
|
License-File: LICENSE
|
23
|
-
Requires-Dist: mcp
|
24
|
-
Requires-Dist: aiohttp
|
25
|
-
Requires-Dist: pydantic
|
25
|
+
Requires-Dist: mcp>=1.0.0
|
26
|
+
Requires-Dist: aiohttp>=3.8.0
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
28
|
+
Provides-Extra: dev
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
30
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
31
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
32
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
33
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
34
|
+
Dynamic: home-page
|
35
|
+
Dynamic: license-file
|
36
|
+
Dynamic: requires-python
|
26
37
|
|
27
38
|
# Binance MCP Server
|
28
39
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
binance_futures_mcp-1.0.9.dist-info/licenses/LICENSE,sha256=zqfwopvOi7kOx5YVOnehgmRFR-IU3x1n9JEShr3QOYg,1075
|
2
|
+
binance_mcp/__init__.py,sha256=ExUxc1kp3GoSwmEtC7eGgFMZlvSQ4IdW1T5xhw-NT98,106
|
3
|
+
binance_mcp/__main__.py,sha256=_9DBrtv0PAvjLjCqKk_cMfGtkqSUOcmU6HeQKFjuFMQ,214
|
4
|
+
binance_mcp/server.py,sha256=NlgfZhT3si4y0UiGxRZE92rAehcWYFGKymMGgkQMKIo,62387
|
5
|
+
binance_futures_mcp-1.0.9.dist-info/METADATA,sha256=vdWuCJtPFPqjiEgVBBCNVl-jEWW_cwnCD38Sk2zwDlk,11872
|
6
|
+
binance_futures_mcp-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
binance_futures_mcp-1.0.9.dist-info/entry_points.txt,sha256=-1iVs9AF7JQBS-xMichP9hQhbCY7YfLFRJVaNKwuN34,69
|
8
|
+
binance_futures_mcp-1.0.9.dist-info/top_level.txt,sha256=RqGhe1caZUvBF_ezvTiLZD8kVS25eiWVkfJfmoND9m8,12
|
9
|
+
binance_futures_mcp-1.0.9.dist-info/RECORD,,
|
binance_mcp/server.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
|
3
3
|
import asyncio
|
4
|
+
import argparse
|
4
5
|
import hashlib
|
5
6
|
import hmac
|
6
7
|
import json
|
8
|
+
import os
|
7
9
|
import time
|
8
10
|
from datetime import datetime
|
9
11
|
from typing import Any, Dict, List, Optional, Union
|
@@ -48,7 +50,7 @@ class BinanceClient:
|
|
48
50
|
timeout=timeout,
|
49
51
|
connector=connector,
|
50
52
|
headers={
|
51
|
-
'User-Agent': 'binance-mcp-server/1.0.
|
53
|
+
'User-Agent': 'binance-mcp-server/1.0.9',
|
52
54
|
'Content-Type': 'application/x-www-form-urlencoded'
|
53
55
|
}
|
54
56
|
)
|
@@ -96,15 +98,21 @@ class BinanceClient:
|
|
96
98
|
try:
|
97
99
|
if method == "GET":
|
98
100
|
async with self.session.get(url, params=params, headers=headers, ssl=False) as response:
|
99
|
-
response.
|
101
|
+
if response.status != 200:
|
102
|
+
error_text = await response.text()
|
103
|
+
raise Exception(f"HTTP {response.status}: {error_text}")
|
100
104
|
return await response.json()
|
101
105
|
elif method == "POST":
|
102
106
|
async with self.session.post(url, data=params, headers=headers, ssl=False) as response:
|
103
|
-
response.
|
107
|
+
if response.status != 200:
|
108
|
+
error_text = await response.text()
|
109
|
+
raise Exception(f"HTTP {response.status}: {error_text}")
|
104
110
|
return await response.json()
|
105
111
|
elif method == "DELETE":
|
106
112
|
async with self.session.delete(url, data=params, headers=headers, ssl=False) as response:
|
107
|
-
response.
|
113
|
+
if response.status != 200:
|
114
|
+
error_text = await response.text()
|
115
|
+
raise Exception(f"HTTP {response.status}: {error_text}")
|
108
116
|
return await response.json()
|
109
117
|
else:
|
110
118
|
raise ValueError(f"Unsupported HTTP method: {method}")
|
@@ -244,26 +252,31 @@ class BinanceMCPServer:
|
|
244
252
|
"properties": {
|
245
253
|
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
246
254
|
"side": {"type": "string", "description": "Order side ('BUY' or 'SELL')"},
|
247
|
-
"
|
255
|
+
"type": {"type": "string", "description": "Order type ('MARKET', 'LIMIT', 'STOP', 'STOP_MARKET', 'TRAILING_STOP_MARKET', etc)"},
|
256
|
+
"order_type": {"type": "string", "description": "Alternative parameter name for 'type' (for backward compatibility)"},
|
248
257
|
"quantity": {"type": "number", "description": "Order quantity"},
|
249
258
|
"price": {"type": "number", "description": "Order price (for LIMIT orders)"},
|
250
|
-
"
|
251
|
-
"
|
252
|
-
"
|
253
|
-
"
|
254
|
-
"
|
255
|
-
"
|
256
|
-
"
|
257
|
-
"
|
258
|
-
"
|
259
|
-
"
|
260
|
-
"
|
261
|
-
"
|
259
|
+
"stopPrice": {"type": "number", "description": "Stop price (for STOP orders)"},
|
260
|
+
"timeInForce": {"type": "string", "description": "Time in force (GTC, IOC, FOK)"},
|
261
|
+
"positionSide": {"type": "string", "description": "Position side ('BOTH', 'LONG', 'SHORT')"},
|
262
|
+
"reduceOnly": {"type": "string", "description": "Reduce only flag ('true' or 'false')"},
|
263
|
+
"newClientOrderId": {"type": "string", "description": "Custom order ID"},
|
264
|
+
"closePosition": {"type": "string", "description": "Close position flag ('true' or 'false')"},
|
265
|
+
"activationPrice": {"type": "number", "description": "Activation price (for TRAILING_STOP_MARKET)"},
|
266
|
+
"callbackRate": {"type": "number", "description": "Callback rate (for TRAILING_STOP_MARKET)"},
|
267
|
+
"workingType": {"type": "string", "description": "Working type (MARK_PRICE, CONTRACT_PRICE)"},
|
268
|
+
"priceProtect": {"type": "string", "description": "Price protection flag ('TRUE' or 'FALSE')"},
|
269
|
+
"newOrderRespType": {"type": "string", "description": "Response type ('ACK', 'RESULT')"},
|
270
|
+
"recvWindow": {"type": "integer", "description": "Receive window"},
|
262
271
|
"timestamp": {"type": "integer", "description": "Timestamp"},
|
263
272
|
"quantity_precision": {"type": "integer", "description": "Quantity precision for validation"},
|
264
273
|
"price_precision": {"type": "integer", "description": "Price precision for validation"}
|
265
274
|
},
|
266
|
-
"required": ["symbol", "side",
|
275
|
+
"required": ["symbol", "side"],
|
276
|
+
"anyOf": [
|
277
|
+
{"required": ["type"]},
|
278
|
+
{"required": ["order_type"]}
|
279
|
+
]
|
267
280
|
}
|
268
281
|
),
|
269
282
|
Tool(
|
@@ -386,6 +399,73 @@ class BinanceMCPServer:
|
|
386
399
|
"required": ["symbol", "order_id"]
|
387
400
|
}
|
388
401
|
),
|
402
|
+
Tool(
|
403
|
+
name="close_position",
|
404
|
+
description="Close current position for a symbol (market order to close all or part of position)",
|
405
|
+
inputSchema={
|
406
|
+
"type": "object",
|
407
|
+
"properties": {
|
408
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
409
|
+
"position_side": {"type": "string", "description": "Position side to close ('BOTH', 'LONG', 'SHORT'). Default 'BOTH' for One-way mode"},
|
410
|
+
"quantity": {"type": "number", "description": "Quantity to close (optional, if not provided will close entire position)"},
|
411
|
+
"close_all": {"type": "boolean", "description": "If true, closes entire position using closePosition=true parameter"}
|
412
|
+
},
|
413
|
+
"required": ["symbol"]
|
414
|
+
}
|
415
|
+
),
|
416
|
+
Tool(
|
417
|
+
name="modify_order",
|
418
|
+
description="Modify an existing order (price, quantity, etc.)",
|
419
|
+
inputSchema={
|
420
|
+
"type": "object",
|
421
|
+
"properties": {
|
422
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
423
|
+
"order_id": {"type": "integer", "description": "Order ID to modify"},
|
424
|
+
"side": {"type": "string", "description": "Order side ('BUY' or 'SELL')"},
|
425
|
+
"quantity": {"type": "number", "description": "New order quantity"},
|
426
|
+
"price": {"type": "number", "description": "New order price"},
|
427
|
+
"priceMatch": {"type": "string", "description": "Price match mode (OPPONENT, OPPONENT_5, OPPONENT_10, OPPONENT_20, QUEUE, QUEUE_5, QUEUE_10, QUEUE_20)"}
|
428
|
+
},
|
429
|
+
"required": ["symbol", "order_id", "side", "quantity", "price"]
|
430
|
+
}
|
431
|
+
),
|
432
|
+
Tool(
|
433
|
+
name="add_tp_sl_to_position",
|
434
|
+
description="Add Take Profit and/or Stop Loss orders to existing position",
|
435
|
+
inputSchema={
|
436
|
+
"type": "object",
|
437
|
+
"properties": {
|
438
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
439
|
+
"position_side": {"type": "string", "description": "Position side ('BOTH', 'LONG', 'SHORT'). Default 'BOTH' for One-way mode"},
|
440
|
+
"take_profit_price": {"type": "number", "description": "Take profit price (optional)"},
|
441
|
+
"stop_loss_price": {"type": "number", "description": "Stop loss price (optional)"},
|
442
|
+
"quantity": {"type": "number", "description": "Quantity for TP/SL orders (optional, defaults to position size)"},
|
443
|
+
"tp_order_type": {"type": "string", "description": "Take profit order type ('LIMIT', 'TAKE_PROFIT_MARKET'). Default 'TAKE_PROFIT_MARKET'"},
|
444
|
+
"sl_order_type": {"type": "string", "description": "Stop loss order type ('STOP_MARKET', 'STOP'). Default 'STOP_MARKET'"},
|
445
|
+
"time_in_force": {"type": "string", "description": "Time in force for LIMIT TP orders (GTC, IOC, FOK). Default 'GTC'"}
|
446
|
+
},
|
447
|
+
"required": ["symbol"]
|
448
|
+
}
|
449
|
+
),
|
450
|
+
Tool(
|
451
|
+
name="place_bracket_order",
|
452
|
+
description="Place a position with automatic Take Profit and Stop Loss orders",
|
453
|
+
inputSchema={
|
454
|
+
"type": "object",
|
455
|
+
"properties": {
|
456
|
+
"symbol": {"type": "string", "description": "Trading pair symbol"},
|
457
|
+
"side": {"type": "string", "description": "Order side ('BUY' or 'SELL')"},
|
458
|
+
"quantity": {"type": "number", "description": "Order quantity"},
|
459
|
+
"entry_price": {"type": "number", "description": "Entry price (for LIMIT entry order, optional for MARKET)"},
|
460
|
+
"take_profit_price": {"type": "number", "description": "Take profit price"},
|
461
|
+
"stop_loss_price": {"type": "number", "description": "Stop loss price"},
|
462
|
+
"entry_order_type": {"type": "string", "description": "Entry order type ('MARKET', 'LIMIT'). Default 'MARKET'"},
|
463
|
+
"positionSide": {"type": "string", "description": "Position side ('BOTH', 'LONG', 'SHORT')"},
|
464
|
+
"timeInForce": {"type": "string", "description": "Time in force for LIMIT orders (GTC, IOC, FOK). Default 'GTC'"}
|
465
|
+
},
|
466
|
+
"required": ["symbol", "side", "quantity", "take_profit_price", "stop_loss_price"]
|
467
|
+
}
|
468
|
+
),
|
389
469
|
|
390
470
|
# Trading Configuration Tools
|
391
471
|
Tool(
|
@@ -656,10 +736,39 @@ class BinanceMCPServer:
|
|
656
736
|
|
657
737
|
# Order Management Tools
|
658
738
|
elif name == "place_order":
|
739
|
+
# Filter out precision parameters and pass through all other parameters directly
|
659
740
|
params = {k: v for k, v in arguments.items() if v is not None and k not in ["quantity_precision", "price_precision"]}
|
660
|
-
|
741
|
+
|
742
|
+
# Handle backward compatibility for order_type parameter
|
661
743
|
if "order_type" in params:
|
662
744
|
params["type"] = params.pop("order_type")
|
745
|
+
|
746
|
+
# Check if type parameter is present
|
747
|
+
if "type" not in params:
|
748
|
+
raise ValueError("Missing required parameter 'type'. Please specify the order type (e.g., 'MARKET', 'LIMIT', 'STOP', etc.)")
|
749
|
+
|
750
|
+
# Validate mandatory parameters based on order type
|
751
|
+
order_type = params.get("type")
|
752
|
+
if order_type == "LIMIT":
|
753
|
+
required_params = ["timeInForce", "quantity", "price"]
|
754
|
+
missing = [p for p in required_params if p not in params]
|
755
|
+
if missing:
|
756
|
+
raise ValueError(f"LIMIT order missing required parameters: {missing}")
|
757
|
+
elif order_type == "MARKET":
|
758
|
+
if "quantity" not in params:
|
759
|
+
raise ValueError("MARKET order missing required parameter: quantity")
|
760
|
+
elif order_type in ["STOP", "TAKE_PROFIT"]:
|
761
|
+
required_params = ["quantity", "price", "stopPrice"]
|
762
|
+
missing = [p for p in required_params if p not in params]
|
763
|
+
if missing:
|
764
|
+
raise ValueError(f"{order_type} order missing required parameters: {missing}")
|
765
|
+
elif order_type in ["STOP_MARKET", "TAKE_PROFIT_MARKET"]:
|
766
|
+
if "stopPrice" not in params:
|
767
|
+
raise ValueError(f"{order_type} order missing required parameter: stopPrice")
|
768
|
+
elif order_type == "TRAILING_STOP_MARKET":
|
769
|
+
if "callbackRate" not in params:
|
770
|
+
raise ValueError("TRAILING_STOP_MARKET order missing required parameter: callbackRate")
|
771
|
+
|
663
772
|
result = await client._make_request("POST", "/fapi/v1/order", params, "TRADE")
|
664
773
|
elif name == "place_multiple_orders":
|
665
774
|
# This requires special handling for batch orders
|
@@ -697,6 +806,230 @@ class BinanceMCPServer:
|
|
697
806
|
elif name == "query_order":
|
698
807
|
params = {"symbol": arguments["symbol"], "orderId": arguments["order_id"]}
|
699
808
|
result = await client._make_request("GET", "/fapi/v1/order", params, "USER_DATA")
|
809
|
+
elif name == "close_position":
|
810
|
+
# Handle position closing
|
811
|
+
symbol = arguments["symbol"]
|
812
|
+
position_side = arguments.get("position_side", "BOTH")
|
813
|
+
quantity = arguments.get("quantity")
|
814
|
+
close_all = arguments.get("close_all", False)
|
815
|
+
|
816
|
+
# First, get current position to determine the side and quantity to close
|
817
|
+
position_params = {"symbol": symbol}
|
818
|
+
positions = await client._make_request("GET", "/fapi/v2/positionRisk", position_params, "USER_DATA")
|
819
|
+
|
820
|
+
# Find the position to close
|
821
|
+
position_to_close = None
|
822
|
+
for pos in positions:
|
823
|
+
if pos["symbol"] == symbol and float(pos["positionAmt"]) != 0:
|
824
|
+
if position_side == "BOTH" or pos["positionSide"] == position_side:
|
825
|
+
position_to_close = pos
|
826
|
+
break
|
827
|
+
|
828
|
+
if not position_to_close:
|
829
|
+
raise ValueError(f"No open position found for {symbol} with position side {position_side}")
|
830
|
+
|
831
|
+
position_amt = float(position_to_close["positionAmt"])
|
832
|
+
current_position_side = position_to_close["positionSide"]
|
833
|
+
|
834
|
+
# Determine order side (opposite of position)
|
835
|
+
if position_amt > 0: # Long position
|
836
|
+
order_side = "SELL"
|
837
|
+
else: # Short position
|
838
|
+
order_side = "BUY"
|
839
|
+
position_amt = abs(position_amt) # Make positive for order quantity
|
840
|
+
|
841
|
+
# Determine quantity to close
|
842
|
+
if close_all:
|
843
|
+
# Use closePosition parameter to close entire position
|
844
|
+
order_params = {
|
845
|
+
"symbol": symbol,
|
846
|
+
"side": order_side,
|
847
|
+
"type": "MARKET",
|
848
|
+
"closePosition": "true"
|
849
|
+
}
|
850
|
+
if current_position_side != "BOTH":
|
851
|
+
order_params["positionSide"] = current_position_side
|
852
|
+
else:
|
853
|
+
# Close specific quantity or entire position
|
854
|
+
close_quantity = quantity if quantity else position_amt
|
855
|
+
order_params = {
|
856
|
+
"symbol": symbol,
|
857
|
+
"side": order_side,
|
858
|
+
"type": "MARKET",
|
859
|
+
"quantity": close_quantity,
|
860
|
+
"reduceOnly": "true"
|
861
|
+
}
|
862
|
+
if current_position_side != "BOTH":
|
863
|
+
order_params["positionSide"] = current_position_side
|
864
|
+
|
865
|
+
result = await client._make_request("POST", "/fapi/v1/order", order_params, "TRADE")
|
866
|
+
elif name == "modify_order":
|
867
|
+
# Modify existing order
|
868
|
+
params = {
|
869
|
+
"symbol": arguments["symbol"],
|
870
|
+
"orderId": arguments["order_id"],
|
871
|
+
"side": arguments["side"],
|
872
|
+
"quantity": arguments["quantity"],
|
873
|
+
"price": arguments["price"]
|
874
|
+
}
|
875
|
+
if "priceMatch" in arguments:
|
876
|
+
params["priceMatch"] = arguments["priceMatch"]
|
877
|
+
result = await client._make_request("PUT", "/fapi/v1/order", params, "TRADE")
|
878
|
+
elif name == "add_tp_sl_to_position":
|
879
|
+
# Add TP/SL to existing position
|
880
|
+
symbol = arguments["symbol"]
|
881
|
+
position_side = arguments.get("position_side", "BOTH")
|
882
|
+
take_profit_price = arguments.get("take_profit_price")
|
883
|
+
stop_loss_price = arguments.get("stop_loss_price")
|
884
|
+
quantity = arguments.get("quantity")
|
885
|
+
tp_order_type = arguments.get("tp_order_type", "TAKE_PROFIT_MARKET")
|
886
|
+
sl_order_type = arguments.get("sl_order_type", "STOP_MARKET")
|
887
|
+
time_in_force = arguments.get("time_in_force", "GTC")
|
888
|
+
|
889
|
+
if not take_profit_price and not stop_loss_price:
|
890
|
+
raise ValueError("At least one of take_profit_price or stop_loss_price must be provided")
|
891
|
+
|
892
|
+
# Get current position to determine side and quantity
|
893
|
+
position_params = {"symbol": symbol}
|
894
|
+
positions = await client._make_request("GET", "/fapi/v2/positionRisk", position_params, "USER_DATA")
|
895
|
+
|
896
|
+
position_to_hedge = None
|
897
|
+
for pos in positions:
|
898
|
+
if pos["symbol"] == symbol and float(pos["positionAmt"]) != 0:
|
899
|
+
if position_side == "BOTH" or pos["positionSide"] == position_side:
|
900
|
+
position_to_hedge = pos
|
901
|
+
break
|
902
|
+
|
903
|
+
if not position_to_hedge:
|
904
|
+
raise ValueError(f"No open position found for {symbol} with position side {position_side}")
|
905
|
+
|
906
|
+
position_amt = float(position_to_hedge["positionAmt"])
|
907
|
+
current_position_side = position_to_hedge["positionSide"]
|
908
|
+
|
909
|
+
# Determine order side (opposite of position)
|
910
|
+
if position_amt > 0: # Long position
|
911
|
+
tp_sl_side = "SELL"
|
912
|
+
else: # Short position
|
913
|
+
tp_sl_side = "BUY"
|
914
|
+
position_amt = abs(position_amt)
|
915
|
+
|
916
|
+
order_quantity = quantity if quantity else position_amt
|
917
|
+
results = []
|
918
|
+
|
919
|
+
# Place Take Profit order
|
920
|
+
if take_profit_price:
|
921
|
+
tp_params = {
|
922
|
+
"symbol": symbol,
|
923
|
+
"side": tp_sl_side,
|
924
|
+
"type": tp_order_type,
|
925
|
+
"quantity": order_quantity,
|
926
|
+
"reduceOnly": "true"
|
927
|
+
}
|
928
|
+
|
929
|
+
if current_position_side != "BOTH":
|
930
|
+
tp_params["positionSide"] = current_position_side
|
931
|
+
|
932
|
+
if tp_order_type == "TAKE_PROFIT_MARKET":
|
933
|
+
tp_params["stopPrice"] = take_profit_price
|
934
|
+
else: # LIMIT
|
935
|
+
tp_params["price"] = take_profit_price
|
936
|
+
tp_params["timeInForce"] = time_in_force
|
937
|
+
|
938
|
+
tp_result = await client._make_request("POST", "/fapi/v1/order", tp_params, "TRADE")
|
939
|
+
results.append({"type": "take_profit", "result": tp_result})
|
940
|
+
|
941
|
+
# Place Stop Loss order
|
942
|
+
if stop_loss_price:
|
943
|
+
sl_params = {
|
944
|
+
"symbol": symbol,
|
945
|
+
"side": tp_sl_side,
|
946
|
+
"type": sl_order_type,
|
947
|
+
"quantity": order_quantity,
|
948
|
+
"reduceOnly": "true"
|
949
|
+
}
|
950
|
+
|
951
|
+
if current_position_side != "BOTH":
|
952
|
+
sl_params["positionSide"] = current_position_side
|
953
|
+
|
954
|
+
if sl_order_type == "STOP_MARKET":
|
955
|
+
sl_params["stopPrice"] = stop_loss_price
|
956
|
+
else: # STOP
|
957
|
+
sl_params["price"] = stop_loss_price
|
958
|
+
sl_params["stopPrice"] = stop_loss_price
|
959
|
+
sl_params["timeInForce"] = time_in_force
|
960
|
+
|
961
|
+
sl_result = await client._make_request("POST", "/fapi/v1/order", sl_params, "TRADE")
|
962
|
+
results.append({"type": "stop_loss", "result": sl_result})
|
963
|
+
|
964
|
+
result = results
|
965
|
+
elif name == "place_bracket_order":
|
966
|
+
# Place entry order with TP/SL
|
967
|
+
symbol = arguments["symbol"]
|
968
|
+
side = arguments["side"]
|
969
|
+
quantity = arguments["quantity"]
|
970
|
+
entry_price = arguments.get("entry_price")
|
971
|
+
take_profit_price = arguments["take_profit_price"]
|
972
|
+
stop_loss_price = arguments["stop_loss_price"]
|
973
|
+
entry_order_type = arguments.get("entry_order_type", "MARKET")
|
974
|
+
position_side = arguments.get("positionSide", "BOTH")
|
975
|
+
time_in_force = arguments.get("timeInForce", "GTC")
|
976
|
+
|
977
|
+
results = []
|
978
|
+
|
979
|
+
# Place entry order
|
980
|
+
entry_params = {
|
981
|
+
"symbol": symbol,
|
982
|
+
"side": side,
|
983
|
+
"type": entry_order_type,
|
984
|
+
"quantity": quantity
|
985
|
+
}
|
986
|
+
|
987
|
+
if position_side != "BOTH":
|
988
|
+
entry_params["positionSide"] = position_side
|
989
|
+
|
990
|
+
if entry_order_type == "LIMIT":
|
991
|
+
if not entry_price:
|
992
|
+
raise ValueError("entry_price is required for LIMIT orders")
|
993
|
+
entry_params["price"] = entry_price
|
994
|
+
entry_params["timeInForce"] = time_in_force
|
995
|
+
|
996
|
+
entry_result = await client._make_request("POST", "/fapi/v1/order", entry_params, "TRADE")
|
997
|
+
results.append({"type": "entry", "result": entry_result})
|
998
|
+
|
999
|
+
# Determine TP/SL side (opposite of entry)
|
1000
|
+
tp_sl_side = "SELL" if side == "BUY" else "BUY"
|
1001
|
+
|
1002
|
+
# Place Take Profit order
|
1003
|
+
tp_params = {
|
1004
|
+
"symbol": symbol,
|
1005
|
+
"side": tp_sl_side,
|
1006
|
+
"type": "TAKE_PROFIT_MARKET",
|
1007
|
+
"quantity": quantity,
|
1008
|
+
"stopPrice": take_profit_price,
|
1009
|
+
"reduceOnly": "true"
|
1010
|
+
}
|
1011
|
+
if position_side != "BOTH":
|
1012
|
+
tp_params["positionSide"] = position_side
|
1013
|
+
|
1014
|
+
tp_result = await client._make_request("POST", "/fapi/v1/order", tp_params, "TRADE")
|
1015
|
+
results.append({"type": "take_profit", "result": tp_result})
|
1016
|
+
|
1017
|
+
# Place Stop Loss order
|
1018
|
+
sl_params = {
|
1019
|
+
"symbol": symbol,
|
1020
|
+
"side": tp_sl_side,
|
1021
|
+
"type": "STOP_MARKET",
|
1022
|
+
"quantity": quantity,
|
1023
|
+
"stopPrice": stop_loss_price,
|
1024
|
+
"reduceOnly": "true"
|
1025
|
+
}
|
1026
|
+
if position_side != "BOTH":
|
1027
|
+
sl_params["positionSide"] = position_side
|
1028
|
+
|
1029
|
+
sl_result = await client._make_request("POST", "/fapi/v1/order", sl_params, "TRADE")
|
1030
|
+
results.append({"type": "stop_loss", "result": sl_result})
|
1031
|
+
|
1032
|
+
result = results
|
700
1033
|
|
701
1034
|
# Trading Configuration Tools
|
702
1035
|
elif name == "change_leverage":
|
@@ -816,7 +1149,7 @@ async def main():
|
|
816
1149
|
write_stream,
|
817
1150
|
InitializationOptions(
|
818
1151
|
server_name="binance-futures-mcp-server",
|
819
|
-
server_version="1.0.
|
1152
|
+
server_version="1.0.9",
|
820
1153
|
capabilities={
|
821
1154
|
"tools": {}
|
822
1155
|
}
|
@@ -1,9 +0,0 @@
|
|
1
|
-
binance_mcp/__init__.py,sha256=ExUxc1kp3GoSwmEtC7eGgFMZlvSQ4IdW1T5xhw-NT98,106
|
2
|
-
binance_mcp/__main__.py,sha256=_9DBrtv0PAvjLjCqKk_cMfGtkqSUOcmU6HeQKFjuFMQ,214
|
3
|
-
binance_mcp/server.py,sha256=mBuB1HX6xf5GSviYV5oIPqKz2werdBiibyxTUA-qnpY,41669
|
4
|
-
binance_futures_mcp-1.0.7.dist-info/LICENSE,sha256=zqfwopvOi7kOx5YVOnehgmRFR-IU3x1n9JEShr3QOYg,1075
|
5
|
-
binance_futures_mcp-1.0.7.dist-info/METADATA,sha256=GgB3I-rPgq5YKmV9Usi-RYvAtpQ9rk7LowADz1-Q5j8,11418
|
6
|
-
binance_futures_mcp-1.0.7.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
7
|
-
binance_futures_mcp-1.0.7.dist-info/entry_points.txt,sha256=-1iVs9AF7JQBS-xMichP9hQhbCY7YfLFRJVaNKwuN34,69
|
8
|
-
binance_futures_mcp-1.0.7.dist-info/top_level.txt,sha256=RqGhe1caZUvBF_ezvTiLZD8kVS25eiWVkfJfmoND9m8,12
|
9
|
-
binance_futures_mcp-1.0.7.dist-info/RECORD,,
|
{binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info}/entry_points.txt
RENAMED
File without changes
|
{binance_futures_mcp-1.0.7.dist-info → binance_futures_mcp-1.0.9.dist-info/licenses}/LICENSE
RENAMED
File without changes
|
File without changes
|