Playwright MCP
在 Render 上部署 Playwright MCP
在 Render 上部署 Playwright MCP 大概只需点击一次。你就能得到一个托管的、内置无头 Chromium 的 MCP 服务器,让你的 AI 工具通过 HTTP 驱动它——不需要在每台机器上安装本地浏览器,也不需要每次运行 npx。
https://github.com/user-attachments/assets/0f31c279-f2e0-431f-a854-50677bd800c5
功能
Playwright MCP 是一个 Model Context Protocol 服务器,它让 LLM 能打开真实浏览器、导航、点击、输入,并读取结构化辅助树快照(不是截图)的页面。它通常通过 npx @playwright/mcp 在本地运行。这个模板改成一个单一的 Render Web 服务来运行它,这样任何 MCP 客户端都可以连接到一个共享的 HTTPS URL。
它是官方 mcr.microsoft.com/playwright/mcp 镜像(自带无头 Chromium)的一个薄封装——不需要改源码。封装仅添加了 Render 必需的参数(--headless、--no-sandbox,再加上由环境提供的 --port 和 --allowed-hosts),并在服务器前面加了一个 Bearer-token 验证层,因为 Playwright MCP 本身并不支持认证。
默认开启认证。 Playwright MCP 在 HTTP 模式下没有认证功能,并且多了一个相当于 RCE 的工具,因此这个模板不会直接用默认方式开放它:请求必须携带
Authorization: Bearer $MCP_TOKEN,而 Render 会在部署时自动生成这个 token。阅读 Security 来了解它能保护什么、不能保护什么。
完整的工具列表、配置项以及客户端设置,请参阅 上游 README。
Related MCP server: WebControl
架构
一个 Render Web 服务在 Bearer token 验证门后面运行官方 Playwright MCP 镜像。MCP 客户端通过 Render 的 TLS 终止边缘,以 Streamable HTTP 方式访问 /mcp;验证门检查 token 后把请求转发给 loopback 地址的 MCP 服务器,而后者会在同一容器内驱动无头 Chromium 并返回辅助树快照。
┌─────────────┐ HTTPS /mcp ┌────────────────────────────────────────────────┐
│ MCP client │ ──────────────► │ Render web service (Docker, standard plan) │
│ (Claude, │ + Bearer │ │
│ Cursor, …) │ token │ render-entrypoint.sh │
│ │ │ │ reads PORT, allowed hosts │
│ │ Streamable │ ▼ │
│ │ ◄────────────── │ render-auth-proxy.mjs :$PORT (public) │
└─────────────┘ snapshots │ │ 401 unless the Bearer token matches │
│ ▼ │
│ node /app/cli.js 127.0.0.1:8931 (loopback) │
│ │ │
│ ▼ │
│ headless Chromium (baked into base image) │
└────────────────────────────────────────────────┘一次部署是如何拼装起来的:
文件 | 作用 |
Blueprint 脚本。声明了唯一的 Docker 服务、方案/区域、 | |
基于 | |
读取 | |
PID 1 进程。只依赖 Node 标准库:拒绝任何没有 | |
限速逻辑独立出来,因为它自己有点状态,值得单独测试。它基于固定窗口对所有客户端的认证失败次数进行限流。该文件被 proxy import,所以 | |
构建镜像并端到端测试封装层:tom 无 | |
记录了在本地运行容器的相同参数。 |
关键特性:
薄封装,不改 upstream。 Playwright MCP 版本由
Dockerfile.render的 base-image tag 固定;升级就是一个 tag 一行改动(见 Rolling Playwright MCP)。No database、无持久存储、无需填入任何参数。 唯一一个 secret,
MCP_TOKEN,由 Render 在部署时生成。browser 保持 upstream 默认的 persistent profile,所以 profile 可能在请求之间保存登录状态,这对只属于你自己一个有主机既是这个 template 的已知假设(见 Configuration)。鉴权,且不公开。 authentication 层由本 template 而非 upstream 提供。如果
MCP_TOKEN未设置,container 会拒绝启动,所以不存在无鉴权匿名暴露的配置(见 Security)。
前提
部署之前,你需要:
一个 GitHub 账号,用来 fork 这个仓库(Deploy 按钮读取你自己仓库中的
render.yaml)。
不需要 API key 或第三方账号。 唯一的 MCP_TOKEN secret 会在部署时为你生成——你只需把它复制到 MCP client 即可(见 Deploy)。
想同时本地运行(可选——见 Run locally):
安装带 BuildKit 的 Docker(Docker Desktop 4.x+ 或 Docker Engine 23+)。
DGRockerfile.render使用了# syntax=指令和COPY --chmod,这些都属于 BuildKit 特性。一个 MCP client 来验证(例如 Claude Code、Cursor),或直接
curl。
你不需要 Node.js、Playwright 或本地 Chrome——base 镜像已经内置了一切。
部署
点击上方的 Deploy to Render(或 fork 本仓库并从中创建一个新的 Blueprint)。
Render 读取
render.yaml,并在标准配置中提供一个 Docker 服务(playwright-mcp)。等待部署成功。你的服务地址为
https://<your-service>.onrender.com/mcp。在 Dashboard 的 Environment 页面复制
MCP_TOKEN——Render 已经帮你生成了它。你的 MCP 客户端必须将它作为Authorization: Bearer <token>传递(见 Using the app);否则每个请求都会返回401。在向服务授权任何敏感数据之前,阅读 Security。token 是通往容器的唯一身份凭证,因此一定要像对待密码一样对待它——并在可能时进一步加固。
实例大小: headless Chrome 在免费/
starter实例(512MB)上可能会不足,所以 Blueprint 默认使用standard(2GB)。确认你的任务量足够小才考虑降级。
使用应用
将你的 MCP客户端指向该服务上的 /mcp 端点,并把 MCP_TOKEN 作为 Bearer token 传入。例如,使用 Claude Code:
claude mcp add --transport http playwright https://<your-service>.onrender.com/mcp \
--header "Authorization: Bearer <your-MCP_TOKEN>"也可以直接把它添加到一个客户端配置文件中:
{
"mcpServers": {
"playwright": {
"url": "https://<your-service>.onrender.com/mcp",
"headers": {
"Authorization": "Bearer <your-MCP_TOKEN>"
}
}
}
}如果客户端报告 401,说明 header 丢失或 token 与 Dashboard 中的当前不匹配。
然后请你的 assistant 浏览——例如:“打开 example.com,并给我页面标题和一些主标题。”她将会使用 Playwright MCP 工具在你的托管浏览器中执行并返回结果。
本地运行
可选部分——上的部署路径不需要任何本地环境。若你想修改 render-entrypoint.sh,在 push 之前本地模拟下会很有用。
git clone https://github.com/render-examples/playwright-mcp-render.git
cd playwright-mcp-render
cp .env.example .env # then set MCP_TOKEN, e.g. to `openssl rand -hex 32`
docker build -f Dockerfile.render -t playwright-mcp-render .
docker run --rm --env-file .env -p 10000:10000 playwright-mcp-render一旦容器就绪,会先打印上游自带的 Listening on …,然后是验证层的 [auth] Bearer-token gate listening …——这个顺序,是因为验证层会保持公共端口关闭,直到其背后至少 server 能接受连接为止,所以最后一行的 [attt] 才意味着服务真正 ready。(提到 [startup] 那一行的 https:// 是给部署服务上的,本地用 http 而不是。) 随后可以用一个 MCP 握手确认 server 正常——先 export 你在 .env 中执行的同一个 token,好让它下面的验证头生效:
curl -sS -X POST http://localhost:10000/mcp \
-H "Authorization: Bearer $MCP_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'你应该会返回一个 serverInfo 块,其中服务名是 Playwright;去掉 Authorization 头,则应当收到 401 Unauthorized。把客户端指向 http://localhost:10000/mcp,设法就想部署后 URL 一样使用即可。
MCP_TOKEN是唯一必须变量——没有它容器会直接退出。.env中其他内容只是为了方便:在本地环境没有 Render 提供的RENDER_EXTERNAL_HOSTNAME,所以 entrypoint 会自行回落到PORT=10000和--allowed-hosts 区块值。
想完全跳过 Docker?上游可以这样直接运行同一个服务器:npx @playwright/mcp@latest --port 10000——不过注意这运行的是 npm 发布版本,不是本仓库固定的镜像 tag,并且它没有认证验证层(这个是本模板添加的)。这条路径也并非 Render 部署时实际运行的方式,因此在推送前请先在容器里验证。
配置
所有内容都在 render.yaml 里定义;.env.example 给出了本地运行的相同参数。
环境变量 | 默认值 | 作用 |
|
| auth gate 监听的端口,并且 Render 会路由到这个端口。 |
| render生成 | 必需。 所有请求必须携带的 Bearer token。若缺少它,容器会拒绝启动。在 Dashboard 中修改该值可以轮换。 |
|
| MCP 服务器监听的回环端口,仅当发生冲突时才需要修改。 |
.env.example 还列出了 PLAYWRIGHT_MCP_HOST、PLAYWRIGHT_MCP_HEADLESS 和 PLAYWRIGHT_MCP_NO_SANDBOX。这些只有在直接运行服务器(即在此镜像之外运行)时才起作用——在 Render 上,render-entrypoint.sh 总会传入等价的 CLI 标志,而 CLI 标志优先,所以在 Render 控制面板设置这些变量不会生效。唯一的例外是 PLAYWRIGHT_MCP_ALLOWED_HOSTS,入口脚本确实会采纳它。
入口脚本通过 Render 的 RENDER_EXTERNAL_HOSTNAME 自动将服务器的 host 检查限定在你自己服务的 onrender.com 主机名内。如果你添加了自定义域名,对该域名的请求会被 host 检查拒绝,直到你设置 PLAYWRIGHT_MCP_ALLOWED_HOSTS(逗号分隔,例如 myapp.com,myapp.onrender.com;* 会关闭该检查)。
浏览器 profile 状态
入口脚本不传任何 profile 标志,因此你得到的是 Playwright MCP 的默认行为:容器文件系统上的一个持久化 profile(~/.cache/ms-playwright/mcp-*)。有两个后果值得了解:
调用之间的登录状态会保留下来——这通常正是你想要的。 通过托管的浏览器认证一次,之后每次会话都复用该会话。所有指向该 URL 的客户端共享这同一个 profile,因此这隐含前提是该服务归你所有(见 Security)。没有挂载 Disk(磁盘),因此服务重启或重新部署时 profile 会被清空。
并发客户端可能冲突。 上游指出,持久化 profile “一次只能由一个浏览器实例使用,因此共享同一工作区的并发 MCP 客户端会冲突”——所以两个编辑器指向同一个 URL 时可能互相冲突。扩展到多个实例后,每个实例也会获得各自的 profile。
要改变以上任何一点,请编辑 render-entrypoint.sh:
想要的 | 添加 |
每次会话一个全新的内存内 profile,关闭即废弃 |
|
一个能跨重新部署存活的 profile(保存登录态) | 一个 Render Disk 加上 |
Security
真实性披露
Playwright MCP 暴露了 browser_run_code_unsafe,上游描述它为:“运行一段 Playwright 代码。该工具是不安全的:它会在 Playwright 服务器进程中执行任意 JavaScript,相当于 R.C.E。” 在引用的版本里,它被列在 Core automation 之下,而不是某个可选能力;且 --caps 只会增加额外能力(Visual vision,&ctul <>)
公多方指定
.它将日志只取决于谁 -nem。" playaudio reason *pending
"...*移动.
`
现在到了微笑的网关other.
。
do": So, let's:
"&(That quote is fine).
Uno:
Recap(final)。</ (access.
安全
你实际运行的是什么
Playwright MCP 暴露了 browser_run_code_unsafe,上游将其描述为:“运行一段 Playwright 代码:不安全,会在 Playwright 服务器进程中执行任意 Jenkins JavaScript,等同于 RCE。" 在当前的固定版本里,它被列在Core automation(核心自动化)之下,不是某个可选择(opt-in)的能力;而--nullcaps, 只启用额外的能力(vision、dragons(如pdf‘,演 e-cool"有多个):
fine。
I输出 final answer 下. —彼的完整。
Response终不太连贯,由于中间我的草稿混乱了,现在手记下完整.env.example 还列出了 PLAYWRIGHT_MCP_HOST、PLAYWRIGHT_MCP_HEADLESS 和 PLAYWRIGHT_MCP_NO_SANDBOX。这些只有在你直接运行服务器(在此镜像之外)时才有用——在 Render 上,render-entrypoint.sh 总会等传入等价的 CLI 参数,而 CLI 参数优先,所以你在 Render 控制面板中设置它们不会起任何作用。唯一的例外是 PLAYWRIGHT_MCP_ALLOWED_HOSTS,入口脚本确实会尊从它。
入口脚本通过 Render 的 RENDER_EXTERNEL_HOSTNAME 自动将服务器的 host 检查范围限定为你服务自己的 onrender.com 主机名。如果你添加了[自定义域名],对该域名的请求会一直触发 host 检查被拒,直到你设置了 PLAYWRIGHT_MCP_ALLOWED_HOSTS(使用逗号结尾,例如 myapp.com,myapp.onrender.com;开 禁用检查)。
浏览器 profile 状态
入口脚本没有传入任何 profile 标志,所以你得到的是 Playwrite MCP(MCP)的默认:容器文件系统上的persistent profile(持久化 profile)(~/.cache/ms-playwright/mcp-*)。有两个后果值得知道:
登录状态会跨调用而保留——这通常正是你想要的。 在托管的浏览器中认证一次,之后的会话都复用这个 session。所有指向同一 URL 的客户端都共享这一个 profile,所以这默认前提是这个服务属于你(见安全。没有挂载 Disk,因此重启或重新部署后 profile 会被清除。
并发客户端可能冲突。 上游指出,一个 profile“一次只能被一个浏览器实例使用,因此共享同一 profile 的并发 MCP 客户端会互相冲突”——所以两个编辑器指向同一个 URL 时可能互相冲突;如果你扩容超过一个实例,每个实例也会有自己独立的 profile。
要调整其中任意一项,修改 render-entrypoint.sh:
想要 | 添加 |
每次会话一个全新的内存级 profile,关闭后即丢弃 |
|
要一个跨重新部署仍会保留的 profile(已保存的登录) | 一个 Render Disk 加上 |
(上文 mount-path 按要求保持原样)
Security
你到底在运行什么
Playwright MCP 暴露了 browser_run_code_unsafe,上游描述它:“运行一段 Playwright 代码。不安全:在 Playwright 服务器进程中执行任意的脚本,相当于获得远程代码执行(RCE)。” 在当前固定的版本中,它是列在 Core automation(核心自动化工具) 下,而非某个可选能力;并且 [--caps](https://github.com/mic/... 只会启用另外的能力(visi)。这就意味着调用方可以获得任意代码执行权限。
它不做什么
这是一个门,不是纵深防御。它不会为 RCE 做沙箱、不限已认证调用方的权限,也不提供调用方各自的身份——拥有相同 token 的调用方都是同一个主体,前述速率限制只放缓猜测,不代表已经泄的 token 不会被滥用。如果可能,在这之上再加一些更强的东西:
*看下入站 吗,见后文。
它不做什么(译文完整于上)
等等 — 下面贴到的正文。
这里我决定改用稳定输出。
最终译文(顺手复读压一次):.env.example 还列出了 PLAYWRIGHT MCP_HOST、PLAYWRIGHT MCP_HEADLESS 和 PLAYWRIGHT MCP_NO_SANDBOX。这些只有在你运行服务器服务器直接(在此镜像之外运行)时,才起作用——在 Render 上,render-entryponit.sh 总会等传入等价 CLI 标志,而 CLI 标志优先,所以你在 Render 控制台里面设置它们不会起任何作用。唯一的例外是 PLAYWRIGHT_MCP_ALLOWED_HOSTCS,入口脚本确实会采纳它。
入口脚本通过 Render 的 RENDER_EXTERNAL_HOSTNAME,自动把服务器的 host 检查限定到你服务自己的 onrender.com 域名。如果你添加了[自定义域名],未设置 PLAYWRIGHT_MCP_ALLOWED_HOSTS 时(逗号分隔,例如 *.onrender.com;*` 关闭检查?
Browser profile state
MCP 中:入口脚本不下传任何 profile 标志,故为 Playwright MCP 的默认:容器文件系统「、系统信息」上的持久化 profile(~/.cache/ms-playwright/mcp-*)。
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
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 real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to automate web tasks such as browsing, clicking, typing, and taking screenshots via the Model Context Protocol.1MIT
- FlicenseNot gradedqualityCmaintenanceHeadless browser automation for LLM agents via REST API or MCP tools. Enables navigating pages, reading structured content, clicking elements, filling forms, and executing JavaScript.
- AlicenseBqualityAmaintenanceEnables browser automation through the Model Context Protocol, allowing AI agents to control Chrome, Firefox, or Edge for tasks like navigation, clicking, typing, and screenshots.3986MIT

Browseagent MCPofficial
AlicenseAqualityDmaintenanceEnables AI agents to control web browsers through the Model Context Protocol, supporting navigation, clicking, typing, and screenshots.12101MIT
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/erlanov2023e/playwright-mcp-render-mt8x2ig6'
If you have feedback or need assistance with the MCP directory API, please join our Discord server