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,
    	};
    }
Install Server

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