Skip to content
/docs

Playwright Integration

Use Veto with Playwright MCP to validate browser automation actions.

Veto works with Playwright MCP by guarding MCP tools/call requests. Playwright MCP exposes browser automation as schema-only MCP tools, so use veto.wrapMCPTools() around your MCP client forwarder.

TypeScript only, uses the Playwright MCP server.

Installation

npm install veto-sdk
npx playwright install

Set up the Playwright MCP server following the Playwright MCP docs.

Quick start

import { Veto } from 'veto-sdk';

const veto = await Veto.init();

// Use your MCP client to list tools and forward calls to Playwright MCP.
const mcpTools = await mcpClient.listTools();

const { tools, callTool } = veto.wrapMCPTools(
  mcpTools,
  { callTool: (input) => mcpClient.callTool(input) },
);

// Give `tools` to the model. Use `callTool` instead of direct MCP calls.
const result = await callTool({
  name: 'browser_navigate',
  arguments: { url: 'https://example.com' },
});

How it works

Playwright MCP exposes browser actions as MCP tool definitions (schema-only, no execution logic). veto.wrapMCPTools() returns:

  1. tools: The original MCP tool definitions (pass to your AI model as-is)
  2. callTool: A validated function that checks arguments before forwarding to the MCP server
AI model generates tool call
         |
         v
  callTool(name, args)
         |
         v
  Veto validates args
         |
    +----+----+
    |         |
  allow     deny
    |         |
    v         v
  forward   ToolCallDeniedError
  to MCP
  server

Example output

MCP tools: browser_navigate, browser_click, browser_type, browser_snapshot
Wrapped 4 MCP tools

browser_navigate({url: 'https://example.com'})         # allowed
browser_navigate({url: 'https://malware.site'})         # DENIED by rule
browser_click({element: 'Submit', ref: '42'})           # allowed
browser_type({element: 'Search', ref: '15', text: 'hello'})  # allowed

total_calls:    4
allowed_calls:  3
denied_calls:   1

YAML rules for Playwright actions

Block navigation to dangerous URLs:

rules:
  - id: block-dangerous-urls
    name: Block navigation to dangerous URLs
    action: block
    tools:
      - browser_navigate
    conditions:
      - field: arguments.url
        operator: matches
        value: "^https?://(.*\\.)?(malware|phishing|darkweb)\\."

  - id: block-file-urls
    name: Block file:// protocol
    action: block
    tools:
      - browser_navigate
    conditions:
      - field: arguments.url
        operator: starts_with
        value: "file://"

Block typing sensitive data:

rules:
  - id: block-sensitive-input
    name: Block typing passwords or tokens
    action: block
    tools:
      - browser_type
    conditions:
      - field: arguments.text
        operator: matches
        value: "(?i)(password|secret|api.?key|token)"

Playwright MCP tool names

Common tool names exposed by the Playwright MCP server:

ToolDescription
browser_navigateNavigate to a URL
browser_clickClick an element
browser_typeType text into an element
browser_snapshotTake an accessibility snapshot
browser_screenshotTake a screenshot
browser_go_backNavigate back
browser_go_forwardNavigate forward
browser_waitWait for a condition
browser_press_keyPress a keyboard key
browser_select_optionSelect a dropdown option

Exact tool names depend on the Playwright MCP server version. Use listTools() to discover available tools.