Skip to main content
Glama
playwright-mcp-server

playwright-mcp-server

by doucej

playwright-mcp-server

CI License: MIT Node.js >=18

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: 30

Available tools

Tool

Required args

Optional args

Description

open_page

url

—

Navigate to a URL

go_back

—

—

Browser back

go_forward

—

—

Browser forward

reload

—

—

Reload current page

get_url

—

—

Return current URL

click

selector

—

Click element

type

selector, text

delay

Type into element (appends)

fill

selector, value

—

Fill input (replaces existing value)

press

selector, key

—

Press keyboard key

hover

selector

—

Hover over element

select_option

selector, value

—

Select <select> option

get_text

selector

—

Get visible text content

get_attribute

selector, attribute

—

Get element attribute value

get_html

—

selector

Get inner HTML (default: body)

evaluate

script

—

Execute JavaScript, return JSON

wait_for_selector

selector

timeout, state

Wait for element

screenshot

—

full_page, selector

Capture PNG screenshot

save_state

—

—

Persist session to disk

load_state

—

—

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 start

Project 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

MIT

Available Tools

19 tools
clickB

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

    A3.6/5.0

    Scored across 19 tools

    Disambiguation5/5

    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.

    Naming Consistency4/5

    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.

    Tool Count3/5

    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.

    Completeness4/5

    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

    ActivityInactive
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      Not graded
      maintenance
      A MCP server that provides browser automation tools, allowing users to navigate websites, take screenshots, click elements, fill forms, and execute JavaScript through Playwright.
      8
      2
      Apache 2.0
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables 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
    • A
      license
      B
      quality
      D
      maintenance
      An 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.
      7
      27 npm
      ISC