Codex and the iOS simulator: MCP setup
Connect Mobster to OpenAI's Codex with codex mcp add, give it an AGENTS.md rule, and let it check your iOS app on a simulator with verdicts from assertions.
The short version
Install Mobster CLI, then run:
codex mcp add mobster -- mobster mcpConfig file: ~/.codex/config.toml
From the docs. This setup follows OpenAI's MCP documentation, read on 8 October 2026. Mobster's MCP server is tested with Claude Code; we haven't run it in Codex ourselves yet. OpenAI’s MCP docs.
Codex can build an iOS app from the terminal, but it can’t look at the result. mobster mcp gives it a headless iOS simulator and a verdict: Codex states what must be true, drives the app through Mobster’s tools, and gets passed or failed from assertions on the accessibility tree, with frames and a report. The same server can drive a real iPhone over 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 or with mobster serve --manage-device (Device setup).
Install Mobster CLI
curl -fsSL https://mobster.dev/install.sh | shor
brew install radishsoftware/tap/mobsterThen check it and prepare the simulator once, so Codex’s first check doesn’t wait for a simulator boot and a WebDriverAgent build:
mobster version
which mobster
mobster sim doctor --fixAdd the server
codex mcp add mobster -- mobster mcpThat writes a block to ~/.codex/config.toml, which the Codex CLI, the IDE extension and the ChatGPT desktop app share. You can write the block yourself instead:
[mcp_servers.mobster]command = "mobster"args = ["mcp"]A trusted project can carry its own .codex/config.toml with the same block, so everyone on the project gets the server.
Timeouts: Codex gives each tool call 60 seconds by default (tool_timeout_sec) and each server 10 seconds to start (startup_timeout_sec). Every Mobster call returns within 45 seconds and wait within 50, so the defaults hold. Work that takes longer, such as the first simulator boot or a Smart run, continues under a run_id that Codex polls with wait. For more margin:
[mcp_servers.mobster]command = "mobster"args = ["mcp"]tool_timeout_sec = 120Key-less checks need no key: Codex drives with its own model, and Mobster judges. For Smart, where Mobster runs the steps itself on your OpenAI or Anthropic key, add your env file to the arguments. Mobster expands the ~ itself:
args = ["mcp", "--env-file", "~/.config/mobster/agent.env"]Check it’s connected
In the codex TUI, /mcp lists your active MCP servers and their tools. From the shell, codex mcp list shows the same. Then ask:
Call mobster's status tool and summarize it.status names Mobster’s version, the simulator setup, whether Smart is on (and why not, when it’s off) and where runs go.
A first check: a setting that survives a relaunch
Daybreak, the sample app in the CLI’s repository, has a Daily reminder switch in Settings. A good first prompt for Codex:
Verify that turning on Daily reminder in Daybreak's Settings survives a relaunch.Codex builds Daybreak for the simulator, then makes these calls. They are the key-less form of Daybreak’s reminder.yaml check:
{"tool": "verify_start", "arguments": { "app_path": "/abs/path/examples/ios/Daybreak/.build/Build/Products/Debug-iphonesimulator/Daybreak.app", "launch_args": ["-DaybreakSkipOnboarding", "YES"], "open_url": "daybreak://settings", "steps": ["Turn on Daily reminder.", "Relaunch the app and open Settings again."], "expect": [{"value": {"id": "daily_reminder"}, "equals": true}]}}{"tool": "tap", "arguments": {"run_id": "…", "target": {"id": "daily_reminder"}}}{"tool": "relaunch", "arguments": {"run_id": "…"}}{"tool": "open_url", "arguments": {"run_id": "…", "url": "daybreak://settings"}}{"tool": "verify_finish", "arguments": {"run_id": "…"}}It passes. Launched with -DaybreakBug reminder-not-saved as well, the switch is off again after the relaunch, and verify_finish fails with value id=daily_reminder == true failed: was off. That is the bug a screenshot glance misses and an assertion catches. verify_finish also returns the path to the run’s one-file HTML report and the overlay frame.
app_path must be absolute. Clients start servers in different folders, so Mobster refuses a relative path. Test your iOS app with Codex covers the loop, saving checks and rerunning them in scripts.
Put the rule in AGENTS.md
Codex reads AGENTS.md. Add the rule with your scheme and app names:
## Verifying UI changesAfter 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 app_path set to the absolute path of .mobster/build/Build/Products/Debug-iphonesimulator/<App>.app, the steps in plain English, and expect: what must be true when the steps are done.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.Use a real iPhone
list_devices names every device Mobster can use: USB iPhones set up for it, Mobster’s simulators and WebDriverAgent addresses. Called with device and no run_id, the phone tools drive that device directly, outside a check. Mobster takes the device’s lock, and stop with the device, or 90 idle seconds, releases it for the Mac app and other commands.
Codex approves a tool, not a device: allowing tap on a simulator allows it on your phone. Keep the server to the phones you choose:
[mcp_servers.mobster]command = "mobster"args = ["mcp", "--allow-device", "Test iPhone"]Any other real device is listed as not_allowed and refused. Simulators are always allowed.
Codex’s default_tools_approval_mode decides when it asks. With writes, it prompts for every tool that isn’t marked read-only. Mobster marks status, screen, list_devices, wait, wait_for, read_notifications and unlock_status as read-only in its MCP annotations, so Codex reads the screen freely and asks before tap, type_text, swipe and the rest. The server’s instructions also tell Codex to ask you before anything that sends, buys, posts or deletes on a real iPhone. A locked phone fails the call at once with “Your iPhone is locked. Unlock it and try again. No action was taken.”
Troubleshooting
| Symptom | Fix |
|---|---|
/mcp doesn’t show mobster | Check the block in ~/.codex/config.toml. A project’s .codex/config.toml loads only in a trusted project |
| Codex says the server didn’t start in time | startup_timeout_sec defaults to 10 seconds. Raise it in the block, for example to 30 |
The first verify_start returns status: "preparing" | The simulator is booting and WebDriverAgent is building. Codex calls wait. mobster sim doctor --fix does this ahead of time |
No verify tool | Smart is off. status says why: no key, a missing env file, or --keyless |
couldnt_run | Read reason.class and reason.fix in the result. Checks lists every class |
The MCP reference has every tool, and Checks the assertion language.
Questions
Is Codex's default tool timeout long enough for Mobster?
Yes. Codex allows 60 seconds per tool call by default, and every Mobster call returns within 45 seconds, wait within 50. Longer work continues under a run_id that Codex polls with wait. Set tool_timeout_sec = 120 if you want more margin.
Where does Codex keep the Mobster server config?
In ~/.codex/config.toml by default, which the Codex CLI, the IDE extension and the ChatGPT desktop app share. A trusted project can also have its own .codex/config.toml.
Can Codex skip approval for Mobster's read-only tools?
Yes. With default_tools_approval_mode set to writes, Codex prompts only for tools that aren't marked read-only. Mobster marks status, screen, list_devices, wait and its other read tools as read-only, so Codex asks before a tap and not before a screen read.
Does Codex have an iOS simulator?
Not one it can see on its own. Codex can build and launch your app with xcodebuild from its terminal, but reading and tapping the running app takes an MCP server. Mobster's gives Codex a headless simulator, each screen as a list of controls by name, and 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.
Codex’s logo is a trademark of OpenAI, shown only to name the product. Mobster isn’t affiliated with or endorsed by OpenAI.