iphone-safari-mcp

iphone-safari-mcp

MCP server that drives Safari on a physically attached iPhone via Apple's safaridriver, enabling navigation, screenshots, DOM snapshots, console logs, network timings, and tap/type/scroll actions on the real device. No Xcode, Appium, or WebDriverAgent required.

Category
Visit Server

README

iphone-safari-mcp

An MCP server that drives Safari on a physically attached iPhone through Apple's safaridriver (platformName: "ios"). No Xcode, no Appium, no WebDriverAgent.

Gives a coding agent the closed loop: navigate → screenshot + DOM snapshot + console + network timings → click/type/tap/scroll → repeat, all on the real device.

Prerequisites

On the iPhone — Settings → Apps → Safari → Advanced:

  • Web Inspector: ON
  • Remote Automation: ON

On the Mac, once:

safaridriver --enable

At session time the phone must be plugged in, unlocked, and trusted. Only one WebDriver session can exist at a time — close any Selenium script or Web Inspector automation session first.

Install

Needs uv. Nothing else — uv fetches Python and the dependencies itself.

Run it straight from the repo, no clone and no venv:

uvx --from git+https://github.com/ikatkov/iphone-safari-mcp \
  iphone-safari-mcp --selftest https://example.com

Or work on it locally:

git clone https://github.com/ikatkov/iphone-safari-mcp
cd iphone-safari-mcp
uv sync                       # resolves dependencies into .venv
uv run iphone-safari-mcp --selftest https://example.com

The selftest prints the user agent (should say iPhone), writes /tmp/iphone-safari-selftest.png, and reports how many interactive elements it found. --help lists everything.

The examples below use uv run iphone-safari-mcp (from a clone); every one of them works with the uvx --from git+… form too.

How it talks to safaridriver

The server starts one long-lived safaridriver and reuses it, rather than letting Selenium spawn a throwaway one per session.

This matters. safaridriver needs several seconds after launch to enumerate USB devices. Selenium's webdriver.Safari() spawns a fresh driver and fires New Session immediately — which lands inside that window, when the attached iPhone is still invisible and only already-cached network-paired devices exist. The symptom is baffling: session creation fails naming some other household device, and your cabled phone is absent from the list entirely while sitting right there in Safari → Develop.

So session creation also retries for IPHONE_SAFARI_DISCOVERY_TIMEOUT seconds (default 45) instead of failing on the first miss.

To debug discovery, run your own driver and attach to it:

safaridriver --diagnose -p 4444          # logs to ~/Library/Logs/com.apple.WebDriver/
IPHONE_SAFARI_DRIVER_URL=http://localhost:4444 uv run iphone-safari-mcp --verify

Pick the right phone

safaridriver will use any paired host that matches, including devices paired over the network that you never plugged in. Always pin the device:

uv run iphone-safari-mcp --list-devices     # what safaridriver can see, and why each was rejected
uv run iphone-safari-mcp --device "My iPhone" --selftest https://example.com

For the MCP server, pin it with an env var — IPHONE_SAFARI_DEVICE_NAME, IPHONE_SAFARI_DEVICE_UDID, or IPHONE_SAFARI_DEVICE_TYPE. UDID is the robust choice since names change. session_info reports both what you pinned and what you got.

A device missing from --list-devices entirely is not paired — check the cable, tap Trust, and confirm it appears under Safari → Develop on the Mac. A device that is listed but rejected tells you the reason ("Web Inspector is not enabled on device").

Register with Claude Code

Verify before you register. Other household devices pair too, and a wrong pin fails silently — it just drives someone else's phone. --verify paints a large random code on whatever screen it actually controls:

uv run iphone-safari-mcp --verify --device "My iPhone"

Only register once the code appears on the phone you intend to drive:

claude mcp add iphone-safari --scope user \
  -e IPHONE_SAFARI_DEVICE_UDID=<udid confirmed by --verify> \
  -- uvx --from git+https://github.com/ikatkov/iphone-safari-mcp iphone-safari-mcp

That pins nothing to this directory — the agent can launch it from anywhere. uv caches the environment, so only the first start needs the network.

To run your own checkout instead, point uv at it by absolute path, since the agent won't launch from this directory:

claude mcp add iphone-safari --scope user \
  -e IPHONE_SAFARI_DEVICE_UDID=<udid confirmed by --verify> \
  -- uv run --directory /abs/path/to/iphone-safari-mcp iphone-safari-mcp

Prefer the UDID over the name: --verify prints the UDID that safaridriver actually bound to, and unlike names it can't drift or collide.

Run this from a real terminal with Claude Code closed — it rewrites ~/.claude.json on exit and will clobber the edit otherwise.

Then in a session: "Use iphone-safari. Report what device you're connected to, open http://localhost:5173, screenshot it and list any console errors."

Tools

Tool Purpose
session_info Confirm you're on the iPhone, not Mac Safari — user agent, viewport, DPR
navigate Open a URL and arm console capture
screenshot Downscaled PNG of the viewport
snapshot Start here. URL, viewport, scroll, and every visible interactive element with a CSS selector, label and rect
page_source Raw HTML, truncated
click / type_text Act on an element by css, xpath or text
tap Real single-finger touch at viewport coordinates
scroll Scroll by pixel delta
evaluate_javascript Run JS in the page
console_logs / install_console_capture Console + uncaught errors + rejections
network_timings Resource timings; transferSize: 0 usually means a failed request
go_back / reload_page / close_session Session control

Prefer snapshot over page_source — it's a fraction of the tokens and gives you selectors you can act on directly.

Limits

Apple's Safari WebDriver is deliberately web-content automation, not device automation. No Home screen, Settings, app switching, rotation, or system dialogs — Apple calls general device automation a non-goal. If you need those, use mobile-next/mobile-mcp, which drives the whole device but requires go-ios + WebDriverAgent provisioned onto the phone.

Safari 27 / STP 247+ ship an MCP server inside safaridriver itself (safaridriver --mcp), but as of Safari 26.2 that flag does not exist, and Apple only documents it against Safari on the Mac.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured