Skip to main content
Glama

MCP Server for Binance Spot Trading

by kydlikebtc
index.ts9.84 kB
#!/usr/bin/env node import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import { SpotOrder } from "./types/binance.js"; import { storeApiKeys, getApiKeys, deleteApiKeys, } from "./services/keystore.js"; import { createSpotOrder, cancelOrder, getAccountBalances, getOpenOrders, } from "./services/binance.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import dotenv from "dotenv"; import { initializeBinanceClient } from "./services/binance.js"; import { configureApiKeysTool, createOrderTool, cancelOrderTool, getBalancesTool, getOpenOrdersTool, createFuturesOrderTool, cancelFuturesOrderTool, getFuturesPositionsTool, setFuturesLeverageTool, getFuturesAccountTool, getFuturesOpenOrdersTool, getFundingRateTool, } from "./services/tools.js"; import { createFuturesOrder, cancelFuturesOrder, getFuturesPositions, setFuturesLeverage, getFuturesAccountInformation as getFuturesAccount, getFuturesOpenOrders, getFundingRate, initializeFuturesClient, changePositionMode, changeMarginType, getFuturesKlines, } from "./services/binanceFutures.js"; import { FuturesOrder, LeverageSettings, TimeInForce, PositionSide, WorkingType, MarginType } from "./types/futures.js"; import * as fs from 'fs'; import * as path from 'path'; import { z } from "zod"; // Load environment variables first dotenv.config(); const logFile = path.join(process.cwd(), 'logs', 'server.log'); // 确保日志目录存在 if (!fs.existsSync(path.dirname(logFile))) { fs.mkdirSync(path.dirname(logFile), { recursive: true }); } function log(message: string) { const timestamp = new Date().toISOString(); fs.appendFileSync(logFile, `${timestamp} - ${message}\n`); } function logError(message: string, error?: unknown) { const timestamp = new Date().toISOString(); const errorMessage = error instanceof Error ? error.message : String(error); fs.appendFileSync(logFile, `${timestamp} - ERROR: ${message} ${error ? `- ${errorMessage}` : ''}\n`); } // 创建高级McpServer实例,而不是低级Server实例 const server = new McpServer({ name: "mcp-server-binance", version: "0.1.0", }); // 注册工具 server.tool( "configure_api_keys", { apiKey: z.string().describe("Binance API key"), apiSecret: z.string().describe("Binance API secret") }, async ({ apiKey, apiSecret }) => { await storeApiKeys(apiKey, apiSecret); const spotInitialized = await initializeBinanceClient(); const futuresInitialized = await initializeFuturesClient(); return { content: [ { type: "text", text: spotInitialized && futuresInitialized ? "API keys configured successfully" : "Failed to initialize Binance clients", }, ], }; } ); server.tool( "create_spot_order", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), side: z.enum(["BUY", "SELL"]).describe("Order side"), type: z.enum(["LIMIT", "MARKET"]).describe("Order type"), quantity: z.string().optional().describe("Order quantity (amount of base asset)"), quoteOrderQty: z.string().optional().describe("Quote order quantity (amount of quote asset to spend or receive, e.g. USDT)"), price: z.string().optional().describe("Order price (required for LIMIT orders)"), timeInForce: z.enum(["GTC", "IOC", "FOK"]).optional().describe("Time in force") }, async (args) => { const order: SpotOrder = { symbol: args.symbol, side: args.side, type: args.type, quantity: args.quantity, quoteOrderQty: args.quoteOrderQty, price: args.price, timeInForce: args.timeInForce, }; const response = await createSpotOrder(order); return { content: [ { type: "text", text: JSON.stringify(response), }, ], }; } ); server.tool( "cancel_order", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), orderId: z.number().describe("Order ID to cancel") }, async ({ symbol, orderId }) => { await cancelOrder(symbol, orderId); return { content: [ { type: "text", text: "Order cancelled successfully", }, ], }; } ); server.tool( "get_balances", {}, async () => { const balances = await getAccountBalances(); return { content: [ { type: "text", text: JSON.stringify(balances), }, ], }; } ); server.tool( "get_open_orders", { symbol: z.string().optional().describe("Trading pair symbol (optional)") }, async ({ symbol }) => { const orders = await getOpenOrders(symbol); return { content: [ { type: "text", text: JSON.stringify(orders), }, ], }; } ); server.tool( "create_futures_order", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), side: z.enum(["BUY", "SELL"]).describe("Order side"), type: z.enum([ "LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET" ]).describe("Order type"), quantity: z.string().describe("Order quantity"), price: z.string().optional().describe("Order price (required for LIMIT orders)"), stopPrice: z.string().optional().describe("Stop price (required for STOP orders)"), timeInForce: z.enum(["GTC", "IOC", "FOK", "GTX"]).optional().describe("Time in force"), reduceOnly: z.boolean().optional().describe("Reduce only flag"), closePosition: z.boolean().optional().describe("Close position flag"), positionSide: z.enum(["BOTH", "LONG", "SHORT"]).optional().describe("Position side"), workingType: z.enum(["MARK_PRICE", "CONTRACT_PRICE"]).optional().describe("Working type"), priceProtect: z.boolean().optional().describe("Price protect flag"), activationPrice: z.string().optional().describe("Activation price for TRAILING_STOP_MARKET orders"), callbackRate: z.string().optional().describe("Callback rate for TRAILING_STOP_MARKET orders") }, async (args) => { const order: FuturesOrder = { symbol: args.symbol, side: args.side, type: args.type, quantity: args.quantity, price: args.price, stopPrice: args.stopPrice, timeInForce: args.timeInForce as TimeInForce, reduceOnly: args.reduceOnly, closePosition: args.closePosition, positionSide: args.positionSide as PositionSide, workingType: args.workingType as WorkingType, priceProtect: args.priceProtect, activationPrice: args.activationPrice, callbackRate: args.callbackRate, }; const response = await createFuturesOrder(order); return { content: [ { type: "text", text: JSON.stringify(response), }, ], }; } ); server.tool( "cancel_futures_order", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), orderId: z.number().describe("Order ID to cancel") }, async ({ symbol, orderId }) => { await cancelFuturesOrder(symbol, orderId); return { content: [ { type: "text", text: "Futures order cancelled successfully", }, ], }; } ); server.tool( "get_futures_positions", {}, async () => { const positions = await getFuturesPositions(); return { content: [ { type: "text", text: JSON.stringify(positions), }, ], }; } ); server.tool( "set_futures_leverage", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)"), leverage: z.number().describe("Leverage value (1-125)") }, async ({ symbol, leverage }) => { const settings: LeverageSettings = { symbol: symbol, leverage: leverage, }; await setFuturesLeverage(settings); return { content: [ { type: "text", text: "Leverage set successfully", }, ], }; } ); server.tool( "get_futures_account", {}, async () => { const account = await getFuturesAccount(); return { content: [ { type: "text", text: JSON.stringify(account), }, ], }; } ); server.tool( "get_futures_open_orders", { symbol: z.string().optional().describe("Trading pair symbol (optional)") }, async ({ symbol }) => { const orders = await getFuturesOpenOrders(symbol); return { content: [ { type: "text", text: JSON.stringify(orders), }, ], }; } ); server.tool( "get_funding_rate", { symbol: z.string().describe("Trading pair symbol (e.g., BTCUSDT)") }, async ({ symbol }) => { const rate = await getFundingRate(symbol); return { content: [ { type: "text", text: JSON.stringify(rate), }, ], }; } ); async function main() { try { // Initialize Binance clients const spotInitialized = await initializeBinanceClient(); const futuresInitialized = await initializeFuturesClient(); if (!spotInitialized || !futuresInitialized) { logError('Binance clients not initialized'); } else { log('Binance clients initialized successfully'); } // 使用stdio传输层 const transport = new StdioServerTransport(); await server.connect(transport); log('Server started successfully with stdio transport'); } catch (error) { logError('Failed to start server:', error); process.exit(1); } } main().catch((error) => { logError('Unhandled error:', error); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kydlikebtc/mcp-server-bn'

If you have feedback or need assistance with the MCP directory API, please join our Discord server