使用说明
反应调试mcp
一个专注的MCP服务器 React应用程序的运行时调试设计用于并排运行 chrome开发工具mcp.
| 问题 | 服务器 |
|---|---|
| 导航、单击、填写表单、截图 | chrome devtools mcp |
| 控制台日志、性能跟踪 | chrome devtools mcp |
| React组件状态和道具 | 反应调试mcp |
| Redux/状态存储检查 | 反应调试mcp |
| API响应机构 | 反应调试mcp |
| 断点、步进、范围检查 | 反应调试mcp |
| 日志点(非暂停值捕获) | 反应调试mcp |
工具(共26个)
反应检查
| 工具 | 目的 |
|---|---|
get_page_info |
检测React、版本、存储、dev/prod、DevTools挂钩 |
get_component_tree |
带有名称、键、可选挂钩/道具的组件层次结构。支持 start_selector 扩展到子树 |
get_react_component_path |
从根组件到CSS选择器处组件的路径。每个节点可选的道具/钩子 |
find_react_component(name) |
使用道具过滤按名称查找所有实例。支持 start_selector 以确定搜索范围。返回完整 parentPath 从根 |
inspect_react_component_by_name(name) |
按名称+目标深度检查特定实例 |
inspect_react_component(selector) |
通过CSS选择器进行检查(快速路径) |
inspect_react_context(selector) |
所有上下文。流入组件的提供程序值 |
get_react_error_boundaries |
错误边界、暂停回退、开发覆盖 |
部件检查工具-- get_component_tree, get_react_component_path, find_react_component, inspect_react_component,以及 inspect_react_component_by_name --接受 show_function_details 将函数值扩展为 {functionName, functionBody, paramCount} 而不是 "[function]".
状态与网络
| 工具 | 目的 |
|---|---|
get_store_state(path?) |
使用点路径读取Redux/Zustand状态 |
get_network_responses(url_pattern?) |
API请求-实时请求包括全文,历史请求(在MCP连接之前)包括URL/状态/时间 |
看到 forwardRef(Anonymous) 在组件树中? 该名称在运行时确实不存在,也不是此服务器中的错误(React DevTools也显示了同样的情况)。 forwardRef() 返回异国情调 物体,以及一个写 export const MdcButton = forwardRef((props, ref) => …) 既不设置 displayName 也不 render.name (JS推断一个函数的 .name 仅在赋值时,从不在调用参数位置),因此React没有可报告的名称。通过将导出名称复制到 displayName 在dev中:
import * as Ids from 'ids-wc/dist/react/components';
import { nameLibraryComponents } from './react-debug-helper';
nameLibraryComponents(Ids); // forwardRef(Anonymous) → MdcButton, MdcGrid, …
get_store_state 是另一个需要你的应用程序配合的工具:store是一个没有DOM存在的闭包变量,所以只有当你把它放在 window 全球(__REDUX_STORE__, __ZUSTAND_STORE__,或 __STORE__).要么自己设置全局,要么 复制 react-debug-helper.ts 进入应用程序的源代码树并调用 exposeStore(store, 'redux' | 'zustand') 你创建商店的地方——它没有开发之外的操作。无论你揭露什么,都必须有一个 .getState() 方法(对于Zustand来说,这意味着钩子本身,而不是 useStore()).没有这个, get_store_state 报告 { store: 'none' }.
源代码检查(捆绑脚本,无暂停)
| 工具 | 目的 |
|---|---|
list_scripts(filter?) |
发现加载的捆绑脚本 set_breakpoint 匹配不明确 |
read_source(file) |
从浏览器读取捆绑/生成的源代码——查看供应商代码或确认加载的内容 |
search_source(query) |
搜索加载的捆绑脚本,以缩小从磁盘读取的文件范围 |
断点(交互式,暂停执行)
| 工具 | 目的 |
|---|---|
set_breakpoint(file, line) |
设置断点——首先从磁盘读取源文件以选择行 |
wait_for_breakpoint |
阻塞直到断点触发,返回作用域 |
inspect_scope(frame_index?) |
读取任何堆栈帧上的变量 |
evaluate_at_breakpoint(expression) |
Eval在暂停帧的上下文中 |
step_over / step_into / step_out |
执行控制 |
resume |
继续执行 |
日志点(被动,无暂停)
| 工具 | 目的 |
|---|---|
set_logpoint(file, line, expressions) |
在不暂停的情况下将值捕获到控制台 |
管理
| 工具 | 目的 |
|---|---|
list_breakpoints |
显示所有活动断点和日志点 |
remove_breakpoint(id) |
删除一个 |
remove_all_breakpoints |
干净的石板 |
evaluate_in_page(expression) |
临时JS评估逃生舱 |
调试工作流
只要您的开发服务器发出源代码,磁盘上的行号就与浏览器匹配
地图(webpack devtool: source-mapVite等)。从文件系统读取文件
选择断点行,然后通过编辑相同的文件来修复错误。
断点流
You: "The checkout total is wrong. Debug it."
Agent: (reads src/hooks/useCheckout.ts from filesystem)
→ 40 │ function calculateTotal(items) {
41 │ const subtotal = items.reduce((s, i) => s + i.price, 0);
42 │ const taxRate = getTaxRate();
43 │ const tax = subtotal * taxRate;
44 │ return { subtotal, tax, total: subtotal + tax };
Agent: set_breakpoint({ file: "useCheckout.ts", line: 42 })
→ "Breakpoint set. Have user trigger the code path."
Agent: "Please click the checkout button."
You: (click checkout in the browser)
Agent: wait_for_breakpoint()
→ paused at useCheckout.ts:42
scope: { items: [...], subtotal: 29.97, taxRate: undefined }
Agent: "Found the bug — getTaxRate() returns undefined at line 42."
Agent: resume()
Agent: (edits src/hooks/useCheckout.ts on disk to fix the bug)
→ webpack dev server hot-reloads the fix
多断点调查(使用search_source缩小范围):
Agent: search_source({ query: "item.price" })
→ CartItem.tsx:23, PriceDisplay.tsx:8, calculateTotal.ts:12
Agent: (reads src/components/CartItem.tsx from filesystem around line 23)
Agent: set_breakpoint({ file: "CartItem.tsx", line: 23 })
Agent: "Click an item to add to cart."
You: (click)
Agent: wait_for_breakpoint()
→ scope: { item: { id: 5, price: "9.99" } } ← price is a string!
Agent: (reads src/utils/calculateTotal.ts from filesystem around line 12)
Agent: set_breakpoint({ file: "calculateTotal.ts", line: 12 })
Agent: resume()
Agent: wait_for_breakpoint()
→ scope: { items: [...], sum: "09.999.99" } ← string concatenation!
Agent: "Root cause: price comes from API as string, not number."
Agent: (edits src/utils/calculateTotal.ts to add parseFloat)
日志点流
You: "Some cart items show wrong prices but I'm not sure which ones."
Agent: (reads src/components/CartItem.tsx from filesystem)
→ line 15: const displayPrice = formatPrice(props.price);
Agent: set_logpoint({
file: "CartItem.tsx",
line: 15,
expressions: { "id": "props.id", "price": "props.price", "computed": "displayPrice" },
label: "cart-price"
})
→ "Logpoint set. Please browse through the cart items."
Agent: "Please scroll through your cart so all items render."
You: (scroll through)
Agent: (uses chrome-devtools-mcp) list_console_messages
→ Finds messages with ⚡RDM|cart-price prefix:
⚡RDM|cart-price|1711234567|{"id":1,"price":9.99,"computed":"$9.99"}
⚡RDM|cart-price|1711234568|{"id":2,"price":"5.00","computed":"$NaN"}
⚡RDM|cart-price|1711234569|{"id":3,"price":12.50,"computed":"$12.50"}
Agent: "Item 2 has price as string '5.00' instead of number."
Agent: (edits the API response handler on disk to fix the type)
设置
要求节点≥20.18 --运行脚本使用 node --env-file-if-exists 和 --import tsx (建议使用节点22+)。
cd react-debug-mcp
yarn install
服务器是用TypeScript编写的,直接通过 tsx --没有构建步骤,没有 dist/.全部四个 start* 脚本加载 .env 自动(参见 环境变量).
| 脚本 | 运行 |
|---|---|
yarn start |
正常启动 |
yarn start:debug |
从打开节点检查器开始 :9229 (附加调试器;断点映射到 .ts) |
yarn start:inspect |
开始包装在MCP Inspector web UI中 |
yarn start:inspect:debug |
MCP检查员 和 节点检查器打开 :9229 |
yarn typecheck |
tsc --noEmit (仅进行类型检查;不发出任何信号) |
将其作为命令安装(建议用于代理配置)
因此,您的代理的MCP配置不需要绝对路径 src/index.ts,安装
包,因此它暴露了一个 react-debug-mcp 二元的:
npm i -g . # or: npm link
现在 react-debug-mcp 在你的 PATH 并且可以从任何地方发射。这个 bin/cli.mjs
垫片寄存器 tsx的加载器正在进程中,并导入TypeScript入口点,所以这
仍然需要 没有构建步骤,也没有 dist/ --它的代码路径与 yarn start.
二进制文件确实如此 不 读
.env(与start*脚本)。全局命令在中运行 您的应用程序 目录,其中a.env属于您的应用程序,而不是此服务器。传递配置 通过MCP客户端environment取而代之的是块。
OpenCode配置
添加到您的项目 opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"react-debug": {
"type": "local",
"command": ["react-debug-mcp"],
"environment": {
"CDP_PORT": "9222",
"CDP_TARGET_URL": "localhost:3000"
},
"enabled": true
},
"chrome-devtools": {
"type": "local",
"command": ["npx", "-y", "chrome-devtools-mcp@latest", "--browser-url", "http://127.0.0.1:9222"],
"enabled": true
}
}
}
如果跳过全局安装,回退是显式路径——它有效,但你有 在每台机器上保持正确:
"command": ["npx", "tsx", "/path/to/react-debug-mcp/src/index.ts"]
启动OpenCode时运行时会发生什么
1. You run `opencode` in your project directory.
2. OpenCode reads opencode.jsonc, finds the "react-debug" MCP config.
3. OpenCode spawns: react-debug-mcp
with CDP_PORT=9222 and CDP_TARGET_URL=localhost:3000 in the env.
The process's stdin/stdout become the JSON-RPC transport.
4. MCP handshake (over stdin/stdout):
← Client sends: { method: "initialize", params: { capabilities: { ... } } }
→ Server responds: { capabilities: { tools: {}, logging: {} } }
← Client sends: { method: "notifications/initialized" }
The server advertises `logging: {}` — this tells the client it
supports the `logging/setLevel` request and will send
`notifications/message` log events.
5. Client discovers tools:
← Client sends: { method: "tools/list" }
→ Server responds: [ { name: "get_component_tree", ... }, ... ] (26 tools)
OpenCode now includes these tools in the LLM's tool list.
6. Server connects to Chrome eagerly in the background (non-blocking).
If Chrome isn't ready yet, retries on first tool call.
7. You ask the agent to debug something. The LLM picks a tool:
← Client sends: { method: "tools/call", params: { name: "get_page_info" } }
→ Server evaluates the snippet in the browser, returns result.
(If eager connect failed, this tool call triggers the retry.)
8. Throughout, the server sends log events. `data` is a structured object
(not a flattened string), so clients render it as expandable JSON:
→ { method: "notifications/message",
params: { level: "info", logger: "react-debug-mcp",
data: { msg: "connected", pageUrl: "http://localhost:3000" } } }
These appear in OpenCode's log output and in the MCP Inspector
logging panel (if running under the Inspector).
MCP检查员
这个 MCP检查员 是web UI
用于手动调用工具并查看原始JSON-RPC交换和日志
实时通知——无需代理。这个 start:inspect 脚本包装
其中的服务器:
yarn start:inspect # Inspector UI (config from .env)
yarn start:inspect:debug # Inspector UI + Node inspector on :9229 (breakpoints map to .ts)
两者都在以下位置打开UI http://localhost:6274。在不编辑的情况下覆盖配置
.env,通过 -e KEY=value 在命令之前:
npx @modelcontextprotocol/inspector -e CDP_TARGET_URL=localhost:3000 \
node --env-file-if-exists=.env --import tsx src/index.ts
⚠️ 检查员无法观察您的代理人的会话
一个自然的假设是: “将检查员指向我的代理人已经在的服务器 与代理人交谈,并观察代理人的行为。" 那是不可能的 --还没结束 stdio,也不能通过HTTP。不要围绕它构建工作流程。
MCP没有观察员角色。 这是点对点JSON-RPC:客户端只能看到 自己的交通。根据设计,没有订阅另一个会话机制的工具 参数和结果通常携带凭据、源和用户数据,因此 默认情况下,跨会话通道将是启用的渗透通道。
| 运输 | 为什么它仍然不起作用 |
|---|---|
| 标准 (此服务器) | 客户端 生成 服务器并拥有其stdin/stdout。你的代理人出生了 过程A;检查员产生了它的 自身流程B两个客户端=两个独立的服务器进程。没有可连接的监听插座 |
| 超文本传输协议 (假设) | 转换传输确实 不 修好它。检查员会打开它 自己的会话 并且仍然只呈现其自己的请求/响应流量。服务器最多只能 广播 活动作为日志通知——日志窗格中的文本提要,而不是作为结构化请求/响应的代理调用。 |
所以检查员是为了 动手探究 --你自己开车,在一个
单独的会话,针对同一Chrome。这真的很有用,这就是
start:inspect 是为了。这不是了解代理人的窗口。
停止间隙: 看看什么 代理 确实,使用服务器自己的日志。服务器
是代理呼叫可见的地方,因此观察发生在那里--
设置 LOG_TOOL_RESULTS=1 和 LOG_FILE,然后跟踪文件。你得到了每一个工具
代理调用、其参数以及返回的内容。看
观看代理会话 在......下面
日志记录
服务器使用双模日志记录:
| 频道 | 何时 | 你看到了什么 |
|---|---|---|
| MCP通知 | 服务器连接到客户端后 | Inspector日志面板或OpenCode日志输出中的结构化日志条目。客户通过以下方式控制级别 logging/setLevel. |
| 标准错误 | 始终(包括连接前) | JSON行。液位控制 LOG_LEVEL 有人。 |
| 日志文件 | 何时 LOG_FILE 设置 |
与stderr相同,写入指定的文件路径。 |
启动消息(在MCP传输连接之前)只会发送到stderr。 一旦连接,每个日志调用都会同时进入两个通道。
观看代理会话
工具总是记录它们的 调用 (名称+参数)。集 LOG_TOOL_RESULTS=1
他们还记录了他们的 结果 一 tool done 带有持续时间、成功标志的行,
结果大小和结果预览(tool threw 如果处理者投掷)。与
LOG_FILE,这使日志成为代理所做工作的完整跟踪 然后回来了:
LOG_FILE=./agent.log LOG_TOOL_RESULTS=1 yarn start # then, in another terminal:
tail -f agent.log
{"level":"info","msg":"tool done","data":{"tool":"list_breakpoints","ms":1,"ok":true,"chars":35,"preview":"No active breakpoints or logpoints."}}
{"level":"info","msg":"tool done","data":{"tool":"get_page_info","ms":2,"ok":false,"chars":143,"preview":"Error: Cannot connect to Chrome on 127.0.0.1:1 …"}}
结果记录一次接线 src/logger.ts (log.setServer() 包裹 server.tool),
因此,它统一涵盖了所有26个工具,包括那些处理程序从未记录的工具
他们自己。它是 默认情况下关闭:它很吵,结果可以携带页面数据
(令牌、存储状态、响应体)。放大 TOOL_RESULT_PREVIEW 在 src/limits.ts
以记录更多的每个结果。
你甚至可能不需要这个文件。 每条记录线都是 也 发送到已连接的
MCP客户端作为 notifications/message,与 data 作为结构化对象。所以与
LOG_TOOL_RESULTS=1,代理自己的客户端(例如OpenCode)已经收到
在MCP日志面板中跟踪并将其呈现为可扩展的JSON——之前请检查
伸手去够 tail(这些是协议级通知;它们不会进入
模型的上下文。)
为什么是日志,而不是检查员? 因为检查员 不能 看a 代理的会话——MCP没有观察者角色,HTTP也不会改变这一点。看 MCP检查员的警告。服务器自己的日志是 只有代理的呼叫可见的地方,这就是观察存在于这里的原因。
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
CDP_HOST |
127.0.0.1 |
Chrome主机(见下面的IPv4注释) |
CDP_PORT |
9222 |
Chrome远程调试端口 |
CDP_TARGET_URL |
(无) | 匹配特定选项卡的URL子字符串 |
LOG_LEVEL |
info |
debug / info / warn / error --控制stderr输出 |
LOG_FILE |
(无) | 写入日志的路径 |
LOG_TOOL_RESULTS |
false |
1 要记录每个工具调用的结果,请参见 观看代理会话 |
所有这些都会被解析一次 src/env.ts 并暴露为打字 ENV 对象。
使用
127.0.0.1,不localhost. Chrome浏览器--remote-debugging-port绑定到 IPv4环回(127.0.0.1)只有。在许多系统上,尤其是Windows 节点18+--localhost解析为IPv6环回(::1) 第一,因此连接 到localhost失败与ECONNREFUSED尽管Chrome正在运行。默认值 是127.0.0.1出于这个原因;仅当Chrome在另一台主机上时才更改它。
.env 文件(推荐)。 复制 .env.example 到 .env 并编辑它——四个
start* 脚本通过Node的内置程序加载它 node --env-file-if-exists=.env,所以一个
编辑适用于每种运行模式。 .env 被忽视; .env.example 是否已承诺
模板。已在shell/CI中设置变量 胜利 结束 .env (节点不
覆盖现有环境),如果 .env 如果不存在,脚本仍将使用默认值运行
上面。
cp .env.example .env # then edit values
yarn start # picks up .env automatically
在启动时热切地连接到Chrome。如果Chrome尚未就绪,请在第一次工具调用时重试。要切换选项卡,请更改 CDP_TARGET_URL 在 .env (或环境)并重新启动服务器。
集中限制(src/limits.ts)
所有可调上限、超时、截断阈值和默认值都在一个文件中定义-- src/limits.ts这使得在不遍历代码库的情况下查看和调整运行时行为变得容易。
文件分为两部分:
浏览器端常量 被退回 browserLimits() 功能。因为代码片段代码通过CDP在浏览器页面内运行 Runtime.evaluate(),这些值必须存在于bundler可以字符串化的自包含函数中。(TypeScript类型的注释在transpile时会被擦除,因此字符串化的输出仍然是干净的浏览器JS——请参阅Project Structure下的注释。)每个使用有界序列化、钩子提取、prop walking或DOM爬升的代码段都会从以下位置读取其限制 browserLimits().
| 常量 | 默认值 | 它控制什么 |
|---|---|---|
SERIALIZE_MAX_DEPTH |
6 | safeSerialize 最大对象嵌套深度 |
SERIALIZE_MAX_CHARS |
2000 | safeSerialize 近似焦炭预算 |
SERIALIZE_STRING_TRUNCATE |
300 | safeSerialize 单个字符串值上限 |
SERIALIZE_MAX_ARRAY_ITEMS |
50 | safeSerialize 最大数组元素数 |
SERIALIZE_MAX_OBJECT_KEYS |
30 | safeSerialize 每个对象的最大键数 |
PROPS_SERIALIZE_DEPTH |
4 | safeProps 每值深度限制 |
PROPS_SERIALIZE_CHARS |
500 | safeProps 每值char预算 |
PROPS_MAX_KEYS |
30 | safeProps 最大道具键 |
FUNCTION_BODY_MAX_LENGTH |
1000 | describeFn 函数体截断 |
MAX_HOOKS_PER_FIBER |
20 | extractHooks 每个组件的最大钩数 |
SELECTOR_MAX_DOM_STEPS |
200 | fiberToSelector DOM父母人数最多 |
ERROR_BOUNDARY_MAX_DEPTH |
50 | 误差边界行走最大深度 |
FIND_COMPONENTS_DEFAULT_MAX |
20 | findComponents 默认结果上限 |
服务器端常量 被退回 serverLimits() 功能。不像 browserLimits() --哪个 必须 是一个函数,因此可以将其字符串化为浏览器代码段-- serverLimits() 是一个纯粹用于对称和分组的函数。消费者在模块加载时破坏他们需要的东西,例如。 const { MAX_NETWORK_BUFFER } = serverLimits();:
| 常量 | 默认值 | 它控制什么 |
|---|---|---|
MAX_NETWORK_BUFFER |
500 | 内存环缓冲区中的网络收集器大小 |
NETWORK_BODY_TRUNCATE |
5000 | 非JSON响应体截断 |
BREAKPOINT_SCOPE_MAX_PROPS |
30 | 断点命中时自动获取作用域属性 |
STEP_TIMEOUT_MS |
10000 | 跨步/进入/退出重新暂停超时 |
SOURCE_DEFAULT_LINE_WINDOW |
200 | 返回的默认行数 read_source |
SOURCE_SEARCH_MAX_SCRIPTS |
100 | 每个用户搜索的最大脚本数 search_source 呼叫 |
SOURCE_SEARCH_MAX_RESULTS |
100 | 来自的最大总匹配数 search_source |
LOG_EXPRESSION_TRUNCATE |
200 | 日志输出中的表达式字符串截断 |
TOOL_RESULT_PREVIEW |
800 | 完成时记录每个工具结果的字符数 |
TREE_DEFAULT_MAX_DEPTH |
4 | get_component_tree 默认最大深度 |
FIND_DEFAULT_MAX_RESULTS |
20 | find_react_component 默认最大结果 |
NETWORK_DEFAULT_LIMIT |
20 | get_network_responses 默认限额 |
BREAKPOINT_DEFAULT_TIMEOUT_S |
60 | wait_for_breakpoint 默认超时(秒) |
项目结构
bin/
└── cli.mjs # `react-debug-mcp` executable: registers tsx, imports src/index.ts
src/
├── index.ts # Entry point
├── env.ts # Parses all env vars once → typed ENV object
├── limits.ts # Centralized limits & tunables (single source of truth)
├── cdp-client.ts # Lazy CDP connection (memoized) + evaluate()
├── logger.ts # Dual-mode logging (MCP notifications + stderr)
├── url-filters.ts # Shared browser-internal URL-prefix filters
├── types/
│ ├── chrome-remote-interface.d.ts # Type shim (package ships no types)
│ └── globals.d.ts # Window augmentations for browser-side snippet globals
├── collectors/
│ ├── network.ts # Captures API requests/responses (live + historical backfill)
│ └── debugger/ # CDP Debugger domain (split into sub-modules)
│ ├── index.ts # Barrel: attach() + re-exports
│ ├── state.ts # Shared mutable state (CDP client, script map, pause state)
│ ├── scripts.ts # Script tracking, source map resolution, URL helpers
│ ├── breakpoints.ts # Set/remove breakpoints and logpoints (source map fallback)
│ ├── pause.ts # Wait, step, resume, scope inspection
│ └── source-reading.ts # Read and search bundled script source (parallel search)
├── tools/
│ ├── react.ts # React component inspection (8 tools)
│ ├── store.ts # State store reading (1 tool)
│ ├── network.ts # Network response querying (1 tool)
│ ├── debugger.ts # Breakpoints, source reading + logpoints (15 tools)
│ └── general.ts # evaluate_in_page (1 tool)
└── snippets/ # Browser-side code that runs inside the page
├── index.ts # Barrel: bundles functions → CDP-ready strings
├── bundle.ts # fn.toString() bundler utility
├── helpers.ts # Shared helpers (fiber lookup, display name, hooks, …)
├── page-info.ts # get_page_info snippet
├── component-tree.ts # get_component_tree snippet
├── component-path.ts # get_react_component_path snippet
├── find-components.ts # find_react_component snippet
├── inspect-by-name.ts # inspect_react_component_by_name snippet
├── inspect-by-selector.ts # inspect_react_component snippet
├── inspect-context.ts # inspect_react_context snippet
├── error-boundaries.ts # get_react_error_boundaries snippet
└── store-reader.ts # get_store_state snippet
TypeScript和代码段打包器
这个 src/snippets/ 功能(和 browserLimits() 在 src/limits.ts)都是
序列化为 fn.toString() 并通过CDP注入页面。定向
ES2022 意味着没有降级,因此类型注释被剥离而没有
__awaiter-风格助手被注入到功能体中。
但“没有注射助手”并不完全正确,例外情况也很严重。 多伦多证券交易所
硬代码esbuild keepNames: true,保存 fn.name 通过重写
每 命名嵌套函数 进入 __name(fn, "fn") 调用并发出
__name 助手at 模块范围。模块作用域不存在 fn.toString(),
因此,幸存的呼叫到达未定义的页面:
Uncaught ReferenceError: __name is not defined
at componentTree (<anonymous>:16:838)
bundle() 因此,船舶是自己建造的 __name 每个包内的定义,
和 在导入时抛出 如果esbuild注入了它不提供的帮助程序--
转向未来的浏览器端 ReferenceError 进入拒绝启动的服务器。
如果您看到该错误,请将缺少的定义添加到 ESBUILD_HELPERS 在
src/snippets/bundle.ts.
编辑代码段代码时:不要使用TS枚举,只引用助手
在每个片段中列出 deps 数组(缺失的dep解析良好,只会失败
ReferenceError 当代码段实际在页面中运行时)。
日志点输出格式
日志点使用结构化前缀写入控制台,以便代理可以找到它们:
⚡RDM|<label>|<timestamp>|<JSON data>
代理人搜索 ⚡RDM 在chromedevtools mcp的控制台输出中。当多个日志点处于活动状态时,标签有助于关联哪个日志点产生了哪些输出。
许可证
麻省理工学院
