PlaywrightMCPSharp is a .NET-native Playwright MCP server for browser automation over Streamable HTTP or stdio. It does not require Node.js or Python to run the server.
The application ships with the Playwright .NET library, but it does not bundle the Playwright browser binaries by default. On a fresh machine, the host still needs the matching Playwright browser runtime installed once unless you pre-package those browser binaries yourself. PlaywrightMCPSharp itself still does not require a separate Node.js or Python install, because it uses Playwright for .NET rather than the Node.js Playwright package or a Python wrapper.
- Hosts a stateful Streamable HTTP MCP endpoint at
http://127.0.0.1:5704/mcpby default. - Can also run as a single-session stdio MCP server for local clients.
- Launches one isolated Playwright browser session per MCP session.
- Exposes
browser_*tools for navigation, snapshots, forms, storage, routing, tracing, verification, and coordinate-based mouse control. - Uses Playwright AI ARIA snapshots so LLMs can work from structured page state instead of pixel screenshots.
- Supports a C#-based
browser_run_codetool with access topage,context,browser,playwright,sessionId, andct. - Exposes MCP tools to inspect and install the required Playwright browser runtime on the host.
- .NET SDK 10.0+
- Windows, macOS, or Linux supported by Playwright for .NET
- One-time Playwright browser install after restore/build
- Restore and build:
dotnet restore
dotnet build- Install the Playwright browser used by the server:
powershell .\src\PlaywrightMCPSharp.Server\bin\Debug\net10.0\playwright.ps1 install chromium- Run the server over HTTP:
dotnet run --project .\src\PlaywrightMCPSharp.Server- Check health:
curl http://127.0.0.1:5704/healthzFor stdio instead of HTTP:
dotnet run --project .\src\PlaywrightMCPSharp.Server -- --stdioFor MCP client configs, prefer launching the built server directly after dotnet build:
dotnet .\src\PlaywrightMCPSharp.Server\bin\Debug\net10.0\PlaywrightMCPSharp.Server.dll --stdioFor long-running local HTTP hosting on Windows, PlaywrightMCPSharp can run as a Windows Service.
- Publish the server:
dotnet publish .\src\PlaywrightMCPSharp.Server -c Release -r win-x64 --self-contained false- Create the service pointing at the published executable:
sc.exe create PlaywrightMCPSharp binPath= "C:\ABSOLUTE\PATH\TO\PlaywrightMCPSharp.exe" start= auto- Start it:
sc.exe start PlaywrightMCPSharpThe service uses HTTP mode and the same PlaywrightMCPSharp.json / environment-variable configuration as the normal app. If you need a different port, route, or security mode, set the corresponding PLAYWRIGHTMCP_PlaywrightMCPSharp__... environment variables for the service.
The repo includes a basic Dockerfile for HTTP-mode hosting:
docker build -t playwrightmcpsharp .
docker run --rm -p 5704:5704 \
-e PLAYWRIGHTMCP_PlaywrightMCPSharp__Server__Host=0.0.0.0 \
-e PLAYWRIGHTMCP_PlaywrightMCPSharp__Server__Port=5704 \
-e PLAYWRIGHTMCP_PlaywrightMCPSharp__Server__Password=change-me \
-e PLAYWRIGHTMCP_PlaywrightMCPSharp__Browser__Headless=true \
playwrightmcpsharpBy default the container listens on http://0.0.0.0:5704/mcp.
Notes:
- The container image is set up for the server itself, not for preinstalled Playwright browser runtimes.
- After the container starts, you can call
browser_runtime_statusandbrowser_install_runtimeif you want to install the configured browser runtime from inside the MCP session. If an MCP client is already connected, it can also do the browser install over MCP by callingbrowser_install_runtime.
Settings live under PlaywrightMCPSharp in PlaywrightMCPSharp.json and can be overridden with environment variables such as PLAYWRIGHTMCP_PlaywrightMCPSharp__Server__Port=9000. Environment variables win over JSON; use __ for nested keys, numeric indexes for arrays such as PLAYWRIGHTMCP_PlaywrightMCPSharp__Server__AllowedHosts__0=*, and true/false for booleans.
PlaywrightMCPSharp:Server:Password is blank by default. Set it to require an MCP endpoint password; clients may send Authorization: Bearer <password>, the Basic auth password, or X-MCP-Password. This password gate is separate from the security mode below.
Http: Streamable HTTP on/mcpplus/healthzStdio: single-session stdio transport over stdin/stdout
You can also override transport from the command line with --stdio or --http.
LocalOnly: only loopback clients may connectRemoteBearer: remote access requiresAuthorization: Bearer <token>RemoteNoAuth: remote unauthenticated access; this is blocked unlessDangerousAllowRemoteNoAuth=true
{
"PlaywrightMCPSharp": {
"Server": {
"Transport": "Http",
"Host": "0.0.0.0",
"Port": 5704,
"Route": "/mcp",
"AllowedHosts": [ "*" ],
"AllowedOrigins": [ "https://your-client.example" ]
},
"Security": {
"Mode": "RemoteBearer",
"BearerToken": "replace-me"
},
"Browser": {
"Headless": true
}
}
}{
"PlaywrightMCPSharp": {
"Server": {
"Transport": "Http",
"Host": "0.0.0.0",
"Port": 5704,
"AllowedHosts": [ "*" ]
},
"Security": {
"Mode": "RemoteNoAuth",
"DangerousAllowRemoteNoAuth": true
}
}
}This mode is intentionally loud and unsafe. Use it only on a trusted network.
For Streamable HTTP clients, point them at:
http://127.0.0.1:5704/mcp
For stdio clients, launch the server command directly:
dotnet run --project .\src\PlaywrightMCPSharp.Server -- --stdio
For desktop/editor MCP clients that store a command plus args, using the built dll is usually more reliable than dotnet run:
{
"command": "dotnet",
"args": [
"C:\\path\\to\\PlaywrightMCPSharp\\src\\PlaywrightMCPSharp.Server\\bin\\Debug\\net10.0\\PlaywrightMCPSharp.Server.dll",
"--stdio"
]
}If the client supports roots, PlaywrightMCPSharp requests them and restricts file access to those roots plus the per-session artifact directory. If the client does not support roots, PlaywrightMCPSharp falls back to the current working directory.
browser_navigatebrowser_navigate_backbrowser_closebrowser_tabsbrowser_snapshotbrowser_take_screenshotbrowser_clickbrowser_hoverbrowser_dragbrowser_typebrowser_fill_formbrowser_select_optionbrowser_press_keybrowser_wait_forbrowser_resizebrowser_handle_dialogbrowser_file_uploadbrowser_console_messagesbrowser_network_requestsbrowser_evaluatebrowser_get_config
browser_network_state_setbrowser_routebrowser_route_listbrowser_unroutebrowser_cookie_getbrowser_cookie_setbrowser_cookie_deletebrowser_cookie_clearbrowser_localstorage_getbrowser_localstorage_setbrowser_localstorage_removebrowser_localstorage_clearbrowser_sessionstorage_getbrowser_sessionstorage_setbrowser_sessionstorage_removebrowser_sessionstorage_clearbrowser_storage_statebrowser_set_storage_state
browser_highlightbrowser_hide_highlightbrowser_generate_locatorbrowser_runtime_statusbrowser_install_runtimebrowser_start_tracingbrowser_stop_tracingbrowser_verify_element_visiblebrowser_verify_text_visiblebrowser_verify_valuebrowser_verify_list_visiblebrowser_mouse_click_xybrowser_mouse_downbrowser_mouse_drag_xybrowser_mouse_move_xybrowser_mouse_upbrowser_mouse_wheelbrowser_run_code
browser_run_code accepts either:
code: inline C# scriptfileName: script file path under an MCP root or the workspace
Available globals:
pagecontextbrowserplaywrightsessionIdctSaveTextAsync(...)SaveJsonAsync(...)
Example:
var title = await page.TitleAsync();
return new { title, url = page.Url };- AI ARIA snapshots are page-derived input and should be treated as untrusted. Prompt injection can be present in page text and accessibility names.
browser_run_codeexecutes arbitrary C# against a live browser session. Disable it withPLAYWRIGHTMCP_PlaywrightMCPSharp__Features__EnableRunCode=falseif that is too much power for your client.RemoteNoAuthis intentionally dangerous and should not be exposed on the public internet.- File operations are root-scoped by default.
AllowUnrestrictedFileAccess=trueremoves that guardrail. browser_install_runtimedownloads executables onto the host machine.withDependencies=truemay also attempt OS-level dependency installation when Playwright supports it.