Skip to main content
Glama
upnorthmedia

Screenshot MCP

by upnorthmedia

capture_element

Take screenshots of specific webpage elements using CSS selectors to document UI components or capture targeted content.

Instructions

Capture a screenshot of a specific element on a webpage

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesThe URL of the webpage
selectorYesCSS selector for the element to capture
viewportNoViewport configuration
standardDelayNoWhether to apply standard 2.5s delay after networkidle2 for better stability

Implementation Reference

  • The `captureElement` method in the `ScreenshotCapture` class that implements the core tool logic: validates URL and selector, navigates to page with Puppeteer, captures element screenshot, processes image with Sharp for resizing if needed, and returns base64 data.
    async captureElement(url, selector, options = {}) { const validatedUrl = validateUrl(url); const validatedSelector = sanitizeSelector(selector); if (!validatedSelector) { throw createError('Invalid selector provided', 'INVALID_SELECTOR'); } await this.initialize(); const page = await this.browser.newPage(); try { await this.configureViewport(page, options.viewport); await page.goto(validatedUrl, { waitUntil: 'networkidle2' }); // Standard delay after networkidle2 for better stability const standardDelay = options.standardDelay !== false ? 2500 : 0; if (standardDelay > 0) { await new Promise(resolve => setTimeout(resolve, standardDelay)); } const element = await page.$(validatedSelector); if (!element) { throw createError(`Element not found: ${validatedSelector}`, 'ELEMENT_NOT_FOUND'); } // * Take the element screenshot const screenshotBase64 = await element.screenshot({ type: 'png', encoding: 'base64' }); // * Decode base64 to buffer for sharp processing let screenshotBuffer = Buffer.from(screenshotBase64, 'base64'); let metadata; try { metadata = await sharp(screenshotBuffer).metadata(); } catch (err) { throw createError('Failed to read element screenshot metadata', 'IMAGE_METADATA_ERROR', { originalError: err.message }); } // * Check if resizing is needed const maxDimension = 8000; if (metadata.width > maxDimension || metadata.height > maxDimension) { // * Calculate scale factor to fit within 8000x8000 const scale = Math.min(maxDimension / metadata.width, maxDimension / metadata.height); const newWidth = Math.floor(metadata.width * scale); const newHeight = Math.floor(metadata.height * scale); try { screenshotBuffer = await sharp(screenshotBuffer) .resize({ width: newWidth, height: newHeight }) .png() .toBuffer(); } catch (err) { throw createError('Failed to resize element screenshot image', 'IMAGE_RESIZE_ERROR', { originalError: err.message }); } } // * Encode back to base64 const finalBase64 = screenshotBuffer.toString('base64'); return { success: true, data: finalBase64, metadata: { url: validatedUrl, selector: validatedSelector, timestamp: new Date().toISOString(), imageWidth: metadata.width, imageHeight: metadata.height } }; } finally { await page.close(); } }
  • The tool definition object including name, description, and inputSchema for validating parameters of the capture_element tool.
    { name: 'capture_element', description: 'Capture a screenshot of a specific element on a webpage', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL of the webpage' }, selector: { type: 'string', description: 'CSS selector for the element to capture' }, viewport: { type: 'object', properties: { preset: { type: 'string', enum: Object.keys(DEVICE_PRESETS), description: 'Device preset (mobile, tablet, desktop)' }, width: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport width in pixels' }, height: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport height in pixels' } }, description: 'Viewport configuration' }, standardDelay: { type: 'boolean', default: true, description: 'Whether to apply standard 2.5s delay after networkidle2 for better stability' } }, required: ['url', 'selector'] } },
  • index.js:179-183 (registration)
    Registers the capture_element tool (included in the `tools` array) by handling ListToolsRequestSchema and returning the list of available tools.
    server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: tools }; });
  • index.js:218-241 (registration)
    Handles incoming calls to the capture_element tool in the CallToolRequestSchema handler by invoking the captureElement method and formatting the image response.
    case 'capture_element': const elementResult = await screenshotCapture.captureElement(args.url, args.selector, { viewport: args.viewport, standardDelay: args.standardDelay }); return { content: [ { type: 'text', text: `Element screenshot captured from ${args.url} (selector: ${args.selector})` }, { type: 'image', data: elementResult.data, mimeType: 'image/png' }, { type: 'text', text: `Metadata: ${JSON.stringify(elementResult.metadata, null, 2)}` } ] };

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/upnorthmedia/ScreenshotMCP'

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