iOS Sim MCP
Drive the iOS Simulator via semantic accessibility-tree snapshots.
Connector by rmathew1973 · GitHub account verified by the MCP Registry
Install
Works with Claude Code, Codex, VS Code, Cursor, Windsurf, Claude Desktop. Read the repository before you give any tool access to your data.
npx agentmarket install connector/rmathew1973-ios-sim-mcp
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this server can do and what it asks for, from its tool list and install config. Checked Oct 25, 2026.
- Tools
- 17 read · 16 write · 8 delete · 5 not yet classified
- Secrets
- None asked for
- Install scripts
- Not scanned yet
- Runs as
- Node.js package
Tools by what they do 46
Read from the source code; the running server may list different tools.
Read 17 · Look things up without changing anything.
dylib_healthdylib_infodylib_pingfindlist_simulatorslog_tailnetwork_get_bodynetwork_statusnetwork_stubsnetwork_tailscreenshotsnapshot
Show 5 more tools
view_get_textview_hit_testview_treewebview_findwebview_list
Write 16 · Create, change, send or run things.
buttondylib_callkeylog_startlog_stopnetwork_startnetwork_stopnetwork_stubpaste_textscrollswipetap
Show 4 more tools
type_textuse_simulatorwebview_clickwebview_fill
Delete 8 · Delete, drop, revoke or wipe things.
eval_jseval_js_resetlog_clearnetwork_clearnetwork_unstubnetwork_unstub_allterminate_appwebview_eval_js
Not yet classified 5 · We could not tell from the name and description.
await_quiescentlaunch_appnetwork_self_testopen_urlview_set_text
Files it touches
- Any path the agent passes to its tools
Tools (46)
Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].
await_quiescentBlock until the accessibility tree stops changing (UI settles). Returns when the tree hash is identical for 'stable_ms' (default 250) consecutive ms, or 'timeout_ms' elapses (default 5000). Use after launch_app, navigation, or async loads instead of sleep.
buttonPress a hardware button: HOME, LOCK, SIDE_BUTTON, SIRI, APPLE_PAY.
dylib_callGeneric escape hatch: invoke an arbitrary method on the Layer 2 dylib. Use dylib_info first to see available methods. Passes 'params' through verbatim. Future phases (2c view_tree, 2d network_*, 2e eval_js) add methods this can reach.
dylib_healthLightweight liveness probe for the Layer 2 dylib. Returns {available, ...stats} when reachable, {available: false, reason} when not. Does NOT throw — safe to call as a feature-detection precheck before reaching for dylib-only tools. Stats include: bundle_id, pid, uptime_s, phase, whether network capture is running, record/stub counts, JS context status, method count.
dylib_infoAsk the Layer 2 dylib to describe its host process: pid, bundle id, process name, bundle path, uptime, and the list of RPC methods it exposes.
dylib_pingRound-trip a ping to the Layer 2 dylib inside an injected app. Returns the response plus measured RTT in ms. Use this first to verify the dylib is loaded and reachable.
eval_jsRun arbitrary JavaScript inside the injected app via JavaScriptCore. Bridged globals: `app` (UIApplication), `key_window()`, `all_windows()`, `defaults` (NSUserDefaults), `pasteboard` (UIPasteboard), `bundle`, `process`, `notif_center`, `first_responder()`, `find_view_by_ax_id(id)`, `find_view_by_class(name)`, `find_vc_by_class(name)`, `post_notification(name, userInfo?)`, `cls(name)` (NSClassFromString), `log(msg)`. JS state PERSISTS across calls — define functions/vars in one call, use them in the next. eval_js_reset throws the context away. For ObjC-bridged return values you get {class, des…
eval_js_resetDrop the persistent JSContext inside the injected app. Variables and helper functions you defined via eval_js are forgotten; bridged globals are reinstalled on the next eval_js call.
findSearch the most recent snapshot for elements. Combine fields with AND. 'id' matches AXUniqueId exactly. 'label' is exact match; 'labelContains' is case-insensitive substring across label/value/title. 'role' accepts 'Button', 'TextField' etc (with or without AX prefix). Auto-snapshots if none cached.
keyPress a single key. Pass either {name} (RETURN, ESCAPE, DELETE, TAB, SPACE, F1-F12, UP/DOWN/LEFT/RIGHT) or {code} (raw HID usage code).
launch_appLaunch an app by bundle id (com.example.App). 'foreground_if_running' terminates first. 'inject' loads the Layer 2 dylib (default path: dylib/build/libios-sim-mcp.dylib relative to the server) via SIMCTL_CHILD_DYLD_INSERT_LIBRARIES — currently just emits a lifecycle log line; future phases add a Unix socket. 'inject_dylib' overrides the dylib path. Inject requires the dylib to be built (run dylib/build.sh).
list_simulatorsList iOS simulators (booted and shutdown). Returns udid, name, state, os_version.
log_clearClear the in-memory log buffer.
log_startStart streaming os_log from the simulator into an in-memory buffer (5000 lines max). Optional bundle_id filters by subsystem substring. Level: default|info|debug.
log_stopStop the log stream subprocess. Buffer is preserved until log_clear or log_start.
Show 31 more tools
log_tailReturn the last N lines from the log buffer (default 100). Requires log_start first.
network_clearDrop all captured records and their bodies. Does not change running state.
network_get_bodyFetch the full request or response body for a captured record. Bodies up to max_body_bytes (default 256KB) are retained per record; larger bodies were truncated at capture time and the response will mark truncated=true. Returns base64 plus a UTF-8 decode when the body is text.
network_self_testFire a real HTTP request from inside the injected app to validate the capture path end-to-end. Useful when the host app makes no network calls of its own during a smoke test. Requires network_start first.
network_startStart capturing HTTP traffic from the injected app's URLSession-based code. Installs an URLProtocol subclass + swizzles +defaultSessionConfiguration / +ephemeralSessionConfiguration so requests made via Alamofire, URLRequest, SwiftUI AsyncImage, or any URLSession-based client are recorded into an in-process ring buffer. Existing URLSessions constructed before start are NOT retro-fitted. Requires dylib injected.
network_statusReport whether capture is running, how many records are held, and current config (max_records, max_body_bytes, filter).
network_stopStop capturing HTTP traffic. The ring buffer is preserved until network_clear; you can keep calling network_tail on captured records after stopping.
network_stubRegister an HTTP stub. When an outgoing request's URL contains `url_substring` (and matches `method` if given), the dylib synthesizes a canned response (status, headers, body) instead of forwarding. Stubbed requests still appear in network_tail with `stubbed:true` and `stub_id`. First-match-wins by insertion order. `body` is a UTF-8 string; pass `body_base64` for binary. `delay_ms` simulates slow networks (response is held back that long before client sees it). Persists until network_unstub / network_unstub_all.
network_stubsList currently registered HTTP stubs (id, url_substring, method filter, status, body preview, delay, when added). Raw body bytes are not returned — call network_get_body on a captured record if you need the actual body delivered.
network_tailReturn the most recent N captured records (default 50). Each record shows id, method, status, timing, sizes, URL. Pass full=true to include headers + body previews inline; otherwise call network_get_body({id}) to fetch a specific full body. Use since_id to page forward from a previous tail.
network_unstubRemove a single HTTP stub by id (as returned from network_stub / network_stubs).
network_unstub_allRemove all HTTP stubs.
open_urlDeliver a URL to the simulator via `xcrun simctl openurl`. Routes through the host OS's URL dispatcher, so http(s) URLs open in Safari and custom-scheme URLs (e.g. myapp://oauth/callback?code=...) are delivered to the registered app's URL handler. Primary use: short-circuit an out-of-process auth flow (ASWebAuthenticationSession / SFSafariViewController) by handing the OAuth callback URL directly to the app, then stub the token-endpoint response with network_stub. Also useful for deep-link testing.
paste_textByte-perfect text input via UIPasteboard + first-responder paste:. Requires the Layer 2 dylib injected and a text field already focused (call tap first). No iOS autocorrect, no capitalization, no smart-quote replacement — what you pass is exactly what the field receives. Use for emails, passwords, OAuth tokens, anything case-sensitive.
screenshotCapture a screenshot. If 'path' is provided, saves PNG and returns the path. Otherwise saves to a temp file and returns both the path and the image inline. Use sparingly — the AX tree is faster and richer for control flow.
scrollScroll a scrollable view. Direction is reader-perspective: 'down' reveals content below (finger drags up); 'up' reveals content above. Optional 'ref' or 'id' to anchor the gesture on a specific scrollable; otherwise uses screen center. 'distance' px (default 300). Default 0.4s duration ensures iOS treats it as a pan, not a tap.
snapshotCapture the simulator's accessibility tree and return it with stable refs (e1, e2, ...). Subsequent tap/type/swipe accept refs. Default filter 'interactive' hides decorative containers; use 'all' for everything, 'actionable' for only tappable controls. Always call this before acting on UI.
swipeSwipe from one point to another. Pass from_ref/from_id or from_x+from_y AND to_ref/to_id or to_x+to_y. Optional duration (seconds) and delta (px step).
tapTap an element. Pass one of: {ref} from latest snapshot, {id} for AXUniqueId, or {x,y} for raw coordinates. Optional 'duration' (seconds) makes it a long-press.
terminate_appTerminate an app by bundle id.
type_textType text into the focused field. Pass ref/id to tap a field first. Newlines/tabs aren't interpreted — use the key tool for RETURN/TAB. via='paste' (default 'auto') routes through the Layer 2 dylib's UIPasteboard so input arrives byte-perfect: no iOS autocorrect, no first-letter capitalization, no shifted-symbol translation — critical for emails, passwords, anything case-sensitive. 'auto' uses paste when the bundle has a connected dylib client, otherwise falls back to keystrokes. 'keystroke' forces idb's text command (typing-like, triggers autocorrect).
use_simulatorSelect a specific simulator by UDID for subsequent calls. If only one is booted, auto-selection happens on first action — you only need this when multiple are booted.
view_get_textLook up a view by AXUniqueId or class name and return its text content (UILabel.text / UIButton.currentTitle / UITextField.text / UITextView.text), plus accessibility label/value as fallback context. Faster than view_tree when you just need 'what does this control say right now?'. Requires the dylib injected.
view_hit_testAsk the running app what view sits topmost at (x,y) in window coords, plus the full responder chain up to UIApplication. The right tool for 'tap at (201,406) isn't doing what I expect' — you see exactly which view receives the hit, whether it's userInteractionEnabled, and what view controllers are in the chain. Requires the dylib injected.
view_set_textSet the text on a UILabel / UITextField / UITextView / any view that responds to setText:. Bypasses focus + keyboard entirely. Use to seed test data directly into a non-focused field, or to programmatically change a label's text mid-test. Requires the dylib injected.
view_treeWalk the running app's UIView hierarchy on the main thread and return a compact text rendering. Strictly richer than snapshot: catches custom-drawn views, transient overlays, things SwiftUI synthesizes that AX flattens; reports actual class names (UIButton vs _UIRoundedRectButton), exact frames in window coords, alpha/hidden/userInteractionEnabled, and annotates which views are a UIViewController's root. Requires the dylib injected (launch_app({inject: true})). Filter the output via class_filter / ax_id_contains / text_contains to scope down before the model has to read it.
webview_clickClick an element inside a WKWebView. Calls element.click() when available, otherwise dispatches a synthesized MouseEvent. selector is a CSS selector. Returns {ok, tag, id, text, rect}. Requires the dylib injected.
webview_eval_jsRun JavaScript in a WKWebView via -[WKWebView evaluateJavaScript:completionHandler:]. The JS runs in the page context — has full DOM access (document, window, etc.) and CAN'T see ObjC bridges. Returns {ok, kind, value} for JSON-able results, or {ok:false, exception} on JS error. Pick the web view by index (from webview_list) or ax_id; defaults to the first visible one. Requires the dylib injected.
webview_fillFill a form field inside a WKWebView. Uses the React/Angular-safe pattern: sets the input value via HTMLInputElement.prototype's native setter (bypasses React's synthetic value tracker), then dispatches input + change events. selector is a CSS selector (e.g. 'input[name=email]', '#password'). Returns {ok, tag, name, id, value} so you can confirm the right field was hit. Requires the dylib injected and a WKWebView present (see webview_list).
webview_findquerySelectorAll inside a WKWebView. Returns matching elements with tag, id, name, type, inner text/value, bounding rect, and visibility. Useful for sanity-checking 'is the email field actually rendered?' before webview_fill, or for enumerating multiple matches. Requires the dylib injected.
webview_listEnumerate WKWebView instances currently in the host app's view hierarchy. Returns an array of {index, ax_id, class, url, title, frame, hidden}. Use this to confirm a web view is present and pick one by index/ax_id for webview_eval_js etc. Note: does NOT see SFSafariViewController / ASWebAuthenticationSession (those run in a separate system process and are unreachable). Requires the dylib injected.
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 0
- Last commit
- Aug 3, 2026 (2 months ago)
- Last release
- May 18, 2026 (5 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- Registry name
io.github.rmathew1973/ios-sim-mcp- Version
- 0.4.2
- Auth
- No auth
- Packages
- npm ios-sim-mcp
- License
- MIT
- Repository
- github.com/rmathew1973/ios-sim-mcp
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
Cite this page
iOS Sim MCP. Agent Mart. https://agentmart.dev/connectors/rmathew1973-ios-sim-mcp (last updated 2026-10-24)