Playwright MCP Server
Sends distributed traces to Jaeger for monitoring browser automation and MCP server requests.
Exports distributed traces from MCP tool calls to any OpenTelemetry-compatible backend using W3C traceparent propagation.
Sends distributed traces to Splunk APM for monitoring browser automation and MCP server requests.
Click on "Install 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 ServerOpen news.ycombinator.com and return the top 5 story titles"
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 production-ready Model Context Protocol (MCP) server that exposes full browser automation over HTTP — built with the MCP Python SDK v2 (
MCPServer) and Playwright, deployable to Azure Container Apps. Supports multiple concurrent clients via isolated sessions — all output returned inline (base64 for images), nothing written to disk.
Control a real Chromium browser through simple HTTP calls. No Selenium, no WebDriver setup, no manual MCP protocol boilerplate. Each client gets an isolated browser session (separate cookies, localStorage, history) so multiple agents can operate in parallel. All output is returned inline — screenshots as base64, DOM as HTML — nothing is written to disk. Requests are authenticated via an x-api-key header, with the secret loaded from a .env file.
When to Use This
Use Case | Example |
AI agent browser control | Let an LLM agent navigate, click, and scrape web pages via MCP tool calls |
End-to-end test automation | Drive a real Chromium browser over HTTP from any language or test runner |
Web scraping pipelines | Extract DOM snapshots, evaluate JS, and capture screenshots programmatically |
RPA (Robotic Process Automation) | Automate repetitive web workflows — form filling, file uploads, multi-tab flows |
Automated screenshots / visual monitoring | Capture full-page screenshots of any URL on demand |
Remote browser execution | Run browser automation on a server or in Azure without a local display |
When NOT to Use This
You only need static HTML parsing — use
requests+BeautifulSoupinsteadYou need parallel browsers at scale — consider Playwright's own grid or Playwright Test
You need a full GUI test framework with assertions and reports — use Playwright Test or Pytest-Playwright directly
Related MCP server: Ghostlight
Architecture
Project Files
File | Purpose |
| Main MCP server — registers all browser tools, applies API-key auth middleware, and starts MCPServer via uvicorn |
| Pre-flight checker — verifies all imports and runtime dependencies |
| Python dependency list |
| Environment variables (API key, etc.) — not committed to git |
How It Works
server.pycreates anMCPServerinstance and builds the ASGI app withmcp.streamable_http_app(stateless_http=True)An
APIKeyMiddleware(Starlette) is added to the ASGI app — every request must include a validx-api-keyheaderThe API key is loaded from a
.envfile viapython-dotenvat startup (MCP_API_KEYvariable)Session-based: each client calls
session_createto get an isolated browser context (separate cookies, localStorage, page). Multiple sessions run in parallel on a shared Chromium instancePlaywright is lazily initialized — the Chromium browser only starts on the first session creation
No disk I/O — screenshots are returned as base64, DOM snapshots as HTML strings. Nothing is written to the filesystem
Idle sessions are automatically evicted after
SESSION_IDLE_TIMEOUT_S(default 10 minutes). The server enforcesMAX_SESSIONS(default 10)A
health_checktool acts as a lightweight health probe — it responds instantly without starting the browserThe server binds to
0.0.0.0and reads thePORTenvironment variable (default8000)
Architecture Diagram
flowchart LR
ClientA[Client A]
ClientB[Client B]
subgraph Server[Playwright MCP Server]
direction TB
Auth[APIKeyMiddleware]
MCPServer[MCPServer]
Sessions[Session Manager]
Browser[Shared Chromium Instance]
CtxA[Context A / Page A]
CtxB[Context B / Page B]
end
ClientA -->|"HTTP + x-api-key"| Auth
ClientB -->|"HTTP + x-api-key"| Auth
Auth -->|valid key| MCPServer
Auth -->|invalid key| ClientA
MCPServer -->|calls tool| Sessions
Sessions -->|session A| CtxA
Sessions -->|session B| CtxB
CtxA -->|isolated browsing| Browser
CtxB -->|isolated browsing| Browser
Sessions -->|"JSON + base64"| MCPServer
MCPServer -->|HTTP response| ClientA
MCPServer -->|HTTP response| ClientBStep-by-step:
Client sends an HTTP POST to
https://<host>/mcpwith anx-api-keyheader
APIKeyMiddlewarevalidates the key — returns401if invalid or missingClient calls
session_createto get an isolatedsession_idAll subsequent tool calls include
session_idto target the correct browser contextThe shared Chromium instance is lazily started on the first session creation
Results (HTML, base64 images, JSON) are returned inline — nothing written to disk
Client calls
session_closewhen done; idle sessions are auto-evicted
Features
Multi-client sessions | Each client gets an isolated browser context (cookies, storage, page) via |
No disk I/O | Screenshots returned as base64, DOM as HTML. Nothing written to the filesystem — safe for serverless/container deployments |
API-key authentication | All requests require a valid |
Auto-cleanup | Idle sessions evicted after configurable timeout; max session limit enforced with LRU eviction |
Lazy-loaded browser | Shared Chromium instance starts on first session creation — zero startup overhead |
Full browser automation | Navigate, click, type, screenshot, evaluate JS, DOM snapshot, resize, and key press |
Azure Container Apps ready | Built-in |
Async / await | Every tool is a native Python async function — no blocking calls |
Streamable HTTP transport | MCPServer uses streamable-http for real-time MCP communication |
Distributed tracing (OTel) | Built-in OpenTelemetry instrumentation with W3C |
Tools Available
All browser tools accept an optional session_id parameter. If omitted, a new session is auto-created.
Session Management
Tool | Description | Input |
| Server health, active session count | None |
| Create an isolated browser session | None |
| Close a session and free resources |
|
| List all active sessions with idle times | None |
Browser Automation
Tool | Description | Input |
| Navigate to a URL (http, https, or data: URI) |
|
| Click an element by selector |
|
| Type text into an input field |
|
| Press a keyboard key |
|
| Capture page as base64 PNG |
|
| Generate a PDF of the current page |
|
| Get full HTML DOM content |
|
| Execute JavaScript in page context |
|
| Resize the browser viewport |
|
Prerequisites
Python 3.8+
pip or conda
Installation
Clone or download this project
Create a virtual environment
python -m venv .venvActivate the virtual environment
Windows:
.venv\Scripts\activateLinux/macOS:
source .venv/bin/activate
Install dependencies
pip install -r requirements.txtConfigure environment variables
Copy the template and fill in your API key:
# Linux/macOS cp .env.example .env # Windows copy .env.example .envThen edit
.envand set at minimum:MCP_API_KEY=your-secure-random-key-hereSee
.env.examplefor all available settings (timeouts, session limits, Azure config, etc.).⚠️ The
.envfile is git-ignored by default. Never commit your API key to source control.
Running Locally
python server.pyThe server will start on http://0.0.0.0:8000 by default. All requests must include the x-api-key header matching the MCP_API_KEY value from your .env file.
Custom Port
Set the PORT environment variable to use a different port:
# Windows
set PORT=3000
python server.py
# Linux/macOS
export PORT=3000
python server.pyConnect from Zoo Code
To use this MCP server from Zoo Code, add the following to your MCP settings file (mcp_settings.json):
{
"mcpServers": {
"playwright_local": {
"type": "streamable-http",
"url": "http://localhost:8100/mcp",
"headers": {
"x-api-key": "YOUR_KEY_HERE"
},
"alwaysAllow": []
}
}
}Replace YOUR_KEY_HERE with the MCP_API_KEY value from your .env file, and adjust the port if you changed PORT in .env.
Tip: Make sure the Docker container is running before connecting. Use
.\scripts\start-docker.ps1or start it manually withdocker run.
Quick Usage Example
With the server running, call any tool via the /mcp endpoint. You must include the x-api-key header with every request.
1. Create a session
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your-secure-random-key-here" \
-d '{
"method": "tools/call",
"params": { "name": "session_create", "arguments": {} }
}'Response:
{ "session_id": "a1b2c3d4-...", "status": "created" }2. Navigate (pass the session_id)
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your-secure-random-key-here" \
-d '{
"method": "tools/call",
"params": {
"name": "browser_navigate",
"arguments": { "session_id": "a1b2c3d4-...", "url": "https://example.com" }
}
}'3. Take a screenshot (returned as base64)
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your-secure-random-key-here" \
-d '{
"method": "tools/call",
"params": {
"name": "browser_take_screenshot",
"arguments": { "session_id": "a1b2c3d4-...", "fullPage": true }
}
}'Response:
{ "base64_png": "iVBORw0KGgoAAAANSUhEUgAA...", "format": "png" }4. Close the session when done
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your-secure-random-key-here" \
-d '{
"method": "tools/call",
"params": {
"name": "session_close",
"arguments": { "session_id": "a1b2c3d4-..." }
}
}'Tip: If you omit
session_idfrom any browser tool, a new session is auto-created and its ID is returned in the response.
If the API key is missing or incorrect, you will receive:
{ "error": "Unauthorized. Provide a valid x-api-key header." }with HTTP status 401.
Test With Postman
You can also test MCP functionality using Postman and the running http://localhost:8000/mcp endpoint.
Open Postman.
Create a new MCP request or a new HTTP POST request if your version does not expose MCP request types.
Set the request URL to:
http://localhost:8000/mcpAdd the authentication header:
Go to the Headers tab.
Add a header with key
x-api-keyand value set to yourMCP_API_KEYfrom the.envfile.
Create a session first, then use the returned
session_idin subsequent calls:{ "method": "tools/call", "params": { "name": "session_create", "arguments": {} } }Use the
session_idfrom the response to call browser tools:{ "method": "tools/call", "params": { "name": "browser_navigate", "arguments": { "session_id": "<session_id from step 5>", "url": "https://example.com" } } }Click Send or Run.
Review the response panel to confirm the tool execution and any returned status.
Deployment to Azure
Quick Deploy — Azure Container Apps (Recommended)
The fastest path to a public HTTPS endpoint with Azure-managed TLS certificates. A single PowerShell script handles everything.
Prerequisites:
Azure CLI installed and logged in (
az login)Container Apps CLI extension:
az extension add --name containerapp --upgradePython 3.8+
Steps:
Configure your
.envfile with Azure settings:AZURE_SUBSCRIPTION_ID=<your-subscription-id> AZURE_RESOURCE_GROUP=mcp-playwright-rg AZURE_LOCATION=westeurope AZURE_APP_NAME=mcp-playwright MCP_API_KEY= # leave empty to auto-generateRun the deploy script:
.\scripts\deploy-aca.ps1The script will:
Create a resource group
Build your Docker image and push it to a managed Azure Container Registry
Create an Azure Container App with public HTTPS ingress
Inject
MCP_API_KEY,HEADLESS, andPORTas environment variablesRun a smoke test against the
health_checktoolPrint the full HTTPS endpoint and API key
Test the endpoint:
curl -X POST https://<your-app>.<region>.azurecontainerapps.io/mcp \ -H "Content-Type: application/json" \ -H "x-api-key: <your-key>" \ -d '{"method":"tools/call","params":{"name":"browser_navigate","arguments":{"url":"https://example.com"}}}'Tear down when finished:
.\scripts\teardown-aca.ps1
See
plans/azure-quick-test-aca.mdfor the full architecture and alternative deployment options.
Alternative: Azure App Service for Containers
Create an App Service with a custom container
az appservice plan create --name <plan-name> --resource-group <rg-name> --sku B2 --is-linux az webapp create --resource-group <rg-name> --plan <plan-name> --name <app-name> --deployment-container-image-name <your-acr>.azurecr.io/playwright-mcp-server:latestConfigure environment (including the API key)
az webapp config appsettings set --resource-group <rg-name> --name <app-name> \ --settings PORT=8000 HEADLESS=true MCP_API_KEY=your-secure-random-key-hereConfigure the health probe (Azure Portal → App Service → Health Check)
Set path to
/mcp
Local Docker
Quick start (recommended): Use the provided PowerShell script to build and run on port 3010 (avoids conflicts with the default 8000):
.\scripts\start-docker.ps1This will:
Build the Docker image from the project
DockerfileStop and remove any existing
playwright-mcpcontainerStart a new container mapping host port 3010 → container port 8000
Read
MCP_API_KEYfrom.env(or auto-generate one)Print the endpoint URL, API key, and test commands
The MCP endpoint will be available at http://localhost:3010/mcp.
Options:
# Use a custom host port
.\scripts\start-docker.ps1 -Port 4000
# Force a no-cache rebuild
.\scripts\start-docker.ps1 -Rebuild
# Both
.\scripts\start-docker.ps1 -Port 4000 -RebuildManual build and run (if you prefer not to use the script):
docker build -t playwright-mcp-server .
docker run -p 3010:8000 --env-file .env playwright-mcp-serverNote: The container listens on port 8000 internally. The
-p 3010:8000flag maps host port 3010 to the container's port 8000, avoiding conflicts if port 8000 is already in use on your machine.
Environment Variables
Variable | Default | Description |
| (none — required) | Secret key for |
|
| Port the server listens on |
|
| Set to |
|
| Maximum time (ms) to wait for page navigation (e.g. |
|
| Maximum time (ms) to wait for element actions (click, fill, etc.). |
|
| Seconds a session can sit idle before automatic eviction (default 10 minutes). |
|
| Maximum number of concurrent browser sessions. When the limit is reached, the oldest idle session is evicted to make room. |
|
| Number of uvicorn workers. Keep at |
|
| Set to |
|
| Path to TLS certificate file. Only used when |
|
| Path to TLS private key file. Only used when |
|
| Host port used by |
| (empty) | OTLP/HTTP endpoint for the OTel Collector (e.g. |
|
| Service name shown in trace backends (Splunk APM, Jaeger, etc.). |
| (empty) | Extra resource attributes as |
All variables can be set in the
.envfile (loaded automatically viapython-dotenv) or passed directly as environment variables.
Scalability
This server runs one shared Chromium instance per process with multiple isolated sessions. To scale:
Strategy | Details |
Session isolation | Each client gets its own |
Auto-eviction | Idle sessions are evicted after |
Horizontal replicas | Deploy multiple container instances behind a load balancer (Azure Container Apps, Kubernetes, App Service scale-out). Each replica manages its own browser and session pool. |
Keep workers = 1 |
|
Graceful shutdown | The server closes all sessions and the browser cleanly on SIGTERM (Docker stop, Azure restart) via |
Timeouts | All browser actions enforce configurable timeouts ( |
No disk I/O | All output (screenshots, DOM) is returned inline — no filesystem writes mean the server is safe for read-only container filesystems and serverless deployments. |
Docker layer caching | The Dockerfile splits pip install and Playwright browser download into separate layers — code-only changes rebuild in seconds, not minutes. |
Testing
Validate Dependencies
python validate_server.pyRun the Test Suite
python test_fastmcp_simple.pyTest with MCP Inspector (Recommended)
MCP Inspector is the official interactive tool for exploring and testing MCP servers. It gives you a visual UI to browse all registered tools, call them with custom inputs, and inspect responses — no Postman or curl needed.
Prerequisites: Node.js installed
Start the server:
python server.pyIn a new terminal, launch MCP Inspector:
npx @modelcontextprotocol/inspectorOpen the Inspector UI (it will print a local URL, typically
http://localhost:5173)Connect to your running server:
Transport: SSE or Streamable HTTP
URL:
http://localhost:8000/mcp
You will see all registered tools (
session_create,session_close,browser_navigate,browser_click,browser_take_screenshot, etc.) listed in the left panel. Click any tool, fill in the inputs, and hit Run Tool to test it live.
MCP Inspector is the fastest way to verify your server is working correctly before deploying to Azure.
Project Structure
.
├── server.py # Main MCP server (API-key auth, browser tools, uvicorn)
├── .env # Environment variables — runtime + Azure config (git-ignored)
├── .env.example # Template with all available settings — copy to .env
├── requirements.txt # Python dependencies
├── Dockerfile # Container image definition (non-root, layered)
├── .dockerignore # Files excluded from Docker build context
├── .gitignore # Files excluded from version control
├── test_fastmcp_simple.py # Test suite
├── validate_server.py # Dependency validation
├── scripts/
│ ├── start-docker.ps1 # Build & run locally in Docker
│ ├── deploy-aca.ps1 # One-command Azure Container Apps deployment
│ ├── teardown-aca.ps1 # Delete all Azure resources
│ └── generate_cert.py # Generate self-signed TLS cert (used during Docker build)
├── plans/
│ └── azure-quick-test-aca.md # Architecture plan for Azure deployment
├── README.md # This file
└── .venv/ # Virtual environment (auto-generated)Troubleshooting
All requests return 401 Unauthorized:
Ensure you are sending the
x-api-keyheader with the correct valueCheck that
MCP_API_KEYis set in your.envfile (or environment)
All requests return 500 — "Server API key not configured":
The
MCP_API_KEYenvironment variable is missing or emptyCreate or edit the
.envfile and addMCP_API_KEY=your-key-here
Browser won't initialize:
Ensure Playwright chromium is installed:
playwright install chromiumCheck system dependencies are installed (Linux/macOS)
Port already in use:
Change the PORT environment variable to an available port
Timeout errors:
Increase
NAVIGATION_TIMEOUT_MSorACTION_TIMEOUT_MSin.envCheck network connectivity to target URLs
Session not found / evicted:
Sessions are automatically evicted after
SESSION_IDLE_TIMEOUT_S(default 10 minutes) of inactivityIf a session's page crashes, the server detects it and removes the session on the next access
Simply call
session_createto get a fresh session and retry your workflow
JavaScript evaluation fails:
The function must be a valid JS expression returning a serializable value
Example:
"() => document.title"not"document.title"
Security
This project includes several layers of security hardening:
Control | Details |
API-key authentication | Every request must carry a valid |
Cryptographic session IDs | Session IDs are generated with |
URL scheme allowlist |
|
Session isolation | Each client operates in its own |
Dead session detection | Every tool call verifies the page is still alive before use. The background cleanup also reaps crashed/dead sessions every 60 seconds. |
Leak-proof creation | If page creation fails during |
TOCTOU-safe session limits | The |
Input length limits | All string fields enforce |
Viewport bounds |
|
Race-condition guard | Browser initialisation uses an |
Non-root Docker container | The |
Minimal error disclosure | Server misconfiguration errors return a generic message — no internal paths or config details are leaked. |
Known trade-offs
Item | Notes |
| Required inside Docker (no kernel namespaces). Mitigated by running as non-root in an isolated container. |
| This is intentional — the tool is designed for trusted callers behind the API key. Do not expose this server to untrusted users. |
No rate limiting | Consider adding rate-limiting middleware (e.g. |
No HTTPS termination by default | Set |
Generating a strong API key
python -c "import secrets; print(secrets.token_urlsafe(32))"Paste the output into your .env file as MCP_API_KEY=<value>.
Below are PowerShell-first commands to build and run this project on Docker Desktop and ensure other containers in the same environment can access it. Key implementation details in code: binds to 0.0.0.0 via uvicorn.run(), reads the port from PORT, requires an API key via APIKeyMiddleware reading MCP_API_KEY, and exposes 8000 in the image (EXPOSE 8000).
Build the image
From the project root (where Dockerfile and server.py live), build a local tag: docker build -t playwright-mcp:local .
Create a user-defined bridge network (enables container-to-container DNS)
This lets other containers reach this service by its container name instead of an IP. docker network create mcp-net
Provide the API key environment
The server rejects requests without a valid x-api-key header enforced by APIKeyMiddleware. Create a .env at the repo root: Set-Content -Path .env -Value "MCP_API_KEY=your-secure-random-key-here"
Optional: add a custom port (defaults to 8000) and headless setting: Add-Content -Path .env -Value "PORT=8000" Add-Content -Path .env -Value "HEADLESS=true"
Run the container (host-accessible AND accessible from other containers)
Maps host port 8000 to container port 8000, attaches to the shared network, and loads .env. docker run --name mcp
--detach
--restart unless-stopped
--network mcp-net
--env-file .env
-p 8000:8000
playwright-mcp:local
Validate from the host (PowerShell)
Build request body to call the health_check() tool over HTTP: $headers = @{ 'Content-Type' = 'application/json'; 'x-api-key' = 'your-secure-random-key-here' } $body = @{ method = 'tools/call'; params = @{ name = 'health_check'; arguments = @{} } } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Method POST -Uri 'http://localhost:8000/mcp' -Headers $headers -Body $body
Expected response: { status = 'healthy', ... } (browser starts only when a session is created).
Validate from another container on the same network
Other containers should talk to this service via its container name mcp on port 8000 (not localhost). docker run --rm --network mcp-net curlimages/curl:8.6.0
-s -H "Content-Type: application/json"
-H "x-api-key: your-secure-random-key-here"
-d "{"method":"tools/call","params":{"name":"health_check","arguments":{}}}"
http://mcp:8000/mcp
Variant: inter-container access only (no host port published)
Omit -p to keep it internal; other containers in mcp-net still reach http://mcp:8000. docker run --name mcp
--detach --restart unless-stopped
--network mcp-net
--env-file .env
playwright-mcp:local
Changing the port (if needed)
If you set PORT in .env (e.g., 8931), the container listens on that port per PORT. Publish and target the same container port: Add-Content -Path .env -Value "PORT=8931" docker run --name mcp --detach --network mcp-net --env-file .env -p 8931:8931 playwright-mcp:local
Other containers in mcp-net then use http://mcp:8931/mcp.
Operational diagnostics and logs
Follow logs to verify startup; you should see the line emitted at app start "Starting Playwright MCP server on 0.0.0.0:{port}": docker logs -f mcp
Confirm the container is on the shared network and has a stable name: docker inspect mcp --format '{{json .NetworkSettings.Networks}}' | Out-String docker network inspect mcp-net | Out-String
If requests fail, ensure the x-api-key header matches the .env value and you are posting to /mcp.
Cleanup
Stop and remove the container, remove the network, optionally remove the image: docker rm -f mcp docker network rm mcp-net docker rmi playwright-mcp:local
Common pitfalls (and quick checks)
Missing MCP_API_KEY ⇒ All requests get 500 via APIKeyMiddleware. Check .env and -Headers 'x-api-key'.
Using localhost from another container ⇒ Use http://mcp:8000 (container name on user-defined network), not localhost.
Wrong port mapping when changing PORT ⇒ If PORT!=8000 in the container, publish -p hostPort:containerPort accordingly.
Docker Desktop set to Windows containers ⇒ This image is Linux-based (Dockerfile); switch to Linux containers.
Not on a user-defined network ⇒ Create mcp-net and attach both the service and clients for DNS-based service discovery.
What this enables
Host access: http://localhost:8000/mcp
Inter-container access: http://mcp:8000/mcp (or the port you configured) within the mcp-net network.
References in the code for clarity
Binding and server start: uvicorn.run(), startup log line logger.info
Port selection: PORT env read
API key enforcement: APIKeyMiddleware reading MCP_API_KEY
Container port exposure: EXPOSE 8000
This set of commands deploys the service to Docker Desktop and configures networking so other containers in the same environment can reliably reach it by container name on the shared bridge network.
OpenTelemetry / Distributed Tracing
The server includes built-in OpenTelemetry instrumentation for distributed
tracing. When a calling service (e.g. a Node.js RAG API) sends a W3C
traceparent header with its MCP tool calls, the Playwright server
automatically continues the trace -- so you see the full request flow
across services in Splunk APM, Jaeger, or any OTLP-compatible backend.
How it works
ASGI middleware (
OpenTelemetryMiddleware) extractstraceparentandtracestatefrom incoming HTTP headers and creates a server span linked to the caller's trace.Tool-level spans -- each MCP tool function is wrapped with a
@traced_tooldecorator that creates a child span namedmcp.tool.<function_name>(e.g.mcp.tool.browser_navigate).OTLP export -- when
OTEL_EXPORTER_OTLP_ENDPOINTis set, spans are exported via OTLP/HTTP to the configured OTel Collector.
Enabling tracing
Add these to your .env:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=playwright-mcp
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=devStartup diagnostics
On container start, the server prints a startup banner that shows whether OTel tracing is enabled and whether the collector is reachable. This makes it easy to verify your configuration without sending test requests.
OTel disabled (no endpoint configured):
==============================================================
Playwright MCP Server — Startup Summary
==============================================================
Listen address : http://0.0.0.0:8000
...
--------------------------------------------------------------
OpenTelemetry (Distributed Tracing)
--------------------------------------------------------------
Status : DISABLED
Detail : OTEL_EXPORTER_OTLP_ENDPOINT is not set.
To enable : Set OTEL_EXPORTER_OTLP_ENDPOINT in your
.env file (e.g. http://localhost:4318).
==============================================================OTel enabled and connected:
--------------------------------------------------------------
OpenTelemetry (Distributed Tracing)
--------------------------------------------------------------
Status : ✅ ENABLED & CONNECTED
Endpoint : http://otel-collector:4318
Service name : playwright-mcp
Traces will be exported via OTLP/HTTP.
==============================================================OTel enabled but collector unreachable (with debug hints):
--------------------------------------------------------------
OpenTelemetry (Distributed Tracing)
--------------------------------------------------------------
Status : ⚠️ ENABLED but COLLECTOR UNREACHABLE
Endpoint : http://otel-collector:4318
Error : Connection failed: [Errno 111] Connection refused
Debug checklist:
1. Is the OTel Collector running?
2. Is the endpoint correct in .env?
3. Is there a firewall or network policy blocking traffic?
4. If using Docker Compose, are both services on the same network?
==============================================================Trace structure
When called from another instrumented service, a single trace shows:
[calling-service] POST /mcp (HTTP client span)
|
+-- [playwright-mcp] POST /mcp (ASGI server span, auto)
|
+-- [playwright-mcp] mcp.tool.browser_navigate (manual span)Without tracing
If OTEL_EXPORTER_OTLP_ENDPOINT is not set, the OTel SDK initializes
in no-op mode -- zero overhead, no traces exported. The server works
exactly as before.
References
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
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
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Live browser debugging for AI assistants — DOM, console, network via MCP.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceMCP server that enables AI agents to automate browser testing via Chromium, providing tools for navigation, interaction, and inspection.-
- AlicenseAqualityAmaintenanceMCP server that lets AI agents drive your real Chromium browser with your existing signed-in sessions, providing visible, local, and inspectable automation for tasks like navigation, clicking, typing, and form filling.251Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to operate an isolated local Chromium browser through MCP, with semantic snapshots, ref-based actions, search, research, crawling, and CDP access.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceProvides a headless Chromium browser through MCP, enabling AI agents to browse JavaScript-rendered pages, search the web, capture screenshots, extract tables and data, and run stateful multi-step interactions like clicking, typing, and form submission.1,360,4141MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/tomscoppock/playwright_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server