Skip to main content
Glama
leo4life2

Minecraft MCP Server

by leo4life2

retrieveItemsFromNearbyFurnace

Automatically fetch smelted items from a furnace in Minecraft using this tool, enabling efficient resource management and automation in gameplay.

Instructions

Retrieve smelted items from a nearby furnace

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Main handler function that finds nearby furnaces, navigates to them, opens each one, and retrieves items from input, fuel, or output slots based on furnace state.
    export const retrieveItemsFromNearbyFurnace = async (
      bot: Bot,
      params: ISkillParams,
      serviceParams: ISkillServiceParams,
    ): Promise<boolean> => {
      const skillName = 'retrieveItemsFromNearbyFurnace';
      const requiredParams: string[] = [];
      if (
        !validateSkillParams(
          params,
          requiredParams,
          skillName,
        )
      ) {
        serviceParams.cancelExecution?.();
        bot.emit(
          'alteraBotEndObservation',
          `Mistake: You didn't provide all of the required parameters ${requiredParams.join(', ')} for the ${skillName} skill.`,
        );
        return false;
      }
    
      const {signal, getStatsData, setStatsData} = serviceParams;
    
      const furnacePositions = findNearbyFurnaces(bot, {
        searchRadius: 10,
        maxFurnaces: 10,
      });
      if (furnacePositions.length === 0) {
        return bot.emit(
          'alteraBotEndObservation',
          'You tried to retrieve items from a nearby furnace but no furnaces were found nearby.',
        );
      }
    
      let msg = '';
      bot.emit(
        'alteraBotStartObservation',
        `You are retrieving items from ${furnacePositions.length} furnaces nearby.`,
      );
    
      for (const furnaceBlock of furnacePositions
        .map((pos) => bot.blockAt(pos))
        .filter(Boolean)) {
        const location = `(${Math.floor(furnaceBlock.position.x)}, ${Math.floor(furnaceBlock.position.y)}, ${Math.floor(furnaceBlock.position.z)})`;
    
        if (isInventoryFull(bot)) {
          return bot.emit(
            'alteraBotEndObservation',
            `You tried to retrieve items at furnace location ${location} but your inventory is full.`,
          );
        }
    
        try {
          await cancelableMove(bot, {
            goal: new GoalNear(
              furnaceBlock.position.x,
              furnaceBlock.position.y,
              furnaceBlock.position.z,
              2,
            ),
            signal,
          });
    
          if (isSignalAborted(signal)) {
            return bot.emit(
              'alteraBotTextObservation',
              interrupt_message_accumulated_items(msg),
            );
          }
    
          bot.lookAt(furnaceBlock.position.offset(0.5, 0.5, 0.5));
          console.log(`You are looking at the furnace at ${location}.`);
    
          const [furnace, cur_msg] = await _retrieveItemFromSingleFurnace(bot, {
            furnaceBlock,
            getStatsData,
            setStatsData,
          });
    
          msg += cur_msg;
          console.log(`Furnace object: ${furnace}`);
    
          if (isSignalAborted(signal)) {
            furnace?.close();
            return bot.emit(
              'alteraBotTextObservation',
              interrupt_message_accumulated_items(msg),
            );
          }
        } catch (err) {
          const error = err as Error;
          console.log(error?.message ?? String(error));
          bot.emit(
            'alteraBotTextObservation',
            `You can't reach the furnace at ${location}. It was too difficult to reach it.`,
          );
          continue;
        }
      }
    
      return bot.emit('alteraBotEndObservation', msg);
    };
  • Schema definition for the tool, indicating no input parameters are required.
    retrieveItemsFromNearbyFurnace: {
        description: "Retrieve smelted items from a nearby furnace",
        params: {},
        required: []
    },
  • Function that registers all skills including retrieveItemsFromNearbyFurnace by loading metadata and creating SkillDefinition objects for MCP tool registration.
    export async function loadSkills(): Promise<SkillDefinition[]> {
        const skills: SkillDefinition[] = [];
    
        for (const [skillName, metadata] of Object.entries(SKILL_METADATA)) {
            skills.push({
                name: skillName,
                description: metadata.description,
                inputSchema: {
                    type: "object",
                    properties: metadata.params,
                    required: metadata.required
                },
                execute: createSkillExecutor(skillName)
            });
        }
    
        return skills;
    }
  • Core helper function that handles interaction with a single furnace: opens it, calculates fuel and smelting progress, retrieves items accordingly, and generates status messages.
    const _retrieveItemFromSingleFurnace = async (
      bot: Bot,
      options: ILRetrieveItemFromSingleFurnaceOptions,
    ) => {
      /*
      Atomic function that retrieves items from a single furnace.
      Note that no text observations are emitted here. We leave it to the outside function to handle text observations.
    
      Behavior:
      - If furnace is in progress, take output items
      - If furnace is not in progress, take all items if there are any.
      */
      const {furnaceBlock, getStatsData, setStatsData} = options;
    
      const smeltTime = 10;
      const location = `${Math.floor(furnaceBlock.position.x)}, ${Math.floor(furnaceBlock.position.y)}, ${Math.floor(furnaceBlock.position.z)}`;
    
      /*
      Mineflayer currently does not update the furnace item and fuel progress correctly.
      Item smelting and fuel burning progress are both null due to packet update errors.
      The code block below is a temporary workaround to get the progress of the furnace.
      */
      const furnaceInfo: any = {}; // This is a temporary workaround to get the progress of the furnace. Not found the type in mineflayer.
    
      const furnaceInfoFunction = (packet: any) => {
        furnaceInfo[packet.property] = packet.value;
      };
      bot._client.on('craft_progress_bar', furnaceInfoFunction);
      const furnace = await asyncwrap({
        func: async () => {
          return await bot.openFurnace(furnaceBlock);
        },
        getStatsData,
        setStatsData,
      });
      await bot.waitForTicks(1);
      bot._client.removeListener('craft_progress_bar', furnaceInfoFunction);
      getFuelSeconds(furnace, furnaceInfo);
      getItemProgress(furnace, furnaceInfo);
      console.log(`Current fuel progress: ${furnace.fuelSeconds}`);
      console.log(`Current item progress: ${furnace.progressSeconds}`);
      const furnaceFuelSeconds = furnace.fuelSeconds.toFixed(1);
      const furnaceProgressSeconds = furnace.progressSeconds.toFixed(1);
    
      const retrieve_message_parts = [];
      let retrieve_message = '';
      try {
        // If furnace is not smelting, take out all items.
        if (furnaceProgressSeconds == 10 || furnaceProgressSeconds == 0) {
          console.log('Furnace is not smelting. Taking out all items.');
          if (furnace.inputItem()) {
            const ir = await furnace.takeInput();
            retrieve_message_parts.push(
              `you retrieved ${ir.count} ${ir.displayName} from the furnace input slot`,
            );
          }
          if (furnace.fuelItem()) {
            const fr = await furnace.takeFuel();
            retrieve_message_parts.push(
              `you retrieved ${fr.count} ${fr.displayName} from the furnace fuel slot`,
            );
          }
          if (furnace.outputItem()) {
            const outr = await furnace.takeOutput();
            retrieve_message_parts.push(
              `you retrieved ${outr.count} ${outr.displayName} from the furnace output slot`,
            );
          }
    
          if (retrieve_message_parts.length != 0) {
            retrieve_message = `At furnace location (${location}),`;
            for (let i = 0; i < retrieve_message_parts.length; i++) {
              if (
                retrieve_message_parts.length > 1 &&
                i == retrieve_message_parts.length - 1
              ) {
                retrieve_message += 'and ';
              }
              retrieve_message += retrieve_message_parts[i];
              if (i < retrieve_message_parts.length - 1) {
                retrieve_message += ', ';
              } else {
                retrieve_message += '. ';
              }
            }
          } else {
            retrieve_message = `There were no items to retrieve at furnace location (${location}). `;
          }
          retrieve_message += `This furnace is currently free for smelting. `;
        } else {
          // If furnace is in use, just take out the output items if there are any and then wait
          const total_wait_time =
            furnaceProgressSeconds + (furnace.inputItem().count - 1) * smeltTime;
          if (furnace.outputItem()) {
            const outr = await furnace.takeOutput();
            retrieve_message += `At furnace location (${location}), you retrieved ${outr.count} ${outr.displayName} from the furnace output slot, and `;
            retrieve_message += `the next ${outr.displayName} will be smelted in ${furnaceProgressSeconds} seconds. `;
            retrieve_message += `This furnace will be free for smelting in ${total_wait_time} seconds. `;
          } else {
            retrieve_message += `Furnace at location (${location}) is currently smelting. `;
            retrieve_message += `The next item will be smelted in ${furnaceProgressSeconds} seconds. `;
            retrieve_message += `It will be free for smelting in ${total_wait_time} seconds. `;
          }
        }
      } catch (error) {
        retrieve_message = `ERROR: Failed to retrieve items from the furnace due to: ${error}`;
      } finally {
        console.log(retrieve_message);
        // bot.emit('alteraBotTextObservation', `${retrieve_message}`);
        furnace.close();
        return [furnace, retrieve_message];
      }
    };
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It implies a read operation ('Retrieve') but doesn't specify if this requires specific conditions, what happens if no items are available, or the format of the return. More context on behavior is needed for a tool with zero annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence with no wasted words, clearly front-loading the core action. It's appropriately sized for a simple tool with no parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of annotations and output schema, the description is incomplete. It doesn't explain what 'nearby' means, what types of items are retrieved, or the return format. For a tool in a game-like context with many siblings, more detail is warranted.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has 0 parameters, and schema description coverage is 100%, so no parameter information is needed. The description doesn't add param details, which is appropriate, earning a baseline score of 4 for this dimension.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Retrieve') and target resource ('smelted items from a nearby furnace'), making the purpose understandable. It doesn't explicitly differentiate from siblings like 'openNearbyChest' or 'pickupItem', but the specificity of 'smelted items' and 'furnace' provides reasonable distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives like 'openNearbyChest' or 'pickupItem', nor does it mention prerequisites such as needing a furnace nearby or smelted items being ready. The description only states what it does, not when it's appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/leo4life2/minecraft-mcp-http'

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