Skip to main content
Glama
rogerheykoop

Safari Screenshot MCP Server

by rogerheykoop

take_screenshot

Capture webpage screenshots using Safari on macOS by providing a URL, with options for dimensions, zoom, and save location.

Instructions

Take a screenshot of a webpage using Safari on macOS

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesURL to capture
outputPathNoPath where the screenshot will be saved (default: ./screenshots/[hostname]-[timestamp].png)
widthNoWindow width in pixels (default: 1024)
heightNoWindow height in pixels (default: 768)
waitTimeNoTime to wait for page load in seconds (default: 3)
zoomLevelNoZoom level (1 = 100%, 0.5 = 50%, 2 = 200%)

Implementation Reference

  • Core handler function that opens the URL in Safari, waits, takes a screenshot using screencapture, verifies it, and cleans up Safari windows.
    export async function takeScreenshot(options: ScreenshotOptions): Promise<ScreenshotResult> { const { url, outputPath, width = 1024, height = 768, waitTime = 3, zoomLevel = 1 } = options; try { // Create screenshots directory if it doesn't exist const dir = path.dirname(outputPath); await fs.mkdir(dir, { recursive: true }); // Open URL in Safari await execAsync(`open -a Safari "${url}"`); // Wait for page load await new Promise((resolve) => setTimeout(resolve, waitTime * 1000)); // Take screenshot using screencapture const command = [ 'screencapture', '-x', // Disable interactive mode width && height ? `-R 0,0,${width},${height}` : '', // Set window size outputPath, ] .filter(Boolean) .join(' '); await execAsync(command); // Verify screenshot was created const stats = await fs.stat(outputPath); if (stats.size < 1000) { throw new Error('Screenshot appears to be empty or too small'); } return { success: true, path: outputPath, }; } catch (error) { throw error instanceof Error ? error : new Error(String(error)); } finally { // Clean up Safari windows await execAsync('osascript -e \'tell application "Safari" to close every window\'').catch(() => {}); } }
  • Defines the MCP tool schema for 'take_screenshot' including input properties, descriptions, defaults, and required fields.
    const SCREENSHOT_TOOL: Tool = { name: 'take_screenshot', description: 'Take a screenshot of a webpage using Safari on macOS', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to capture', }, outputPath: { type: 'string', description: 'Path where the screenshot will be saved (default: ./screenshots/[hostname]-[timestamp].png)', default: '', }, width: { type: 'number', description: 'Window width in pixels (default: 1024)', default: 1024, }, height: { type: 'number', description: 'Window height in pixels (default: 768)', default: 768, }, waitTime: { type: 'number', description: 'Time to wait for page load in seconds (default: 3)', default: 3, }, zoomLevel: { type: 'number', description: 'Zoom level (1 = 100%, 0.5 = 50%, 2 = 200%)', default: 1, }, }, required: ['url'], }, };
  • src/index.ts:94-98 (registration)
    Registers the 'take_screenshot' tool in the MCP server capabilities.
    capabilities: { tools: { take_screenshot: SCREENSHOT_TOOL, }, },
  • src/index.ts:103-105 (registration)
    Registers the handler for listing tools, which advertises 'take_screenshot'.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [SCREENSHOT_TOOL], }));
  • Dispatcher case in CallToolRequestHandler that validates args, calls takeScreenshot, and returns success response.
    case 'take_screenshot': { if (!isScreenshotArgs(args)) { throw new Error('Invalid arguments for take_screenshot'); } const outputPath = args.outputPath || `./screenshots/${new URL(args.url).hostname}-${Date.now()}.png`; const result = await takeScreenshot({ url: args.url, outputPath, width: args.width, height: args.height, waitTime: args.waitTime, zoomLevel: args.zoomLevel, }); return { content: [ { type: 'text', text: `Screenshot saved to: ${result.path}`, }, ], isError: false, }; }

Other Tools

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/rogerheykoop/mcp-safari-screenshot'

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