viewpo_screenshot
Capture screenshots of webpages at multiple viewport widths to verify responsive design across different screen sizes.
Instructions
Capture screenshots of a URL at one or more viewport widths. Returns base64 JPEG images. Use this to SEE what a webpage looks like at different screen sizes.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL to screenshot | |
| viewports | No | Viewports to capture. Defaults to desktop (1920px) if omitted. Common widths: 375 (phone), 820 (tablet), 1920 (desktop). |
Implementation Reference
- src/index.ts:40-96 (handler)Tool registration and handler implementation for viewpo_screenshot. Defines the tool schema using zod, handles the request by calling client.screenshot(), processes the response into text and image content, and returns formatted results or error messages.// --- Tool: viewpo_screenshot --- server.tool( "viewpo_screenshot", "Capture screenshots of a URL at one or more viewport widths. Returns base64 JPEG images. Use this to SEE what a webpage looks like at different screen sizes.", { url: z.string().url().describe("The URL to screenshot"), viewports: z .array( z.object({ width: z .number() .int() .min(100) .max(3840) .describe("Viewport width in CSS pixels"), name: z .string() .optional() .describe('Label for this viewport (e.g. "phone", "desktop")'), }) ) .optional() .describe( "Viewports to capture. Defaults to desktop (1920px) if omitted. Common widths: 375 (phone), 820 (tablet), 1920 (desktop)." ), }, async ({ url, viewports }) => { try { const result = await client.screenshot({ url, viewports }); const content = result.viewports.flatMap((vp) => [ { type: "text" as const, text: `**${vp.viewport}** (${vp.width}\u00d7${vp.height})`, }, { type: "image" as const, data: vp.image_base64, mimeType: "image/jpeg" as const, }, ]); return { content }; } catch (error) { return { content: [ { type: "text" as const, text: `Screenshot failed: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } );
- src/types.ts:3-24 (schema)Type definitions for the screenshot tool. Includes ViewportSpec (width and optional name), ScreenshotRequest (url and optional viewports array), ViewportResult (viewport dimensions and base64 image), and ScreenshotResponse (array of viewport results).// --- Screenshot --- export interface ViewportSpec { width: number; name?: string; } export interface ScreenshotRequest { url: string; viewports?: ViewportSpec[]; } export interface ViewportResult { viewport: string; width: number; height: number; image_base64: string; } export interface ScreenshotResponse { viewports: ViewportResult[]; }
- src/client.ts:30-32 (helper)HTTP client method that sends POST request to /screenshot endpoint. Takes ScreenshotRequest parameters and returns ScreenshotResponse, handling communication with the Viewpo macOS app's bridge API.async screenshot(request: ScreenshotRequest): Promise<ScreenshotResponse> { return this.post<ScreenshotResponse>("/screenshot", request); }
- src/index.ts:42-66 (schema)Zod schema validation for the viewpo_screenshot tool parameters. Defines url as a required URL string, and viewports as an optional array of objects with width (100-3840) and optional name fields.server.tool( "viewpo_screenshot", "Capture screenshots of a URL at one or more viewport widths. Returns base64 JPEG images. Use this to SEE what a webpage looks like at different screen sizes.", { url: z.string().url().describe("The URL to screenshot"), viewports: z .array( z.object({ width: z .number() .int() .min(100) .max(3840) .describe("Viewport width in CSS pixels"), name: z .string() .optional() .describe('Label for this viewport (e.g. "phone", "desktop")'), }) ) .optional() .describe( "Viewports to capture. Defaults to desktop (1920px) if omitted. Common widths: 375 (phone), 820 (tablet), 1920 (desktop)." ), },
- src/client.ts:50-57 (helper)Generic POST method implementation that handles HTTP requests with JSON body, including authentication headers and response processing via handleResponse method.private async post<T>(path: string, body: unknown): Promise<T> { const response = await fetch(`${this.baseURL}${path}`, { method: "POST", headers: this.headers(true), body: JSON.stringify(body), }); return this.handleResponse<T>(response); }