Bybit MCP Server
by sammcj
- src
- tools
import { Tool } from "@modelcontextprotocol/sdk/types.js"
import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js"
import { z } from "zod"
import { BaseToolImplementation } from "./BaseTool.js"
import {
AccountTypeV5,
APIResponseV3WithTime,
WalletBalanceV5
} from "bybit-api"
// Zod schema for input validation
const inputSchema = z.object({
accountType: z.enum(["UNIFIED", "CONTRACT", "SPOT"]),
coin: z.string().optional()
})
type ToolArguments = z.infer<typeof inputSchema>
// Type for the formatted response
interface FormattedWalletResponse {
accountType: AccountTypeV5
coin?: string
data: {
list: WalletBalanceV5[]
}
timestamp: string
meta: {
requestId: string
}
}
export class GetWalletBalance extends BaseToolImplementation {
name = "get_wallet_balance"
toolDefinition: Tool = {
name: this.name,
description: "Get wallet balance information for the authenticated user",
inputSchema: {
type: "object",
properties: {
accountType: {
type: "string",
description: "Account type",
enum: ["UNIFIED", "CONTRACT", "SPOT"],
},
coin: {
type: "string",
description: "Cryptocurrency symbol, e.g., BTC, ETH, USDT. If not specified, returns all coins.",
},
},
required: ["accountType"],
},
}
private async getWalletData(
accountType: AccountTypeV5,
coin?: string
): Promise<APIResponseV3WithTime<{ list: WalletBalanceV5[] }>> {
this.logInfo(`Fetching wallet balance for account type: ${accountType}${coin ? `, coin: ${coin}` : ''}`)
return await this.client.getWalletBalance({
accountType,
coin,
})
}
async toolCall(request: z.infer<typeof CallToolRequestSchema>) {
try {
this.logInfo("Starting get_wallet_balance tool call")
if (this.isDevMode) {
throw new Error("Cannot get wallet balance in development mode - API credentials required")
}
// Parse and validate input
const validationResult = inputSchema.safeParse(request.params.arguments)
if (!validationResult.success) {
throw new Error(`Invalid input: ${validationResult.error.message}`)
}
const { accountType, coin } = validationResult.data
this.logInfo(`Validated arguments - accountType: ${accountType}${coin ? `, coin: ${coin}` : ''}`)
// Execute API request with rate limiting and retry logic
const response = await this.executeRequest(async () => {
return await this.getWalletData(accountType, coin)
})
// Format response
const result: FormattedWalletResponse = {
accountType,
coin,
data: {
list: response.list
},
timestamp: new Date().toISOString(),
meta: {
requestId: crypto.randomUUID()
}
}
this.logInfo(`Successfully retrieved wallet balance for ${accountType}${coin ? ` (${coin})` : ''}`)
return this.formatResponse(result)
} catch (error) {
this.logInfo(`Error in get_wallet_balance: ${error instanceof Error ? error.message : String(error)}`)
return this.handleError(error)
}
}
}
export default GetWalletBalance