Skip to main content
Glama

Web Inspector MCP

by antonzherdev
elementPosition.ts4.84 kB
import { BrowserToolBase } from './base.js'; import { ToolContext, ToolResponse, createSuccessResponse, createErrorResponse } from '../common/types.js'; /** * Tool for getting element position and size */ export class ElementPositionTool extends BrowserToolBase { /** * Execute the element position tool */ async execute(args: any, context: ToolContext): Promise<ToolResponse> { return this.safeExecute(context, async (page) => { const selector = this.normalizeSelector(args.selector); const locator = page.locator(selector); try { // Check if element exists const count = await locator.count(); if (count === 0) { return createErrorResponse(`Element not found: ${args.selector}`); } // Handle multiple matches by using first() - show warning const targetLocator = count > 1 ? locator.first() : locator; const multipleMatchWarning = count > 1 ? `⚠ Warning: Selector matched ${count} elements, showing first:\n\n` : ''; // Get bounding box const boundingBox = await targetLocator.boundingBox(); if (!boundingBox) { // Get element info for better error message const hiddenInfo = await targetLocator.evaluate((element) => { const styles = window.getComputedStyle(element); const tagName = element.tagName.toLowerCase(); const testId = element.getAttribute('data-testid') || element.getAttribute('data-test') || element.getAttribute('data-cy'); let descriptor = `<${tagName}`; if (testId) descriptor += ` data-testid="${testId}"`; descriptor += '>'; return { descriptor, display: styles.display, opacity: styles.opacity, visibility: styles.visibility, width: parseFloat(styles.width) || 0, height: parseFloat(styles.height) || 0 }; }); // Return structured response instead of error let reason = 'unknown reason'; if (hiddenInfo.display === 'none') { reason = 'display: none'; } else if (hiddenInfo.width === 0 || hiddenInfo.height === 0) { reason = 'zero size'; } else if (parseFloat(hiddenInfo.opacity) === 0) { reason = 'opacity: 0'; } else if (hiddenInfo.visibility === 'hidden') { reason = 'visibility: hidden'; } const output = multipleMatchWarning + `Position: ${hiddenInfo.descriptor}\n` + `@ null (element hidden: ${reason})\n` + `display: ${hiddenInfo.display}, opacity: ${hiddenInfo.opacity}, visibility: ${hiddenInfo.visibility}`; return createSuccessResponse(output); } // Check if in viewport and get element tag info const elementData = await targetLocator.evaluate((element) => { const rect = element.getBoundingClientRect(); const viewportHeight = window.innerHeight; const viewportWidth = window.innerWidth; // Element is in viewport if any part is visible const inViewport = ( rect.bottom > 0 && rect.right > 0 && rect.top < viewportHeight && rect.left < viewportWidth ); // Build element descriptor const tagName = element.tagName.toLowerCase(); const testId = element.getAttribute('data-testid') || element.getAttribute('data-test') || element.getAttribute('data-cy'); const id = element.id ? `#${element.id}` : ''; const classes = element.className && typeof element.className === 'string' ? `.${element.className.split(' ').filter(c => c).join('.')}` : ''; let descriptor = `<${tagName}`; if (testId) descriptor += ` data-testid="${testId}"`; else if (id) descriptor += id; else if (classes) descriptor += classes; descriptor += '>'; return { inViewport, descriptor }; }); // Build compact text format const x = Math.round(boundingBox.x); const y = Math.round(boundingBox.y); const width = Math.round(boundingBox.width); const height = Math.round(boundingBox.height); const viewportSymbol = elementData.inViewport ? '✓' : '✗'; const viewportStatus = elementData.inViewport ? 'in viewport' : 'outside viewport'; const output = multipleMatchWarning + `Position: ${elementData.descriptor}\n@ (${x},${y}) ${width}x${height}px, ${viewportSymbol} ${viewportStatus}`; return createSuccessResponse(output); } catch (error) { return createErrorResponse(`Failed to get position: ${(error as Error).message}`); } }); } }

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/antonzherdev/mcp-web-inspector'

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