Skip to main content
Glama

listTrades

Retrieve available trades from villagers within a specified range using natural language commands for efficient inventory management in Minecraft via MCP Minecraft Remote.

Instructions

List available trades from a nearby villager

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rangeNoRange to search for villagers
villagerNameNoName or identifier of the villager (optional)

Implementation Reference

  • The handler function for the listTrades tool. Finds nearby villagers matching the optional name within the given range, selects the closest, opens the trading window, extracts non-null slots as trades (name, displayName, count), formats a numbered list response, handles errors and window closing.
    async ({ villagerName, range }) => { if (!botState.isConnected || !botState.bot) { return createNotConnectedResponse() } try { // Find villagers in range const villagers = Object.values(botState.bot.entities).filter( (entity) => { if (!entity || !entity.position || !botState.bot) return false const distance = entity.position.distanceTo( botState.bot.entity.position ) return ( distance <= range && String(entity.type) === 'villager' && (!villagerName || (entity.name && entity.name .toLowerCase() .includes(villagerName.toLowerCase()))) ) } ) if (villagers.length === 0) { return createSuccessResponse( villagerName ? `No villager named "${villagerName}" found nearby.` : 'No villagers found nearby.' ) } // Choose the closest villager if multiple are found const villager = villagers.reduce((closest, current) => { if (!closest.position || !current.position || !botState.bot) return current const distClosest = closest.position.distanceTo( botState.bot.entity.position ) const distCurrent = current.position.distanceTo( botState.bot.entity.position ) return distCurrent < distClosest ? current : closest }) // We need to use the real Villager class // First step is to use openVillager method const villagerEntity = await botState.bot.openVillager(villager as any) await botState.bot.trade(villagerEntity, 1, 1) // Just to open the window, numbers don't matter // Check if window is open before accessing properties if (!botState.bot.currentWindow) { return createSuccessResponse( `Could not open trading window with villager.` ) } const trades = botState.bot.currentWindow.slots .filter((item) => item !== null && item !== undefined) .map((item) => { if (!item) return null // Try to extract trade details return { name: item.name, displayName: item.displayName || item.name, count: item.count || 1, // Add more properties as needed } }) .filter((trade) => trade !== null) // Close the trading window if open if (botState.bot.currentWindow) { await botState.bot.closeWindow(botState.bot.currentWindow) } if (trades.length === 0) { return createSuccessResponse( `Villager found, but no trades are available.` ) } // Format the response let response = `Available trades from villager ${ villager.name || 'Unknown' } (${villager.position .distanceTo(botState.bot.entity.position) .toFixed(1)} blocks away):\n\n` trades.forEach((trade, index) => { response += `${index + 1}. ${trade.displayName} (x${trade.count})\n` }) return createSuccessResponse(response) } catch (error) { return createErrorResponse(error) } }
  • Zod input schema for listTrades: villagerName (optional string, villager identifier), range (optional number default 4, search range).
    { villagerName: z .string() .optional() .describe('Name or identifier of the villager (optional)'), range: z .number() .optional() .default(4) .describe('Range to search for villagers'), },
  • server.tool registration for 'listTrades', including description 'List available trades from a nearby villager', schema, and handler function.
    'listTrades', 'List available trades from a nearby villager', { villagerName: z .string() .optional() .describe('Name or identifier of the villager (optional)'), range: z .number() .optional() .default(4) .describe('Range to search for villagers'), }, async ({ villagerName, range }) => { if (!botState.isConnected || !botState.bot) { return createNotConnectedResponse() } try { // Find villagers in range const villagers = Object.values(botState.bot.entities).filter( (entity) => { if (!entity || !entity.position || !botState.bot) return false const distance = entity.position.distanceTo( botState.bot.entity.position ) return ( distance <= range && String(entity.type) === 'villager' && (!villagerName || (entity.name && entity.name .toLowerCase() .includes(villagerName.toLowerCase()))) ) } ) if (villagers.length === 0) { return createSuccessResponse( villagerName ? `No villager named "${villagerName}" found nearby.` : 'No villagers found nearby.' ) } // Choose the closest villager if multiple are found const villager = villagers.reduce((closest, current) => { if (!closest.position || !current.position || !botState.bot) return current const distClosest = closest.position.distanceTo( botState.bot.entity.position ) const distCurrent = current.position.distanceTo( botState.bot.entity.position ) return distCurrent < distClosest ? current : closest }) // We need to use the real Villager class // First step is to use openVillager method const villagerEntity = await botState.bot.openVillager(villager as any) await botState.bot.trade(villagerEntity, 1, 1) // Just to open the window, numbers don't matter // Check if window is open before accessing properties if (!botState.bot.currentWindow) { return createSuccessResponse( `Could not open trading window with villager.` ) } const trades = botState.bot.currentWindow.slots .filter((item) => item !== null && item !== undefined) .map((item) => { if (!item) return null // Try to extract trade details return { name: item.name, displayName: item.displayName || item.name, count: item.count || 1, // Add more properties as needed } }) .filter((trade) => trade !== null) // Close the trading window if open if (botState.bot.currentWindow) { await botState.bot.closeWindow(botState.bot.currentWindow) } if (trades.length === 0) { return createSuccessResponse( `Villager found, but no trades are available.` ) } // Format the response let response = `Available trades from villager ${ villager.name || 'Unknown' } (${villager.position .distanceTo(botState.bot.entity.position) .toFixed(1)} blocks away):\n\n` trades.forEach((trade, index) => { response += `${index + 1}. ${trade.displayName} (x${trade.count})\n` }) return createSuccessResponse(response) } catch (error) { return createErrorResponse(error) } } )
  • Invocation of registerTradingTools() within registerAllTools(), which registers the listTrades tool.
    registerTradingTools()
  • src/index.ts:7-7 (registration)
    Invocation of registerAllTools() which ultimately registers the listTrades tool.
    registerAllTools()

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/nacal/mcp-minecraft-remote'

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