tauri_webview_keyboard
Simulate keyboard input in Tauri applications by typing text or sending key events to automate UI testing and debugging workflows.
Instructions
[Tauri Apps Only] Type text or send keyboard events in a Tauri app. Requires active tauri_driver_session. Targets the only connected app, or the default app if multiple are connected. Specify appIdentifier (port or bundle ID) to target a specific app. For browser keyboard input, use Chrome DevTools MCP instead.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| windowId | No | Window label to target (defaults to "main") | |
| appIdentifier | No | App port or bundle ID to target. Defaults to the only connected app or the default app if multiple are connected. | |
| action | Yes | Keyboard action type: "type" for typing text into an element, "press/down/up" for key events | |
| selector | No | CSS selector for element to type into (required for "type" action) | |
| text | No | Text to type (required for "type" action) | |
| key | No | Key to press (required for "press/down/up" actions, e.g., "Enter", "a", "Escape") | |
| modifiers | No | Modifier keys to hold |
Implementation Reference
- Core handler function that parses arguments, builds appropriate JavaScript script using buildTypeScript or buildKeyEventScript, and executes it in the Tauri webview via executeInWebview.export async function keyboard(options: KeyboardOptions): Promise<string> { const { action, selectorOrKey, textOrModifiers, modifiers, windowId, appIdentifier } = options; // Handle the different parameter combinations based on action if (action === 'type') { const selector = selectorOrKey; const text = textOrModifiers as string; if (!selector || !text) { throw new Error('Type action requires both selector and text parameters'); } const script = buildTypeScript(selector, text); try { return await executeInWebview(script, windowId, appIdentifier); } catch(error: unknown) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Type action failed: ${message}`); } } // For press/down/up actions: key is required, modifiers optional const key = selectorOrKey; const mods = Array.isArray(textOrModifiers) ? textOrModifiers : modifiers; if (!key) { throw new Error(`${action} action requires a key parameter`); } const script = buildKeyEventScript(action, key, mods || []); try { return await executeInWebview(script, windowId, appIdentifier); } catch(error: unknown) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Keyboard action failed: ${message}`); } }
- Zod schema defining input parameters for the tauri_webview_keyboard tool.export const KeyboardSchema = WindowTargetSchema.extend({ action: z.enum([ 'type', 'press', 'down', 'up' ]) .describe('Keyboard action type: "type" for typing text into an element, "press/down/up" for key events'), selector: z.string().optional().describe('CSS selector for element to type into (required for "type" action)'), text: z.string().optional().describe('Text to type (required for "type" action)'), key: z.string().optional().describe('Key to press (required for "press/down/up" actions, e.g., "Enter", "a", "Escape")'), modifiers: z.array(z.enum([ 'Control', 'Alt', 'Shift', 'Meta' ])).optional().describe('Modifier keys to hold'), });
- packages/mcp-server/src/tools-registry.ts:358-393 (registration)Tool registration in the central TOOLS array, including description, schema reference, annotations, and inline handler wrapper that invokes the core keyboard() function.{ name: 'tauri_webview_keyboard', description: '[Tauri Apps Only] Type text or send keyboard events in a Tauri app. ' + 'Requires active tauri_driver_session. ' + MULTI_APP_DESC + ' ' + 'For browser keyboard input, use Chrome DevTools MCP instead.', category: TOOL_CATEGORIES.UI_AUTOMATION, schema: KeyboardSchema, annotations: { title: 'Keyboard Input in Tauri', readOnlyHint: false, destructiveHint: false, openWorldHint: false, }, handler: async (args) => { const parsed = KeyboardSchema.parse(args); if (parsed.action === 'type') { return await keyboard({ action: parsed.action, selectorOrKey: parsed.selector, textOrModifiers: parsed.text, windowId: parsed.windowId, appIdentifier: parsed.appIdentifier, }); } return await keyboard({ action: parsed.action, selectorOrKey: parsed.key, textOrModifiers: parsed.modifiers, windowId: parsed.windowId, appIdentifier: parsed.appIdentifier, }); }, },
- Helper function that generates JavaScript code for typing text into a selected element (used for 'type' action).export function buildTypeScript(selector: string, text: string): string { const escapedText = text.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); return ` (function() { const selector = '${selector}'; const text = '${escapedText}'; const element = document.querySelector(selector); if (!element) { throw new Error('Element not found: ' + selector); } element.focus(); element.value = text; element.dispatchEvent(new Event('input', { bubbles: true })); element.dispatchEvent(new Event('change', { bubbles: true })); return 'Typed "' + text + '" into ' + selector; })() `; }
- Helper function that generates JavaScript code for dispatching key events (keydown, keypress, keyup) with modifiers (used for 'press', 'down', 'up' actions).export function buildKeyEventScript( action: string, key: string, modifiers: string[] = [] ): string { return ` (function() { const action = '${action}'; const key = '${key}'; const modifiers = ${JSON.stringify(modifiers)}; const eventOptions = { key: key, code: key, bubbles: true, cancelable: true, ctrlKey: modifiers.includes('Control'), altKey: modifiers.includes('Alt'), shiftKey: modifiers.includes('Shift'), metaKey: modifiers.includes('Meta'), }; const activeElement = document.activeElement || document.body; if (action === 'press') { activeElement.dispatchEvent(new KeyboardEvent('keydown', eventOptions)); activeElement.dispatchEvent(new KeyboardEvent('keypress', eventOptions)); activeElement.dispatchEvent(new KeyboardEvent('keyup', eventOptions)); return 'Pressed key: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } else if (action === 'down') { activeElement.dispatchEvent(new KeyboardEvent('keydown', eventOptions)); return 'Key down: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } else if (action === 'up') { activeElement.dispatchEvent(new KeyboardEvent('keyup', eventOptions)); return 'Key up: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } throw new Error('Unknown action: ' + action); })() `; }