e2e mcp gives a coding agent such as Claude Code, Codex, or Cursor a live session on your app, on web, iOS, or Android. The agent sees the screen, acts on it, and checks its work.

Why it matters

TaskWithout e2e mcpWith e2e mcp
Write a testGuesses locators, runs, fails, guesses againWrites the test as it walks the flow, from checked test lines
Change the UIDone when it compilesOpens the page and checks the result
Reproduce a bugGuesses from the codeFollows the steps in the app
Show a change in a PRDescribes itRecords a video

The server needs no model.

Set it up

e2e init offers to register the server in .mcp.json (Claude Code) and .cursor/mcp.json (Cursor). By hand:

claude mcp add --scope project e2e -- npx e2e mcp

A session starts the target’s app command, if it has one.

Ask the agent

  • “Add a Remember me checkbox to the login form. Check it in the app with e2e.”
  • “Write a test for checkout while you walk it in the app.”
  • “Reproduce issue #123 in the app and record a video.”

Add “headed” to watch a local browser or simulator.

How it writes a test line

Each action in a session answers with the test line that repeats it. The line’s locator matched that control alone on the live screen:

Tapped #n31.
Test line: await screen.getByRole("button", "Sign in").tap();

The agent copies the lines it needs into the test as it walks the flow. test_lines returns every line so far, in order, as a draft test body. See test_lines for how a line is built.

How it checks a locator

For a line no action printed, such as an assertion, the agent tries the locator in the session first. A wrong guess fails there, not in a test run:

0 nodes match getByLabel("Email").
A test using this locator would fail with LOCATOR_NOT_FOUND. ...

1 node matches getByRole("button", name: "Sign in").
Use: screen.getByRole("button", "Sign in")

Run tests next to a session

A session doesn’t run tests and writes no test results or cache recordings. The agent runs tests with e2e run and, when a run can go beside the session, keeps the session open between runs. After a failed run, it goes to the failing screen in that session instead of opening a new one.

On web, a run next to a session depends on the target’s app:

Target’s appA run while a session is open
No commandBoth use the app you started.
url on port 0Each starts its own copy of the app. A dev server that runs one copy per directory, such as next dev, fails the run.
command with reuseExisting: trueThe run uses the app the session started. When the session closes, also during a run, that app stops.
command on a fixed port, without reuseExistingFails with APP_ALREADY_RUNNING.

When CI is set, e2e ignores reuseExisting, and the run fails as on a fixed port. Close the session before a run that would fail. On mobile, run on a device no session uses.

Run several agents

Each agent, subagents included, opens its own session with its own browser or device, up to four by default. On mobile, give each session its own target.

Secrets

type_secret fills a secret without showing it to the agent. After a secret is filled, the session stops returning screenshots.

Videos from start_recording are not masked.

Next