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)}`); } }

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