playwright-mcp-server
Allows Hermes Agent to perform browser automation tasks such as navigation, clicking, typing, and state persistence.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@playwright-mcp-server Navigate to example.com and get the page title"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
playwright-mcp-server
A stateful MCP server that wraps Playwright for browser automation.
Stateful — single Chromium browser/context/page shared across all tool calls
Persistent — session state (cookies, localStorage, active URL) survives server restarts
Resilient — structured MCP error results on every tool call; browser crash auto-recovery
Tested — 49 unit tests, no browser required to run the test suite
Quick start
git clone https://github.com/doucej/playwright-mcp-server.git
cd playwright-mcp-server
npm install
npx playwright install chromium
npm run build
npm start
# [playwright-mcp] Server ready — listening on stdio.Related MCP server: Playwright MCP
MCP client configuration
opencode (~/.config/opencode/opencode.json)
{
"mcp": {
"playwright": {
"type": "local",
"command": ["node", "/path/to/playwright-mcp-server/dist/server.js"],
"enabled": true
}
}
}Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"playwright": {
"command": "node",
"args": ["/path/to/playwright-mcp-server/dist/server.js"]
}
}
}Hermes Agent (config.yaml)
mcp_servers:
playwright:
command: "node"
args: ["/path/to/playwright-mcp-server/dist/server.js"]
env:
STATE_DIR: "/path/to/playwright-mcp-server/state"
timeout: 120
connect_timeout: 30Available tools
Tool | Required args | Optional args | Description |
|
| — | Navigate to a URL |
| — | — | Browser back |
| — | — | Browser forward |
| — | — | Reload current page |
| — | — | Return current URL |
|
| — | Click element |
|
|
| Type into element (appends) |
|
| — | Fill input (replaces existing value) |
|
| — | Press keyboard key |
|
| — | Hover over element |
|
| — | Select |
|
| — | Get visible text content |
|
| — | Get element attribute value |
| — |
| Get inner HTML (default: |
|
| — | Execute JavaScript, return JSON |
|
|
| Wait for element |
| — |
| Capture PNG screenshot |
| — | — | Persist session to disk |
| — | — | Restore session from disk |
State persistence
save_state (and graceful shutdown via SIGINT/SIGTERM) writes state/session.json containing Playwright's storageState (cookies + localStorage for all visited origins) plus the current page URL.
On the next startup the session is rehydrated automatically — storageState is passed to newContext() and the page navigates back to the saved URL.
Override the state directory:
STATE_DIR=/tmp/my-session npm startProject structure
src/
server.ts MCP server entrypoint — stdio transport, startup, graceful shutdown
session.ts PlaywrightSession — lazy init, crash recovery, state save/restore
persistence.ts Read/write state/session.json; STATE_DIR override
tools.ts All 19 tool definitions + handlers; Zod validation; handle() wrapper
types.ts SessionState / StorageState interfaces
tests/
persistence.test.ts 7 unit tests — no browser required
session.test.ts 11 unit tests — Playwright mocked with vi.hoisted
tools.test.ts 31 unit tests — session mocked inline
state/ Created at runtime; holds session.json (git-ignored)
dist/ TypeScript compile output (git-ignored)Development
npm run dev # run with tsx (no compile step)
npm test # run test suite (49 tests, no browser needed)
npm run typecheck # type-check without emitting
npm run build # compile TypeScript → dist/Architecture
Singleton session — the MCP server is a long-running stdio process; a single PlaywrightSession instance guarantees exactly one browser across all tool dispatches.
Error isolation — every tool handler runs inside the handle() wrapper (src/tools.ts). Both Zod validation errors and Playwright runtime exceptions are caught and returned as { isError: true } MCP results. The server never throws.
Crash recovery — ensureInitialized() checks browser.isConnected() and page.isClosed() before every call. If the browser has crashed it relaunches and restores from the last persisted state.
License
Available Tools
19 toolsclickB
Click the first element matching the given selector.
Inputs: selector (required).
evaluateA
Execute a JavaScript expression in the page context and return the result as JSON. The expression may return any serialisable value.
Inputs: script (required).
fillA
Set the value of an input or textarea, replacing any existing content.
Inputs: value (required), selector (required).
get_attributeB
Return the value of an attribute on the first element matching the selector.
Inputs: selector (required), attribute (required).
get_htmlA
Return the inner HTML of the first matching element. Defaults to when no selector is provided.
Inputs: selector.
get_textA
Return the visible text content of the first element matching the selector.
Inputs: selector (required).
get_urlA
Return the URL of the current page.
Inputs: no named parameters.
go_backA
Navigate back in the browser history.
Inputs: no named parameters.
go_forwardA
Navigate forward in the browser history.
Inputs: no named parameters.
hoverC
Move the mouse over an element.
Inputs: selector (required).
load_stateA
Reload the browser session from the last state saved on disk. Closes the current browser and opens a fresh one with the persisted cookies and URL.
Inputs: no named parameters.
open_pageA
Navigate to a URL. Waits for DOMContentLoaded before returning.
Inputs: url (required).
pressA
Focus an element and press a keyboard key (e.g. Enter, Tab, Escape, ArrowDown).
Inputs: key (required), selector (required).
reloadA
Reload the current page.
Inputs: no named parameters.
save_stateA
Persist the current browser session (cookies, localStorage, active URL) to disk. The state is reloaded automatically on server restart.
Inputs: no named parameters.
screenshotA
Capture a PNG screenshot of the current page or a specific element.
Inputs: selector, full_page.
select_optionA
Select an option in a element by value.
Inputs: value (required), selector (required).
typeA
Type text into a focusable element, appending to any existing value. Use fill to replace the existing value instead.
Inputs: text (required), selector (required), delay.
wait_for_selectorA
Wait until an element matching the selector is present.
Inputs: selector (required), state, timeout.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 19 tools
Each tool targets a distinct browser action: navigation, input, extraction, evaluation, and state management. Type and fill are clearly differentiated by append vs. replace, and other tools like get_text and get_html have distinct return types.
All names use lowercase snake_case with imperative verbs. Most follow a verb_noun pattern (open_page, get_text), but a few are bare verbs (click, reload, hover), which is a minor deviation rather than a major inconsistency.
With 19 tools, the set is on the heavier side and crosses into the 'feels heavy' range. While browser automation justifies many actions, some tools like save_state and load_state seem auxiliary and could potentially be combined or omitted.
The set covers core browser workflows: navigation, interaction, extraction, waiting, screenshots, and state persistence. Minor gaps exist (e.g., no explicit drag-and-drop or dialog handling), but these can be worked around using evaluate or other tools.
Maintenance
Related MCP Connectors
Official Browserless MCP server: browser automation, scraping, screenshots and PDFs for AI agents.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Related MCP Servers
- AlicenseBqualityNot gradedmaintenanceA MCP server that provides browser automation tools, allowing users to navigate websites, take screenshots, click elements, fill forms, and execute JavaScript through Playwright.82Apache 2.0
- FlicenseBqualityDmaintenancePlaywright wrapper for MCP that enables LLM-powered clients to control a browser for automation tasks.101-
- AlicenseNot gradedqualityDmaintenanceEnables browser automation and web scraping by exposing Playwright tools through an HTTP-based MCP server. Users can navigate pages, interact with web elements, capture screenshots, and extract structured content using a persistent Chromium instance.MIT
- AlicenseBqualityDmaintenanceAn MCP server for generic browser automation using Playwright. Enables MCP clients to navigate pages, inspect elements, execute JavaScript, capture screenshots, and monitor console logs and network traffic via a headless Chromium instance.727 npmISC