Skip to main content
Glama
sammcj

Bybit MCP Server

by sammcj

get_instrument_info

Retrieve detailed information for a specific trading pair on Bybit, including symbol and instrument category, to facilitate informed trading decisions.

Instructions

Get detailed instrument information for a specific trading pair

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoryNoCategory of the instrument (spot, linear, inverse)
symbolYesTrading pair symbol (e.g., 'BTCUSDT')

Implementation Reference

  • The main handler function that parses arguments, calls Bybit API's getInstrumentsInfo, formats the response based on category (spot/linear/inverse), and handles errors.
    async toolCall(request: z.infer<typeof CallToolRequestSchema>) {
      try {
        const args = request.params.arguments as unknown
        if (!args || typeof args !== 'object') {
          throw new Error("Invalid arguments")
        }
    
        const typedArgs = args as Record<string, unknown>
    
        if (!typedArgs.symbol || typeof typedArgs.symbol !== 'string') {
          throw new Error("Missing or invalid symbol parameter")
        }
    
        const symbol = typedArgs.symbol
        const category = (
          typedArgs.category &&
          typeof typedArgs.category === 'string' &&
          ["spot", "linear", "inverse"].includes(typedArgs.category)
        ) ? typedArgs.category as SupportedCategory
          : CONSTANTS.DEFAULT_CATEGORY as SupportedCategory
    
        const params: GetInstrumentsInfoParamsV5 = {
          category,
          symbol,
        }
    
        const response = await this.client.getInstrumentsInfo(params)
    
        if (response.retCode !== 0) {
          throw new Error(`Bybit API error: ${response.retMsg}`)
        }
    
        if (!response.result.list || response.result.list.length === 0) {
          throw new Error(`No instrument info found for symbol: ${symbol}`)
        }
    
        const info = response.result.list[0]
        let formattedInfo: any
    
        if (category === 'spot') {
          const spotInfo = info as SpotInstrumentInfoV5
          formattedInfo = {
            symbol: spotInfo.symbol,
            status: spotInfo.status,
            baseCoin: spotInfo.baseCoin,
            quoteCoin: spotInfo.quoteCoin,
            innovation: spotInfo.innovation === "1",
            marginTrading: spotInfo.marginTrading,
            lotSizeFilter: {
              basePrecision: spotInfo.lotSizeFilter.basePrecision,
              quotePrecision: spotInfo.lotSizeFilter.quotePrecision,
              minOrderQty: spotInfo.lotSizeFilter.minOrderQty,
              maxOrderQty: spotInfo.lotSizeFilter.maxOrderQty,
              minOrderAmt: spotInfo.lotSizeFilter.minOrderAmt,
              maxOrderAmt: spotInfo.lotSizeFilter.maxOrderAmt,
            },
            priceFilter: {
              tickSize: spotInfo.priceFilter.tickSize,
            },
          }
        } else {
          const futuresInfo = info as LinearInverseInstrumentInfoV5
          formattedInfo = {
            symbol: futuresInfo.symbol,
            status: futuresInfo.status,
            baseCoin: futuresInfo.baseCoin,
            quoteCoin: futuresInfo.quoteCoin,
            settleCoin: futuresInfo.settleCoin,
            contractType: futuresInfo.contractType,
            launchTime: futuresInfo.launchTime,
            deliveryTime: futuresInfo.deliveryTime,
            deliveryFeeRate: futuresInfo.deliveryFeeRate,
            priceFilter: {
              tickSize: futuresInfo.priceFilter.tickSize,
            },
            lotSizeFilter: {
              qtyStep: futuresInfo.lotSizeFilter.qtyStep,
              minOrderQty: futuresInfo.lotSizeFilter.minOrderQty,
              maxOrderQty: futuresInfo.lotSizeFilter.maxOrderQty,
            },
            leverageFilter: {
              minLeverage: futuresInfo.leverageFilter.minLeverage,
              maxLeverage: futuresInfo.leverageFilter.maxLeverage,
              leverageStep: futuresInfo.leverageFilter.leverageStep,
            },
            fundingInterval: futuresInfo.fundingInterval,
          }
        }
    
        // Add category and timestamp to the root level
        formattedInfo.category = category
        formattedInfo.retrievedAt = new Date().toISOString()
    
        return this.formatResponse(formattedInfo)
      } catch (error) {
        return this.handleError(error)
      }
    }
  • Tool definition including name, description, and input schema specifying required 'symbol' and optional 'category' enum.
    toolDefinition: Tool = {
      name: this.name,
      description: "Get detailed instrument information for a specific trading pair",
      inputSchema: {
        type: "object",
        properties: {
          symbol: {
            type: "string",
            description: "Trading pair symbol (e.g., 'BTCUSDT')",
          },
          category: {
            type: "string",
            description: "Category of the instrument (spot, linear, inverse)",
            enum: ["spot", "linear", "inverse"],
          },
        },
        required: ["symbol"],
      },
    };
  • Dynamically discovers, imports, instantiates, and validates tool classes (including GetInstrumentInfo) from the src/tools directory.
    export async function loadTools(): Promise<BaseToolImplementation[]> {
      try {
        const toolsPath = await findToolsPath()
        const files = await fs.readdir(toolsPath)
        const tools: BaseToolImplementation[] = []
    
        for (const file of files) {
          if (!isToolFile(file)) {
            continue
          }
    
          try {
            const modulePath = `file://${join(toolsPath, file)}`
            const { default: ToolClass } = await import(modulePath)
    
            if (!ToolClass || typeof ToolClass !== 'function') {
              console.warn(JSON.stringify({
                type: "warning",
                message: `Invalid tool class in ${file}`
              }))
              continue
            }
    
            const tool = new ToolClass()
    
            if (
              tool instanceof BaseToolImplementation &&
              tool.name &&
              tool.toolDefinition &&
              typeof tool.toolCall === "function"
            ) {
              tools.push(tool)
              console.info(JSON.stringify({
                type: "info",
                message: `Loaded tool: ${tool.name}`
              }))
            } else {
              console.warn(JSON.stringify({
                type: "warning",
                message: `Invalid tool implementation in ${file}`
              }))
            }
          } catch (error) {
            console.error(JSON.stringify({
              type: "error",
              message: `Error loading tool from ${file}: ${error instanceof Error ? error.message : String(error)}`
            }))
          }
        }
    
        return tools
      } catch (error) {
        console.error(JSON.stringify({
          type: "error",
          message: `Failed to load tools: ${error instanceof Error ? error.message : String(error)}`
        }))
        return []
      }
    }
  • src/index.ts:134-147 (registration)
    Initializes the toolsMap by loading all tools via toolLoader and logs the loaded tools including 'get_instrument_info', used by MCP ListTools and CallTool handlers.
    const tools = await loadTools()
    toolsMap = createToolsMap(tools)
    
    if (tools.length === 0) {
      console.log(JSON.stringify(formatJsonRpcMessage(
        "warning",
        "No tools were loaded. Server will start but may have limited functionality."
      )))
    } else {
      console.log(JSON.stringify(formatJsonRpcMessage(
        "info",
        `Loaded ${tools.length} tools: ${tools.map(t => t.name).join(", ")}`
      )))
    }
Install Server

Other Tools

Related Tools

Latest Blog Posts

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/sammcj/bybit-mcp'

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