screenshot
Capture a screenshot of the iOS Simulator screen and save it to a file. Choose image format, display, and mask options for non-rectangular screens.
Instructions
Takes a screenshot of the iOS Simulator
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| udid | No | Udid of target, can also be set with the IDB_UDID env var | |
| 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. | |
| 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) |
Implementation Reference
- src/index.ts:846-932 (registration)Registration of the 'screenshot' tool via server.tool() with name 'screenshot' and description 'Takes a screenshot of the iOS Simulator'
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)" ), }, { title: "Take Screenshot", readOnlyHint: false, openWorldHint: true }, 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:850-880 (schema)Zod schema defining input parameters for the screenshot tool: udid, output_path (required), 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:882-931 (handler)Handler function for the screenshot tool. Executes 'xcrun simctl io <udid> screenshot' with optional type/display/mask flags, saves to output path, and returns the result text.
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:819-844 (helper)Helper function that resolves relative file paths to absolute paths using IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR or ~/Downloads as the base directory. Used by the screenshot handler to determine the output path.
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); }