---
title: "Codex and the iOS simulator: MCP setup | Mobster"
description: "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."
canonical: "https://mobster.dev/integrations/codex"
last-updated: "2026-10-08"
---

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.

# 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 mcp
```

Config 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](https://learn.chatgpt.com/docs/extend/mcp).

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](https://docs.mobster.dev/device-setup)).

## Install Mobster CLI

```
curl -fsSL https://mobster.dev/install.sh | sh
```

or

```
brew install radishsoftware/tap/mobster
```

Then 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 --fix
```

## Add the server

```
codex mcp add mobster -- mobster mcp
```

That 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 = 120
```

Key-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](https://mobster.dev/blog/test-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](https://docs.mobster.dev/checks) lists every class |

The [MCP reference](https://docs.mobster.dev/mcp-server) has every tool, and [Checks](https://docs.mobster.dev/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 8 October 2026. Corrections are welcome at the [GitHub repo](https://github.com/RadishSoftware/mobster/issues).

- [Codex docs: Model Context Protocol](https://learn.chatgpt.com/docs/extend/mcp)
- [Codex docs: AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md)
- [MCP specification: ToolAnnotations (readOnlyHint)](https://modelcontextprotocol.io/specification/2025-11-25/schema)
- [Apple: enabling Developer Mode on a device](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device)
- [Mobster docs: MCP server](https://docs.mobster.dev/mcp-server)
- [Mobster docs: checks](https://docs.mobster.dev/checks)
- [Mobster docs: device setup](https://docs.mobster.dev/device-setup)

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

## Read next

- [Every MCP tool, in the reference](https://docs.mobster.dev/mcp-server)
- [Getting started with verify](https://docs.mobster.dev/verify)
- [Test your iOS app with Codex](https://mobster.dev/blog/test-ios-app-with-codex)

## Other agents

- [Claude Code](https://mobster.dev/integrations/claude-code)
- [Cursor](https://mobster.dev/integrations/cursor)
- [VS Code](https://mobster.dev/integrations/vs-code)
- [Claude Desktop](https://mobster.dev/integrations/claude-desktop)
- [Gemini CLI](https://mobster.dev/integrations/gemini-cli)
- [opencode](https://mobster.dev/integrations/opencode)
- [Windsurf (Devin Desktop)](https://mobster.dev/integrations/windsurf)
