Playwright MCP Integration
Learn how to expose Playwright's browser automation capabilities as MCP Tools, enabling your AI agents to autonomously navigate, click, and assert DOM state.
How The Workflow Operates
When a user prompts the LLM to "Test the login page", the LLM doesn't write static code. It dynamically selects the `browser_navigate` tool, passes the URL as a JSON argument, and the MCP client routes this to the Playwright server. The server executes it in a real browser and returns the result (e.g. DOM snapshot) back to the LLM.

How AI Helps Generate Scripts
You can use the Playwright MCP server in a dual mode. Instead of just running tests, you can ask the agent: "Navigate to /checkout, find all input fields, and generate a robust Playwright TypeScript test file."
1. AI Explores the DOM
The agent uses `browser_evaluate` to dump the accessibility tree and find stable data-test-ids automatically.
2. AI Writes the Script
Using standard `fs` (FileSystem) MCP tools alongside Playwright, the agent writes the `.spec.ts` file perfectly formatted directly to your repo.
Step-by-Step E2E Implementation
You can build your Playwright MCP pipeline using either the official **TypeScript/Node.js stack** or a custom **Python-based FastMCP stack**. Explore the complete guides for both options below.
⚡ The 60-Second Zero-Code Setup (Recommended)
You do NOT need to write a single line of custom code to use Playwright MCP! You can use Microsoft's official pre-built server immediately. Just copy and paste this JSON block into your AI client configuration (e.g. Cursor, Windsurf, or Claude Desktop):
{
"mcpServers": {
"official-playwright": {
"command": "npx",
"args": ["-y", "@playwright/mcp@latest"]
}
}
}Option ATypeScript: Official Microsoft & Custom SDK Setup
Under Node.js, you can build a customized server using Microsoft's official @playwright/mcp and the standard @modelcontextprotocol/sdk.
Step 1: Install NPM Packages
Initialize a Node project and install the official SDK and compiler utilities:
npm init -y
npm install @modelcontextprotocol/sdk playwright
npm install --save-dev typescript @types/node tsx
Step 2: Build the Server
Write a custom script `mcp_playwright_server.ts` to manage Chromium page instances asynchronously:
import{ Server }from"@modelcontextprotocol/sdk/server/index.js";import{ StdioServerTransport }from"@modelcontextprotocol/sdk/server/stdio.js";import{ CallToolRequestSchema, ListToolsRequestSchema }from"@modelcontextprotocol/sdk/types.js";import{ chromium, Browser, Page }from"playwright";letbrowser: Browser |null=null;letpage: Page |null=null;constserver =newServer(
{ name:"playwright-mcp-ts", version:"1.0.0"},
{ capabilities: { tools: {} } }
);
// 1. Expose the list of custom Playwright tools to LLM
server.setRequestHandler(ListToolsRequestSchema,async() => {
return{
tools: [
{
name:"navigate_and_query",
description:"Navigates to URL and performs locator DOM snapshot query.",
inputSchema: {
type:"object",
properties: { url: { type:"string"} },
required: ["url"]
}
}
]
};
});
// 2. Handle execution of the Playwright tool
server.setRequestHandler(CallToolRequestSchema,async(request) => {
const{ name, arguments: args } = request.params;
if(!browser) {
browser =awaitchromium.launch({ headless:true});
page =awaitbrowser.newPage();
}
if(name ==="navigate_and_query") {
consturl = args?.urlasstring;
awaitpage.goto(url, { waitUntil:"networkidle"});
constcontent =awaitpage.content();
return{
content: [{ type:"text", text: `Title: ${await page.title()}. DOM: ${content.slice(0, 300)}...` }]
};
}
throw newError("Tool execution failed.");
});async functionrun() {
consttransport =newStdioServerTransport();
awaitserver.connect(transport);
}
run().catch(console.error);
Option BPython: Custom FastMCP Server Wrapper Setup
Alternatively, you can build your server using Python's high-level fastmcp framework to quickly expose complex custom locators and auth actions.
Step 1: Install Python Libraries
Install FastMCP and Playwright, then register standard browser binaries:
pip install fastmcp playwright
playwright install chromium
Step 2: Build the Server
Write `playwright_mcp_server.py` to register custom navigation functions as client-accessible tools:
fromfastmcpimportFastMCPfromplaywright.sync_apiimportsync_playwright
# Initialize Server
server = FastMCP("Custom-Playwright-Server")@server.tool()defnavigate_and_screenshot(url:str) ->str:
"""Navigates to a URL and takes a screenshot for visual validation."""
withsync_playwright()asp:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(url)
# Dump the DOM context for the LLM to read
dom_snapshot = page.content()
browser.close()
returnf"Successfully navigated to {url}. DOM state: {dom_snapshot[:300]}..."if__name__ =="__main__":
server.run(transport="stdio")
Instructor Note
Notice how we return the `page.content()` back to the LLM? This is critical! The LLM needs the DOM string as "Observation" so it can decide its next Thought and Action.
Python vs. TypeScript MCP Playwright Options
Depending on your team's stack, you can implement Playwright MCP using either Microsoft's official TypeScript server or a custom Python-based server. Use this comprehensive comparison matrix to decide the best architectural path for your QA automation pipeline.
| Feature / Option | TypeScript Option (Microsoft) | Python Option (Custom FastMCP) |
|---|---|---|
| Ecosystem Package | @playwright/mcp | fastmcp + playwright |
| Official Status | Official by Microsoft | Community Standard |
| Installation & Boot | Instant (run via npx) | Requires virtualenv & package dependencies installation |
| Vision & Screen Capture | Automatic base64-encoded visual capture built-in | Requires custom writing of base64 image-saving logic |
| DOM Representation | Advanced Semantic Accessibility trees (highly efficient for non-vision LLMs) | Raw HTML snippets or element extraction strings |
| Customization Scale | Standardized suite (harder to adapt to in-house testing frameworks) | Extremely High (custom Python decorators map seamlessly to any setup) |
| Execution Runtime | Node.js (Low resource footprint, native async operations) | Python (FastMCP auto-generates schema types effortlessly) |