Skip to content

Cursor and the iOS simulator: MCP setup

Add Mobster to Cursor with one button in Mobster for Mac, or in mcp.json by hand, then let Cursor's agent check your iOS app's screens on a simulator.

In Mobster for Mac

Settings › Connectors › Add, next to Cursor. Then restart Cursor.

Or by hand

Add the mobster block below to ~/.cursor/mcp.json, or .cursor/mcp.json in a project.

What Cursor gets back from mobster verify on your app: the lesson and its “Great job!” pass, but the streak stays at 3, so the check fails.

Cursor’s agent can write a SwiftUI screen, and then someone has to open the simulator and look at it. With Mobster’s MCP server in Cursor, the agent does that part: it states what the screen must show, drives your app on a headless simulator Mobster manages, and gets a verdict of passed or failed from assertions on the accessibility tree. It can also use a real iPhone on your Mac’s USB.

You need an Apple silicon Mac with macOS 15 or later and Xcode with an iOS Simulator runtime. A real iPhone also needs Developer Mode and the WebDriverAgent runner, set up in Mobster for Mac (Device setup).

Install Mobster for Mac

Get Mobster for Mac, drag it to Applications and open it. Its MCP server is the agent inside the app, so the command every client starts is this path, with mcp:

/Applications/Mobster.app/Contents/MacOS/mobster-agent

The first check creates Mobster’s own simulator, boots it headless and builds WebDriverAgent, once per Xcode version. Mobster never touches your own simulators: each one it creates has a name that starts with “Mobster”.

Add the server

In Mobster for Mac, open Settings › Connectors › Use Mobster from… and press Add next to Cursor. It writes the mobster entry for you in ~/.cursor/mcp.json, and when the app holds your model key it passes the app’s settings file with --env-file, so Smart uses the same key.

By hand: Cursor reads .cursor/mcp.json in a project and ~/.cursor/mcp.json for every project. Put this in one of them:

{  "mcpServers": {    "mobster": {      "type": "stdio",      "command": "/Applications/Mobster.app/Contents/MacOS/mobster-agent",      "args": ["mcp"]    }  }}

Two details matter. Cursor’s docs say command must be on the system path or a full path, and as a GUI app Cursor may not see the PATH your shell sets up, so the full path is the safe choice. Cursor’s field table also lists "type": "stdio" as required while its examples leave it out; the block above includes it, which works either way. Save the file and restart Cursor.

For Smart, where Mobster runs the steps itself on your OpenAI or Anthropic key, add your env file to args: ["mcp", "--env-file", "~/.config/mobster/agent.env"]. Mobster expands the ~ itself. Key-less checks need no key.

Cursor’s docs don’t state a tool-call timeout. Mobster doesn’t depend on a long one: every call returns within 45 seconds and wait within 50, and longer work, such as the first simulator boot, continues under a run_id that the agent polls with wait.

Check it’s connected

Open Customize, then MCPs: mobster should be there, switched on, with its tools listed. If it isn’t, the Output panel (Cmd+Shift+U) has a channel named MCP Logs with the server’s start-up errors. Then ask the agent:

Call mobster's status tool and tell me what it reports.

A first check: onboarding

Say your app opens with a short onboarding that asks for notification permission. A prompt for Cursor’s agent:

Build my app for the simulator, then verify that a new user can completeonboarding without allowing notifications and lands on the first lesson.

The agent calls verify_start with the absolute app_path, the steps and the expectations, then taps through. A real key-less session on a sample app’s onboarding, from Mobster’s own smoke script on 28 Sep 2026 with the app renamed YourApp, with each call, how long it took and the first line it returned:

verify_start   3.94 s  Run 20260928-151841-816e is ready. Drive the app with the refs below, then call verify_finish.tap            1.86 s  Tapped “Continue”; the screen changed.tap            2.13 s  Tapped “Continue”; the screen changed.tap            1.89 s  Tapped “Turn on reminders”; the screen didn't change.screen         0.46 s  Screen  com.example.yourapp  402×874 pt  keyboard: none  alert: "“YourApp” Would Like to Send You Notifications …"alert          2.13 s  Dismissed the alert "“YourApp” Would Like to Send You Notifications …".tap            4.13 s  Tapped “Get started”; the screen changed.wait_for       4.50 s  All 1 hold (4.5 s).verify_finish  3.07 s  Verdict: passed  Complete onboarding. Don't allow notifications.  (24.1 s)

The simulator was already up. Note the fourth line: the tap didn’t change the screen because the system alert came up, and alert answered it. verify_finish returns the verdict, the report path and the overlay frame. On failed, the agent fixes the code, rebuilds and verifies again.

Add a project rule

Cursor applies project rules from .cursor/rules, as .mdc files with front matter. With a description and alwaysApply: false, the agent reads the description and pulls the rule in when it’s relevant:

---description: How to verify a change to this iOS app's screens with Mobster before saying it worksalwaysApply: false---After you change a screen in this iOS app, verify it before you say it works.1. Build for the simulator:   xcodebuild -scheme <Scheme> -destination 'generic/platform=iOS Simulator' -derivedDataPath .mobster/build CODE_SIGNING_ALLOWED=NO build2. Call mobster's verify_start with the absolute app_path of   .mobster/build/Build/Products/Debug-iphonesimulator/<App>.app, the steps, and expect.3. Drive with screen, tap, type_text and swipe, then call verify_finish.4. If the verdict is failed, fix the code and verify again. Report the verdict and the report path.

Save it as .cursor/rules/mobster.mdc. A plain .md file there is ignored. If you prefer plain Markdown, Cursor also reads an AGENTS.md at the project root.

Use a real iPhone

The agent calls list_devices, then passes a USB iPhone’s name as device to screen, tap, type_text, swipe, alert, open_url, launch_app and home, with no run_id. Mobster takes the phone’s lock for the session, and stop with the device, or 90 idle seconds, gives it back.

Cursor asks for approval before MCP tools by default. Your approval covers a tool, not a device, so allowing tap while you test on a simulator allows it on your phone as well. Limit the server to the phones you mean:

"args": ["mcp", "--allow-device", "Test iPhone"]

To skip the prompt for reads only, list Mobster’s read-only tools in mcpAllowlist in ~/.cursor/permissions.json or the workspace’s .cursor/permissions.json, as server:tool entries such as "mobster:screen", "mobster:status" and "mobster:list_devices". Avoid "mobster:*", which also allows tap and type_text without asking. Mobster’s MCP annotations mark which tools only read, and its instructions tell the agent to ask before anything that sends, buys, posts or deletes on a real iPhone. A locked phone stops the call at once, and Mobster never enters a passcode.

Troubleshooting

SymptomFix
mobster doesn’t start, or shows an error in MCP LogsUse the full path /Applications/Mobster.app/Contents/MacOS/mobster-agent in command, check that Mobster is in Applications, then restart Cursor
The server is listed, but every call asks for approvalThat is Cursor’s default. Add the read-only tools to mcpAllowlist
The first verify_start returns status: "preparing"The simulator is booting and WebDriverAgent is building. The agent calls wait
couldnt_run, or no verify toolreason.fix in the result says what to do. status says why Smart is off

The MCP reference lists every tool. AI end-to-end tests for iOS explains how the verdict is decided.

Questions

  • Why does Cursor fail to start the Mobster server?

    Cursor is a GUI app and may not see your shell's PATH. Cursor's docs say the command must be on the system path or a full path, so put the full path /Applications/Mobster.app/Contents/MacOS/mobster-agent in the command field and restart Cursor.

  • Should the Cursor config include "type": "stdio"?

    Yes. Cursor's field table marks type as required for a local server while its examples leave it out. Including it works under both readings.

  • Can Cursor run Mobster's read-only tools without asking?

    Yes. Add entries such as mobster:screen and mobster:status to mcpAllowlist in Cursor's permissions.json. Keep the acting tools, like tap and type_text, out of the list so Cursor still asks before them.

  • How do I connect Cursor to the iOS Simulator?

    Add Mobster's MCP server to ~/.cursor/mcp.json, or press Add next to Cursor in Mobster for Mac's Settings › Connectors, then restart Cursor. Its agent can then run your app on a headless simulator Mobster manages, read each screen by element name, tap and type, and get passed or failed from assertions.

Sources

We read each of these on 8 October 2026. Reviewed by Andy Guo on . Corrections are welcome at the GitHub repo.

Cursor’s logo is a trademark of Anysphere, shown only to name the product. Mobster isn’t affiliated with or endorsed by Anysphere.