Skip to main content
Glama
daninden

playwright-mcp-azure

by daninden

playwright-mcp-azure

A remote MCP server that gives an MCP client general-purpose headless-browser control via Playwright, exposed over Streamable HTTP and deployable to Azure Container Apps.

A single process holds one shared headless Chromium browser. Each client connection gets its own Playwright BrowserContext + active Page, tracked by an in-memory session manager with idle eviction and a concurrency cap. Sessions are in-memory only — nothing persists across a restart.

Prerequisites

  • Node.js 20+

  • npm

  • Docker (only needed for building/deploying the container)

  • Azure CLI (only needed for deploy)

Related MCP server: Playwright MCP Server

Local setup

npm install
npx playwright install chromium   # one-time, downloads the Chromium binary

The server requires a bearer token for auth:

export MCP_BEARER_TOKEN=some-local-dev-token   # PowerShell: $env:MCP_BEARER_TOKEN = "..."
npm run dev

This starts the server on http://localhost:3000, with the MCP endpoint mounted at /mcp (Streamable HTTP) and an unauthenticated health check at /healthz.

Environment variables

Variable

Required

Default

Description

MCP_BEARER_TOKEN

yes

Bearer token clients must send as Authorization: Bearer <token> on /mcp.

IDLE_TIMEOUT_MS

no

600000

Milliseconds of inactivity before a session's browser context is closed.

MAX_SESSIONS

no

5

Maximum concurrent browser sessions.

PORT

no

3000

Port the HTTP server listens on.

Running tests

npm test

Integration tests launch real headless Chromium instances, so the Playwright browser install step above is required first.

Building

npm run build   # compiles src/ to dist/
npm start        # runs the compiled server (dist/server.js)

Connecting an MCP client

Point an MCP client that supports Streamable HTTP at http://<host>:<port>/mcp, sending Authorization: Bearer <MCP_BEARER_TOKEN> on every request. The server exposes these tools:

browser_start_session, browser_navigate, browser_navigate_back, browser_click, browser_type, browser_fill_form, browser_snapshot, browser_screenshot, browser_evaluate, browser_wait_for, browser_tabs, browser_network_requests, browser_close.

Browser sessions are identified by an app-level sessionId, not by the MCP transport's own session id -- some MCP clients (notably Azure AI Foundry's agent tool integration) open a brand-new transport connection for every single tool call and never reuse the transport-level session, so nothing tied to that id would survive between calls. Call browser_start_session once at the start of a task to get a sessionId, then pass that same sessionId as an argument on every other browser_* call for that task. If a call returns an error naming browser_start_session, the session expired or was closed (idle timeout, or an explicit browser_close) -- start a new one and resume from there.

browser_snapshot returns a role/name listing of interactive elements, each stamped with a ref (e.g. e3); pass that ref to browser_click/browser_type/browser_fill_form to act on that element.

browser_network_requests records XHR and fetch GET/POST requests across every tab in the session (up to the last 200; older entries drop off). Call it with { "action": "list" } for { url, method, requestBody, status, responseBody } per request, optionally adding "urlPattern": "*/api/*" to filter by a *-wildcard match on the URL, or { "action": "clear" } to empty the log.

Tool failures are never reported via the MCP protocol's isError flag -- Azure AI Foundry's agent orchestration treats an isError result as a fatal tool-call failure and stops the run instead of letting the model see and react to it. Instead, a failed call still returns a normal result whose content is a JSON object like { "error": "<description>" }, so the model can read the error and decide how to proceed (retry, call browser_start_session again, etc.).

Deploying to Azure Container Apps

Infrastructure (infra/main.bicep) provisions an Azure Container Registry, a Log Analytics workspace, a Container Apps environment, and a single Container App (HTTPS-only ingress, pinned to 1 replica). It needs a container image to deploy, and the registry doesn't exist until the infra is applied — so the first deploy provisions with a placeholder image, then infra/deploy.ps1 builds and pushes the real one.

  1. Log in and create a resource group (skip if you already have one):

    az login
    az group create --name rg-playwright-mcp --location westeurope
  2. Provision the infrastructure with a placeholder image:

    az deployment group create \
      --resource-group rg-playwright-mcp \
      --template-file infra/main.bicep \
      --parameters mcpBearerToken=<a-strong-random-token> \
                   containerImage=mcr.microsoft.com/k8se/quickstart:latest

    Note the acrLoginServer output (or a name prefix segment of it) — that's the -AcrName value for the next step.

  3. Build, test, and deploy the real image:

    ./infra/deploy.ps1 -ResourceGroup rg-playwright-mcp -AcrName <acr-name-from-step-2>

    This runs npm ci, installs the Chromium browser, builds, runs the test suite, then builds and pushes a Docker image and updates the Container App to use it. Re-run this script for subsequent deploys — the infra step only needs to run once (or again if infra/main.bicep changes).

  4. Get the URL:

    az containerapp show --name playwright-mcp-app --resource-group rg-playwright-mcp \
      --query properties.configuration.ingress.fqdn -o tsv

    The MCP endpoint is https://<fqdn>/mcp.

To change IDLE_TIMEOUT_MS, MAX_SESSIONS, or PORT in Azure, edit their values in infra/main.bicep's container env block and redeploy the infra step.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables web browser automation through Playwright, providing tools for navigation, element interaction, screenshot capture, and accessibility snapshots. Uses streamableHttp transport for seamless integration with MCP clients.
    6
    1,414
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides browser automation capabilities via HTTP endpoints by wrapping the official Playwright MCP package, enabling serverless deployments and cloud environments where STDIO-based communication is not possible.
    1
  • 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

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/daninden/playwright-mcp-azure'

If you have feedback or need assistance with the MCP directory API, please join our Discord server