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';
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It states the action but lacks critical details: whether this requires specific permissions (e.g., avatar control), if it's reversible, what happens if duration is zero/negative, or what visual/state changes occur. For a mutation tool with zero annotation coverage, this is inadequate.

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 zero wasted words. It's front-loaded with the core action ('Turn to look') and specifies the scope ('in a specific direction'), making it immediately understandable without unnecessary elaboration.

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 this is a mutation tool (implied by 'Turn') with no annotations and no output schema, the description is insufficient. It doesn't explain what 'looking' entails (e.g., camera rotation, avatar head turn), success/failure conditions, or return values, leaving significant gaps for agent understanding.

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

Parameters3/5

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

Schema description coverage is 100%, with clear parameter documentation in the schema itself. The description adds no additional meaning about parameters beyond implying directionality, so it meets the baseline of 3 where the schema does the heavy lifting without compensating for gaps.

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 ('Turn to look') and specifies the target ('in a specific direction'), making the purpose immediately understandable. However, it doesn't differentiate this tool from potential sibling actions like 'move_avatar' or 'set_avatar_parameter' that might also involve orientation changes, preventing a perfect score.

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?

The description provides no guidance on when to use this tool versus alternatives like 'set_avatar_parameter' for orientation or 'move_avatar' for directional movement. There's no mention of prerequisites, context (e.g., avatar must be controllable), or exclusions, leaving usage entirely implicit.

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

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