Skip to main content
Glama

look_direction

Control avatar gaze direction in VRChat by sending commands to turn left or right for a set duration, enabling precise AI-driven interactions in virtual environments.

Instructions

Turn to look in a specific direction.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
directionYesDirection to look
durationNoDuration in seconds

Implementation Reference

  • Main handler function implementing the look_direction tool. Sends LookLeft or LookRight OSC inputs via WebSocket to turn the avatar's view.
    public async look(
      direction: LookDirection,
      duration: number = 1.0,
      ctx?: ToolContext
    ): Promise<string> {
      if (ctx) {
        await ctx.info(`Looking ${direction} for ${duration} seconds`);
      }
      
      if (direction !== 'left' && direction !== 'right') {
        return `Unknown direction: ${direction}`;
      }
      
      // ボタン入力名を決定
      const inputName = direction === 'left' ? 'LookLeft' : 'LookRight';
      
      try {
        logger.info(`[LOOK] Starting look ${direction} operation, duration: ${duration}s`);
        
        // ボタン入力を実行
        const result = await this.tryButtonLook(inputName, duration);
        
        if (!result.success) {
          return `Failed to look ${direction}: ${result.error}`;
        }
        
        return `Looked ${direction} for ${duration} seconds`;
      } catch (error) {
        const errorMsg = `Error during look ${direction}: ${error instanceof Error ? error.message : String(error)}`;
        logger.error(`[LOOK] ${errorMsg}`);
        
        // 緊急リセット
        try {
          await this.wsClient.sendInput(inputName, 0);
          logger.info(`[LOOK] Emergency reset of look input after error`);
        } catch (resetError) {
          logger.error(`[LOOK] Failed emergency reset: ${resetError instanceof Error ? resetError.message : String(resetError)}`);
        }
        
        return errorMsg;
      }
    }
  • Supporting helper method that handles the precise sequence of button press, hold, and release for look inputs, including retries and safety resets.
    private async tryButtonLook(
      inputName: string,
      duration: number
    ): Promise<{success: boolean, error?: string}> {
      try {
        // ボタン入力では、まず0(リリース)を送信してから1(プレス)を送信する必要がある
        logger.info(`[LOOK-BUTTON] Initializing button ${inputName}=0`);
        await this.wsClient.sendInput(inputName, 0);
        
        // 少し待機
        await new Promise(r => setTimeout(r, 50));
        
        // ボタンプレスを送信
        logger.info(`[LOOK-BUTTON] Pressing button ${inputName}=1`);
        const pressSuccess = await this.wsClient.sendInput(inputName, 1);
        
        if (!pressSuccess) {
          return {success: false, error: `Failed to press button ${inputName}`};
        }
        
        // 時間待機
        await new Promise(r => setTimeout(r, (duration+2)*100 ));
        
        // ボタンリリースを送信
        logger.info(`[LOOK-BUTTON] Releasing button ${inputName}=0`);
        const releaseSuccess = await this.wsClient.sendInput(inputName, 0);
        
        if (!releaseSuccess) {
          logger.warn(`[LOOK-BUTTON] Failed to release button ${inputName}`);
          // 再試行
          await new Promise(r => setTimeout(r, 100));
          await this.wsClient.sendInput(inputName, 0);
        }
        
        // // 指定された持続時間だけ待機
        // if (duration > 0.2) { // すでに少し待機したので調整
        //   logger.info(`[LOOK-BUTTON] Waiting for remaining duration: ${duration - 0.2} seconds`);
        //   await new Promise(resolve => setTimeout(resolve, (duration - 0.2) * 1000));
        // }
        
        return {success: true};
      } catch (error) {
        const errorMsg = `Error in button look: ${error instanceof Error ? error.message : String(error)}`;
        logger.error(`[LOOK-BUTTON] ${errorMsg}`);
        return {success: false, error: errorMsg};
      } finally {
        // 最終的な安全策として、もう一度入力をリセットする
        try {
          await this.wsClient.sendInput(inputName, 0);
          logger.info(`[LOOK-BUTTON] Final safety reset of ${inputName}`);
        } catch (e) {
          // エラーを無視
        }
      }
    }
  • MCP server registration of the 'look_direction' tool, including input schema validation with zod and delegation to InputTools.look handler.
    server.tool(
      'look_direction',
      'Turn to look in a specific direction.',
      {
        direction: z.enum(['left', 'right']).describe('Direction to look'),
        duration: z.number().default(1.0).describe('Duration in seconds')
      },
      async ({ direction, duration }, extra) => {
        try {
          const ctx = createToolContext(extra);
          const result = await inputTools.look(direction as LookDirection, duration, ctx);
          return { content: [{ type: 'text', text: result }] };
        } catch (error) {
          return { 
            content: [{ 
              type: 'text', 
              text: `Error looking direction: ${error instanceof Error ? error.message : String(error)}` 
            }],
            isError: true
          };
        }
      }
    );
  • Type definition for LookDirection used in the tool's input schema.
    export type LookDirection = 'left' | 'right';

Tool Definition Quality

Score is being calculated. Check back soon.

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/Krekun/vrchat-mcp-osc'

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