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.
@@ -1,12 +1,14 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: binance-futures-mcp
3
- Version: 1.0.7
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
- Project-URL: Bug Tracker, https://github.com/alexcandrabersiva/bin-mcp/issues
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
- Keywords: mcp binance trading futures api model-context-protocol
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 (>=1.0.0)
24
- Requires-Dist: aiohttp (>=3.8.0)
25
- Requires-Dist: pydantic (>=2.0.0)
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
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.7',
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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
- "order_type": {"type": "string", "description": "Order type ('MARKET', 'LIMIT', 'STOP', 'STOP_MARKET', 'TRAILING_STOP_MARKET', etc)"},
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
- "stop_price": {"type": "number", "description": "Stop price (for STOP orders)"},
251
- "time_in_force": {"type": "string", "description": "Time in force (GTC, IOC, FOK)"},
252
- "position_side": {"type": "string", "description": "Position side ('BOTH', 'LONG', 'SHORT')"},
253
- "reduce_only": {"type": "string", "description": "Reduce only flag"},
254
- "new_client_order_id": {"type": "string", "description": "Custom order ID"},
255
- "close_position": {"type": "string", "description": "Close position flag"},
256
- "activation_price": {"type": "number", "description": "Activation price (for TRAILING_STOP_MARKET)"},
257
- "callback_rate": {"type": "number", "description": "Callback rate (for TRAILING_STOP_MARKET)"},
258
- "working_type": {"type": "string", "description": "Working type (MARK_PRICE, CONTRACT_PRICE)"},
259
- "price_protect": {"type": "string", "description": "Price protection flag"},
260
- "new_order_resp_type": {"type": "string", "description": "Response type"},
261
- "recv_window": {"type": "integer", "description": "Receive window"},
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", "order_type"]
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
- # Convert order_type to type for API
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.7",
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,,