screenshot
Capture screenshots of iOS Simulator displays by specifying the output path, image format, and display type. Supports various image formats and handles non-rectangular displays with mask options.
Instructions
Takes a screenshot of the iOS Simulator
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| display | No | Display to capture (internal or external). Default depends on device type. | |
| mask | No | For non-rectangular displays, handle the mask by policy (ignored, alpha, or black) | |
| output_path | Yes | File path where the screenshot will be saved. If relative, it uses the directory specified by the `IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR` env var, or `~/Downloads` if not set. | |
| type | No | Image format (png, tiff, bmp, gif, or jpeg). Default is png. | |
| udid | No | Udid of target, can also be set with the IDB_UDID env var |
Implementation Reference
- src/index.ts:677-725 (handler)The main handler function that executes the screenshot tool logic using xcrun simctl to capture and save the screenshot to a file.async ({ udid, output_path, type, display, mask }) => { try { const actualUdid = await getBootedDeviceId(udid); const absolutePath = ensureAbsolutePath(output_path); // command is weird, it responds with stderr on success and stdout is blank const { stderr: stdout } = await run("xcrun", [ "simctl", "io", actualUdid, "screenshot", ...(type ? [`--type=${type}`] : []), ...(display ? [`--display=${display}`] : []), ...(mask ? [`--mask=${mask}`] : []), // When passing user-provided values to a command, it's crucial to use `--` // to separate the command's options from positional arguments. // This prevents the shell from misinterpreting the arguments as options. "--", absolutePath, ]); // throw if we don't get the expected success message if (stdout && !stdout.includes("Wrote screenshot to")) { throw new Error(stdout); } return { isError: false, content: [ { type: "text", text: stdout, }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: errorWithTroubleshooting( `Error taking screenshot: ${toError(error).message}` ), }, ], }; } }
- src/index.ts:646-676 (schema)Zod input schema defining parameters for the screenshot tool: udid, output_path, type, display, mask.{ udid: z .string() .regex(UDID_REGEX) .optional() .describe("Udid of target, can also be set with the IDB_UDID env var"), output_path: z .string() .max(1024) .describe( "File path where the screenshot will be saved. If relative, it uses the directory specified by the `IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR` env var, or `~/Downloads` if not set." ), type: z .enum(["png", "tiff", "bmp", "gif", "jpeg"]) .optional() .describe( "Image format (png, tiff, bmp, gif, or jpeg). Default is png." ), display: z .enum(["internal", "external"]) .optional() .describe( "Display to capture (internal or external). Default depends on device type." ), mask: z .enum(["ignored", "alpha", "black"]) .optional() .describe( "For non-rectangular displays, handle the mask by policy (ignored, alpha, or black)" ), },
- src/index.ts:642-727 (registration)Registration of the 'screenshot' tool on the MCP server, including conditional filtering.if (!isToolFiltered("screenshot")) { server.tool( "screenshot", "Takes a screenshot of the iOS Simulator", { udid: z .string() .regex(UDID_REGEX) .optional() .describe("Udid of target, can also be set with the IDB_UDID env var"), output_path: z .string() .max(1024) .describe( "File path where the screenshot will be saved. If relative, it uses the directory specified by the `IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR` env var, or `~/Downloads` if not set." ), type: z .enum(["png", "tiff", "bmp", "gif", "jpeg"]) .optional() .describe( "Image format (png, tiff, bmp, gif, or jpeg). Default is png." ), display: z .enum(["internal", "external"]) .optional() .describe( "Display to capture (internal or external). Default depends on device type." ), mask: z .enum(["ignored", "alpha", "black"]) .optional() .describe( "For non-rectangular displays, handle the mask by policy (ignored, alpha, or black)" ), }, async ({ udid, output_path, type, display, mask }) => { try { const actualUdid = await getBootedDeviceId(udid); const absolutePath = ensureAbsolutePath(output_path); // command is weird, it responds with stderr on success and stdout is blank const { stderr: stdout } = await run("xcrun", [ "simctl", "io", actualUdid, "screenshot", ...(type ? [`--type=${type}`] : []), ...(display ? [`--display=${display}`] : []), ...(mask ? [`--mask=${mask}`] : []), // When passing user-provided values to a command, it's crucial to use `--` // to separate the command's options from positional arguments. // This prevents the shell from misinterpreting the arguments as options. "--", absolutePath, ]); // throw if we don't get the expected success message if (stdout && !stdout.includes("Wrote screenshot to")) { throw new Error(stdout); } return { isError: false, content: [ { type: "text", text: stdout, }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: errorWithTroubleshooting( `Error taking screenshot: ${toError(error).message}` ), }, ], }; } } ); }
- src/index.ts:615-640 (helper)Helper function to resolve relative output paths for screenshot and other tools, using env var or ~/Downloads.function ensureAbsolutePath(filePath: string): string { if (path.isAbsolute(filePath)) { return filePath; } // Handle ~/something paths in the provided filePath if (filePath.startsWith("~/")) { return path.join(os.homedir(), filePath.slice(2)); } // Determine the default directory from env var or fallback to ~/Downloads let defaultDir = path.join(os.homedir(), "Downloads"); const customDefaultDir = process.env.IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR; if (customDefaultDir) { // also expand tilde for the custom directory path if (customDefaultDir.startsWith("~/")) { defaultDir = path.join(os.homedir(), customDefaultDir.slice(2)); } else { defaultDir = customDefaultDir; } } // Join the relative filePath with the resolved default directory return path.join(defaultDir, filePath); }