Skip to main content
Glama

key_press

Simulate key presses on an iOS simulator using keycodes, enabling testing of keyboard interactions in app development. Supports common keys like Return, Backspace, Tab, and Space.

Instructions

Press a single key by keycode on the simulator. Common keycodes: 40=Return, 42=Backspace, 43=Tab, 44=Space, 58-67=F1-F10.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
durationNo
keyCodeYes
simulatorUuidYes

Implementation Reference

  • Core handler function implementing the key_press tool logic. Parses params, constructs axe 'key' command, executes it via executor, handles errors and returns responses.
    export async function key_pressLogic(
      params: KeyPressParams,
      executor: CommandExecutor,
      axeHelpers: AxeHelpers = {
        getAxePath,
        getBundledAxeEnvironment,
        createAxeNotAvailableResponse,
      },
    ): Promise<ToolResponse> {
      const toolName = 'key_press';
      const { simulatorId, keyCode, duration } = params;
      const commandArgs = ['key', String(keyCode)];
      if (duration !== undefined) {
        commandArgs.push('--duration', String(duration));
      }
    
      log('info', `${LOG_PREFIX}/${toolName}: Starting key press ${keyCode} on ${simulatorId}`);
    
      try {
        await executeAxeCommand(commandArgs, simulatorId, 'key', executor, axeHelpers);
        log('info', `${LOG_PREFIX}/${toolName}: Success for ${simulatorId}`);
        return createTextResponse(`Key press (code: ${keyCode}) simulated successfully.`);
      } 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 simulate key press (code: ${keyCode}): ${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 defining the input parameters for the key_press tool: simulatorId (UUID), keyCode (0-255), optional duration.
    const keyPressSchema = z.object({
      simulatorId: z.string().uuid('Invalid Simulator UUID format'),
      keyCode: z.number().int('HID keycode to press (0-255)').min(0).max(255),
      duration: z.number().min(0, 'Duration must be non-negative').optional(),
    });
  • Tool registration exporting the key_press tool with name, description, public schema (omitting simulatorId), and session-aware handler wrapping the logic function.
    const publicSchemaObject = keyPressSchema.omit({ simulatorId: true } as const).strict();
    
    export default {
      name: 'key_press',
      description:
        'Press a single key by keycode on the simulator. Common keycodes: 40=Return, 42=Backspace, 43=Tab, 44=Space, 58-67=F1-F10.',
      schema: publicSchemaObject.shape, // MCP SDK compatibility
      handler: createSessionAwareTool<KeyPressParams>({
        internalSchema: keyPressSchema as unknown as z.ZodType<KeyPressParams>,
        logicFunction: (params: KeyPressParams, executor: CommandExecutor) =>
          key_pressLogic(params, executor, {
            getAxePath,
            getBundledAxeEnvironment,
            createAxeNotAvailableResponse,
          }),
        getExecutor: getDefaultCommandExecutor,
        requirements: [{ allOf: ['simulatorId'], message: 'simulatorId is required' }],
      }),
    };
  • Inline helper function to execute axe commands, used by the key_press handler. Handles axe binary path, udid, environment, execution, and error wrapping.
    async function executeAxeCommand(
      commandArgs: string[],
      simulatorId: string,
      commandName: string,
      executor: CommandExecutor = getDefaultCommandExecutor(),
      axeHelpers: AxeHelpers = { getAxePath, getBundledAxeEnvironment, createAxeNotAvailableResponse },
    ): Promise<void> {
      // 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}`,
          );
        }
    
        // Function now returns void - the calling code creates its own response
      } 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)}`);
      }
    }
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/cameroncooke/XcodeBuildMCP'

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