Skip to main content
Glama

describe_ui

Retrieve the full view hierarchy, including precise frame coordinates (x, y, width, height) for all visible elements in a simulator. Use JSON tree output for accurate UI automation and layout validation.

Instructions

Gets entire view hierarchy with precise frame coordinates (x, y, width, height) for all visible elements. Use this before UI interactions or after layout changes - do NOT guess coordinates from screenshots. Returns JSON tree with frame data for accurate automation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
simulatorUuidYes

Implementation Reference

  • Core handler logic for the describe_ui tool: executes 'axe describe-ui' command on the simulator to fetch UI hierarchy with precise frame coordinates, handles errors, and formats response with next steps.
    export async function describe_uiLogic(
      params: DescribeUiParams,
      executor: CommandExecutor,
      axeHelpers: AxeHelpers = {
        getAxePath,
        getBundledAxeEnvironment,
        createAxeNotAvailableResponse,
      },
    ): Promise<ToolResponse> {
      const toolName = 'describe_ui';
      const { simulatorId } = params;
      const commandArgs = ['describe-ui'];
    
      log('info', `${LOG_PREFIX}/${toolName}: Starting for ${simulatorId}`);
    
      try {
        const responseText = await executeAxeCommand(
          commandArgs,
          simulatorId,
          'describe-ui',
          executor,
          axeHelpers,
        );
    
        // Record the describe_ui call for warning system
        recordDescribeUICall(simulatorId);
    
        log('info', `${LOG_PREFIX}/${toolName}: Success for ${simulatorId}`);
        return {
          content: [
            {
              type: 'text',
              text:
                'Accessibility hierarchy retrieved successfully:\n```json\n' + responseText + '\n```',
            },
            {
              type: 'text',
              text: `Next Steps:
    - Use frame coordinates for tap/swipe (center: x+width/2, y+height/2)
    - Re-run describe_ui after layout changes
    - Screenshots are for visual verification only`,
            },
          ],
        };
      } catch (error) {
        log('error', `${LOG_PREFIX}/${toolName}: Failed - ${error}`);
        if (error instanceof DependencyError) {
          return axeHelpers.createAxeNotAvailableResponse();
        } else if (error instanceof AxeError) {
          return createErrorResponse(
            `Failed to get accessibility hierarchy: ${error.message}`,
            error.axeOutput,
          );
        } else if (error instanceof SystemError) {
          return createErrorResponse(
            `System error executing axe: ${error.message}`,
            error.originalError?.stack,
          );
        }
        return createErrorResponse(
          `An unexpected error occurred: ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    }
  • Zod schema and TypeScript type definition for describe_ui tool input parameters (simulatorId: UUID string).
    const describeUiSchema = z.object({
      simulatorId: z.string().uuid('Invalid Simulator UUID format'),
    });
    
    // Use z.infer for type safety
    type DescribeUiParams = z.infer<typeof describeUiSchema>;
  • MCP tool definition and registration: exports default object with name 'describe_ui', description, schema (without simulatorId for public), and session-aware handler wrapping describe_uiLogic.
    export default {
      name: 'describe_ui',
      description:
        'Gets entire view hierarchy with precise frame coordinates (x, y, width, height) for all visible elements. Use this before UI interactions or after layout changes - do NOT guess coordinates from screenshots. Returns JSON tree with frame data for accurate automation.',
      schema: publicSchemaObject.shape, // MCP SDK compatibility
      handler: createSessionAwareTool<DescribeUiParams>({
        internalSchema: describeUiSchema as unknown as z.ZodType<DescribeUiParams>,
        logicFunction: (params: DescribeUiParams, executor: CommandExecutor) =>
          describe_uiLogic(params, executor, {
            getAxePath,
            getBundledAxeEnvironment,
            createAxeNotAvailableResponse,
          }),
        getExecutor: getDefaultCommandExecutor,
        requirements: [{ allOf: ['simulatorId'], message: 'simulatorId is required' }],
      }),
    };
  • Supporting helper function that executes axe CLI commands, manages binary detection, UDID injection, environment vars, and comprehensive error wrapping (DependencyError, AxeError, SystemError).
    async function executeAxeCommand(
      commandArgs: string[],
      simulatorId: string,
      commandName: string,
      executor: CommandExecutor = getDefaultCommandExecutor(),
      axeHelpers: AxeHelpers = { getAxePath, getBundledAxeEnvironment, createAxeNotAvailableResponse },
    ): Promise<string> {
      // Get the appropriate axe binary path
      const axeBinary = axeHelpers.getAxePath();
      if (!axeBinary) {
        throw new DependencyError('AXe binary not found');
      }
    
      // Add --udid parameter to all commands
      const fullArgs = [...commandArgs, '--udid', simulatorId];
    
      // Construct the full command array with the axe binary as the first element
      const fullCommand = [axeBinary, ...fullArgs];
    
      try {
        // Determine environment variables for bundled AXe
        const axeEnv = axeBinary !== 'axe' ? axeHelpers.getBundledAxeEnvironment() : undefined;
    
        const result = await executor(fullCommand, `${LOG_PREFIX}: ${commandName}`, false, axeEnv);
    
        if (!result.success) {
          throw new AxeError(
            `axe command '${commandName}' failed.`,
            commandName,
            result.error ?? result.output,
            simulatorId,
          );
        }
    
        // Check for stderr output in successful commands
        if (result.error) {
          log(
            'warn',
            `${LOG_PREFIX}: Command '${commandName}' produced stderr output but exited successfully. Output: ${result.error}`,
          );
        }
    
        return result.output.trim();
      } catch (error) {
        if (error instanceof Error) {
          if (error instanceof AxeError) {
            throw error;
          }
    
          // Otherwise wrap it in a SystemError
          throw new SystemError(`Failed to execute axe command: ${error.message}`, error);
        }
    
        // For any other type of error
        throw new SystemError(`Failed to execute axe command: ${String(error)}`);
      }
    }
Behavior4/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 effectively describes the tool's behavior: it returns a JSON tree with frame data, operates on visible elements, and is intended for automation accuracy. However, it lacks details on potential errors, performance implications, or data freshness, leaving some behavioral aspects unspecified.

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 highly concise and well-structured, using two sentences that front-load key information: the core functionality and usage guidelines. Every sentence adds value without redundancy, making it efficient and easy to parse for an AI agent.

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

Completeness4/5

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

Given the tool's complexity (UI hierarchy analysis) and lack of annotations or output schema, the description does a good job covering purpose, usage, and return format. However, it misses details on the parameter and potential edge cases (e.g., handling invisible elements), leaving minor gaps in completeness for automation scenarios.

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?

The input schema has 0% description coverage, but the description does not mention the 'simulatorUuid' parameter at all. While it implies context about simulators through usage guidance, it fails to explain what this parameter means or how to obtain it. With low schema coverage, the description does not compensate adequately, resulting in a baseline score.

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

Purpose5/5

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

The description clearly states the tool's purpose with specific verbs ('Gets entire view hierarchy') and resources ('with precise frame coordinates for all visible elements'). It distinguishes itself from sibling tools like 'screenshot' by emphasizing coordinate accuracy over visual guessing, making its role in UI automation explicit.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool ('before UI interactions or after layout changes') and when not to ('do NOT guess coordinates from screenshots'). It implicitly suggests alternatives like screenshot-based methods but clearly directs users to this tool for accurate automation, offering strong contextual usage rules.

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/getsentry/XcodeBuildMCP'

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