QA MCP for QA20-server field guide

Category 1 of 5 · Servers 01–05

Browser & mobile automation

This is the category where MCP earns its keep fastest, because the bottleneck in UI automation was never running the test — it was writing a locator that survives the next sprint. An agent that reads the accessibility tree picks better locators than most humans do at 4pm on a Friday.

Pick one driver, not three

Playwright, Selenium, and Puppeteer all expose click-shaped tools. Connecting two at once is the single most common cause of an agent grabbing the wrong tool mid-flow. Chrome DevTools MCP is the exception — it complements Playwright rather than competing, because its tools are named for observation (list_network_requests, performance_start_trace) rather than interaction.

01

Playwright MCP

The default pick. Drives Chromium, Firefox and WebKit through structured accessibility snapshots instead of pixels or brittle CSS selectors.

Official · Microsoft npx @playwright/mcp No credentials Core stack

Why a tester should care

Traditional agent-driven browser automation took a screenshot and asked a vision model where to click. That is slow, expensive, and non-deterministic. Playwright MCP instead hands the model an accessibility snapshot: a structured tree of roles, names, and stable element references. The model then says "click the button with ref e17", which is exact.

The QA consequence is significant. Because the agent is reasoning over roles and accessible names, the specs it writes naturally reach for getByRole('button', { name: 'Submit claim' }) rather than div.css-1x7k9 > span:nth-child(3). You get accessible-by-construction locators for free, and a spec that survives a CSS refactor.

Second-order benefit: if the agent can't find an element in the accessibility tree, that is itself a finding. An unlabelled icon button that the agent cannot address is an unlabelled icon button your screen-reader users cannot address either.

Tool surface

Tool groupRepresentative toolsWhat you use it for
Perceptionbrowser_snapshot, browser_take_screenshotGet the a11y tree (cheap, precise) or a picture (expensive, for visual bugs)
Navigationbrowser_navigate, browser_navigate_back, browser_tabsMove through the app, multi-tab flows, OAuth popups
Interactionbrowser_click, browser_type, browser_select_option, browser_hover, browser_drag, browser_press_keyDrive the flow; keyboard tools also give you tab-order testing
Files & dialogsbrowser_file_upload, browser_handle_dialogUpload flows, native confirm/alert handling
Diagnosticsbrowser_console_messages, browser_network_requestsCatch the silent 500 behind a "nothing happened" bug
Escape hatchbrowser_evaluateArbitrary JS in page context — powerful, and the one to restrict
Waitingbrowser_wait_forWait on text appearing/disappearing rather than sleeping

Wire it up

Claude Code, one line:

shell
claude mcp add playwright -- npx -y @playwright/mcp@latest --isolated --browser chromium

Or as JSON config, for clients that use an mcpServers block:

mcp config — headed local debugging
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "-y", "@playwright/mcp@latest",
        "--browser", "chromium",
        "--viewport-size", "1440,900",
        "--isolated",
        "--allowed-origins", "https://staging.example.com;https://api.staging.example.com",
        "--save-trace",
        "--output-dir", "./artifacts/playwright-mcp"
      ]
    }
  }
}
--isolated
Fresh in-memory profile per session. Use it: a shared profile leaks login state between runs and produces phantom passes.
--storage-state
The deliberate opposite — load a saved auth state so the agent starts logged in. Point it at a JSON file your normal auth setup already produces.
--allowed-origins
Origin allowlist. The strongest single guardrail here: the agent physically cannot navigate to production or to an attacker-controlled link found on a page.
--device
Device emulation, e.g. "iPhone 15". Cheap responsive checks without a device lab.
--save-trace
Writes a Playwright trace per session. This is your evidence artifact — attach it to the defect.
--headless
For CI. Keep it headed locally: watching the agent drive is how you catch it "succeeding" on the wrong element.

Workflows that actually pay off

1 · Explore-then-codify

The highest-value pattern, and the one most teams skip. Don't ask for a spec first — ask for exploration first.

Navigate to the staging checkout flow and complete a purchase with the test card 4242…. Take a snapshot at each step. Then list every element you interacted with, the locator you'd use for it, and flag any that had no accessible name.
Now write that flow as a Playwright test in tests/checkout.spec.ts, matching the fixtures and page-object style already used in tests/login.spec.ts. Run it. If it fails, fix the test — not the app — and show me the diff.

The second prompt matters more than the first. "Run it, and iterate until green" is what separates an agent from a code generator: it closes the loop itself, and you review a spec that has already passed rather than one that merely looks plausible.

2 · Reproducing a bug report into a regression test

Here's the bug report: "On mobile, applying a promo code clears the cart." Reproduce it with the iPhone 15 device profile against staging. Capture console messages and network requests around the failure. If it reproduces, write a failing Playwright test that encodes the correct behaviour and save it under tests/regression/.

You end up with three artifacts from one prompt: a confirmed repro, a network/console trace that tells the developer why, and the regression test that stops it coming back.

3 · Accessibility sweep as a side effect

Snapshot every page reachable from the main nav. For each, list interactive elements with a missing or ambiguous accessible name, and any heading-level skips. Output as a markdown table sorted by page.

4 · Cross-device regression

Run tests/checkout.spec.ts at 1440×900, 768×1024, and the iPhone 15 profile. Screenshot the order-summary panel in each and tell me where the layout diverges.

Gotchas

  • Snapshot size on heavy pages. A dense data grid produces a very large accessibility tree and can eat the context window in one call. Navigate to a narrower view, or ask the agent to snapshot after applying a filter.
  • Generated specs drift toward the happy path. Agents write the flow they just walked. Negative cases, boundary values, and error states still need you to ask for them explicitly — and they are where the bugs live.
  • browser_evaluate is a hole in your guardrails. Arbitrary JS in page context can set localStorage, call internal APIs, or bypass the UI entirely. Convenient for setup, but a test that reaches state via evaluate is not testing the UI. Watch for it in generated code.
  • Non-determinism between runs. The same prompt won't produce the same click sequence twice. Conversational driving is for exploration; the committed spec is the regression asset. Never wire "ask the agent to test checkout" into CI.
  • Page content is untrusted input. If the agent reads a product review, a support ticket, or a PDF rendered in the browser, that text is data — not instructions. Prompt-injection through user-generated content is a live risk for any browser-driving agent, and it matters more when the same agent also has write access to Jira or the database.
  • First run downloads browsers. Budget for it in CI images, or pre-bake with npx playwright install --with-deps chromium.
Verdict

Install this one first. If you only ever adopt a single MCP server for testing, it is this one, and the ROI shows up in week one on spec authoring and bug reproduction.

02

Chrome DevTools MCP

Gives the agent the DevTools panels: console, network, performance traces, and CPU/network emulation.

Official · Chrome DevTools team npx chrome-devtools-mcp Chromium only

Why a tester should care

Playwright tells you the test failed. Chrome DevTools MCP tells you the page fired a request that 404'd, blocked the main thread for 1.8 seconds, and shifted layout twice after first paint. It converts "the page feels slow" — the least actionable bug report in existence — into a trace with named insights and a number attached.

For a QA-to-AI engineer this is also the most useful server for root-causing your own flakes. A test that intermittently fails on a click is very often a test racing a slow XHR. The network panel shows you that in one call.

Tool surface

Tool groupRepresentative toolsQA use
Performanceperformance_start_trace, performance_stop_trace, performance_analyze_insightCore Web Vitals, long tasks, render-blocking resources — with the trace as evidence
Networklist_network_requests, get_network_requestStatus codes, payloads, timing, waterfall order
Consolelist_console_messagesSilent JS errors that never surface in the UI
Emulationemulate_cpu, emulate_network, resize_pageReproduce the bug that only happens on a mid-tier Android on 3G
Interactionnavigate_page, click, fill, take_snapshotEnough driving to reach the state you want to measure

Wire it up

shell
claude mcp add chrome-devtools -- npx -y chrome-devtools-mcp@latest
mcp config — attach to an already-running Chrome
{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": [
        "-y", "chrome-devtools-mcp@latest",
        "--headless=false",
        "--isolated=true"
      ]
    }
  }
}

It can also attach to an existing Chrome instance started with a remote debugging port, which is how you point it at a session you've already logged into by hand — useful for SSO-gated apps where scripting the login is more trouble than it's worth.

Workflows

1 · Performance budget as an acceptance criterion

Record a performance trace of a cold load of the staging dashboard on a 4× CPU slowdown and Slow 4G. Report LCP, CLS, and TBT, list the top three insights, and name the specific resources responsible. Then compare against production and tell me if the release regressed.

The comparison is the part that makes it a test rather than a measurement. A single LCP number is trivia; LCP versus the previous release is a pass/fail.

2 · The "nothing happened" bug

Click Save on the profile form, then show me every network request it triggered with status and response body, plus any console errors. The UI shows no feedback at all.

3 · Flake root-cause

This test fails ~1 in 8 runs on the click after login. Load the page, list network requests with timings, and tell me which request the button depends on and how variable its response time is.

4 · Third-party weight audit

List all network requests by third-party domain, with transfer size and blocking time. Which ones are render-blocking?

Gotchas

  • Traces are big. Ask for analysed insights, not raw trace dumps, or you'll fill the context window with JSON.
  • Numbers move. Local performance measurements vary with whatever else your machine is doing. Treat single runs as directional; only trust deltas measured back to back under the same emulation settings.
  • Chromium only. No Safari or Firefox story here. Pair with BrowserStack for real cross-browser performance.
  • Overlaps with Playwright. Both can click and navigate. If you run both, tell the agent explicitly which one owns driving ("use Playwright to reach the state, DevTools only to measure") or it will thrash between them.
Verdict

Add second, right after Playwright. It's read-only, needs no credentials, and turns vague performance complaints into filed, numbered defects.

03

Selenium MCP

WebDriver automation for the suite you already have. Built by Angie Jones; the pragmatic choice when migration isn't on the roadmap.

Community npx @angiejones/mcp-selenium Grid-compatible

Why a tester should care

Be honest about the situation this solves. If you have 4,000 Selenium tests in Java, a Grid in your own data centre, and a compliance process that signed off on that stack, "just migrate to Playwright" is not advice — it's a two-year project. Selenium MCP lets an agent work inside that world: prototype a flow, confirm locator behaviour on a real WebDriver session, and hand you something that fits the existing page objects.

There's a second, less obvious use: the agent as a locator archaeologist. Point it at a page and ask which of your existing XPaths still resolve. Legacy suites accumulate dead selectors, and finding them by hand is miserable work.

Tool surface

Deliberately WebDriver-shaped, which is the point — the vocabulary matches what your existing suite already speaks: start_browser, navigate, find_element, click_element, send_keys, get_element_text, hover, double_click, right_click, drag_and_drop, press_key, upload_file, take_screenshot, close_session.

Locator strategies are the familiar set: id, css, xpath, name, tag, class. Note what's missing versus Playwright — there's no accessibility snapshot, so the agent is working from screenshots and its own guesses at selectors rather than a structured tree. That is the core trade-off.

Wire it up

shell
claude mcp add selenium -- npx -y @angiejones/mcp-selenium
mcp config
{
  "mcpServers": {
    "selenium": {
      "command": "npx",
      "args": ["-y", "@angiejones/mcp-selenium"]
    }
  }
}

Browser drivers must be resolvable on the host — modern Selenium handles most of this via Selenium Manager, but a corporate proxy will break that silently. Test start_browser before assuming the install worked. For Grid, the agent starts a session against your hub URL, so the same network access rules as your normal suite apply.

Workflows

1 · Locator audit

Here are the 30 XPath locators from CheckoutPage.java. Open staging, try each one, and report which resolve, which resolve to more than one element, and which fail. For the failures, suggest a replacement using a stable attribute.

2 · Prototype before you write Java

Walk the guest-checkout flow on staging with Selenium. Record the exact locators and actions that worked, then output them as a Java page object matching the structure of LoginPage.java.

3 · Migration triage

Read src/test/java/checkout/. Which tests depend on implicit waits or Thread.sleep? Rank them by how likely they are to be flaky and estimate migration effort to Playwright.

Gotchas

  • No accessibility tree means guessier locators. The agent is inferring selectors rather than reading references. Review everything it produces; a locator that worked once may have matched by accident.
  • Session leakage. Agents forget to call close_session. Orphaned browsers accumulate, and on a shared Grid that's someone else's outage. Check for stray sessions after long conversations.
  • Community maintenance. Check the repo's commit activity before committing a team to it. This is not a vendor-supported product with an SLA.
  • Don't run alongside Playwright MCP. Tool collision is near-certain.
Verdict

Right tool for a real constraint. If you have a choice and no legacy suite, choose Playwright — the accessibility-tree difference is not a small one. If you don't have a choice, this is a genuinely useful bridge and a good way to build the migration business case with data.

04

Puppeteer MCP

Lightweight Chromium driving for headless verification and scraping-adjacent tasks.

Reference server archived Community forks Chromium only
Read this before installing

The original @modelcontextprotocol/server-puppeteer reference implementation was moved to the archived section of the MCP servers repository. Several community forks continue it under various names and quality levels. Nothing about Puppeteer MCP is uniquely capable versus Playwright MCP — if you are choosing today with no existing Puppeteer code, choose Playwright and skip this section.

Where it still fits

Three honest cases. First, you already have a Puppeteer codebase and want the agent to speak the same API. Second, you want a very small footprint for a scheduled headless check — "does the login page render and return 200" — where Playwright's browser matrix is overkill. Third, content extraction: pulling rendered HTML out of a JS-heavy page into the agent's context, where Fetch MCP would only get you the empty shell.

That third case is real and under-appreciated. If you're building test data or a RAG corpus from pages that render client-side, a headless browser is the only thing that works.

Tool surface

Small by design: puppeteer_navigate, puppeteer_screenshot, puppeteer_click, puppeteer_fill, puppeteer_select, puppeteer_hover, puppeteer_evaluate. CSS selectors throughout — no accessibility-tree reasoning, no built-in tracing, no network panel.

Wire it up

mcp config — verify the package first
{
  "mcpServers": {
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
      "env": {
        "PUPPETEER_LAUNCH_OPTIONS": "{\"headless\": true, \"args\": [\"--no-sandbox\"]}",
        "ALLOW_DANGEROUS": "false"
      }
    }
  }
}
--no-sandbox

Common in containers, and it disables a Chromium security boundary. If the agent then navigates to arbitrary external URLs, you've combined "runs untrusted web content" with "no sandbox". Keep this flag inside a container you'd be willing to throw away, and don't set ALLOW_DANGEROUS=true because a tool error suggested it.

Workflows

1 · Post-deploy smoke

For each of these 12 URLs, navigate, wait for network idle, screenshot, and report any that returned non-200, showed an error boundary, or rendered an empty main region.

2 · Rendered-content extraction for test data

Open each product page in urls.txt, extract the rendered title, price, and stock status, and write them to fixtures/products.json.

Gotchas

  • Maintenance is on you. Archived reference, forks of varying quality. Pin a version and read the source before it touches anything sensitive.
  • Scraping has rules. Respect robots.txt, terms of service, and rate limits. "The agent did it" is not a defence.
  • No trace, no network panel. When something fails you get a screenshot and a shrug.
Verdict

Skip unless you have existing Puppeteer code or a specific need for a minimal headless renderer. Playwright MCP does everything here, better, with a maintained upstream.

05

Maestro MCP

Mobile UI automation for Android and iOS, exposed through a thin gateway over the Maestro CLI.

Vendor · mobile.dev Ships with Maestro CLI Android + iOS

Why a tester should care

Mobile automation has historically been the worst developer experience in test engineering: Appium capability matrices, driver version drift, and a feedback loop measured in minutes. Maestro's pitch is declarative YAML flows with built-in waiting — no explicit sleeps, no WebDriverWait ceremony. The MCP server puts an agent in front of that.

The gateway architecture matters practically: the MCP server is a thin layer, and the actual device interaction is the same Maestro CLI your CI already runs. Flows the agent authors are ordinary .yaml files you commit — no separate agent-only execution path. That is exactly the property you want, and it's what makes generated mobile tests trustworthy.

Tool surface

GroupRepresentative toolsQA use
Devicestart_device, list_devices, launch_app, stop_appBoot a simulator/emulator, install and launch the build
Perceptiontake_screenshot, inspect_view_hierarchyThe hierarchy is the mobile equivalent of the a11y tree — prefer it over screenshots
Interactiontap_on, input_text, back, swipeDrive the flow
Flowsrun_flow, run_flow_files, check_flow_syntaxExecute inline YAML or committed flow files; validate before running

Wire it up

Install the Maestro CLI first — the MCP server is a subcommand of it, not a separate package.

shell — install Maestro (macOS/Linux)
curl -fsSL "https://get.maestro.mobile.dev" | bash
maestro --version
mcp config
{
  "mcpServers": {
    "maestro": {
      "command": "maestro",
      "args": ["mcp"]
    }
  }
}

Prerequisites are the usual mobile ones and they are the real install cost: Android SDK plus a configured emulator (or a device with USB debugging), and for iOS, Xcode with a booted simulator on macOS. Windows users testing iOS still need a Mac somewhere — MCP does not change that.

Workflows

1 · Author a flow by doing it

Launch the app on the Pixel 8 emulator, sign in as qa+demo@example.com, and add an item to the basket. Inspect the view hierarchy at each step and prefer accessibility ids over text. Then write it as .maestro/basket-add.yaml, check the syntax, and run it twice to confirm it's stable.

"Run it twice" is not padding. A mobile flow that passes once and fails the second time is the most common failure mode, usually an animation or a permission dialog on first launch.

2 · Permission and interrupt handling

Run the onboarding flow on a freshly reset emulator. Note every system dialog — notifications, location, tracking — and add explicit handling for each to the flow so it works on both a clean install and an upgrade.

3 · Cross-platform parity

Run .maestro/checkout.yaml on both the Android emulator and the iOS simulator. Where the flow needed platform-specific selectors, list them and tell me whether the difference is a real UX divergence or just an accessibility-id gap.

That last question is the valuable one — parity testing frequently surfaces accessibility labelling that one platform team did and the other didn't.

Gotchas

  • Environment setup dominates. Ninety percent of the pain is SDKs, emulators, and signing. The MCP layer is the easy part; budget accordingly.
  • Emulators are not devices. They won't reproduce thermal throttling, real network conditions, biometric hardware, or manufacturer skins. Pair with BrowserStack for the real-device matrix on anything user-facing.
  • Screenshot-driven tapping is fragile. Push the agent to inspect_view_hierarchy and address elements by accessibility id. Tapping coordinates derived from a screenshot breaks on the next device size.
  • iOS needs macOS. No way around it.
Verdict

The best available answer for conversational mobile testing, mostly because the generated artifact is a plain committed YAML flow rather than an agent-only script. Adopt if mobile is in scope; the flows outlive the conversation.

How to choose between them

If your situation is…UseBecause
Greenfield web UI automationPlaywrightAccessibility-tree locators, tracing, cross-browser, maintained by Microsoft
"It's slow" / "it errors silently"Chrome DevToolsOnly one with traces, network waterfall, and CPU/network emulation
Large existing WebDriver suiteSeleniumSpeaks your suite's vocabulary; no migration required
Minimal headless checks or rendered-page extractionPuppeteer (or just Playwright)Smaller surface — but check fork maintenance
Native Android / iOSMaestroDeclarative flows with implicit waiting; generated flows are committable
Real devices, many browsers, no labBrowserStackSee Test management
The pairing that works

Playwright + Chrome DevTools, and nothing else in this category. Playwright drives and asserts; DevTools observes and explains. Together they cover authoring, execution, debugging, and performance without a single credential between them — which also makes this the safest pair to hand a junior engineer.