screenshot_viewport
Capture the current browser viewport to verify UI elements, debug layout issues, and inspect page state.
Instructions
Take a screenshot of what's currently visible in the browser window. Use this to see the current state of the page, verify UI elements, or debug layout issues. Returns an image you can view.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Image format: png (default, lossless) or jpeg (smaller file size) | |
| quality | No | JPEG quality 0-100 (higher = better quality, larger file) | |
| tabId | No | Target tab ID (defaults to currently active tab) | |
| apiKey | No | API key for authentication if enabled |
Implementation Reference
- src/tools/screenshot.ts:16-35 (handler)The handler function that executes the screenshot_viewport tool logic. Sends a 'screenshot_viewport' command via the WebSocket bridge, receives the image data, and returns it as an image content response.
async ({ format, quality, tabId, apiKey }) => { const result = await bridge.sendCommand({ command: 'screenshot_viewport', params: { format, quality }, tabId, apiKey, timeout: LONG_TIMEOUT, }); if (!result.success) { return { content: [{ type: 'text', text: `Error: ${result.error?.message}` }], isError: true }; } const data = result.data as { image: string; mimeType: string }; return { content: [{ type: 'image', data: data.image, mimeType: data.mimeType, }], }; } - src/tools/screenshot.ts:10-15 (schema)Zod schema defining the input parameters for screenshot_viewport: format (png/jpeg), quality (0-100), tabId, and apiKey.
{ format: z.enum(['png', 'jpeg']).optional().describe('Image format: png (default, lossless) or jpeg (smaller file size)'), quality: z.number().min(0).max(100).optional().describe('JPEG quality 0-100 (higher = better quality, larger file)'), tabId: z.number().optional().describe('Target tab ID (defaults to currently active tab)'), apiKey: z.string().optional().describe('API key for authentication if enabled'), }, - src/tools/screenshot.ts:7-36 (registration)The tool is registered with the MCP server via server.tool() with the name 'screenshot_viewport', a description, schema, and handler.
server.tool( 'screenshot_viewport', 'Take a screenshot of what\'s currently visible in the browser window. Use this to see the current state of the page, verify UI elements, or debug layout issues. Returns an image you can view.', { format: z.enum(['png', 'jpeg']).optional().describe('Image format: png (default, lossless) or jpeg (smaller file size)'), quality: z.number().min(0).max(100).optional().describe('JPEG quality 0-100 (higher = better quality, larger file)'), tabId: z.number().optional().describe('Target tab ID (defaults to currently active tab)'), apiKey: z.string().optional().describe('API key for authentication if enabled'), }, async ({ format, quality, tabId, apiKey }) => { const result = await bridge.sendCommand({ command: 'screenshot_viewport', params: { format, quality }, tabId, apiKey, timeout: LONG_TIMEOUT, }); if (!result.success) { return { content: [{ type: 'text', text: `Error: ${result.error?.message}` }], isError: true }; } const data = result.data as { image: string; mimeType: string }; return { content: [{ type: 'image', data: data.image, mimeType: data.mimeType, }], }; } ); - src/tools/index.ts:33-55 (registration)The registerScreenshotTools function is called from registerAllTools in the tools index, which bootstraps all tool registrations.
registerScreenshotTools(server, bridge); registerClickTools(server, bridge); registerInputTools(server, bridge); registerDragDropTools(server, bridge); registerHoverTools(server, bridge); registerDevtoolsSourcesTools(server, bridge); registerDevtoolsModifyTools(server, bridge); registerDevtoolsNetworkTools(server, bridge); registerDevtoolsStorageTools(server, bridge); registerDevtoolsConsoleTools(server, bridge); registerAccessibilityTools(server, bridge); registerEmulationTools(server, bridge); registerElementTools(server, bridge); registerAuditTools(server, bridge); registerInteractionTools(server, bridge); registerMonitoringTools(server, bridge); registerQaTools(server, bridge); registerGestureTools(server, bridge); registerMacroTools(server, bridge); registerVisualRegressionTools(server, bridge); } - src/websocket-bridge.ts:63-103 (helper)The sendCommand helper on WebSocketBridge that sends the 'screenshot_viewport' command over WebSocket to the Chrome extension and waits for a response.
async sendCommand(cmd: BridgeCommand): Promise<BridgeResponse> { if (!this.isConnected()) { return { success: false, error: { code: 'NOT_CONNECTED', message: 'Chrome extension is not connected. Ensure the extension is installed, enabled, and the browser is running.', }, }; } const id = crypto.randomUUID(); const timeout = cmd.timeout ?? DEFAULT_TIMEOUT; return new Promise<BridgeResponse>((resolve, reject) => { const timer = setTimeout(() => { this.pending.delete(id); resolve({ success: false, error: { code: 'TIMEOUT', message: `Command '${cmd.command}' timed out after ${timeout}ms`, }, }); }, timeout); this.pending.set(id, { resolve, reject, timer }); const message = { id, type: 'request', command: cmd.command, params: cmd.params, tabId: cmd.tabId, apiKey: cmd.apiKey, timestamp: Date.now(), }; this.client!.send(JSON.stringify(message)); }); }