resize_viewport
Resize the browser viewport to test responsive designs at various screen sizes. Optionally emulate mobile, touch, and custom user agent.
Instructions
Resize the browser viewport to specific dimensions. Use this to test responsive layouts at different screen sizes.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| width | Yes | Viewport width in pixels | |
| height | Yes | Viewport height in pixels | |
| deviceScaleFactor | No | Device pixel ratio (default: 1) | |
| mobile | No | Whether to emulate mobile (default: false) | |
| userAgent | No | Custom user agent string | |
| touch | No | Enable touch emulation (default: false) | |
| tabId | No | Target tab ID (defaults to currently active tab) | |
| apiKey | No | API key for authentication if enabled |
Implementation Reference
- src/tools/emulation.ts:14-40 (registration)The 'resize_viewport' tool is registered via server.tool() inside registerEmulationTools(). This is the MCP tool registration point.
export function registerEmulationTools(server: McpServer, bridge: WebSocketBridge) { server.tool( 'resize_viewport', 'Resize the browser viewport to specific dimensions. Use this to test responsive layouts at different screen sizes.', { width: z.number().describe('Viewport width in pixels'), height: z.number().describe('Viewport height in pixels'), deviceScaleFactor: z.number().optional().describe('Device pixel ratio (default: 1)'), mobile: z.boolean().optional().describe('Whether to emulate mobile (default: false)'), userAgent: z.string().optional().describe('Custom user agent string'), touch: z.boolean().optional().describe('Enable touch emulation (default: false)'), 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 ({ width, height, deviceScaleFactor, mobile, userAgent, touch, tabId, apiKey }) => { const result = await bridge.sendCommand({ command: 'resize_viewport', params: { width, height, deviceScaleFactor, mobile, userAgent, touch }, tabId, apiKey, }); if (!result.success) { return { content: [{ type: 'text', text: `Error: ${result.error?.message}` }], isError: true }; } return { content: [{ type: 'text', text: `Viewport resized to ${width}x${height}` }] }; } ); - src/tools/emulation.ts:28-39 (handler)The async handler that executes the 'resize_viewport' tool logic. It sends a 'resize_viewport' command via WebSocketBridge and returns the result.
async ({ width, height, deviceScaleFactor, mobile, userAgent, touch, tabId, apiKey }) => { const result = await bridge.sendCommand({ command: 'resize_viewport', params: { width, height, deviceScaleFactor, mobile, userAgent, touch }, tabId, apiKey, }); if (!result.success) { return { content: [{ type: 'text', text: `Error: ${result.error?.message}` }], isError: true }; } return { content: [{ type: 'text', text: `Viewport resized to ${width}x${height}` }] }; } - src/tools/emulation.ts:18-27 (schema)Zod schema definitions for the 'resize_viewport' tool's input parameters: width, height, deviceScaleFactor, mobile, userAgent, touch, tabId, apiKey.
{ width: z.number().describe('Viewport width in pixels'), height: z.number().describe('Viewport height in pixels'), deviceScaleFactor: z.number().optional().describe('Device pixel ratio (default: 1)'), mobile: z.boolean().optional().describe('Whether to emulate mobile (default: false)'), userAgent: z.string().optional().describe('Custom user agent string'), touch: z.boolean().optional().describe('Enable touch emulation (default: false)'), 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/websocket-bridge.ts:63-103 (helper)The sendCommand() helper that forwards the 'resize_viewport' command over WebSocket to the Chrome extension backend.
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)); }); }