Skip to main content
Glama
mgcrea

@mgcrea/mcp-ios-simulator

by mgcrea

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
IOS_SIMULATOR_IDNoUDID, name, or `booted`. Two booted and no value is an error that names them.
IOS_SIMULATOR_DEBUGNoLog every `simctl` and WebDriverAgent call to stderr.false
IOS_SIMULATOR_CONFIGNoPath to the config file; used to move the default config location.~/.config/ios-simulator-mcp/config.json
IOS_SIMULATOR_WDA_URLNoExplicit override; rarely needed.http://127.0.0.1:8100
IOS_SIMULATOR_WDA_PORTNoMust match the runner's `USE_PORT`. One port per simulator.8100
IOS_SIMULATOR_OUTPUT_DIRNoScreenshots, launch logs, the runner log.$TMPDIR/mcp-ios-simulator
IOS_SIMULATOR_TIMEOUT_MSNoBudget for one `simctl` call; a boot is slow.120000
IOS_SIMULATOR_LAUNCH_ARGSNoLaunch arguments applied when `launch` passes none of its own.
IOS_SIMULATOR_ALLOW_WRITESNo`0` drops the fourteen driving tools from `tools/list`.on
IOS_SIMULATOR_MAX_TREE_BYTESNoByte cap on a `ui_tree` payload.24000
IOS_SIMULATOR_WDA_TIMEOUT_MSNoBudget for one WebDriverAgent call.30000

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
resources
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
ios_simulator_diagnosticsA

Report both lanes separately and never fail: which simulators exist and which are usable, which one this server would drive, its screen geometry, and whether WebDriverAgent is answering — including which simulator owns its port, which is the one way to catch a second runner quietly taking your taps. Start here when anything else misbehaves.

ios_simulator_listA

List the simulators on this machine, with the UDID every other tool takes. Shows the usable ones: a typical machine carries thirty-odd simulators and a good fraction of them are orphans whose runtime is no longer installed, which cannot be booted, driven or screenshotted at all. The result still says how many were left out and how to delete them, and include_unavailable brings them back with available: false and the reason, so "why can't I use that one" is still answerable here.

ios_simulator_list_appsA

List the apps installed on a simulator, with the bundle id every other tool takes. Defaults to your own apps: a stock simulator carries about thirty, and twenty-five of them are Apple's. Each entry also carries dataContainer — an ordinary path on this Mac, so an app's database or logs can be read directly with no copy step.

ios_simulator_screenshotA

Capture the screen and return it as an image. By default it is scaled to exactly the device's point size, which means a position read off this image can be passed straight to ios_simulator_tap with no conversion — the returned metadata says coordinateSpace: "points" when that holds. Pair it with ios_simulator_ui_tree rather than choosing between them: the image shows you what the screen looks like, the tree gives you exact labels and identifiers. Re-screenshot after every action rather than chaining blind taps.

ios_simulator_ui_treeA

List the addressable elements on screen — type, label, accessibility identifier, and the exact point to tap — flattened rather than nested. Prefer this over reading coordinates off a screenshot whenever you can: a label or identifier survives the screen moving, and a pixel position does not. The raw hierarchy is tens of KB, so this returns controls only by default; use contains or types to narrow further and detail to widen. A short answer is not proof the screen is bare — check the filtered field, which counts what the filters left out and names the argument that brings it back. Coordinates are in points, the same space ios_simulator_tap takes.

ios_simulator_wait_for_elementA

Poll until an element appears, or until it goes away. This is the tool for a screen that loads: a generation step, a network round trip, a long import. settle_ms on the action tools is a pause for an animation and caps at ten seconds — it is not a wait, and using it as one is how you end up verifying a server instead of the screen. Give exactly one of id, label or predicate, the same way ios_simulator_tap_element takes them. Your MCP client may have a request timeout of its own, commonly 60 seconds, and it will cut this call off before timeout_ms does — for a longer wait, raise it there too or call this twice.

ios_simulator_list_crash_logsA

List crash reports from simulator processes, newest first. A simulator app's crash is written by this Mac into ~/Library/Logs/DiagnosticReports alongside the Mac's own crashes; this keeps only the simulators' and says which simulator each came from. Most of them are the simulators' own system daemons, so pass process to find your app's. Read one with ios_simulator_get_crash_log. Nothing needs to be booted.

ios_simulator_get_crash_logA

Read one simulator crash report and return what matters in it: the exception, why the process was terminated, any application-specific message, and the faulting thread's top frames with library names resolved. The full report's path is returned too; it is often tens of kilobytes, so read it only when the summary is not enough. A Swift fatalError's message may not be in the report at all — on a simulator it goes to the app's stderr.

ios_simulator_tapA

Tap a position on screen, in points. Prefer ios_simulator_tap_element when the target has a label or an accessibility identifier — a position stops being right the moment the layout shifts, and nothing about a wrong tap looks wrong. Coordinates come from a default ios_simulator_screenshot image or from a tap field in ios_simulator_ui_tree, which are the same space.

ios_simulator_tap_elementA

Tap the element with this accessibility identifier or label, letting the device resolve its position. This is the tool to reach for: it survives the screen scrolling, the layout changing and the copy being reworded, none of which a coordinate does. Give exactly one of id, label or predicate; identifiers from ios_simulator_ui_tree.

ios_simulator_swipeA

Drag from one point to another, in points — how you scroll a list, pull to refresh, or swipe a row open. To scroll down a page, swipe from low on the screen to high on it. duration_ms is what separates a scroll from a fling: a short one throws the list past where you aimed.

ios_simulator_typeA

Type text into whatever currently has keyboard focus, or into a named field. Focus is the trap: with nothing focused the keystrokes go nowhere and the call still succeeds, so pass id or label to have the field tapped first unless you know a field is already active.

ios_simulator_press_buttonA

Press a hardware button. home is the way back to the home screen and the reliable way to background the app under test without terminating it.

ios_simulator_powerA

Boot or shut down a simulator. Booting is the one thing this server will not do for you implicitly — a cold boot takes tens of seconds and puts a window on the user's screen, and it changes which simulator an unqualified call resolves to afterwards. Both directions are idempotent: booting a booted simulator succeeds.

ios_simulator_eraseA

Wipe a simulator back to a factory state: installed apps, their data, the keychain and every granted permission. Irreversible, hence confirm; ios_simulator_uninstall is the narrower way to a first launch of one app. A booted simulator is shut down first and booted again afterwards, because simctl refuses to erase a running one.

ios_simulator_installA

Install a build. The path must be a .app bundle directory built for the simulator — not an .ipa, and not a device build, both of which fail with a bare "No such file or directory" that reads like a typo. Installing over an existing copy replaces it and keeps its data.

ios_simulator_launchA

Launch an installed app. Pass arguments to put it into a fixture or demo mode — that is what IOS_SIMULATOR_LAUNCH_ARGS sets as the default for every launch that does not override it. Standard output and error are captured to files under the output directory, so an app that dies on launch leaves something readable behind. Pass capture_logs: true to also get its Logger/os_log output, in one file read with ios_simulator_read_logs.

ios_simulator_uninstallA

Remove an app from the simulator, with its data container — documents, databases and preferences all go, and nothing brings them back. To get back to a cold start while keeping the data, use ios_simulator_terminate. To test a genuine first launch of one app, this is narrower than ios_simulator_erase, which wipes every app on the simulator. Uninstalling an app that is not installed also succeeds, so success does not prove it was there.

ios_simulator_terminateA

Kill a running app. The app is not uninstalled and its data is untouched — this is how you get back to a cold start without erasing anything.

ios_simulator_open_urlA

Open a URL on the simulator, which is how you exercise a deep link or a universal link without finding a way to tap one. An https:// link opens in Safari unless the app claims it; a custom scheme goes straight to whichever app registered it.

ios_simulator_read_logsA

Read an app's log output: stdout, stderr and every Logger/os_log message the process emits, interleaved in one file. Only available for an app started with ios_simulator_launch capture_logs: true. Returns the newest limit lines plus a next cursor; pass it back to get only what arrived since, which is how to see what one tap logged. capturing turns false once the app's process has exited, and what it wrote stays readable. A crash's backtrace is not in here — see ios_simulator_list_crash_logs — but its fatalError message is.

ios_simulator_set_environmentA

Stage the simulator before a screenshot or a test: dark mode, Dynamic Type size, increased contrast, a frozen status bar, a simulated location, and app permissions. None of this is possible on a physical device, and it is most of the reason to prefer a simulator for UI work. Every field is optional; those given are applied in order and the result reports the state afterwards. A status bar override survives a reboot, so clear it when you are done or it quietly pollutes later screenshots.

ios_simulator_add_mediaA

Put photos or videos into the simulator's photo library. A simulator has no camera, and this is how you get around that: seed the library first, then drive the app's picker as normal. Without it, every flow that starts with an image is untestable here. Files are copied in, so the originals are untouched and the simulator keeps them until it is erased. Pair it with permission on ios_simulator_set_environment to skip the access prompt entirely.

ios_simulator_pushA

Deliver a push notification, with no APNs certificate and no server. The payload is a normal remote-notification body and must contain an aps key. Only remote pushes are simulated — not VoIP, complications or file-provider. The app must be installed; it does not have to be running.

ios_simulator_restart_wdaA

Start the WebDriverAgent runner, or restart it after it has died. Only the UI tree and the input tools need it — screenshots and everything simctl does keep working without it. The runner is started detached so it outlives this conversation, and its output goes to a log file rather than to you. It does not wait: give it fifteen seconds or so, then check ios_simulator_diagnostics.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
diagnosticsThe same report as ios_simulator_diagnostics, as a resource.

TDQS

A4.3/5.0

Scored across 25 tools

Disambiguation5/5

Each tool targets a clearly distinct action, and the descriptions explicitly steer between look-alikes: tap vs tap_element, terminate vs uninstall vs erase, and the three log/crash tools are all distinguished with concrete guidance. Overlaps that could confuse (screenshot vs ui_tree) are addressed directly by telling the agent to pair them rather than choose.

Naming Consistency5/5

Every tool uses the same ios_simulator_ snake_case prefix with a predictable verb_noun or verb structure (list_apps, launch, terminate, press_button, open_url). No mixed casing or divergent verb styles; the pattern is uniform across all 25 tools.

Tool Count4/5

At 25 tools it sits at the heavy end, but the domain genuinely spans device lifecycle, app lifecycle, UI interaction, log reading, media, push, and WDA management, so the count is earned rather than padded. Each tool maps to a real capability with no redundancy.

Completeness4/5

Coverage is broad and lifecycle-complete for simulators, apps, UI input, logs, media, and push. Minor gaps remain around input gestures (no long-press, pinch, or rotation/orientation control), which agents can partially work around but would notice.

Maintenance

ActivityMaintained
ResponsivenessNo issues