Skip to main content
Glama

press_select

Activates the SELECT button on a GameBoy emulator for a specified duration in frames, enabling precise control within the MCP GameBoy Server environment.

Instructions

Press the SELECT button on the GameBoy

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
duration_framesNoNumber of frames to hold the button

Implementation Reference

  • src/tools.ts:20-37 (registration)
    Dynamic registration of the 'press_select' tool (and other press_* buttons) with inline input schema, description, and handler function. The handler presses the SELECT button via EmulatorService and returns the screen image.
    // Register button press tools
    Object.values(GameBoyButton).forEach(button => {
      server.tool(
        `press_${button.toLowerCase()}`,
        `Press the ${button} button on the GameBoy`,
        {
          duration_frames: z.number().int().positive().optional().default(1).describe('Number of frames to hold the button').default(25)
        },
        async ({ duration_frames }): Promise<CallToolResult> => {
          // Press the button using the service (advances one frame)
          emulatorService.pressButton(button, duration_frames);
    
          // Return the current screen using the service
          const screen = emulatorService.getScreen();
          return { content: [screen] };
        }
      );
    });
  • Invokes registerGameBoyTools which registers the press_select tool among others.
    // Register GameBoy tools
    registerGameBoyTools(server, emulatorService); // Pass emulatorService
  • GameBoyButton enum defining SELECT button used in dynamic tool registration.
    export enum GameBoyButton {
      UP = 'UP',
      DOWN = 'DOWN',
      LEFT = 'LEFT',
      RIGHT = 'RIGHT',
      A = 'A',
      B = 'B',
      START = 'START',
      SELECT = 'SELECT'
    }
  • EmulatorService.pressButton method called by the press_select tool handler. Delegates to GameBoyEmulator and returns screen.
    pressButton(button: GameBoyButton, durationFrames: number): ImageContent {
      log.debug(`Pressing button: ${button}`);
      if (!this.isRomLoaded()) {
        log.warn('Attempted to press button with no ROM loaded');
        throw new Error('No ROM loaded');
      }
      this.emulator.pressButton(button, durationFrames); // This advances one frame
      return this.getScreen();
    }
  • Low-level GameBoyEmulator.pressButton implementation that maps SELECT to keycode, presses for duration_frames, and advances emulation frames.
    public pressButton(button: GameBoyButton, durationFrames: number = 1): void {
      if (!this.romLoaded) {
        throw new Error('No ROM loaded');
      }
    
      // Map our button enum to serverboy's keymap
      const buttonMap: Record<GameBoyButton, number> = {
        [GameBoyButton.UP]: Gameboy.KEYMAP.UP,
        [GameBoyButton.DOWN]: Gameboy.KEYMAP.DOWN,
        [GameBoyButton.LEFT]: Gameboy.KEYMAP.LEFT,
        [GameBoyButton.RIGHT]: Gameboy.KEYMAP.RIGHT,
        [GameBoyButton.A]: Gameboy.KEYMAP.A,
        [GameBoyButton.B]: Gameboy.KEYMAP.B,
        [GameBoyButton.START]: Gameboy.KEYMAP.START,
        [GameBoyButton.SELECT]: Gameboy.KEYMAP.SELECT
      };
    
      for (let i=0; i < durationFrames; i++) {
        this.gameboy.pressKeys([buttonMap[button]]);
        this.gameboy.doFrame();
      }
    
      // for now: advance one frame so we dont "hold" the button all the time.
      this.gameboy.doFrame();
    }
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/mario-andreschak/mcp-gameboy'

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