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

1256 lines
32 KiB
Markdown

---
id: "MCP-BINANCE-CONNECTOR-SPEC"
title: "Especificacion MCP Binance Connector"
type: "Technical Specification"
project: "trading-platform"
version: "1.0.0"
created_date: "2026-01-04"
updated_date: "2026-01-04"
author: "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](#vision-general)
2. [Arquitectura](#arquitectura)
3. [MCP Tools Specification](#mcp-tools-specification)
4. [Seguridad](#seguridad)
5. [Configuracion](#configuracion)
6. [Implementacion](#implementacion)
7. [Testing](#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
```json
{
"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)
```typescript
// 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)
```typescript
// 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)
```typescript
// 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)
```typescript
// 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
```typescript
// 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
```typescript
// 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
```typescript
// 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
```bash
# .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
```typescript
// 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
```typescript
// 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
# 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
```typescript
// 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
```typescript
// 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