Playwright MCP Server: What It Exposes
Playwright MCP is a Model Context Protocol server from Microsoft that lets an AI agent drive a browser through Playwright. It works on structured accessibility snapshots rather than screenshots, so the agent reads the page as a tree of roles and names, picks an element reference out of it, and acts on that reference. No vision model sits in the loop.
That design decision is the reason it behaves differently from screenshot-driven browser agents. A snapshot gives the model an exact handle for every interactive element, so a click lands on the element it named instead of on coordinates it estimated. It also means the agent works in the same vocabulary Playwright locators use, which matters the moment you want the session to end in code you can keep.
What the server exposes
The default tool set covers the whole interaction surface: browser_navigate, browser_click, browser_type, browser_fill_form, browser_select_option, browser_hover, browser_drag, browser_press_key, browser_file_upload, browser_handle_dialog, browser_wait_for, and browser_snapshot for reading the page back. Inspection comes with it: browser_console_messages, browser_network_requests, browser_evaluate, browser_find.
Everything else is opt in through --caps, which keeps the tool schema small until you need more.
| Capability | Tools it adds | When it earns its place |
|---|---|---|
testing | browser_generate_locator, browser_verify_element_visible, browser_verify_text_visible, browser_verify_value, browser_verify_list_visible | Turning an exploratory walk into assertions and locators you can paste into a spec |
storage | Cookie, localStorage, and sessionStorage tools plus browser_storage_state | Logged-in flows, and saving auth state so the next run skips the login form |
network | browser_route, browser_unroute, browser_route_list, browser_network_state_set | Mocking a backend response or taking the page offline to test an error path |
devtools | browser_start_recording, browser_stop_recording, tracing, video, browser_highlight | Recording a flow you perform by hand and getting Playwright code back |
vision | browser_mouse_click_xy and the other coordinate tools | Canvas, maps, drag handles: anything with no accessibility node to target |
pdf | browser_pdf_save | Checking a generated document rather than a page |
browser_start_recording deserves a callout. You demonstrate a flow in the browser yourself, then browser_stop_recording hands back what you did as Playwright code. That is the shortest path from a manual reproduction to something a runner can execute.
Configuration is CLI flags. --browser picks chrome, msedge, firefox, or webkit. --device "iPhone 15" or --mobile emulates a phone, and the README notes mobile pages are usually lighter, which saves tokens. --test-id-attribute changes what generated locators anchor to, defaulting to data-testid. --codegen sets the language for generated code: TypeScript by default, with Python, Java, and C# available.
How this differs from writing Playwright tests
Both end in the same place, which is why the distinction gets missed. The difference is what each one guarantees.
Playwright Test is the enforcement layer. It has fixtures, retries, sharding across machines, a trace per retry, an HTML report, and a CI exit code. Run it twice on the same commit and it does the same thing twice.
Playwright MCP is an authoring and exploration layer. The agent decides which tool to call next, so the route through the page varies between runs. It has no retries, no sharding, and no report. What it produces is a session, plus whatever locators, assertions, and code you extract from that session before it ends.
Use MCP to find out how the page behaves and to draft the spec. Use the test runner to hold the line afterward. A team that stops at the MCP session has an agent that browsed the app, not a regression suite.
The Playwright team is direct about a related tradeoff: for high-throughput coding agents, they point at the Playwright CLI with skills instead, because CLI invocations avoid loading large tool schemas and verbose accessibility trees into the model's context. MCP stays the better fit for agentic loops that need persistent browser state and iterative reasoning over page structure, such as exploratory automation or self-healing tests.
Playwright MCP or Chrome DevTools MCP
| Playwright MCP | Chrome DevTools MCP | |
|---|---|---|
| Browsers | Chrome, Edge, Firefox, WebKit | Chrome and Chrome for Testing |
| Strongest at | Driving flows, mocking network, saving auth state, producing locators and code | Performance traces, Lighthouse audits, heap snapshots, deep protocol-level inspection |
| Output you keep | Playwright code, locators, storage state | A diagnosis of what the page did |
| Parallel sessions | Supported with --isolated or separate profiles | One browser per server instance |
The split is clean enough to state in one line each. Reach for Playwright MCP when the goal is a test that will exist tomorrow. Reach for Chrome DevTools MCP when the goal is understanding why a page is slow, leaking, or throwing today, and cross-browser coverage is not part of the question.
Running both is reasonable. They are separate servers with separate tool namespaces, and the cost is context, not conflict.
Where it fails
It is not a security boundary. The project says so directly, and adds that the origin allowlist and blocklist are not security boundaries either and do not affect redirects. File access is restricted to workspace roots unless you pass --allow-unrestricted-file-access, and that flag deserves more thought than it usually gets.
Persistent profiles collide. The default profile is persistent and only one browser instance can hold it at a time, so two MCP clients in the same workspace conflict. Give each one --isolated or its own --user-data-dir.
Generated locators inherit whatever the page gives them. On a UI with no test ids, the agent falls back to roles and accessible names, and those move when someone rewrites a label. Setting data-testid attributes before an agent starts generating locators is the cheapest stability you will buy all quarter.
Snapshots of heavy pages cost real context. A dense DOM produces a long tree on every action. --mobile and a narrower starting page help. So does turning off capability groups you are not using.
The Docker image runs headless Chromium only. Containerized setups lose the cross-browser advantage that is otherwise the main reason to pick this server over the DevTools one.
Nothing here reviews the test. An agent that walked a flow successfully will happily assert that the flow it just walked works. Assertions written from observed behavior encode the current behavior, bug included, which is the failure mode worth watching for in every AI-authored suite.
What is worth automating
The mechanical half is a good handoff: exploring an unfamiliar screen, finding stable locators, capturing auth state once instead of logging in on every run, and converting a manual reproduction into a first draft spec.
Deciding what the assertion should be stays a human call. A generated test tells you the page still does what it did the day it was recorded. Whether that is what the requirement asked for is a separate question, and it is answered upstream, in the test cases, not in the browser.