Core vs Ios Agent

A side-by-side look at the Core and Ios Agent MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.

Core logoCoreOS AutomationAgent-native MCP server for driving, inspecting, and asserting on real Electron desktop apps.55GoodAuth: no auth requiredIos Agent logoIos AgentOS Automation · Local subprocess (stdio)Drive a real iPhone or an iOS Simulator with an AI agent, through XCUIAutomation.59GoodAuth: not declared

Verdict: choose Core for os automation work; choose Ios Agent for os automation as a local process. You can also run both side by side in one mcpServers block.

Which MCP server should you choose?

Core logoChoose Core when

  • You need dedicated capabilities in the OS Automation domain.
  • Its auth model fits you: No auth required.
  • You have the keys it needs: DISPLAY, WAYLAND_DISPLAY.
  • You want tools like electron_assert_pattern, electron_attach, electron_check.
Explore Core

Ios Agent logoChoose Ios Agent when

  • You need dedicated capabilities in the OS Automation domain.
  • You prefer a local stdio subprocess transport.
  • You want tools like ios_doctor, ios_list_devices, ios_open_session.
Explore Ios Agent

Feature & specification comparison

Rows where the two servers differ are marked.

SpecCore logoCoreIos Agent logoIos Agent
CategoryOS AutomationOS Automation
Quality signal55/100 · Good59/100 · Good
Install commandNot confirmed yetConfirmed
Transport—Local subprocess (stdio)
AuthNo auth requiredNot declared
PricingFreeNot declared
Required env varsDISPLAYWAYLAND_DISPLAYNone listed
Verified ownerCommunity listingCommunity listing
GitHub stars123
Directory activity 6 views 0 installs 0 upvotes 1 views 0 installs 0 upvotes
Tools5531

Tools & capabilities

Core tools 55

  • electron_assert_patternValidate, in a single check (no polling), that an element's text or a named attribute matches a pattern. Target by ref or selector. With `attribute` set, reads that attribute; otherwise reads the element's trimmed text. Provide exactly one of: equals, contains, matches_regex. Optional flags (any of i, m, s, u) apply to matches_regex; g and y are rejected as stateful. Returns: { ok, session_id, matched, actual }. Errors: EXPECTATION_FAILED (element found but its value did not match the pattern — details carry expected + actual; a missing attribute reads as actual: null), SELECTOR_NO_MATCH (no element matched — this is one-shot, so a missing element is a precondition failure, not a retry; carries similar_refs), REF_NOT_FOUND (stale ref), TRANSPORT_UNSUPPORTED, NOT_RUNNING, BAD_ARGUMENT (no/multiple predicates, invalid regex or flags, or ref+selector both/neither).
  • electron_attachAttach to an already-running Electron app exposing a CDP debug endpoint (use electron_discover_running to find one, or start the app with --remote-debugging-port). Provide port (+ optional loopback host) or a loopback cdpUrl; pid alone is not attachable over CDP but, when supplied alongside, lets stop escalate to SIGKILL. The CDP transport supports eval/read/observe and core interaction surfaces against the attached app. The selected CDP page is also the default snapshot/find surface; explicit iframe/webview surface targeting remains unavailable. Returns: { ok, session_id, transport, windows, capabilities }. Errors: TRANSPORT_UNSUPPORTED (no attach-capable transport), CDP_DISCONNECTED (endpoint unreachable or dropped; retryable), CDP_TIMEOUT (handshake/method timeout; retryable), BAD_ARGUMENT (missing target selector or non-loopback endpoint).
  • electron_checkCheck the checkbox/radio identified by ref or selector (no-op if already checked). Options: force, timeoutMs. Returns: { ok, session_id, target, checked: true }. Errors: REF_NOT_FOUND / SELECTOR_NO_MATCH (carries similar_refs), ELEMENT_NOT_VISIBLE (retryable), ELEMENT_DISABLED, NOT_RUNNING, BAD_ARGUMENT.
  • electron_clear_inputClear the value of the input/textarea identified by ref or selector (sets it to empty). Options: force, timeoutMs. Returns: { ok, session_id, target, cleared }. Errors: REF_NOT_FOUND / SELECTOR_NO_MATCH (carries similar_refs), ELEMENT_NOT_VISIBLE (retryable), ELEMENT_DISABLED, NOT_RUNNING, BAD_ARGUMENT.
  • electron_clickClick the element identified by ref (from a snapshot) or selector. Options: button (left|right|middle, default left), clickCount (2 = double-click), force (bypass actionability), timeoutMs. Returns: { ok, session_id, target }. Errors: REF_NOT_FOUND / SELECTOR_NO_MATCH (no such element — re-snapshot; not retryable, carries similar_refs), ELEMENT_NOT_VISIBLE (retryable), ELEMENT_DISABLED (not retryable), NOT_RUNNING, BAD_ARGUMENT (ref+selector both/neither).
  • electron_console_logsRead the captured renderer console output for the session, newest-relevant entries last. Filters (all optional, ANDed): type (one or more of log/info/warning/error/debug/...), match (a regular expression the text must match), since (epoch ms — only entries at/after it), limit (max entries, default 200, max 1000 — the most recent are kept). Returns: { ok, session_id, entries: [{ type, text, timestamp, windowId?, location? }], count, overflowed }. overflowed is the number of older entries the buffer dropped. Errors: NOT_RUNNING, BAD_ARGUMENT (invalid regex, or multiple sessions).
  • electron_detachDisconnect from an attached or injected app without stopping it. A launch-owned session cannot detach because its transport owns the process; this includes Playwright development launches and packaged CDP launches. Use electron_stop for that case. Returns: { ok, session_id, detached: true }. Errors: TRANSPORT_UNSUPPORTED (launch-owned session; not retryable), NOT_RUNNING (no such session), BAD_ARGUMENT (multiple sessions).
  • electron_dialog_handlerArm the auto-responder for native JS dialogs (alert/confirm/prompt/beforeunload) and read which dialogs fired. Dialogs block the renderer, so the policy is applied automatically the instant one appears. Arming args (all optional): action (accept|dismiss — the default for every dialog), perType (per-kind overrides, e.g. {"confirm":"accept","beforeunload":"dismiss"}, falls back to action), promptText (text submitted to prompt() when it is accepted), oneShot (apply to exactly the next dialog, then revert to dismiss). With NO arming args the call is inspect-only and leaves the policy unchanged. Read args (all optional): type (one or more kinds to include), since (epoch ms), limit (max events, default 50, max 200 — most recent kept), clear (flush the whole buffer after reading). Until armed, the default policy is dismiss, so dialogs never hang the app. Returns: { ok, session_id, policy, entries: [{ type, message, action, defaultValue?, promptText?, timestamp, windowId? }], count, overflowed }. overflowed counts dropped events across the whole buffer, not just the returned (type/since/limit-filtered) subset. Errors: NOT_RUNNING, BAD_ARGUMENT (promptText without an accepting prompt policy, or oneShot without a policy to arm).
  • electron_discover_runningScan the conventional CDP debug ports (9222-9225 by default) for already-running, debuggable Electron apps on loopback only. No session required. Returns: { ok, targets, count, scanned } where each target is { targetId, port, appName, pid } and scanned reports { host, ports, elapsed_ms } so an empty result is unambiguous. Errors: BAD_ARGUMENT (non-loopback host, invalid port list, or timeout outside bounds). A failed probe is simply "no target on that port".
  • electron_doctorRun non-mutating preflight checks without starting an Electron session: Node version, Playwright, Electron, Linux display, configured app root and screenshot directory, eval policy, and project Electron runtime alignment. Returns: { ok, doctor_ok, checks, runtime }, where runtime includes server and, with --app-root, target Electron/Node/V8/ABI facts plus a bounded native-addon inventory. Inspect failed checks and warnings before electron_launch. Errors: none.
  • electron_dragDrag the source element (ref or selector) onto the target element (targetRef or targetSelector), using the real mouse API. Options: force, timeoutMs. Returns: { ok, session_id, source, target }. Errors: SELECTOR_NO_MATCH / REF_NOT_FOUND (carries similar_refs), ELEMENT_NOT_VISIBLE (retryable), NOT_RUNNING, BAD_ARGUMENT (a side missing or both ref+selector given).
  • electron_drop_fileSimulate dropping OS files onto the element identified by ref or selector. Web DataTransfer mode: reads each path on the host running the server, rebuilds the files in the renderer, and dispatches dragenter/dragover/drop with a real DataTransfer — engaging standard web drop handlers. Paths must be ABSOLUTE (max 10 files, 5242880 bytes each). default_prevented reports whether a drop handler engaged (called preventDefault); false usually means the target has no web drop handler. Apps that resolve dropped files to native OS paths need an app-specific IPC convention this tool does not simulate. Options: mimeType, timeoutMs. Returns: { ok, session_id, target, files, default_prevented }. Errors: ABSOLUTE_PATH_REQUIRED, FILE_NOT_FOUND, BAD_ARGUMENT (too many/large files, or ref+selector both), SELECTOR_NO_MATCH / REF_NOT_FOUND (carries similar_refs), NOT_RUNNING.
  • +43 more on the listing page

Ios Agent tools 31

  • ios_doctorCheck that this machine can drive an iOS device, and say how to fix what it can't. Run this first when a session fails to start, when a device does not appear, or after an Xcode or iOS upgrade. Every failing check comes with a concrete remedy.
  • ios_list_devicesList iOS Simulators and attached physical iPhones available for automation. `ready` is false when something blocks automation; `blockers` says what.
  • ios_open_sessionAttach to a device and start driving it. Boots the simulator or verifies the phone, starts WebDriverAgent, and opens a tuned session. Omitting `device` prefers an already-booted simulator over a connected iPhone, so acting on a real device is always a deliberate choice.
  • ios_session_statusReport the current session: device, foreground app, and safety state.
  • ios_close_sessionRelease the device and shut down its WebDriverAgent runner.
  • ios_list_appsList apps installed on the device, with their bundle identifiers.
  • ios_launch_appBring an app to the foreground and return its screen.
  • ios_terminate_appForce-quit an app.
  • ios_open_urlOpen a URL or deep link. Usually the cheapest way to reach a screen: a deep link skips the navigation an agent would otherwise have to tap through.
  • ios_install_appInstall an app from a local .app or .ipa.
  • ios_observeRead the screen as a compact list of elements with short refs. Each line is one element: `e7 button "Send" @(340,70)`. Pass those refs to the action tools rather than coordinates. If the result says elements were omitted, narrow with `query` or `region` instead of raising `budget`; a smaller answer is usually the more useful one.
  • ios_screenshotCapture the screen as an image. Use this when an element has no accessibility label, when the layout matters, or when `ios_observe` cannot find something you can plainly see. With `annotate_refs` each element is boxed and labelled with its ref, so you can pick one by eye and pass it to an action tool. Annotating re-reads the screen first, so the refs on the image are the current ones rather than whatever was observed last. That costs a tree fetch, and needs the `vision` extra installed.
  • +19 more on the listing page

Ready-to-paste client configs

Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.

Core

No confirmed install command for Core yet — follow the setup steps linked from its listing page rather than a guessed package name.

Ios Agent

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "ios-agent": {
      "command": "uvx",
      "args": [
        "ios-mcp"
      ]
    }
  }
}

Frequently asked questions

Core is categorized under OS Automation and uses an install path we have not confirmed yet. Ios Agent belongs to OS Automation and uses a local stdio subprocess. Pick Core for os automation work and Ios Agent for os automation.

Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client. Core has no confirmed install command yet — follow its own setup instructions.

Core is listed as free. Auth: no auth required. Ios Agent has no declared pricing — check the project's own site. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.

Yes. MCP clients support multiple servers: add core and ios-agent as separate keys in the same mcpServers object, and your assistant will call tools from either one.

On AllMCPs, Core has a quality signal of 55/100 (Good) with 6 views, 0 installs and 12 GitHub stars. Ios Agent has 59/100 (Good) with 1 views, 0 installs and 3 GitHub stars.