Resource library

QA How-To

Playwright MCP Server Tutorial for Testers

Playwright MCP Server tutorial for testers: connect VS Code, inspect snapshots, verify TodoMVC behavior, and turn an agent session into a repeatable test.

17 min read | 3,040 words

TL;DR

Register @playwright/mcp@latest with your MCP client, navigate to a test page, use snapshot refs for exploratory actions, and call testing verification tools for explicit results. Convert the proven flow into a Playwright Test spec for repeatable regression coverage.

Key Takeaways

  • Use Node.js 20 or newer and register @playwright/mcp@latest in an MCP capable client.
  • Enable --caps=testing to get explicit browser verification tools.
  • Read a fresh accessibility snapshot before acting on an element reference.
  • Use --isolated when a scenario needs clean browser state.
  • Verify expected page text with MCP tools, then encode the flow in Playwright Test.
  • Review generated locators and protect private test environments with client permissions.

A Playwright MCP Server tutorial for testers should end with more than an AI assistant opening a page. You will connect the server to an MCP client, inspect an accessibility snapshot, run a TodoMVC scenario, verify the result, and turn the useful actions into a repeatable Playwright test. The server lets the assistant call browser tools through the Model Context Protocol (MCP); the tester still chooses the expected behavior and reviews the evidence.

This walkthrough uses the public TodoMVC demo and VS Code with a chat agent that supports MCP tools. It keeps the first browser session isolated so a previous login, cookie, or unfinished todo cannot change the result. The Playwright tutorial for beginners covers the test runner if you need that foundation before converting the exploratory session into code.

What You Will Build

  • A local Playwright MCP server registered in VS Code through the documented code --add-mcp command.
  • An isolated browser session that opens https://demo.playwright.dev/todomvc and exposes its controls as accessibility snapshot entries.
  • A short scenario that adds two todos, completes one, and checks the active count with MCP verification tools.
  • A saved TypeScript Playwright test that reruns the same behavior outside the assistant.

The server is a bridge between an MCP client and a Playwright controlled browser. The client sends a named tool call such as browser_navigate; the server performs it and returns page state. The snapshot contains roles, accessible names, and temporary element references. You use those references during exploration, then use durable locators and assertions in the test file. That division matters: an assistant conversation is useful for discovery, while a test runner supplies repeatable pass or fail results.

Prerequisites

Use Node.js 20 or newer, the minimum stated in the current Playwright MCP installation guide. Install the current stable VS Code release and enable a chat agent with MCP support, such as GitHub Copilot agent mode. The documented package command uses @playwright/mcp@latest; it resolves to the current release when you run it. If your team requires a pinned release, replace latest with the exact version your team has tested, and keep that package version aligned across the client configuration and any troubleshooting commands. Do not guess a pin from an unrelated Playwright Test dependency.

Make the VS Code code command available in your shell. On macOS, use the command palette action to install the code shell command; on Windows or Linux, confirm that the executable is on PATH. You need network access on first use because the package and a browser may be downloaded. Use a disposable local workspace for the final test artifact. The public TodoMVC demo requires no account and no test credentials.

node --version
npm --version
code --version

Verify: node --version must report major version 20 or higher, and the other commands must print their versions without a command-not-found error. The exact npm and VS Code versions can vary. If your organization locks tool versions, record the output in your team's setup notes and use those approved versions consistently.

Step 1: Verify the Playwright MCP Server Tutorial setup

First check that your shell can resolve the server package. This isolates package or proxy problems before you involve the editor. The command below asks the package to print its supported options and exits; it does not register an MCP server or run a browser session.

npx -y @playwright/mcp@latest --help

Look for --isolated, --caps, and --headless in the help output. The default browser mode is headed, so you can observe what the assistant does. This guide deliberately keeps it headed during exploration. If a corporate proxy blocks npm, configure npm's approved registry or proxy first, then repeat this command. A working node binary alone does not prove that npx can fetch the MCP package.

Verify: Run npx -y @playwright/mcp@latest --help a second time. It should return usage text again, usually faster because npm has cached the package. If it remains waiting, check whether npm is prompting for registry access or a proxy login. This check tests the executable, not the client connection; the next step registers that connection.

Step 2: Register the server in VS Code

Use the VS Code CLI form documented by Playwright. The JSON value gives the server a name, starts it with npx, and enables the testing capability. --isolated gives each session fresh browser state, which makes the TodoMVC assertions easier to interpret. Keep the command as one shell line, including the single quotes around the JSON on a POSIX shell.

code --add-mcp '{"name":"playwright","command":"npx","args":["@playwright/mcp@latest","--isolated","--caps=testing"]}'

In VS Code, open the MCP server list from the chat tools interface and find playwright. Start or enable it if the client asks. Then open a new agent conversation so the updated tool list is loaded. Client UI labels can change; the reliable signal is that the conversation can see tools named browser_navigate, browser_snapshot, and browser_verify_text_visible. The last one belongs to the enabled testing capability. A generic client config may use an mcpServers object, but code --add-mcp expects the smaller object shown above.

Verify: In the chat agent, ask: "List the Playwright browser tools available in this conversation. Do not open a page yet." Confirm that navigation, snapshot, and text verification tools are available. If only navigation appears, the server may be running without --caps=testing; inspect the registered command and restart the server. If none appear, check MCP server status in VS Code before diagnosing the web page.

Step 3: Open TodoMVC and read the snapshot

Give the agent a narrow instruction that includes a target URL and a stopping point. This makes the first call easy to audit. It should invoke browser_navigate and return a page URL, title, and accessibility tree. You can ask it to call browser_snapshot explicitly if the first response is abbreviated.

Use Playwright MCP to navigate to https://demo.playwright.dev/todomvc.
Show the page URL and the accessible textbox for a new todo.
Stop before typing or clicking anything.

The underlying tool arguments should be equivalent to this real MCP call:

{"url":"https://demo.playwright.dev/todomvc"}

The snapshot should include a textbox named "What needs to be done?" and a heading named "todos". It may also include an element reference such as e5. Treat that reference as short lived. It identifies an element in the current snapshot, not a stable locator you should paste into a source file. If the agent reports a different URL, confirm that it did not follow an unrelated search result. A screenshot can help a human see the layout, but the snapshot is the primary input for selecting semantic controls.

Verify: Ask "Call browser_snapshot and report the textbox role and accessible name." Expect textbox "What needs to be done?". Do not proceed if the page is an error screen or the textbox is absent. This is also a useful accessibility check: a control with no usable name will be harder for both an agent and an assistive technology user to operate.

Step 4: Add two todos using current element references

Tell the agent exactly which two items to create and instruct it to read the latest snapshot before choosing a target. The browser_type tool accepts the current textbox reference or a unique selector, plus text. Its submit: true option presses Enter after filling the field. The sample e5 below is illustrative; copy the reference returned in your own session if you call the tool manually.

Read the current snapshot. Add "Buy groceries" and "Walk the dog"
through the new-todo textbox, submitting each with Enter.
After each submission, show the resulting snapshot. Do not complete an item yet.
{"target":"e5","text":"Buy groceries","submit":true}

After the first submission, inspect the new response before adding the second item. The textbox may retain its reference, but you should not assume it will. Once both are present, look for two list items and 2 items left in the content area. This is an exploratory action, so the visible state is evidence rather than a formal test assertion. If the page has been used earlier in a persistent profile, stale items can invalidate the expected count. The isolated option avoids that state leak by starting a fresh context.

Verify: Ask the agent to call browser_snapshot and identify both exact todo texts plus the remaining count. The expected state is two visible items and 2 items left. If only one item appears, check whether Enter was sent and whether a later action accidentally replaced the first item. Inspect the last tool response rather than repeating both entries blindly.

Step 5: Turn observations into MCP assertions

An agent saying "looks good" is weaker than an explicit verification call. The testing capability provides tools that return Done on success and an error on failure. Ask for exact checks on the two item texts and the count. The tool browser_verify_text_visible takes the expected text, while browser_verify_element_visible takes a role and accessible name. Use the latter for controls that have clear semantics.

Use Playwright MCP verification tools to confirm that "Buy groceries"
and "Walk the dog" are visible and that "2 items left" is visible.
Report each tool result separately. Stop if any check fails.
{"text":"Buy groceries"}

The JSON object is the argument to browser_verify_text_visible, not a shell command. Run the same tool with {"text":"Walk the dog"} and {"text":"2 items left"}. A verification tool failure should trigger investigation, not an instruction to mark the scenario passed anyway. Tool responses may include generated Playwright expect(...) code. Save the useful locator and expectation ideas, but review them before putting them in a test: a broad getByText may match a hidden duplicate or a second component in a larger app.

Verify: Require three Done results, one per text. To prove the check can catch an error, ask for browser_verify_text_visible with a deliberately absent phrase such as "99 items left"; it should fail. Then return to the real assertions. This negative check demonstrates that the agent is calling the tool rather than paraphrasing the snapshot.

Step 6: Complete one item and inspect failures

Now change state. Ask the agent to find the checkbox belonging to "Buy groceries" in the newest snapshot, click that checkbox, and check the count. The page may expose checkboxes with the same accessible name, so the neighboring list item text is important context. In exploratory MCP calls, use the reference tied to the correct list item. In the automated test later, scope the checkbox to the matching list item.

Use the latest snapshot to find the checkbox inside the "Buy groceries"
list item. Click it. Verify "1 item left" and confirm "Walk the dog"
remains visible. Then report browser console errors, if any.

The click tool takes the current checkbox reference:

{"target":"<checkbox-ref-from-current-snapshot>"}

The placeholder signals that the reference comes from your live snapshot; there is no universal e10 for every session. Ask for browser_console_messages with {"level":"error"} after the state change. Console output helps explain a broken UI, but a quiet console does not prove that the intended checkbox changed. The count assertion and item state answer that question. For an application with an API backend, browser_network_requests can add request evidence, but TodoMVC mainly exercises client state and needs no guessed API endpoint.

Verify: Require a successful browser_verify_text_visible call for 1 item left, then call browser_snapshot and locate the completed checkbox under the groceries item. If the count remains two, check whether the agent clicked the other checkbox or an unrelated control. If it reports a stale reference error, get a new snapshot and retry with the new reference. Do not store element refs for use in the final test.

Step 7: Convert the Playwright MCP Server Tutorial flow into a test

The MCP session has helped you find the behavior and useful locators. Put the regression in a normal test file so CI can run it without an AI client. Create a fresh project directory and install the current Playwright Test package. npx playwright install chromium downloads the browser build matching the installed package. If your project already has Playwright Test, use its existing version and install command instead of creating a second dependency tree.

Need Playwright MCP session Playwright Test spec
Discover controls Read live accessibility snapshots Review source and locators
Act on a target Use a current snapshot ref Use a durable locator
Record a result Inspect verification tool responses Assert with expect and a runner exit code
Repeat in CI Requires an MCP client and agent workflow Run the committed spec directly
mkdir playwright-mcp-todo-check
cd playwright-mcp-todo-check
npm init -y
npm install -D @playwright/test@latest
npx playwright install chromium
mkdir tests

Create tests/todo.spec.ts with the complete test below. It limits items to .todo-list li because the footer also has list items, then scopes the checkbox to the item text so identical checkbox names do not make the action ambiguous. toHaveText waits for the count to update, and toHaveCount verifies that the two entries exist before the state change. The test opens a fresh page for each run, which gives it the same clean starting condition as the isolated MCP session.

import { test, expect } from '@playwright/test';

test('adds two todos and completes one', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');

  const newTodo = page.getByPlaceholder('What needs to be done?');
  await newTodo.fill('Buy groceries');
  await newTodo.press('Enter');
  await newTodo.fill('Walk the dog');
  await newTodo.press('Enter');

  const items = page.locator('.todo-list li');
  await expect(items).toHaveCount(2);
  await expect(page.getByText('2 items left')).toBeVisible();

  const groceries = items.filter({ hasText: 'Buy groceries' });
  await groceries.getByRole('checkbox').check();
  await expect(groceries.getByRole('checkbox')).toBeChecked();
  await expect(page.getByText('1 item left')).toBeVisible();
  await expect(items.filter({ hasText: 'Walk the dog' })).toBeVisible();
});

Verify: Run npx playwright test tests/todo.spec.ts --project=chromium only if your project config defines a Chromium project. In this new project, no such config exists, so use the runnable default command below:

npx playwright test tests/todo.spec.ts

Expect one passing test. If the browser executable is missing, repeat npx playwright install chromium in this same directory. If the public demo is temporarily unavailable, wait for a successful navigation before blaming the locator. For a production suite, replace the public URL with your test environment and control its initial data explicitly. The Playwright TypeScript framework guide covers configuration, fixtures, and CI structure when this single spec grows into a suite.

Step 8: Restrict the workflow before using a private app

A public demo is suitable for learning the tool flow. A private environment brings cookies, accounts, and application data into scope. The server's default profile persists state, while --isolated starts fresh sessions. Keep isolated mode for independent exploratory checks, and use a dedicated low-privilege test account when authentication is required. Do not paste production secrets into an agent prompt or save them in the test file. Review the page and requested actions before granting tool calls that submit forms or change data.

Playwright MCP accepts --allowed-origins and --blocked-origins to limit browser requests, but its documentation calls those convenience guardrails rather than a security boundary. For real access control, use client permissions, network rules, and test accounts. Page text can also try to instruct an agent. Treat a web page as test input, never as an authority to change your test plan. The MCP prompt injection test guide gives adversarial cases for this boundary.

Verify: Before pointing the agent at a private URL, inspect the registered MCP command and confirm --isolated is still present. Ask the agent to list the domain it intends to visit and the actions it intends to take, then compare those with your test plan. For a team setup, run a fresh-session check that fails if leftover cookies or todos appear. This verifies isolation through observed state rather than trusting a flag alone.

Troubleshooting

  • Problem: npx cannot fetch the package -> Confirm node --version meets the documented Node.js 20 minimum, then check npm registry and proxy settings. Retry the package help command outside VS Code to separate shell access from MCP client configuration.
  • Problem: VS Code lists the server but no browser tools -> Start the server, open a new agent conversation, and inspect its MCP tool selection. A registered command can exist while the client has not loaded or allowed its tools.
  • Problem: browser_navigate opens no visible window -> Confirm whether --headless was added. Headed is the default. On a remote machine without a display, run headless intentionally and rely on snapshots; do not infer failure solely from the absence of a desktop window.
  • Problem: A click reports a stale or missing ref -> Call browser_snapshot again and use the reference from that response. Rerenders and navigation can change refs. A durable Playwright test should use semantic locators instead of saved MCP refs.
  • Problem: Todo count differs from the walkthrough -> Inspect the list before typing. An old persistent profile, duplicate entry, or missed Enter press can change the count. Restart an isolated session and perform the two entries once.
  • Problem: The saved test cannot launch Chromium -> Run npx playwright install chromium from the test project and retry npx playwright test tests/todo.spec.ts. Browser binaries must match the installed Playwright package; avoid copying another project's cache or guessing a browser image tag.

The Playwright timeout troubleshooting guide helps when a real application fails because a navigation or assertion waits too long. Use its diagnosis after checking the current page snapshot and console, since a missing element and an unavailable server call are different failures.

Interview Questions and Answers

The model answers in interviewQnA cover server transport, snapshots, tool capabilities, verification, state, and test conversion. Practice explaining why you used each boundary in this scenario, rather than memorizing the names of tools. A strong answer describes the evidence returned by a tool and what it cannot establish.

Common Mistakes

  • Copying e5 from a screenshot of someone else's run. Refs are tied to a live snapshot, so get your own current target.
  • Treating an agent's natural-language "passed" as an assertion. Require a verification tool result or a Playwright Test expectation.
  • Clicking the first "Toggle Todo" checkbox without checking its parent item. Two identical names make that target ambiguous.
  • Reusing an authenticated profile for an independent scenario. Cookies and local storage can change the starting state.
  • Shipping generated Playwright code without reviewing selector scope, data setup, and failure messages. Convert the observed flow into an owned test.

The AI-assisted exploratory testing guide offers a broader charter-based approach. If you want to measure whether an agent picks the right browser tool for each task, use the MCP tool-selection accuracy guide.

Where To Go Next

Keep the passing TodoMVC spec as a small reference, then repeat the exercise against one safe workflow in your own staging app. Define its starting data, ask the agent to inspect the interface, and convert only the useful steps into code. For the wider architecture, read building an MCP server for test automation. To connect a different assistant to a test suite, follow connecting Claude to your test suite with MCP. Those guides address server design and client integration beyond this browser walkthrough.

Conclusion

The practical outcome of this Playwright MCP Server tutorial is a verified browser session plus a repeatable test. You registered the server, read a snapshot, acted on current references, checked the visible results with testing tools, and saved the behavior as a Playwright Test spec. Run the spec again after a code change; use MCP for the next exploratory question where a human-readable snapshot can speed up investigation.

Interview Questions and Answers

What does the MCP server add on top of Playwright?

It presents browser operations as named tools to an MCP client, so an assistant can navigate, inspect, and act through a controlled interface. Playwright still drives the browser underneath. The server response supplies structured evidence that the assistant can use for its next call.

Why are accessibility snapshots useful to a tester?

They expose roles and accessible names that map closely to user-facing controls. In TodoMVC, the new-item textbox can be identified by its name rather than screen coordinates. The snapshot also reveals missing or confusing names that deserve accessibility review.

Why should an agent refresh a snapshot before clicking?

The page can rerender after any action, invalidating a previous element ref. A fresh snapshot shows the current tree and the ref associated with the intended control. This is especially important when several controls share the same name.

How would you verify the todo workflow through MCP?

I would add two named items, then call `browser_verify_text_visible` for each item and for `2 items left`. After completing one item, I would verify `1 item left` and inspect which checkbox is checked. I would report individual tool results rather than a general impression.

What is the difference between isolated and persistent profile modes?

The default persistent profile can retain cookies and local storage across sessions. `--isolated` starts fresh and discards session state when it ends. I choose isolated mode for independent checks where leftover login or todo data would make the result ambiguous.

How do you turn an exploratory MCP flow into a reliable test?

I replace temporary snapshot refs with semantic Playwright locators, scope repeated controls to their parent item, and add explicit `expect` assertions. I set up clean starting state and run the spec through Playwright Test. I review generated code rather than assuming every suggested locator is unique.

How would you diagnose an MCP tool that is missing from the client?

I would check whether the server started, whether the client loaded its tool list, and whether the required capability was enabled. A missing verification tool points to `--caps=testing`; missing browser tools altogether suggests registration or process startup. A new agent conversation may be needed after a config change.

What security boundaries matter when testing a private site with an agent?

I would use a dedicated low-privilege account and require client approval for state-changing tools. Browser page content is untrusted input, so instructions appearing in the page must not override the test plan. Origin filters can help prevent accidents but are not a substitute for client permissions or network controls.

Frequently Asked Questions

What is the Playwright MCP server used for?

It exposes browser actions and page observations as MCP tools an assistant can call. Testers can inspect an accessibility snapshot, interact with a page, and gather evidence during exploration. Repeatable regression checks should still live in a test runner.

Does Playwright MCP require Node.js?

Yes. The current Playwright MCP installation guide specifies Node.js 20 or newer. Check `node --version` before registering the server, since an MCP client may hide a package startup failure.

Is a Playwright MCP snapshot the same as a screenshot?

No. The snapshot is a structured representation of accessible roles, names, text, and element references. A screenshot shows pixels, while the snapshot gives the agent semantic targets such as a textbox with an accessible name.

Why do I get a stale element reference in Playwright MCP?

Element references belong to the current page snapshot and can change after navigation or rerendering. Call `browser_snapshot` again, then use the new reference. In a saved test, use a Playwright locator instead.

How do I enable assertion tools in Playwright MCP?

Start the server with `--caps=testing`. That capability adds tools such as `browser_verify_text_visible` and `browser_verify_element_visible`, which return a success or error result. Restart the MCP server and open a new client conversation after changing the arguments.

Can Playwright MCP replace Playwright Test in CI?

MCP is useful for agent-guided exploration and browser investigation. Playwright Test provides test files, assertions, a runner, and a CI-friendly pass or fail result. Convert stable exploratory flows into committed tests.

How can I keep an MCP browser session clean?

Use `--isolated` so each session starts without the saved profile state. Check the page before acting to confirm that cookies or earlier test data are not influencing the scenario. For authenticated work, use a dedicated test account and an approved state setup.

Related Guides