get_focused_element
Retrieve the currently keyboard-focused element's accessibility details and suggested selectors to verify focus management in accessible user interfaces.
Instructions
Returns the currently keyboard-focused element's accessibility info and suggested selectors. Useful for checking focus management in accessible UIs.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/getFocusedElement.ts:12-96 (handler)Main handler function that retrieves the currently keyboard-focused element's accessibility information. Takes no arguments, uses Puppeteer's accessibility snapshot to find the focused node, then retrieves additional details via CDP including DOM attributes, tag name, and suggested selectors.export async function getFocusedElementHandler( _args: Record<string, never> ): Promise<ReturnType<typeof toolSuccess | typeof toolError>> { try { const { page, cdpSession } = browserManager.requireConnection(); // Snapshot the full AX tree (unfiltered) to find focused node const snapshot = await page.accessibility.snapshot({ interestingOnly: false }); if (!snapshot) { return toolSuccess({ focused: null, message: 'No accessibility snapshot available.', }); } // Find the focused node via the snapshot // Puppeteer's snapshot returns plain objects; we need to walk the tree const focusedNode = findFocusedInSnapshot(snapshot as unknown as Record<string, unknown>); if (!focusedNode) { return toolSuccess({ focused: null, message: 'No element is currently focused.', }); } // Try to get additional selector info via CDP // Use DOM.getFocusedNodeDetails if available, otherwise use JS evaluation let suggestedSelectors = null; let domAttributes: Record<string, string> | null = null; let tagName: string | null = null; try { // Get focused element via JavaScript const focusedHandle = await page.evaluateHandle(() => document.activeElement); const remoteObj = focusedHandle.remoteObject(); if (remoteObj.objectId) { const describeResult = await cdpSession.send('DOM.describeNode', { objectId: remoteObj.objectId, depth: 0, }) as DomDescribeNodeResponse; const domNode = describeResult.node; tagName = domNode.localName; domAttributes = parseAttributes(domNode.attributes); // Get AX tree for this specific node const axResult = await cdpSession.send('Accessibility.getPartialAXTree', { backendNodeId: domNode.backendNodeId, fetchRelatives: false, }) as GetPartialAXTreeResponse; const primaryAXNode = (axResult.nodes ?? []).find((n) => !n.ignored); if (primaryAXNode) { const name = (primaryAXNode.name?.value as string) ?? ''; const role = (primaryAXNode.role?.value as string) ?? ''; suggestedSelectors = buildSelectorFromRawNode( name, role, tagName, domNode.attributes ); } } } catch { // DOM info unavailable — still return what we have from the snapshot } return toolSuccess({ focused: { role: focusedNode['role'] as string, name: focusedNode['name'] as string, ...(focusedNode['value'] !== undefined && { value: focusedNode['value'] }), ...(focusedNode['description'] !== undefined && { description: focusedNode['description'] }), ...(tagName && { tagName }), ...(domAttributes && { domAttributes }), ...(suggestedSelectors && { suggestedSelectors }), }, }); } catch (error) { return toolError(error); } }
- src/tools/getFocusedElement.ts:10-10 (schema)Schema definition for get_focused_element tool - an empty object since the tool takes no arguments.export const getFocusedElementSchema = {};
- src/index.ts:118-129 (registration)Tool registration in the MCP server, registering 'get_focused_element' with its metadata and handler function.// ── get_focused_element ────────────────────────────────────────────────────── server.registerTool( 'get_focused_element', { title: 'Get Focused Element', description: 'Returns the currently keyboard-focused element\'s accessibility info ' + 'and suggested selectors. Useful for checking focus management in accessible UIs.', inputSchema: getFocusedElementSchema, }, getFocusedElementHandler );
- Helper functions: findFocusedInSnapshot recursively walks the accessibility tree to find the node with focused=true; parseAttributes converts CDP's attributes array format into an object map.function findFocusedInSnapshot( node: Record<string, unknown> ): Record<string, unknown> | null { if (node['focused'] === true) return node; const children = node['children'] as Record<string, unknown>[] | undefined; if (!children) return null; for (const child of children) { const found = findFocusedInSnapshot(child); if (found) return found; } return null; } function parseAttributes(attrs: string[] | undefined): Record<string, string> { const map: Record<string, string> = {}; if (!attrs) return map; for (let i = 0; i + 1 < attrs.length; i += 2) { map[attrs[i]] = attrs[i + 1]; } return map; }