跳到主要内容

配置面与能力开关:config.d.ts 与 --caps

30 秒导读: config.d.ts 是 Playwright MCP 对外承诺的完整配置形状——一份 TypeScript 类型,列清了你能配什么(用哪个浏览器、监听哪个端口、开哪些工具、拦哪些网络请求)。这一章带你读透这份契约,并用测试文件把「类型上写了什么」和「运行时真的会怎样」对上。贯穿全章的一条暗线:凡是名字里带『安全感』的开关(secrets、allowUnrestrictedFileAccess、allowedHosts),官方注释都明说它们是便利护栏、不是安全边界——真正的边界靠 client 侧权限。


1. 这是什么(零基础也能懂)

一句话定义: config.d.ts 是这个 MCP server 的配置契约——一个纯类型声明文件,描述了「你可以传给它哪些配置项、每项是什么类型、默认什么行为」。

为什么类型文件就是权威? 这个仓库(playwright-mcp)是一层薄包壳:真正的 server 实现打包在 playwright-core 里(见 入口与包壳)。所以你在本仓库里看不到 config 的解析代码。但你能看到两样东西,而它们恰恰是「对外契约」:

契约载体文件它保证了什么
类型声明config.d.ts配置对象的形状(字段名、类型、可选性)
集成测试tests/capabilities.spec.ts某个配置运行时真会产生哪些工具

给谁用: 想用配置文件(--config config.json)或环境变量精调这个 server 的人;想知道「开了 --caps=vision 到底多出哪几个工具」的 agent 作者。

一句话直觉:config.d.ts 当成一家餐厅的菜单——它不做菜(实现在后厨/playwright-core),但它权威地告诉你「有哪些菜、每道菜什么规格」。而 capabilities.spec.ts 就是验菜的人:点了「vision 套餐」,上桌的是不是真的那三道菜。


2. 顶层全景:配置怎么进来、能力怎么分层

2.1 配置的三个来源

一份最终生效的配置,由三处合并而成(优先级从低到高):配置文件 → 环境变量 → CLI flag。本仓库有个工具能把合并结果打回来看——browser_get_config,其描述原话是 "Get the final resolved config after merging CLI options, environment variables and config file"(README.md:1099,该工具属 --caps=config)。

config.json 环境变量 CLI flag
(--config path) (PLAYWRIGHT_MCP_*) (--browser / --caps ...)
│ │ │
└────────┬─────────┴───────────┬───────────┘
▼ ▼
合并解析(在 playwright-core 内,本仓库不可见)


最终 Config 对象 ──► 决定「开哪些浏览器 / 监听哪 / 亮哪些工具」
(browser_get_config 可回读)

怎么读这张图:三个来源向下汇流成一个 Config;后面的每一节都是这个 Config 上的一块字段。

2.2 能力(capability)= 按需点亮的分层工具面

最能体现这个 server 设计取向的,是工具不是一次全给,而是分层 opt-in:

  • 默认只给 core——23 个 browser_* 工具,覆盖点击/输入/导航/截图等日常自动化。
  • 其余能力显式开启——pdfvisiondevtoolsnetworkstoragetestingconfig 都要你用 --caps=<name> 主动点亮,点亮后才多出对应工具。

这就像 Linux 的能力位(capability):进程默认最小权限,需要什么额外能力单独授予。下一节我们逐字读 ToolCapability 这个联合类型。


3. ToolCapability:能力的枚举

config.d.ts:19-31 用一个字符串联合类型,穷举了所有可能的能力名:

export type ToolCapability =
'config' |
'core' |
'core-navigation' |
'core-tabs' |
'core-input' |
'core-install' |
'network' |
'pdf' |
'storage' |
'testing' |
'vision' |
'devtools';

分两族理解:

成员含义
core 及其细分corecore-navigationcore-tabscore-inputcore-install默认就在的浏览器自动化底盘;细分名让你能更细粒度地引用其中一块
额外 opt-inconfignetworkpdfstoragetestingvisiondevtools默认关闭,靠 --caps 或配置里的 capabilities 数组点亮

一处值得注意的契约 vs 帮助文本的落差: CLI 的 --caps 帮助文本只列了三个值——"possible values: vision, pdf, devtools"(README.md:394)。但类型里明明还有 network/storage/testing/config,而且 README 的工具目录里它们各自都标着 "opt-in via --caps=network"(README.md:1105)、"--caps=storage"(README.md:1150)、"--caps=testing"(README.md:1503)、"--caps=config"(README.md:1092)。以类型和工具目录为准:这些能力都可通过 --caps 开启,帮助文本只是没把全部列全。


4. Config 类型全貌(逐块读)

Config 定义在 config.d.ts:33-239。下面按功能块拆开讲,每块点出「它配什么」和「有没有那条『护栏非安全』的暗线」。

4.1 browser 块:用哪个浏览器、怎么连(config.d.ts:37-103)

这块决定「拿哪个浏览器、以什么方式启动或连接」:

字段作用
browserName:41'chromium' | 'firefox' | 'webkit'
isolated:46配置留在内存、不落盘(每次关浏览器即丢弃 profile)
userDataDir:52持久化 profile 的目录;默认建临时目录
launchOptions:60透传给 Playwright 的启动选项(channelheadlessexecutablePath 等)
contextOptions:67浏览器上下文选项(如 viewport)
cdpEndpoint:72连一个已存在的 Chromium 系浏览器(CDP)
remoteEndpoint:91连一个已存在的 Playwright server(WS URL 或 ConnectOptions 对象)
initScript:102一批 JS 文件,在每个页面的任何脚本之前先执行

isolated(内存态 profile)与 userDataDir(落盘持久)是一对互斥取向:一个求「干净、用完即弃」,一个求「像真浏览器一样记住登录态」。

4.2 server 块:监听在哪、DNS-rebinding 防护(config.d.ts:112-128)

server?: {
port?: number; // :116 监听端口(SSE / MCP 传输)
host?: string; // :121 绑定主机,默认 localhost;0.0.0.0 = 所有网卡
allowedHosts?: string[]; // :127 允许服务的 Host 头集合
},

allowedHosts 的注释(config.d.ts:123-127)专门澄清了它不是干什么的:

"This is not for CORS, but rather for the DNS rebinding protection."

也就是说,它校验的是请求的 Host 头,防的是 DNS rebinding 攻击(攻击者让一个域名先解析到无害 IP、绕过同源后再重绑到 localhost,借你浏览器去打本机服务)。它不是 CORS,别拿它当跨域策略用;默认就是 server 绑定到的那个 host。

4.3 capabilities 数组(config.d.ts:137)

配置文件里点亮能力的方式,等价于 CLI 的 --caps:

capabilities?: ToolCapability[]; // config.d.ts:137

注释(config.d.ts:130-136)举了核心几项:'core' 基础自动化、'pdf' PDF 生成、'vision' 坐标交互、'devtools' 开发者工具。

4.4 secrets:『便利,非安全』(config.d.ts:149-154)

secrets?: Record<string, string>; // config.d.ts:154

这是理解本 server 安全取向的第一个关键注释(config.d.ts:149-153),原话:

"Secrets are used to replace matching plain text in the tool responses to prevent the LLM from accidentally getting sensitive data. It is a convenience and not a security feature, make sure to always examine information coming in and from the tool on the client."

翻成白话:它会在工具返回给 LLM 的文本里做字符串替换,把命中的敏感值涂掉,避免密钥顺着响应漏进模型上下文。但注释明说这只是便利、不是安全特性——所以 client 侧仍要自己审查进出工具的数据。

4.5 network 块:允许/拦截哪些请求 + 通配端口语法(config.d.ts:173-191)

network?: {
allowedOrigins?: string[]; // :181 允许浏览器请求的 origin;默认全放行
blockedOrigins?: string[]; // :190 禁止浏览器请求的 origin
};

两条规则写在注释里,记住这两点就够:

  1. 黑名单优先——"Origins matching both allowedOrigins and blockedOrigins will be blocked."(config.d.ts:175:184)同时命中黑白名单 → 拦。
  2. 端口可通配——支持两种写法(config.d.ts:177-179):
写法例子匹配
完整 originhttps://example.com:8080仅该 origin
通配端口http://localhost:*localhost 上 http 协议的任意端口

提示:README 里对应的 CLI flag --blocked-origins 又补了一句更强的免责——"does not serve as a security boundary and does not affect redirects"(README.md:391)。又一次:这是网络护栏,不是安全边界。

4.6 allowUnrestrictedFileAccess:护栏而非边界(config.d.ts:227-233)

本 server 安全取向的第二个关键注释,也是全章标题里那句话的出处:

allowUnrestrictedFileAccess?: boolean; // config.d.ts:233

注释(config.d.ts:227-232)几乎是在替自己划清责任:

"allowUnrestrictedFileAccess acts as a guardrail to prevent the LLM from accidentally wandering outside its intended workspace. It is a convenience defense to catch unintended file access, not a secure boundary; a deliberate attempt to reach other directories can be easily worked around, so always rely on client-level permissions for true security."

即:默认把文件访问限制在 workspace 根目录内(READMe 侧还说明默认会拦 file:// 导航,README.md:390),这是拦『手滑』而非拦『蓄意』。存心越界很容易绕开,真安全靠 client 级权限。

4.7 其余渲染/行为字段

一组更琐碎但常用的开关:

字段作用
imageResponses:218'allow' | 'omit'——是否把图片响应发给 client(注释还提到 'auto':能显示图的 client 才发,:216)
snapshot.mode:224'full' | 'none'——响应里附带的可访问性快照粒度
testIdAttribute:196test id 用哪个属性,默认 data-testid
timeouts.action:202默认动作超时,默认 5000ms
timeouts.navigation:207默认导航超时,默认 60000ms
timeouts.expect:212断言超时,默认 5000ms
codegen:238代码生成语言 'typescript' | 'none'

5. 用测试把「类型」和「运行时」对上

类型只说「能配什么」,不说「配了会怎样」。tests/capabilities.spec.ts 用真 MCP client 连真 server(机制见 测试机制),把这层落差补上。

5.1 默认:精确的 23 个 browser_* 工具

不加任何 --caps 时,listTools() 返回的集合必须精确等于这 23 个(tests/capabilities.spec.ts:21-45,用 Set 全等断言,多一个少一个都算失败):

#工具#工具
1browser_click13browser_navigate_back
2browser_console_messages14browser_navigate
3browser_drag15browser_network_request
4browser_drop16browser_network_requests
5browser_evaluate17browser_press_key
6browser_file_upload18browser_resize
7browser_fill_form19browser_run_code_unsafe
8browser_handle_dialog20browser_snapshot
9browser_hover21browser_tabs
10browser_select_option22browser_take_screenshot
11browser_type23browser_wait_for
12browser_close

这 23 个就是 §2.2 说的 core 层默认工具面。

5.2 --caps=pdf 多出 PDF 工具(:48-55)

startClient({ args: ['--caps=pdf'] }) 起 server,断言工具清单包含 browser_pdf_save:

const { client } = await startClient({ args: ['--caps=pdf'] }); // :49-50
const toolNames = tools.map(t => t.name);
expect(toolNames).toContain('browser_pdf_save'); // :54

5.3 --caps=vision 多出坐标类工具(:57-66)

vision 能力点亮的是基于像素坐标的交互(而非默认的基于快照 ref 的语义交互),断言包含三个 _xy 工具:

// args: ['--caps=vision'] → :57-62
expect(toolNames).toContain('browser_mouse_move_xy'); // :63
expect(toolNames).toContain('browser_mouse_click_xy'); // :64
expect(toolNames).toContain('browser_mouse_drag_xy'); // :65

5.4 legacy --vision 兼容(:68-77)

历史上曾有独立的 --vision flag;它现在等价于 --caps=vision,测试专门守住这条向后兼容——args: ['--vision'] 也要点亮同样那三个 _xy 工具(tests/capabilities.spec.ts:68-77)。

5.5 一张能力 → 工具的对照

把上面几条测试连同 README 工具目录汇成一表:

能力怎么开代表性多出的工具依据
core(默认)无需开上面那 23 个capabilities.spec.ts:21-45
pdf--caps=pdfbrowser_pdf_savecapabilities.spec.ts:48-55
vision--caps=vision(或 legacy --vision)browser_mouse_{move,click,drag}_xycapabilities.spec.ts:57-77
network--caps=network网络控制类工具README.md:1105
storage--caps=storage存储态类工具README.md:1150
devtools--caps=devtools开发者工具类README.md:1313
testing--caps=testing断言类工具README.md:1503
config--caps=configbrowser_get_configREADME.md:1092-1099

6. 巧妙之处 / 设计取向

  • 契约与实现解耦。 实现藏在 playwright-core,但类型契约(config.d.ts)和行为契约(capabilities.spec.ts)都留在本仓库,让「对外承诺」独立于实现演进而可核对。README 里那份 config 类型甚至是从 config.d.ts 自动同步生成的(见 文档即真相)。

  • 默认最小、能力 opt-in。 默认只亮 23 个 core 工具,pdf/vision/devtools/network/storage/testing/config 全要显式开。这既缩小了给 LLM 的工具面(减少误触、省 token),也让权限「看得见地」分层。

  • 反复出现的『护栏 ≠ 安全边界』取向(本章核心)。 三处独立字段的注释异口同声:

    • secrets —— "a convenience and not a security feature"(config.d.ts:151-152)
    • allowedHosts —— "not for CORS, but ... DNS rebinding protection"(config.d.ts:125-126,划清它负责什么)
    • allowUnrestrictedFileAccess —— "a guardrail ... not a secure boundary ... always rely on client-level permissions"(config.d.ts:228-232)
    • blockedOrigins —— "does not serve as a security boundary"(README.md:391)

    这是一个一致且诚实的设计立场:server 提供的所有「安全感」开关都只拦『意外/手滑』,真正的信任边界被显式地推给 client 权限层。读这个配置时,别把这些开关误当护城河。


7. 边界与局限

  • 本仓库无解析逻辑。 三来源(文件/环境变量/CLI)如何合并、优先级细节,不在本仓库源码里(在 playwright-core);本章只依据类型契约与测试断言,合并语义靠 browser_get_config 回读验证。
  • --caps 帮助文本不全。 CLI 帮助只列了 vision, pdf, devtools(README.md:394),而 network/storage/testing/config 同样可开——以 ToolCapability 类型和工具目录为准。
  • 护栏可被蓄意绕过。 如 §6 所述,secrets/allowUnrestrictedFileAccess/allowedHosts/blockedOrigins 都不构成对抗蓄意攻击的边界。

8. 代码地图(导航索引)

主题文件符号 / 锚点
能力枚举config.d.ts:19-31ToolCapability
配置总形状config.d.ts:33-239Config
浏览器块config.d.ts:37-103Config.browser(browserName/isolated/userDataDir/launchOptions/contextOptions/cdpEndpoint/remoteEndpoint/initScript)
DNS-rebinding 防护config.d.ts:123-127Config.server.allowedHosts
能力数组config.d.ts:137Config.capabilities
secrets『便利非安全』config.d.ts:149-154Config.secrets
网络允许/拦截 + 通配端口config.d.ts:173-191Config.network.allowedOrigins / blockedOrigins
文件访问护栏config.d.ts:227-233Config.allowUnrestrictedFileAccess
渲染/行为开关config.d.ts:196-238imageResponses / snapshot.mode / testIdAttribute / timeouts / codegen
默认 23 工具断言tests/capabilities.spec.ts:19-46test('test snapshot tool list')
pdf 能力tests/capabilities.spec.ts:48-55test('test capabilities (pdf)')browser_pdf_save
vision 能力tests/capabilities.spec.ts:57-66test('test capabilities (vision)')browser_mouse_*_xy
legacy --vision 兼容tests/capabilities.spec.ts:68-77test('support for legacy --vision option')
--caps / 各 flag 目录README.md:390-425CLI options 表
能力 → 工具分组目录README.md:1088-1503opt-in via --caps=* 折叠块

相关章节: 入口与包壳(config 在何处被消费)· 文档即真相(README 里的 config 类型如何从 config.d.ts 生成)· 测试机制(startClient 如何用真 client 打真 server)。