bybit-mcp-server
Version:
MCP server for Bybit trading API access
129 lines • 5.17 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BybitMCPServer = void 0;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const client_js_1 = require("./client.js");
const tools_js_1 = require("./tools.js");
class BybitMCPServer {
constructor(config) {
this.server = new index_js_1.Server({
name: 'bybit-mcp-server',
version: '1.0.0',
});
this.client = new client_js_1.BybitClient(config);
this.setupHandlers();
}
setupHandlers() {
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
tools: tools_js_1.tools,
}));
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
try {
const { name, arguments: args } = request.params;
const result = await this.handleToolCall(name, args);
return result;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logError(`Error in tool call: ${errorMessage}`);
return {
content: [
{
type: 'text',
text: `Error: ${this.sanitizeError(errorMessage)}`,
},
],
isError: true,
};
}
});
}
async handleToolCall(name, args) {
try {
let result;
switch (name) {
case 'get_price':
result = await this.client.getPrice(args.symbol);
break;
case 'get_orderbook':
result = await this.client.getOrderBook(args.symbol, args.limit);
break;
case 'get_klines':
result = await this.client.getKlines(args.symbol, args.interval, args.limit);
break;
case 'get_24hr_ticker':
result = await this.client.get24hrTicker(args.symbol);
break;
case 'get_account_info':
result = await this.client.getAccountInfo();
break;
case 'get_wallet_balance':
result = await this.client.getWalletBalance(args.accountType, args.coin);
break;
case 'get_open_orders':
result = await this.client.getOpenOrders(args.category, args.symbol, args.limit);
break;
case 'get_order_history':
result = await this.client.getOrderHistory(args.category, args.symbol, args.limit);
break;
case 'place_order':
result = await this.client.placeOrder({
category: args.category,
symbol: args.symbol,
side: args.side,
orderType: args.orderType,
qty: args.qty,
price: args.price,
timeInForce: args.timeInForce,
});
break;
case 'cancel_order':
result = await this.client.cancelOrder(args.category, args.symbol, args.orderId, args.orderLinkId);
break;
case 'cancel_all_orders':
result = await this.client.cancelAllOrders(args.category, args.symbol);
break;
default:
throw new Error(`Unknown tool: ${name}`);
}
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
isError: false,
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(errorMessage);
}
}
logError(message) {
console.error(`[${new Date().toISOString()}] ${message}`);
}
sanitizeError(error) {
const sensitivePatterns = [
/api[_-]?key[s]?[:\s=][\w-]+/gi,
/secret[s]?[:\s=][\w-]+/gi,
/token[s]?[:\s=][\w-]+/gi,
/password[s]?[:\s=][\w-]+/gi,
];
let sanitized = error;
sensitivePatterns.forEach(pattern => {
sanitized = sanitized.replace(pattern, '[REDACTED]');
});
return sanitized;
}
async start() {
const transport = new stdio_js_1.StdioServerTransport();
await this.server.connect(transport);
this.logError(`Bybit MCP Server started with ${tools_js_1.tools.length} tools`);
}
}
exports.BybitMCPServer = BybitMCPServer;
//# sourceMappingURL=server.js.map