trading-platform/docs/01-arquitectura/MCP-BINANCE-CONNECTOR-SPEC.md
rckrdmrd c1b5081208 feat(ml): Complete FASE 11 - BTCUSD update and comprehensive documentation alignment
ML Engine Updates:
- Updated BTCUSD with Polygon API data (2024-2025): 215,699 new records
- Re-trained all ML models: Attention (R²: 0.223), Base, Metamodel (87.3% confidence)
- Backtest results: +176.71R profit with aggressive_filter strategy

Documentation Consolidation:
- Created docs/99-analisis/_MAP.md index with 13 new analysis documents
- Consolidated inventories: removed duplicates from orchestration/inventarios/
- Updated ML_INVENTORY.yml with BTCUSD metrics and training results
- Added execution reports: FASE11-BTCUSD, correction issues, alignment validation

Architecture & Integration:
- Updated all module documentation with NEXUS v3.4 frontmatter
- Fixed _MAP.md indexes across all folders
- Updated orchestration plans and traces

Files: 229 changed, 5064 insertions(+), 1872 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 09:31:29 -06:00

32 KiB

id title type project version created_date updated_date author
MCP-BINANCE-CONNECTOR-SPEC Especificacion MCP Binance Connector Technical Specification trading-platform 1.0.0 2026-01-04 2026-01-04 Orquestador Agent - Trading Platform

MCP Binance Connector - Especificacion Tecnica

Version: 1.0.0 Fecha: 2026-01-04 Modulo: OQI-010-llm-trading-integration Puerto: 3606


Tabla de Contenidos

  1. Vision General
  2. Arquitectura
  3. MCP Tools Specification
  4. Seguridad
  5. Configuracion
  6. Implementacion
  7. Testing

Vision General

Proposito

El MCP Binance Connector expone las funcionalidades de Binance como herramientas MCP (Model Context Protocol), permitiendo que los agentes LLM interactuen con el exchange de forma segura y controlada.

Capacidades

Categoria Funcionalidades
Market Data Precios, order book, velas, 24h stats
Account Balance, posiciones, historial
Trading Ordenes market/limit, cancelacion
Futures Posiciones, leverage, funding

Integracion con LLM Agent

┌─────────────────────────────────────────────────────────────────┐
│                      LLM TRADING AGENT                           │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                   MCP ORCHESTRATOR                         │ │
│  │                                                            │ │
│  │   ┌──────────────────┐      ┌──────────────────┐          │ │
│  │   │  MCP MT4         │      │  MCP BINANCE     │          │ │
│  │   │  Connector       │      │  Connector       │          │ │
│  │   │  :3605           │      │  :3606           │          │ │
│  │   └────────┬─────────┘      └────────┬─────────┘          │ │
│  └────────────┼─────────────────────────┼────────────────────┘ │
│               │                         │                       │
└───────────────┼─────────────────────────┼───────────────────────┘
                │                         │
                ▼                         ▼
        ┌───────────────┐         ┌───────────────┐
        │   MetaAPI     │         │   Binance     │
        │   (MT4/MT5)   │         │   Exchange    │
        └───────────────┘         └───────────────┘

Arquitectura

Estructura del Proyecto

apps/mcp-binance-connector/
├── src/
│   ├── index.ts                 # Entry point & MCP server
│   ├── config.ts                # Configuration management
│   │
│   ├── services/
│   │   ├── binance-client.ts    # CCXT wrapper for Binance
│   │   ├── rate-limiter.ts      # Rate limiting service
│   │   └── websocket-manager.ts # WebSocket connections
│   │
│   ├── tools/
│   │   ├── index.ts             # Tool registry
│   │   ├── market.ts            # Market data tools
│   │   ├── account.ts           # Account info tools
│   │   ├── orders.ts            # Order management tools
│   │   ├── positions.ts         # Position management (futures)
│   │   └── utils.ts             # Utility tools
│   │
│   ├── middleware/
│   │   ├── auth.ts              # API key validation
│   │   ├── risk-check.ts        # Pre-trade risk validation
│   │   └── logging.ts           # Request/response logging
│   │
│   └── types/
│       ├── binance.ts           # Binance-specific types
│       └── mcp.ts               # MCP protocol types
│
├── tests/
│   ├── unit/
│   │   ├── market.test.ts
│   │   └── orders.test.ts
│   └── integration/
│       └── binance-api.test.ts
│
├── docs/
│   ├── ARCHITECTURE.md
│   └── MCP-TOOLS-SPEC.md
│
├── Dockerfile
├── package.json
├── tsconfig.json
├── .env.example
└── README.md

Dependencias Principales

{
  "dependencies": {
    "@modelcontextprotocol/sdk": "^0.6.0",
    "ccxt": "^4.0.0",
    "express": "^4.18.2",
    "zod": "^3.22.0",
    "redis": "^4.6.0",
    "winston": "^3.11.0",
    "axios": "^1.6.0"
  },
  "devDependencies": {
    "typescript": "^5.3.0",
    "ts-node-dev": "^2.0.0",
    "jest": "^29.7.0",
    "@types/node": "^20.10.0"
  }
}

MCP Tools Specification

Tool Categories

1. Market Data Tools (Read-Only, Low Risk)

// tools/market.ts

/**
 * Tool: binance_get_ticker
 * Obtiene precio actual y estadisticas 24h de un simbolo
 */
export const getTickerTool: MCPTool = {
  name: "binance_get_ticker",
  description: "Obtiene el precio actual y estadisticas de 24h para un simbolo de trading",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading (ej: BTCUSDT, ETHUSDT)",
        pattern: "^[A-Z]{2,10}$"
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol }) => {
    const ticker = await binanceClient.fetchTicker(symbol);
    return {
      symbol: ticker.symbol,
      price: ticker.last,
      bid: ticker.bid,
      ask: ticker.ask,
      high24h: ticker.high,
      low24h: ticker.low,
      volume24h: ticker.baseVolume,
      change24h: ticker.percentage,
      timestamp: ticker.timestamp
    };
  }
};

/**
 * Tool: binance_get_orderbook
 * Obtiene el order book con profundidad especificada
 */
export const getOrderbookTool: MCPTool = {
  name: "binance_get_orderbook",
  description: "Obtiene el order book (bids y asks) con la profundidad especificada",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      limit: {
        type: "number",
        description: "Profundidad del orderbook (5, 10, 20, 50, 100)",
        enum: [5, 10, 20, 50, 100],
        default: 20
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol, limit = 20 }) => {
    const orderbook = await binanceClient.fetchOrderBook(symbol, limit);
    return {
      symbol,
      bids: orderbook.bids.slice(0, 10),
      asks: orderbook.asks.slice(0, 10),
      spread: orderbook.asks[0][0] - orderbook.bids[0][0],
      spreadPercentage: ((orderbook.asks[0][0] - orderbook.bids[0][0]) / orderbook.bids[0][0]) * 100,
      timestamp: orderbook.timestamp
    };
  }
};

/**
 * Tool: binance_get_klines
 * Obtiene velas historicas (OHLCV)
 */
export const getKlinesTool: MCPTool = {
  name: "binance_get_klines",
  description: "Obtiene velas historicas (OHLCV) para analisis tecnico",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      interval: {
        type: "string",
        description: "Intervalo temporal",
        enum: ["1m", "5m", "15m", "30m", "1h", "4h", "1d", "1w"],
        default: "5m"
      },
      limit: {
        type: "number",
        description: "Numero de velas (max 500)",
        default: 100,
        maximum: 500
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol, interval = "5m", limit = 100 }) => {
    const ohlcv = await binanceClient.fetchOHLCV(symbol, interval, undefined, limit);
    return {
      symbol,
      interval,
      candles: ohlcv.map(c => ({
        timestamp: c[0],
        open: c[1],
        high: c[2],
        low: c[3],
        close: c[4],
        volume: c[5]
      })),
      count: ohlcv.length
    };
  }
};

/**
 * Tool: binance_get_trades
 * Obtiene trades recientes
 */
export const getRecentTradesTool: MCPTool = {
  name: "binance_get_trades",
  description: "Obtiene los trades mas recientes del mercado",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      limit: {
        type: "number",
        description: "Numero de trades (max 100)",
        default: 50,
        maximum: 100
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol, limit = 50 }) => {
    const trades = await binanceClient.fetchTrades(symbol, undefined, limit);
    return {
      symbol,
      trades: trades.map(t => ({
        id: t.id,
        price: t.price,
        amount: t.amount,
        side: t.side,
        timestamp: t.timestamp
      })),
      count: trades.length
    };
  }
};

2. Account Tools (Read-Only, Medium Risk)

// tools/account.ts

/**
 * Tool: binance_get_account
 * Obtiene balance y estado de la cuenta
 */
export const getAccountTool: MCPTool = {
  name: "binance_get_account",
  description: "Obtiene el balance y estado de la cuenta de trading",
  inputSchema: {
    type: "object",
    properties: {},
    required: []
  },
  handler: async () => {
    const balance = await binanceClient.fetchBalance();

    // Filtrar solo activos con balance > 0
    const nonZeroBalances = Object.entries(balance.total)
      .filter(([_, amount]) => amount > 0)
      .map(([asset, total]) => ({
        asset,
        free: balance.free[asset],
        locked: balance.used[asset],
        total
      }));

    return {
      accountType: "SPOT",
      balances: nonZeroBalances,
      totalUSDT: await calculateTotalUSDT(nonZeroBalances),
      canTrade: true,
      canWithdraw: true,
      updateTime: Date.now()
    };
  }
};

/**
 * Tool: binance_get_open_orders
 * Obtiene ordenes abiertas
 */
export const getOpenOrdersTool: MCPTool = {
  name: "binance_get_open_orders",
  description: "Obtiene todas las ordenes abiertas (pendientes de ejecucion)",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo especifico (opcional, si no se especifica retorna todos)"
      }
    },
    required: []
  },
  handler: async ({ symbol }) => {
    const orders = await binanceClient.fetchOpenOrders(symbol);
    return {
      orders: orders.map(o => ({
        id: o.id,
        symbol: o.symbol,
        side: o.side,
        type: o.type,
        price: o.price,
        amount: o.amount,
        filled: o.filled,
        remaining: o.remaining,
        status: o.status,
        createdAt: o.timestamp
      })),
      count: orders.length
    };
  }
};

/**
 * Tool: binance_get_trade_history
 * Obtiene historial de trades ejecutados
 */
export const getTradeHistoryTool: MCPTool = {
  name: "binance_get_trade_history",
  description: "Obtiene el historial de trades ejecutados por el usuario",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      limit: {
        type: "number",
        description: "Numero de trades (max 100)",
        default: 50,
        maximum: 100
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol, limit = 50 }) => {
    const trades = await binanceClient.fetchMyTrades(symbol, undefined, limit);
    return {
      symbol,
      trades: trades.map(t => ({
        id: t.id,
        orderId: t.order,
        side: t.side,
        price: t.price,
        amount: t.amount,
        cost: t.cost,
        fee: t.fee,
        timestamp: t.timestamp
      })),
      totalPnL: calculatePnL(trades),
      count: trades.length
    };
  }
};

3. Order Management Tools (High Risk, Requires Confirmation)

// tools/orders.ts

/**
 * Tool: binance_create_order
 * Crea una orden de trading
 * ALTO RIESGO - Requiere confirmacion explicita
 */
export const createOrderTool: MCPTool = {
  name: "binance_create_order",
  description: "Crea una orden de compra o venta. ALTO RIESGO - Asegurate de validar con el usuario antes de ejecutar.",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading (ej: BTCUSDT)"
      },
      side: {
        type: "string",
        description: "Direccion de la orden",
        enum: ["buy", "sell"]
      },
      type: {
        type: "string",
        description: "Tipo de orden",
        enum: ["market", "limit", "stop_loss", "take_profit"],
        default: "market"
      },
      amount: {
        type: "number",
        description: "Cantidad a comprar/vender"
      },
      price: {
        type: "number",
        description: "Precio limite (requerido para ordenes limit)"
      },
      stopPrice: {
        type: "number",
        description: "Precio de activacion para stop orders"
      }
    },
    required: ["symbol", "side", "amount"]
  },
  riskLevel: "HIGH",
  requiresConfirmation: true,
  handler: async ({ symbol, side, type = "market", amount, price, stopPrice }) => {
    // Pre-trade risk check
    const riskCheck = await performRiskCheck({ symbol, side, amount, price });
    if (!riskCheck.allowed) {
      return {
        success: false,
        error: "RISK_CHECK_FAILED",
        details: riskCheck.reason
      };
    }

    try {
      let order;
      if (type === "market") {
        order = await binanceClient.createMarketOrder(symbol, side, amount);
      } else if (type === "limit" && price) {
        order = await binanceClient.createLimitOrder(symbol, side, amount, price);
      } else if (type === "stop_loss" && stopPrice) {
        order = await binanceClient.createOrder(symbol, "stop_loss", side, amount, undefined, {
          stopPrice
        });
      }

      return {
        success: true,
        order: {
          id: order.id,
          symbol: order.symbol,
          side: order.side,
          type: order.type,
          price: order.price || order.average,
          amount: order.amount,
          filled: order.filled,
          status: order.status,
          timestamp: order.timestamp
        }
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
};

/**
 * Tool: binance_cancel_order
 * Cancela una orden pendiente
 */
export const cancelOrderTool: MCPTool = {
  name: "binance_cancel_order",
  description: "Cancela una orden pendiente",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      orderId: {
        type: "string",
        description: "ID de la orden a cancelar"
      }
    },
    required: ["symbol", "orderId"]
  },
  riskLevel: "MEDIUM",
  handler: async ({ symbol, orderId }) => {
    try {
      const result = await binanceClient.cancelOrder(orderId, symbol);
      return {
        success: true,
        cancelledOrder: {
          id: result.id,
          symbol: result.symbol,
          status: "CANCELLED"
        }
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
};

/**
 * Tool: binance_cancel_all_orders
 * Cancela todas las ordenes de un simbolo
 */
export const cancelAllOrdersTool: MCPTool = {
  name: "binance_cancel_all_orders",
  description: "Cancela todas las ordenes pendientes de un simbolo",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      }
    },
    required: ["symbol"]
  },
  riskLevel: "MEDIUM",
  handler: async ({ symbol }) => {
    try {
      const result = await binanceClient.cancelAllOrders(symbol);
      return {
        success: true,
        cancelledCount: result.length
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
};

4. Futures Tools (High Risk)

// tools/positions.ts

/**
 * Tool: binance_get_futures_positions
 * Obtiene posiciones abiertas en futuros
 */
export const getFuturesPositionsTool: MCPTool = {
  name: "binance_get_futures_positions",
  description: "Obtiene posiciones abiertas en Binance Futures",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo especifico (opcional)"
      }
    },
    required: []
  },
  handler: async ({ symbol }) => {
    // Cambiar a cliente de futuros
    const positions = await binanceFuturesClient.fetchPositions(symbol);

    const activePositions = positions.filter(p =>
      parseFloat(p.contracts) !== 0
    );

    return {
      positions: activePositions.map(p => ({
        symbol: p.symbol,
        side: parseFloat(p.contracts) > 0 ? 'LONG' : 'SHORT',
        size: Math.abs(parseFloat(p.contracts)),
        entryPrice: parseFloat(p.entryPrice),
        markPrice: parseFloat(p.markPrice),
        unrealizedPnL: parseFloat(p.unrealizedPnl),
        leverage: p.leverage,
        liquidationPrice: parseFloat(p.liquidationPrice),
        marginType: p.marginType
      })),
      count: activePositions.length
    };
  }
};

/**
 * Tool: binance_set_leverage
 * Configura el leverage para un simbolo
 */
export const setLeverageTool: MCPTool = {
  name: "binance_set_leverage",
  description: "Configura el nivel de leverage para un simbolo en Futures",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de trading"
      },
      leverage: {
        type: "number",
        description: "Nivel de leverage (1-125)",
        minimum: 1,
        maximum: 125
      }
    },
    required: ["symbol", "leverage"]
  },
  riskLevel: "HIGH",
  handler: async ({ symbol, leverage }) => {
    // Validar leverage maximo
    if (leverage > 20) {
      return {
        success: false,
        error: "LEVERAGE_TOO_HIGH",
        message: "Leverage mayor a 20x no recomendado por politica de riesgo"
      };
    }

    try {
      await binanceFuturesClient.setLeverage(leverage, symbol);
      return {
        success: true,
        symbol,
        leverage,
        message: `Leverage configurado a ${leverage}x`
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
};

/**
 * Tool: binance_close_position
 * Cierra una posicion de futuros
 */
export const closePositionTool: MCPTool = {
  name: "binance_close_position",
  description: "Cierra completamente una posicion de futuros. ALTO RIESGO.",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de la posicion a cerrar"
      }
    },
    required: ["symbol"]
  },
  riskLevel: "HIGH",
  requiresConfirmation: true,
  handler: async ({ symbol }) => {
    try {
      // Obtener posicion actual
      const positions = await binanceFuturesClient.fetchPositions(symbol);
      const position = positions.find(p =>
        p.symbol === symbol && parseFloat(p.contracts) !== 0
      );

      if (!position) {
        return {
          success: false,
          error: "NO_POSITION",
          message: `No hay posicion abierta para ${symbol}`
        };
      }

      const size = Math.abs(parseFloat(position.contracts));
      const side = parseFloat(position.contracts) > 0 ? 'sell' : 'buy';

      // Crear orden de cierre
      const order = await binanceFuturesClient.createMarketOrder(
        symbol,
        side,
        size,
        undefined,
        { reduceOnly: true }
      );

      return {
        success: true,
        closedPosition: {
          symbol,
          closedSize: size,
          closedSide: side === 'sell' ? 'LONG' : 'SHORT',
          realizedPnL: parseFloat(position.unrealizedPnl),
          orderId: order.id
        }
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
};

5. Utility Tools

// tools/utils.ts

/**
 * Tool: binance_get_exchange_info
 * Obtiene informacion del exchange
 */
export const getExchangeInfoTool: MCPTool = {
  name: "binance_get_exchange_info",
  description: "Obtiene informacion del exchange: simbolos disponibles, limites, etc.",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo especifico (opcional)"
      }
    },
    required: []
  },
  handler: async ({ symbol }) => {
    const markets = await binanceClient.loadMarkets();

    if (symbol) {
      const market = markets[symbol];
      if (!market) {
        return { error: `Symbol ${symbol} not found` };
      }
      return {
        symbol: market.symbol,
        base: market.base,
        quote: market.quote,
        precision: market.precision,
        limits: market.limits,
        active: market.active
      };
    }

    // Retornar resumen general
    const activeMarkets = Object.values(markets).filter(m => m.active);
    return {
      totalMarkets: activeMarkets.length,
      topMarkets: activeMarkets
        .filter(m => m.quote === 'USDT')
        .slice(0, 20)
        .map(m => m.symbol)
    };
  }
};

/**
 * Tool: binance_get_funding_rate
 * Obtiene funding rate actual (futures)
 */
export const getFundingRateTool: MCPTool = {
  name: "binance_get_funding_rate",
  description: "Obtiene el funding rate actual para un simbolo de futuros",
  inputSchema: {
    type: "object",
    properties: {
      symbol: {
        type: "string",
        description: "Simbolo de futuros (ej: BTCUSDT)"
      }
    },
    required: ["symbol"]
  },
  handler: async ({ symbol }) => {
    const funding = await binanceFuturesClient.fetchFundingRate(symbol);
    return {
      symbol,
      fundingRate: funding.fundingRate,
      fundingTimestamp: funding.fundingTimestamp,
      nextFundingTime: funding.nextFundingTimestamp,
      annualized: funding.fundingRate * 3 * 365 * 100 // Aproximado anualizado
    };
  }
};

Seguridad

Niveles de Riesgo

Nivel Herramientas Requiere Confirmacion
LOW get_ticker, get_klines, get_orderbook No
MEDIUM get_account, cancel_order No
HIGH create_order, close_position, set_leverage SI

Middleware de Autorizacion

// middleware/auth.ts

import { Request, Response, NextFunction } from 'express';

export const authMiddleware = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  // 1. Verificar API key del MCP client
  const mcpKey = req.headers['x-mcp-api-key'];
  if (!mcpKey || mcpKey !== process.env.MCP_API_KEY) {
    return res.status(401).json({ error: 'Invalid MCP API key' });
  }

  // 2. Verificar que Binance API keys estan configuradas
  if (!process.env.BINANCE_API_KEY || !process.env.BINANCE_API_SECRET) {
    return res.status(500).json({ error: 'Binance API not configured' });
  }

  next();
};

Pre-Trade Risk Check

// middleware/risk-check.ts

interface RiskCheckParams {
  symbol: string;
  side: 'buy' | 'sell';
  amount: number;
  price?: number;
}

export const performRiskCheck = async (params: RiskCheckParams) => {
  const { symbol, side, amount, price } = params;

  // 1. Verificar balance suficiente
  const balance = await binanceClient.fetchBalance();
  const quoteAsset = symbol.replace(/.*?(USDT|BUSD|USDC)$/, '$1');
  const available = balance.free[quoteAsset] || 0;

  const orderValue = price ? amount * price : amount * (await getCurrentPrice(symbol));

  if (side === 'buy' && available < orderValue) {
    return {
      allowed: false,
      reason: `Insufficient balance. Required: ${orderValue}, Available: ${available}`
    };
  }

  // 2. Verificar tamano maximo de orden
  const maxOrderValue = parseFloat(process.env.MAX_ORDER_VALUE_USDT || '1000');
  if (orderValue > maxOrderValue) {
    return {
      allowed: false,
      reason: `Order value ${orderValue} exceeds maximum ${maxOrderValue} USDT`
    };
  }

  // 3. Verificar limites diarios
  const dailyVolume = await getDailyTradingVolume();
  const maxDailyVolume = parseFloat(process.env.MAX_DAILY_VOLUME_USDT || '10000');
  if (dailyVolume + orderValue > maxDailyVolume) {
    return {
      allowed: false,
      reason: `Daily volume limit reached. Current: ${dailyVolume}, Limit: ${maxDailyVolume}`
    };
  }

  return { allowed: true };
};

Configuracion

Variables de Entorno

# .env.example

# === MCP Server ===
PORT=3606
MCP_API_KEY=your_mcp_api_key_here

# === Binance API ===
BINANCE_API_KEY=your_binance_api_key
BINANCE_API_SECRET=your_binance_api_secret

# === Network ===
BINANCE_TESTNET=true  # Usar testnet por defecto
BINANCE_FUTURES_TESTNET=true

# === Risk Limits ===
MAX_ORDER_VALUE_USDT=1000
MAX_DAILY_VOLUME_USDT=10000
MAX_LEVERAGE=20
MAX_POSITION_SIZE_PCT=5

# === Logging ===
LOG_LEVEL=info
LOG_FILE=logs/mcp-binance.log

# === Redis (para rate limiting) ===
REDIS_URL=redis://localhost:6379

Configuracion de CCXT

// config.ts

import ccxt from 'ccxt';

export const createBinanceClient = () => {
  const isTestnet = process.env.BINANCE_TESTNET === 'true';

  return new ccxt.binance({
    apiKey: process.env.BINANCE_API_KEY,
    secret: process.env.BINANCE_API_SECRET,
    sandbox: isTestnet,
    options: {
      defaultType: 'spot',
      adjustForTimeDifference: true,
    },
    enableRateLimit: true,
    rateLimit: 100
  });
};

export const createBinanceFuturesClient = () => {
  const isTestnet = process.env.BINANCE_FUTURES_TESTNET === 'true';

  return new ccxt.binance({
    apiKey: process.env.BINANCE_API_KEY,
    secret: process.env.BINANCE_API_SECRET,
    sandbox: isTestnet,
    options: {
      defaultType: 'future',
      adjustForTimeDifference: true,
    },
    enableRateLimit: true,
    rateLimit: 100
  });
};

Implementacion

Entry Point

// src/index.ts

import express from 'express';
import { Server } from '@modelcontextprotocol/sdk/server';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio';
import { createBinanceClient, createBinanceFuturesClient } from './config';
import { registerTools } from './tools';
import { authMiddleware } from './middleware/auth';
import { loggingMiddleware } from './middleware/logging';
import logger from './utils/logger';

const app = express();
const PORT = process.env.PORT || 3606;

// Middleware
app.use(express.json());
app.use(loggingMiddleware);

// Health check
app.get('/health', (req, res) => {
  res.json({
    status: 'healthy',
    service: 'mcp-binance-connector',
    version: '1.0.0',
    testnet: process.env.BINANCE_TESTNET === 'true',
    timestamp: new Date().toISOString()
  });
});

// MCP Server setup
const server = new Server({
  name: 'trading-binance-mcp',
  version: '1.0.0'
}, {
  capabilities: {
    tools: {}
  }
});

// Initialize clients
const binanceClient = createBinanceClient();
const binanceFuturesClient = createBinanceFuturesClient();

// Register all tools
registerTools(server, binanceClient, binanceFuturesClient);

// Tool execution endpoint (HTTP fallback)
app.post('/tools/:toolName', authMiddleware, async (req, res) => {
  const { toolName } = req.params;
  const params = req.body;

  try {
    const result = await executeToolByName(toolName, params);
    res.json(result);
  } catch (error) {
    logger.error(`Tool execution failed: ${toolName}`, error);
    res.status(500).json({ error: error.message });
  }
});

// List available tools
app.get('/tools', (req, res) => {
  res.json({
    tools: getAllToolDefinitions()
  });
});

// Start HTTP server
app.listen(PORT, () => {
  logger.info(`MCP Binance Connector running on port ${PORT}`);
  logger.info(`Testnet mode: ${process.env.BINANCE_TESTNET === 'true'}`);
});

// Start MCP stdio transport
const transport = new StdioServerTransport();
server.connect(transport).catch((error) => {
  logger.error('MCP transport connection failed', error);
});

export default app;

Dockerfile

# Dockerfile

FROM node:20-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy source
COPY . .

# Build TypeScript
RUN npm run build

# Environment
ENV NODE_ENV=production
ENV PORT=3606

EXPOSE 3606

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3606/health || exit 1

CMD ["node", "dist/index.js"]

Testing

Unit Tests

// tests/unit/market.test.ts

import { getTickerTool, getKlinesTool } from '../../src/tools/market';

describe('Market Tools', () => {
  describe('getTickerTool', () => {
    it('should return ticker data for valid symbol', async () => {
      const result = await getTickerTool.handler({ symbol: 'BTCUSDT' });

      expect(result).toHaveProperty('symbol', 'BTCUSDT');
      expect(result).toHaveProperty('price');
      expect(result.price).toBeGreaterThan(0);
    });

    it('should handle invalid symbol', async () => {
      const result = await getTickerTool.handler({ symbol: 'INVALID' });

      expect(result).toHaveProperty('error');
    });
  });

  describe('getKlinesTool', () => {
    it('should return OHLCV data', async () => {
      const result = await getKlinesTool.handler({
        symbol: 'BTCUSDT',
        interval: '5m',
        limit: 10
      });

      expect(result.candles).toHaveLength(10);
      expect(result.candles[0]).toHaveProperty('open');
      expect(result.candles[0]).toHaveProperty('high');
      expect(result.candles[0]).toHaveProperty('low');
      expect(result.candles[0]).toHaveProperty('close');
      expect(result.candles[0]).toHaveProperty('volume');
    });
  });
});

Integration Tests

// tests/integration/binance-api.test.ts

import request from 'supertest';
import app from '../../src/index';

describe('MCP Binance Connector API', () => {
  const API_KEY = process.env.MCP_API_KEY;

  describe('GET /health', () => {
    it('should return healthy status', async () => {
      const res = await request(app).get('/health');

      expect(res.status).toBe(200);
      expect(res.body.status).toBe('healthy');
    });
  });

  describe('POST /tools/binance_get_ticker', () => {
    it('should return ticker data', async () => {
      const res = await request(app)
        .post('/tools/binance_get_ticker')
        .set('x-mcp-api-key', API_KEY)
        .send({ symbol: 'BTCUSDT' });

      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('symbol', 'BTCUSDT');
      expect(res.body).toHaveProperty('price');
    });
  });

  describe('POST /tools/binance_create_order', () => {
    it('should reject without confirmation', async () => {
      const res = await request(app)
        .post('/tools/binance_create_order')
        .set('x-mcp-api-key', API_KEY)
        .send({
          symbol: 'BTCUSDT',
          side: 'buy',
          amount: 0.001
        });

      // En testnet deberia funcionar, pero verificar risk check
      expect(res.status).toBe(200);
    });
  });
});

Metricas y Monitoring

Metrica Target Alerta
Latency <200ms >500ms
Error Rate <1% >5%
Uptime 99.9% <99%
Rate Limit Usage <80% >90%

Documento Generado: 2026-01-04 Autor: Orquestador Agent - Trading Platform Version: 1.0.0