Navigate to a URL in real Safari on iOS Simulator.
- Input:
{ url: string, waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' } - Output:
{ url, status, loadTime }
Capture real Safari screen via WebKit Protocol.
- Input:
{ format?: 'png', fullPage?: boolean } - Output: Base64 encoded image
Execute JavaScript in page context via Runtime.evaluate.
- Input:
{ expression: string } - Output: Evaluation result
Extract visible text content from the page.
- Input:
{} - Output: Page text
Tap element by CSS selector or coordinates.
- Input:
{ selector?: string, x?: number, y?: number }
Type text into input field.
- Input:
{ selector: string, text: string, delay?: number }
Scroll page in direction.
- Input:
{ direction: 'up'|'down'|'left'|'right', amount: number }
Query DOM element with details.
- Input:
{ selector: string } - Output:
{ tag, text, attributes, boundingBox, computedStyles, isVisible }
Get/set/clear Safari cookies (WebKit Page domain).
- Input:
{ action: 'get'|'set'|'clear', cookies?: Cookie[], domain?: string }
Boot a simulator device.
- Input:
{ device: string }(preset key like 'iphone-17')
Shutdown a simulator.
- Input:
{ deviceId?: string }
Launch an app by bundle identifier on a booted iOS Simulator.
- Input:
{ bundleId: string, deviceId?: string, args?: string[], env?: Record<string, string> } - Output:
{ pid, bundleId, deviceId } - Errors:
APP_NOT_INSTALLEDif bundle ID not found,DEVICE_NOT_BOOTEDif no booted simulator
Terminate a running app by bundle identifier.
- Input:
{ bundleId: string, deviceId?: string } - Output:
{ terminated: boolean, bundleId, deviceId } - Errors:
APP_NOT_INSTALLEDif bundle ID not found
Bring an app to the foreground. Launches the app if not already running.
- Input:
{ bundleId: string, deviceId?: string } - Output:
{ activated: boolean, bundleId, deviceId }
List running foreground apps (UIKit) with bundle IDs and PIDs.
- Input:
{ deviceId?: string } - Output:
{ deviceId, apps: [{ label, pid }], count }
Reset app state: terminate, reset privacy permissions, uninstall. The app must be reinstalled after reset.
- Input:
{ bundleId: string, deviceId?: string } - Output:
{ reset: boolean, bundleId, deviceId, steps: string[] } - Steps:
terminated→privacy_reset→uninstalled(each step proceeds independently)
Detect WebView targets inside a running native iOS app and list available ones. Classifies each target as safari vs webview and surfaces a classificationReason for debuggability. Uses ios-webkit-debug-proxy to enumerate all open debugging targets on the device.
- Input:
bundleId?: string— Optional. When provided, targets whose proxy-supplied metadata (appId,bundleId, orapp_idfields) matches the value, or whosetitle/urlcontains it as a substring, are promoted towebviewvia thebundle_matchrule. The result list is then restricted to those bundle-matched WebViews.deviceId?: string— Optional simulator UDID. Defaults to the active device when omitted.
- Output:
{ "deviceId": "string", "targets": [ { "id": "string", "title": "string", "url": "string", "type": "safari | webview", "classificationReason": "bundle_match | proxy_type | url_scheme" } ], "count": "number" } - Classification priority (first match wins):
bundle_match—bundleIdargument matches the target's proxy metadata or appears as a substring in thetitle/url. Classifies the target aswebview. HTTPS WebViews such as payment-return pages or OAuth callbacks are promoted via this rule whenbundleIdis supplied.proxy_type— proxy emits atypefield:safari/mobilesafari→safari; any value containingwebview→webview.url_scheme(fallback) — empty URL orabout:blank→safari; non-http(s)scheme →webview;http(s)→safari.
- Notes:
webSocketDebuggerUrlis intentionally stripped from the response. Useset_active_contextwith the returnedidto switch into a WebView target.- See also:
set_active_context.
Accept, dismiss, or press a named button on a system alert/dialog on a booted iOS Simulator.
- Input:
action?: 'accept' | 'dismiss'— Accept (Return key) or dismiss (Escape key) the alert. Used only when nobuttonLabel/buttonLabelsis provided.buttonLabel?: string— Exact button label to press (case-insensitive, trimmed). Walks the front-most alert's accessibility tree and invokesAXPresson the first match. Takes precedence overaction.buttonLabels?: string[]— Ordered list of candidate labels tried in priority order; the first match is pressed. Takes precedence overbuttonLabelandaction. Useful for multi-locale support.deviceId?: string— Simulator UDID. Falls back to the active device if omitted.
- Output:
{ handled: true, buttonLabel?, action?, deviceId, method, _meta } - Errors:
DEVICE_NOT_BOOTED— No booted simulator found.MISSING_PARAMS— NeitheractionnorbuttonLabel/buttonLabelsprovided.INVALID_ACTION—actionis not"accept"or"dismiss".NO_MATCHING_BUTTON— None of the supplied labels matched a visible button; the error payload includesvisibleLabelslisting what was found.ALERT_HANDLE_FAILED— Key send or AX press failed.
- Examples:
// Keyboard fallback — accept the default button { "action": "accept" } // Press a specific button by label (StoreKit, permission sheet, etc.) { "buttonLabel": "Allow While Using App" } // Multi-locale: try the localized label first, then English fallback { "buttonLabels": ["앱을 사용하는 동안 허용", "Allow While Using App"] }
- Notes:
- The
buttonLabel/buttonLabelspath uses macOSAXUIElementaccessibility API (ax-bridge) — it works on StoreKit password sheets, 3-button permission dialogs, and any alert where the default button is not the accept action. _meta._telemetry[0].backendis"ax-press"on the label path and the backend kind (e.g."simctl") on the keyboard path.- For non-English simulators, build the candidate list with
resolveLocalizedButtonLabelsfromsrc/native/localized-button-matcher.tsor seed it fromsrc/native/system-button-catalog.ts. - For StoreKit / In-App Purchase QA see StoreKit Automation Guide.
- The
inspect, wait_for, long_press, swipe, press, dismiss_keyboard, select_option, device_list, device_rotate, appearance_toggle
batch_navigate, batch_screenshot, batch_execute, cross_viewport_compare, workflow_init, workflow_status, workflow_collect, workflow_collect_partial, workflow_cleanup, worker_update, worker_complete
qa_auto_zoom, qa_touch_targets, qa_hover_only, qa_input_type, qa_safe_area, qa_keyboard_overlap, qa_horizontal_overflow, qa_100vh, qa_fixed_stacking, qa_scroll_lock, qa_dark_mode, qa_orientation, qa_pwa_meta, qa_full_audit
Run all 13 iOS QA detectors and generate a scored report.
- Input:
url?: string— URL to audit (uses current page if omitted)format?: 'markdown' | 'junit' | 'json' | 'html'— Report format (default:markdown)markdown— Human-readable Markdown summary (default)junit— JUnit XML for CI systems (GitHub Actions, Jenkins, CircleCI)json— Structured JSON for programmatic processing or dashboardshtml— Self-contained HTML report saved to disk; returns the file path
annotate?: boolean— Overlay issue bounding boxes on a screenshot (default:false,markdownformat only)
- Output: Report content as text (or file path for
htmlformat) - CI usage: See CI/CD Integration for example GitHub Actions workflows, exit code gating, and Jenkins/CircleCI examples.
{
"mcpServers": {
"opensafari": {
"command": "opensafari",
"args": ["serve"]
}
}
}