Skip to main content
Glama

MCP iOS Simulator Screenshot

by yorifuji
index.ts7.34 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { ListResourcesRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { config } from './config.js'; import { ScreenshotOptions, ScreenshotResult } from './types.js'; import { ScreenshotService } from './services/screenshot-service.js'; import { OutputDirectoryManager } from './services/output-directory-manager.js'; import * as path from 'path'; import * as fs from 'fs'; /** * Parse command line arguments */ function parseCommandLineArgs(): { [key: string]: string } { const args = process.argv.slice(2); const result: { [key: string]: string } = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--') && i + 1 < args.length && !args[i + 1].startsWith('--')) { const key = arg.slice(2); result[key] = args[i + 1]; i++; // Skip the next argument as it's the value } } return result; } /** * iOS Simulator Screenshot Server * A server that uses MCP protocol to capture screenshots from iOS Simulator */ class IOSSimulatorScreenshotServer { private server: Server; private screenshotService: ScreenshotService; private outputManager: OutputDirectoryManager; /** * Constructor */ // Package info loaded from package.json private packageInfo: { name: string; version: string }; constructor() { // Load package info this.packageInfo = this.loadPackageInfo(); // Initialize output directory manager with default subdirectory name this.outputManager = new OutputDirectoryManager( config.screenshot.defaultOutputDirName ); // Apply command line arguments this.applyCommandLineArgs(); // Initialize screenshot service this.screenshotService = new ScreenshotService(this.outputManager); // Initialize MCP server this.server = new Server( { name: this.packageInfo.name, version: this.packageInfo.version, }, { capabilities: { resources: {}, tools: {}, }, } ); // Set up handlers this.setupHandlers(); // Set up error handling this.setupErrorHandling(); } /** * Load package info from package.json */ private loadPackageInfo(): { name: string; version: string } { try { // Try to load from package.json in the same directory as the running script const packagePath = path.resolve(process.cwd(), 'package.json'); const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8')); return { name: packageData.name || 'mcp-ios-simulator-screenshot', version: packageData.version || '1.0.0' }; } catch (error) { // Fallback values if package.json cannot be read return { name: 'mcp-ios-simulator-screenshot', version: '1.0.0' }; } } /** * Apply command line arguments */ private applyCommandLineArgs(): void { const args = parseCommandLineArgs(); // Handle output directory argument if (args['output-dir']) { // Set the root directory to the specified output directory // and use it directly (without subdirectory) this.outputManager.setRootDirectory(args['output-dir'], true); } } /** * Set up all handlers */ private setupHandlers(): void { // Resource handlers (empty list) this.server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [] }; }); // Tool list handler this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [this.getScreenshotToolDefinition()] })); // Tool invocation handler this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'get_screenshot') { return await this.handleScreenshotRequest(request); } else { throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } }); } /** * Get screenshot tool definition */ private getScreenshotToolDefinition() { return { name: 'get_screenshot', description: 'Capture a screenshot from iOS Simulator', inputSchema: { type: 'object', properties: { output_filename: { type: 'string', description: 'Output filename (if not specified, timestamp.png will be used)' }, output_directory_name: { type: 'string', description: 'Subdirectory name for screenshots (if not specified, .screenshots will be used)', default: config.screenshot.defaultOutputDirName }, resize: { type: 'boolean', description: 'Whether to resize the image to approximately VGA size', default: true }, max_width: { type: 'integer', description: 'Maximum width for resizing (pixels)', default: config.screenshot.defaultMaxWidth }, device_id: { type: 'string', description: 'Specify a simulator device (if not specified, the booted device will be used)' } }, required: [] } }; } /** * Handle screenshot request */ private async handleScreenshotRequest(request: any): Promise<any> { try { const args = request.params.arguments as Record<string, unknown> || {}; // Map API parameters to internal options const options: ScreenshotOptions = { outputFileName: args.output_filename as string, outputDirectoryName: args.output_directory_name as string, resize: args.resize as boolean, maxWidth: args.max_width as number, deviceId: args.device_id as string }; // Capture screenshot const result = await this.screenshotService.captureScreenshot(options); // Return formatted response return this.createMcpResponse(result); } catch (error) { const err = error as Error; return this.createMcpResponse({ success: false, message: `Error: ${err.message}`, error: { code: 'UNEXPECTED_ERROR' } }); } } /** * Set up error handling */ private setupErrorHandling(): void { this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } /** * Create MCP response from screenshot result */ private createMcpResponse(result: ScreenshotResult): any { return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: !result.success }; } /** * Start the server */ async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('MCP iOS Simulator Screenshot server running on stdio'); } } // Create and run server const server = new IOSSimulatorScreenshotServer(); server.run().catch(console.error);

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/yorifuji/mcp-ios-simulator-screenshot'

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