Skip to main content
Glama
ademdeniz
by ademdeniz

playwright-mcp

An MCP server that gives Claude direct control of a real browser via Playwright — enabling AI-driven web testing, autonomous test execution, and live failure analysis through natural language.

TypeScript Playwright MCP CI License


What It Does

Connect this server to Claude Desktop or Cursor and Claude gains the ability to:

  • Navigate to any URL and read the full page state

  • Click elements, fill forms, pick dropdown options, press keys, and submit data

  • Wait for slow content instead of guessing with sleeps

  • Take screenshots it can actually see (returned as images, not base64 text)

  • Read console errors, uncaught exceptions, and failed network requests

  • Assert expected conditions — with auto-retry, pass/fail with the actual value

  • Analyze failures autonomously without you touching a test script

It ships with two portable QA skills (skills/) that work with this server or Microsoft's @playwright/mcp: one runs written test scenarios and reports a PASS/FAIL table with a root cause, the other turns a verified run into a Playwright spec that follows your repo's conventions.

Example prompt to Claude:

"Test the login flow on the-internet.herokuapp.com. Use username 'tomsmith' and password 'SuperSecretPassword!'. Verify the success message and take a screenshot."

Claude will navigate, fill the form, click submit, assert the result, and take a screenshot — all without you writing a single line of test code.


Related MCP server: Glance

Architecture

┌──────────────────────────────────────────────────────┐
│              Claude Desktop / Cursor                  │
│                                                       │
│   "Test the login flow on example.com"                │
└──────────────────────┬───────────────────────────────┘
                       │ MCP (stdio, Streamable HTTP, or SSE)
┌──────────────────────▼───────────────────────────────┐
│               playwright-mcp server                   │
│                                                       │
│  Tools:                                               │
│   navigate       → page.goto(url)                    │
│   get_page_state → text + elements + errors          │
│   screenshot     → page.screenshot() → image         │
│   click / fill   → locator.click() / .fill()         │
│   select_option  → locator.selectOption()            │
│   press_key      → keyboard.press()                  │
│   wait_for       → element / text / URL              │
│   evaluate       → page.evaluate(js)                 │
│   assert         → 9 assertion types, auto-retry     │
│   close_browser  → browser.close()                   │
└──────────────────────┬───────────────────────────────┘
                       │ Playwright CDP
┌──────────────────────▼───────────────────────────────┐
│      Chromium / Firefox / WebKit (headless)           │
└──────────────────────────────────────────────────────┘

Tools

Tool

Description

navigate

Go to a URL, returns title, final URL, status code; resets the error log

get_page_state

Title, URL, visible text, interactive elements with ready-to-use selectors, console errors, uncaught exceptions, failed requests

screenshot

Capture viewport, full page, or one element — returned as an image; optional save

click

Click by CSS selector or visible text; follows links that open a new tab

fill

Type into input fields (password values are never echoed back or logged)

select_option

Choose a <select> option by value, label, or index

press_key

Press Enter, Escape, Tab, chords like Control+A

wait_for

Wait for an element state, visible text, or URL

set_viewport

Resize the viewport (e.g. 320 px wide for mobile layout and reflow checks); reports horizontal scrolling

set_browser_mode

Switch between headless and a visible window while running: reopens the current page, keeps logins with a persistent profile

evaluate

Run JavaScript in the page context (can be disabled)

assert

title_contains, url_contains, text_visible, text_absent, element_exists, element_visible, element_hidden, input_value, element_count — retries up to 5 s by default

close_browser

Close browser and release resources

Only visible elements are targeted, so hidden duplicates (mobile menus, templates) don't cause timeouts.


Setup

Prerequisites

  • Node.js 20+

  • Claude Desktop or any MCP-compatible host

Install

git clone https://github.com/ademdeniz/playwright-mcp.git
cd playwright-mcp
npm install
npm run install-browsers   # downloads Chromium
npm run build

Connect to Claude Code

claude mcp add playwright -- node /absolute/path/to/playwright-mcp/dist/server.js

Connect to Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "playwright": {
      "command": "node",
      "args": ["/absolute/path/to/playwright-mcp/dist/server.js"]
    }
  }
}

Restart Claude Desktop. You'll see a 🔌 icon showing the server is connected.

Connect to Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "playwright": {
      "command": "node",
      "args": ["/absolute/path/to/playwright-mcp/dist/server.js"]
    }
  }
}

QA Agent Setup (LibreChat + SSE)

Day-to-day operations (start, stop, health checks, logs) are collected in COMMANDS.md. The complete agent recipe (endpoint, model parameters, instructions, skills) is in examples/qa-agent-setup.md.

Beyond stdio hosts, this server ships an SSE transport so Docker-hosted MCP clients — like a self-hosted LibreChat — can drive the browser over HTTP. This powers a full AI QA Engineer agent: a chat UI where you type test steps in plain English and watch them execute against a real browser, with tunable model parameters, reusable skills, and a local audit log of every tool call.

Run the HTTP server

npm run start:sse          # http://127.0.0.1:8931 — /mcp, GET /sse, POST /messages, GET /health
PORT=9000 npm run start:sse

It serves both Streamable HTTP (/mcp, the current MCP spec) and legacy SSE (/sse). It listens on 127.0.0.1 only by default. Docker containers can't reach that, so for LibreChat see Securing the HTTP server.

Register in LibreChat (librechat.yaml)

mcpSettings:
  allowedAddresses:        # SSRF exemption for the host-mapped address
    - 'host.docker.internal:8931'

mcpServers:
  playwright:
    type: sse
    url: http://host.docker.internal:8931/sse
    timeout: 300000
    headers:                 # only when PLAYWRIGHT_MCP_TOKEN is set (recommended)
      Authorization: "Bearer ${PLAYWRIGHT_MCP_TOKEN}"

Then build an agent in LibreChat's Agent Builder: attach the playwright MCP tools, paste examples/librechat-agent-instructions.md into the Instructions field, and add the skills: the generic ones from skills/ plus the app-specific ones from examples/skills/ (app selector map, repo conventions) and the scenarios in examples/scenarios/.

Model notes (learned the hard way)

  • Context window matters: Ollama defaults to 4096 tokens, which silently truncates tool schemas — the model then hallucinates Selenium code instead of calling tools. Run OLLAMA_CONTEXT_LENGTH=8192 ollama serve minimum.

  • Thinking models stall: qwen3-style reasoning burns minutes of monologue per tool call on modest hardware. Use a non-thinking instruct variant, or a fast cloud endpoint (Groq / Gemini free tiers) for the agent brain while the browser and tests stay local.

  • Some models batch tool calls: llama-3.3 emits all steps at once, which arrive in scrambled order. The server rejects concurrent calls with an instructive error so such clients recover by re-issuing steps one at a time.

Hardening built into the server

  • Per-call timeout — a call that hangs (e.g. an infinite loop in evaluate) is cut off after 60 s and the browser is reset, so the server never wedges

  • Crash recovery — a crashed or closed browser is relaunched on the next call

  • Auto-retrying asserts — checks wait for the page to settle instead of failing on the first look

  • Clear argument errors — a missing selector returns a message the model can act on, not a stack trace

  • Clean shutdown — the browser is closed on exit, so no orphaned processes

  • One tool at a time — concurrent calls are rejected, not queued, so a stray close_browser can never execute mid-scenario

  • Launch lock — concurrent getPage() calls share one Chromium launch instead of racing several

  • Token-lean page state — get_page_state caps text and element output, since agent loops re-pay for every past tool result on each round

  • Call logging — every tool call is logged with its arguments; when the client's transcript and reality disagree, the server log is ground truth


Configuration

All options are environment variables. Put them in the env block of your MCP client config, or prefix the start command.

Variable

Default

Purpose

PLAYWRIGHT_MCP_BROWSER

chromium

chromium, firefox, or webkit (install with npx playwright install <name>)

PLAYWRIGHT_MCP_HEADLESS

true

false shows the browser window — handy for watching a run

PLAYWRIGHT_MCP_VIEWPORT

1280x800

Viewport size, WIDTHxHEIGHT

PLAYWRIGHT_MCP_USER_AGENT

browser default

Override the user agent

PLAYWRIGHT_MCP_TOOL_TIMEOUT_MS

60000

Hard limit per tool call; on timeout the browser is reset

PLAYWRIGHT_MCP_OUTPUT_DIR

<tmp>/playwright-mcp

Screenshots can only be saved inside this directory

PLAYWRIGHT_MCP_SCREENSHOT_IMAGE

true

false returns screenshot metadata only (for text-only models)

PLAYWRIGHT_MCP_DISABLE_EVALUATE

false

true removes the evaluate tool

PLAYWRIGHT_MCP_ALLOW_FILE_URLS

false

true allows navigate to file:// URLs

PLAYWRIGHT_MCP_USER_DATA_DIR

—

Persistent browser profile folder: cookies and SSO logins survive close_browser and restarts (see below)

PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS

false

true accepts self-signed / internal certificates. Test environments only

HOST / PORT

127.0.0.1 / 8931

HTTP server bind address and port

PLAYWRIGHT_MCP_TOKEN

—

HTTP server: require Authorization: Bearer <token>

PLAYWRIGHT_MCP_ALLOW_NO_AUTH

false

HTTP server: allow a non-localhost bind without a token


Testing behind SSO (company environments)

The agent never types your SSO credentials: you log in once, in a visible browser, and the server keeps that session.

  1. Register the server with a visible browser and a persistent profile:

    claude mcp add --scope user playwright \
      -e PLAYWRIGHT_MCP_HEADLESS=false \
      -e PLAYWRIGHT_MCP_USER_DATA_DIR=~/.playwright-mcp/profile \
      -- node /absolute/path/to/playwright-mcp/dist/server.js

    Add -e PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS=true if your preview/test environments use internal certificates the browser doesn't trust.

  2. Ask the agent to open your environment (e.g. a preview URL). When it lands on the SSO page, log in yourself in the browser window it opened, then tell the agent to continue.

  3. Headless first pass, visible window to investigate. You can also start headless (PLAYWRIGHT_MCP_HEADLESS=true): the agent runs fast and invisibly, and calls set_browser_mode to open a visible window when it needs you to log in, or to reproduce a failure where you can watch. The profile keeps the login across the switch.

  4. The SSO session is stored in the profile. Later sessions — and other preview environments behind the same identity provider — usually go straight through without logging in again, until your company's SSO session expires.

Notes:

  • One session per profile. A visible browser locks its profile, so a second session on the same folder gets a clear error. Give parallel sessions their own folder (…/profile-2). Headless browsers don't lock it, so don't share a profile between headless sessions either.

  • The profile holds live login cookies. Keep it in your home folder, never in a repository, and delete it (rm -rf ~/.playwright-mcp/profile) to log out everywhere.

  • Use test or preview environments and test accounts — not production.


Securing the HTTP server

Whoever can reach the HTTP server can drive the browser and run JavaScript in it, so it is locked down by default:

  • Localhost only. It binds 127.0.0.1 and rejects requests whose Host or Origin header isn't localhost, which blocks DNS-rebinding attacks from web pages you visit.

  • Token for anything wider. Binding another address (e.g. HOST=0.0.0.0 for Docker) is refused unless you set a token:

    export PLAYWRIGHT_MCP_TOKEN="$(openssl rand -hex 32)"
    HOST=0.0.0.0 npm run start:sse

    Clients then send Authorization: Bearer <token> (see the LibreChat headers example above; LibreChat reads ${PLAYWRIGHT_MCP_TOKEN} from its own .env).

  • Opting out on a fully trusted network: PLAYWRIGHT_MCP_ALLOW_NO_AUTH=1. scripts/start-stack.sh uses the token when it's exported and falls back to this with a warning.

The stdio transport has no network surface and needs none of this.


Skills

skills/ holds portable skills in the open SKILL.md format for Claude Code, Cursor, Copilot, and other agents. Each works with this server or Microsoft's @playwright/mcp:

Skill

What it does

regression-scenarios

Runs written scenarios (smoke, regression, ad-hoc steps), classifies each failure (product defect, expected rejection, test issue, environment), and reports a PASS/FAIL table with evidence

write-playwright-test

Turns a verified run into a Playwright Test spec that follows the repo's own page objects, fixtures, tags, and locator style

Install in Claude Code by copying a folder into ~/.claude/skills/ (all projects) or .claude/skills/ (one project):

cp -r skills/regression-scenarios skills/write-playwright-test ~/.claude/skills/

App-specific examples — a selector map, repo conventions, and scenarios for the-internet.herokuapp.com — are in examples/.


Development

npm test     # builds, then runs the end-to-end suite against local fixture pages

The suite drives a real Chromium through the MCP protocol (stdio, Streamable HTTP, and SSE), including the auth rules above. CI runs it on Node 20 and 22.


Example Flows

Login test

You: "Test login on https://the-internet.herokuapp.com/login
      with tomsmith / SuperSecretPassword!"

Claude: navigate → fill username → fill password → click Login
        assert text_visible "You logged into a secure area!" → ✓ PASSED
        screenshot → saved to screenshots/login_success.png

Broken image analysis

You: "Check https://the-internet.herokuapp.com/broken_images
      and tell me which images failed to load"

Claude: navigate → get_page_state → evaluate (check naturalWidth)
        "2 of 3 images are broken — both return 404.
         Root cause: server paths do not exist."

Form validation

You: "Submit the contact form on example.com with empty fields
      and verify the validation errors appear"

Claude: navigate → click Submit → get_page_state
        assert element_exists ".error-message" → ✓
        assert text_visible "This field is required" → ✓

Project Structure

playwright-mcp/
├── src/
│   ├── server.ts              # MCP server — tool registry, one-at-a-time execution, timeouts, call log
│   ├── sse.ts                 # HTTP transport — Streamable HTTP + SSE, localhost/token auth
│   ├── browser.ts             # BrowserManager — launch lock, crash recovery, tabs, diagnostics
│   ├── config.ts              # environment-variable configuration
│   └── tools/
│       ├── navigate.ts        # page.goto()
│       ├── getPageState.ts    # text + elements with selectors + errors (token-lean)
│       ├── screenshot.ts      # page/element screenshot → image content
│       ├── click.ts           # locator.click() — selector preferred over text
│       ├── fill.ts            # locator.fill()
│       ├── selectOption.ts    # locator.selectOption()
│       ├── pressKey.ts        # keyboard.press()
│       ├── waitFor.ts         # wait for element / text / URL
│       ├── setViewport.ts     # page.setViewportSize()
│       ├── evaluate.ts        # page.evaluate(js)
│       ├── assert.ts          # 9 assertion types, auto-retry
│       ├── closeBrowser.ts    # browser.close()
│       └── util.ts            # shared helpers
├── skills/                    # portable SKILL.md skills (work with either Playwright MCP)
├── test/                      # end-to-end tests against local fixture pages
├── examples/
│   ├── claude_desktop_config.json
│   ├── librechat-agent-instructions.md   # QA agent system prompt for LibreChat
│   ├── skills/                # app-specific skills — the-internet selector map, playwright-e2e conventions
│   ├── scenarios/             # example scenario file for the regression-scenarios skill
│   ├── login_flow.md
│   └── failure_analysis.md
├── LICENSE
├── package.json
└── tsconfig.json

This server is part of a broader AI-powered QA tooling portfolio:


What's Next

  • Trace recording — capture Playwright traces for failed sessions

  • Network interception — mock API responses mid-test

  • Multi-tab control (new tabs are followed automatically today)

  • wait_for tool — wait for element, text, or URL


Author

Adem Garic — SDET / QA Engineer 6+ years in mobile and web test automation (Appium, Selenium, Playwright, Jenkins, BrowserStack) LinkedIn · GitHub

Available Tools

8 tools
assertA

Assert a condition about the current page state. Returns pass/fail with details — use this to verify test expectations.

NameRequiredDescriptionDefault
typeYesThe type of assertion to perform
countNoExpected element count (for element_count type)
expectedNoExpected value or text to match against
selectorNoCSS selector (required for element_exists, element_hidden, input_value, element_count, text_visible with scope)

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that the tool 'returns pass/fail with details,' which is a key behavioral trait. However, it does not mention whether the tool is read-only, how it behaves on failure (e.g., if it throws or just returns), or any side effects. The disclosure is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the tool's purpose, and every word earns its place. No fluff or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity and 100% schema coverage, the description is largely complete. It clarifies the return format ('pass/fail with details') even though there is no output schema. It could mention usage relative to get_page_state or waiting behavior, but these are not essential for an assert tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description does not add any parameter-specific details beyond what the schema already provides. The schema's descriptions are clear, but the tool description itself offers no added semantic value for parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Assert a condition about the current page state.' It uses a specific verb (assert) and resource (current page state), and distinguishes itself from sibling tools like get_page_state by mentioning it returns pass/fail and is for verifying test expectations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: 'use this to verify test expectations.' It does not explicitly compare to alternatives or state when not to use, but this guidance is sufficient for an assertion tool in a test automation context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clickB

Click an element on the page identified by a CSS selector or text content.

NameRequiredDescriptionDefault
textNoVisible text of the element to click (alternative to selector)
selectorNoCSS selector for the element to click
waitForNavigationNoWait for navigation after click (default: false)

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses the identification method but omits side effects (e.g., navigation, visibility requirements, return value, or error behavior). The description is minimally transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that conveys the essential purpose and identification method without any fluff or redundancy. Highly concise and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no annotations and no output schema, yet the description only covers the basic action. It fails to clarify that at least one of selector/text must be provided (both are optional in schema), nor does it explain return values or potential failure modes. For a 3-param tool, this leaves significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (selector, text, waitForNavigation) having a clear description. The tool description echoes the selector/text content choice but adds no meaning beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (click), the resource (element on the page), and how it is identified (CSS selector or text content). This distinguishes it from siblings like fill or evaluate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage (clicking an element) but offers no explicit guidance on when to choose this tool over alternatives such as fill for form inputs or evaluate for JavaScript. Context is clear but exclusions and alternative mentions are absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

close_browserA

Close the browser and release all resources. Call this when the test session is complete.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description carries the burden of behavioral disclosure. It explicitly mentions 'release all resources,' which goes beyond the simple 'close' and indicates side effects such as freeing memory and connections. While it does not detail all consequences (e.g., state loss), the statement is sufficient for this simple tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence that front-loads the action and includes only essential information. Every word contributes to understanding the tool's purpose and usage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters, no output schema, and a simple cleanup function, the description covers the necessary information: what it does, what happens (releases resources), and when to use it. It is complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, and the schema coverage is 100%. According to the baseline, a score of 4 is appropriate. The description does not need to explain parameters that do not exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool closes the browser and releases all resources, using a specific verb and resource. It distinguishes itself from the sibling tools which are all about navigation, inspection, and interaction rather than session cleanup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly advises calling this tool when the test session is complete, providing clear timing guidance. There are no alternative tools for closing the browser, so no exclusions are needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

evaluateA

Execute JavaScript in the browser page context and return the result. Use for assertions, reading DOM values, or custom interactions.

NameRequiredDescriptionDefault
expressionYesJavaScript expression to evaluate. Must be a valid JS expression (not a statement). Example: "document.title" or "document.querySelector('h1').textContent"

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden for behavioral disclosure. It mentions 'Execute JavaScript in the browser page context and return the result,' but fails to disclose that arbitrary JavaScript may have side effects on the page, potential error behavior, or that the result format is unspecified. This is a significant gap for a tool that can modify the page.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the core function and follows with use cases. Every word earns its place; there is no redundancy or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description provides enough to understand the tool's purpose and general usage, but lacks critical context about potential side effects, error handling, and return value shape. With no annotations and no output schema, the description should do more to fully set expectations for a JavaScript execution tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with the 'expression' parameter fully described (valid JS expression, examples). The tool description adds usage context but no additional parameter-specific meaning. Per the rubric, high schema coverage sets a baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: 'Execute JavaScript in the browser page context and return the result.' This clearly distinguishes it from sibling tools like navigate, fill, and click, which handle other browser interactions. It also lists concrete use cases ('assertions, reading DOM values, or custom interactions'), making the tool's purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use for assertions, reading DOM values, or custom interactions,' providing clear context for when to use this tool. However, it does not mention when not to use it or name alternative tools (e.g., assert or get_page_state), so it lacks explicit exclusions. This aligns with 'clear context, no exclusions.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fillA

Type text into an input field, textarea, or contenteditable element.

NameRequiredDescriptionDefault
valueYesText to type into the field
selectorYesCSS selector for the input field
clearFirstNoClear the field before typing (default: true)

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden for behavioral disclosure. It only states the core action of typing text and does not mention the default clearing behavior (clearFirst=true) or any side effects like event triggering. This is a significant gap for a mutation operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single clear sentence, front-loaded with the verb, and contains no extraneous information. It is concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate for a simple tool, but it omits key behavioral context such as the default clearing behavior. The schema compensates for parameter details, yet the overall context is still somewhat sparse given the lack of annotations or output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so each parameter has a description. The tool description does not add further parameter-specific meaning, but the baseline of 3 applies because the schema already documents the parameters effectively.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Type text' and the resource types ('input field, textarea, or contenteditable element'), distinguishing it from sibling tools like 'click' or 'navigate'. It is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied by the element types mentioned, but there is no explicit guidance on when to use this tool versus alternatives, nor any exclusions or prerequisites. The description does not reference sibling tools or contrast with them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_page_stateA

Get the current state of the page — title, URL, visible text, interactive elements, and console errors. Use this to understand what is on screen before deciding the next action.

NameRequiredDescriptionDefault
selectorNoScope to a specific element — returns only that element's state
includeHtmlNoInclude truncated outer HTML of the body (default: false)

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses what the tool returns (title, URL, visible text, etc.) and mentions truncated HTML, which gives useful context. However, it does not explicitly state that the tool is non-mutating or describe any side effects, permissions, or limitations beyond truncation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences. The first states what it does and what it returns; the second provides usage guidance. There is no redundancy or extraneous detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with no output schema, the description lists the main return components and usage context. It could be more explicit about response structure or the meaning of 'interactive elements', but it is sufficiently complete for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Both parameters have 100% schema coverage, so the baseline is 3. The description does not add significant meaning beyond the schema; it only mentions the tool's overall output, not how the parameters affect the result. The schema already explains selector and includeHtml.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets the current page state and enumerates specific components (title, URL, visible text, interactive elements, console errors). This is more specific than just 'get state' and distinguishes it from siblings like screenshot (visual) and evaluate (JavaScript).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly advises to use this tool to understand what is on screen before deciding the next action, providing a clear context. It does not explicitly name alternatives or exclusions, but the instruction is enough to guide appropriate use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

screenshotA

Take a screenshot of the current page or a specific element. Returns base64-encoded PNG.

NameRequiredDescriptionDefault
fullPageNoCapture full scrollable page (default: false)
savePathNoOptional file path to save the screenshot to disk
selectorNoCSS selector to screenshot a specific element (optional — omit for full page)

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the return format (base64-encoded PNG) but does not disclose side effects, whether the screenshot captures the viewport or full page by default, implications of the savePath parameter, or any waiting/network behavior. This is a significant gap for a tool with no annotation safety hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, consisting of two short sentences that front-load the core purpose. Every word earns its place: 'Take a screenshot of the current page or a specific element' immediately conveys scope, and the return type is specified in the second sentence. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is relatively simple, and the schema fully documents all three optional parameters, so the description does not need to repeat those details. However, with no output schema and no annotations, the description should provide more context on return value usage, potential errors, or behavior nuances (e.g., element screenshots may require visibility). The current description is minimal but not fully inadequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers 100% of the parameters with descriptions, so the baseline is 3. The tool description adds no additional meaning beyond the schema; it references 'specific element' which aligns with the selector parameter, but does not elaborate on fullPage or savePath semantics. It neither compensates for schema gaps nor adds extra value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Take a screenshot of the current page or a specific element.' It uses a specific verb ('take a screenshot') and names the resources (current page or element). This distinguishes it from sibling tools like navigate, fill, or evaluate, which serve different functions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by mentioning 'current page or a specific element,' but it does not explicitly state when to prefer screenshot over alternatives like get_page_state, nor does it provide exclusions or conditions. There is no 'use this instead of X' guidance, so the agent must infer usage from the tool's purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv1.0.0
    • First observedassert
    • First observedclick
    • First observedclose_browser
    • First observedevaluate
    • First observedfill
    • First observedget_page_state
    • First observednavigate
    • First observedscreenshot

TDQS

A4/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: navigating, reading state, capturing visuals, interacting, executing custom JS, asserting conditions, and closing the browser. No two tools overlap in function.

Naming Consistency5/5

All tool names follow an imperative verb pattern with consistent snake_case (e.g., get_page_state, close_browser). Even single-word names like navigate and click are verbs, maintaining a uniform style.

Tool Count5/5

8 tools is well-scoped for a browser automation server, covering navigation, interaction, inspection, visualization, scripting, verification, and teardown without bloat or redundancy.

Completeness4/5

The tool surface covers the core browser automation lifecycle (navigate, interact, observe, assert, cleanup). Missing explicit waits or advanced interactions (hover, dropdowns) but these are workable via evaluate, so gaps are minor.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server that gives Claude Code a real browser to navigate, click, type, screenshot, and inspect pages via accessibility snapshots. It also runs multi-step test scenarios with assertions, session recording, visual regression, and console/network monitoring from the terminal.
    106 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server that gives Claude Code a real browser, enabling it to navigate pages, click, type, capture screenshots, run multi-step test scenarios with assertions, and monitor console and network activity directly from the terminal.
    106 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server that gives Claude Code a real browser for navigation, interaction, screenshots, and end-to-end testing, including assertions, session recording, visual regression, and console/network monitoring.
    106 npm
    MIT