Skip to content
Agentmart
Submit a tool

iOS Sim MCP

Drive the iOS Simulator via semantic accessibility-tree snapshots.

Connector by rmathew1973 · GitHub account verified by the MCP Registry

IndexedMITLocal (stdio)
Write a review

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.

We use your email only for this newsletter. Privacy

About

Drive the iOS Simulator via semantic accessibility-tree snapshots. Sub-200ms, no WebDriverAgent.

No 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_health
  • dylib_info
  • dylib_ping
  • find
  • list_simulators
  • log_tail
  • network_get_body
  • network_status
  • network_stubs
  • network_tail
  • screenshot
  • snapshot
Show 5 more tools
  • view_get_text
  • view_hit_test
  • view_tree
  • webview_find
  • webview_list

Write 16 · Create, change, send or run things.

  • button
  • dylib_call
  • key
  • log_start
  • log_stop
  • network_start
  • network_stop
  • network_stub
  • paste_text
  • scroll
  • swipe
  • tap
Show 4 more tools
  • type_text
  • use_simulator
  • webview_click
  • webview_fill

Delete 8 · Delete, drop, revoke or wipe things.

  • eval_js
  • eval_js_reset
  • log_clear
  • network_clear
  • network_unstub
  • network_unstub_all
  • terminate_app
  • webview_eval_js

Not yet classified 5 · We could not tell from the name and description.

  • await_quiescent
  • launch_app
  • network_self_test
  • open_url
  • view_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_quiescent

    Block 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.

  • button

    Press a hardware button: HOME, LOCK, SIDE_BUTTON, SIRI, APPLE_PAY.

  • dylib_call

    Generic 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_health

    Lightweight 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_info

    Ask 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_ping

    Round-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_js

    Run 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_reset

    Drop 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.

  • find

    Search 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.

  • key

    Press a single key. Pass either {name} (RETURN, ESCAPE, DELETE, TAB, SPACE, F1-F12, UP/DOWN/LEFT/RIGHT) or {code} (raw HID usage code).

  • launch_app

    Launch 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_simulators

    List iOS simulators (booted and shutdown). Returns udid, name, state, os_version.

  • log_clear

    Clear the in-memory log buffer.

  • log_start

    Start 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_stop

    Stop the log stream subprocess. Buffer is preserved until log_clear or log_start.

Show 31 more tools
  • log_tail

    Return the last N lines from the log buffer (default 100). Requires log_start first.

  • network_clear

    Drop all captured records and their bodies. Does not change running state.

  • network_get_body

    Fetch 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_test

    Fire 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_start

    Start 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_status

    Report whether capture is running, how many records are held, and current config (max_records, max_body_bytes, filter).

  • network_stop

    Stop capturing HTTP traffic. The ring buffer is preserved until network_clear; you can keep calling network_tail on captured records after stopping.

  • network_stub

    Register 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_stubs

    List 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_tail

    Return 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_unstub

    Remove a single HTTP stub by id (as returned from network_stub / network_stubs).

  • network_unstub_all

    Remove all HTTP stubs.

  • open_url

    Deliver 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_text

    Byte-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.

  • screenshot

    Capture 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.

  • scroll

    Scroll 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.

  • snapshot

    Capture 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.

  • swipe

    Swipe 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).

  • tap

    Tap 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_app

    Terminate an app by bundle id.

  • type_text

    Type 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_simulator

    Select 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_text

    Look 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_test

    Ask 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_text

    Set 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_tree

    Walk 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_click

    Click 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_js

    Run 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_fill

    Fill 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_find

    querySelectorAll 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_list

    Enumerate 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
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)