@roxybrowser/playwright 2.0.2-beta.0 → 2.0.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -113,3 +113,58 @@ await startRoxyBrowserMcpStdio({
113
113
  outputDir
114
114
  });
115
115
  ```
116
+
117
+ ## MCP inspector workflow
118
+
119
+ This repo includes [`@modelcontextprotocol/inspector`](https://github.com/modelcontextprotocol/inspector) as a dev dependency so we can debug the Playwright MCP server locally.
120
+
121
+ ### Local stdio inspector
122
+
123
+ Use the inspector to spawn the built MCP server over `stdio`:
124
+
125
+ ```bash
126
+ pnpm inspector
127
+ ```
128
+
129
+ That command will:
130
+
131
+ - build the TypeScript sources into `dist/`
132
+ - start the MCP Inspector UI on `http://127.0.0.1:6274`
133
+ - launch `node ./dist/bin/roxybrowser-mcp.js` as the inspected MCP server
134
+
135
+ This is the fastest loop when you want to manually exercise tools from the inspector UI.
136
+
137
+ ### Local HTTP inspector
138
+
139
+ If you want to keep the MCP server running separately and connect the inspector over Streamable HTTP:
140
+
141
+ Terminal 1:
142
+
143
+ ```bash
144
+ pnpm mcp:http
145
+ ```
146
+
147
+ Terminal 2:
148
+
149
+ ```bash
150
+ pnpm inspector:http
151
+ ```
152
+
153
+ By default the HTTP server listens on `http://127.0.0.1:3333/mcp`.
154
+
155
+ ### MCP server CLI options
156
+
157
+ The bundled `roxybrowser-mcp` launcher supports both transports:
158
+
159
+ ```bash
160
+ node ./dist/bin/roxybrowser-mcp.js --transport stdio
161
+ node ./dist/bin/roxybrowser-mcp.js --transport http --port 3333 --host 127.0.0.1 --path /mcp
162
+ ```
163
+
164
+ Optional flags:
165
+
166
+ - `--output-dir /absolute/path`
167
+ - `--snapshot-mode full`
168
+ - `--snapshot-mode none`
169
+
170
+ Note: in the currently installed inspector version, the `mcp-inspector` CLI wrapper itself has a local dependency compatibility issue in this workspace, so the reliable path here is the inspector UI flow above via `client/bin/start.js`.
@@ -1,6 +1,73 @@
1
1
  #!/usr/bin/env node
2
- import { startRoxyBrowserMcpStdio } from "../mcp/index.js";
3
- void startRoxyBrowserMcpStdio().catch((error) => {
2
+ import { parseArgs } from "node:util";
3
+ import { startRoxyBrowserMcpHttp, startRoxyBrowserMcpStdio } from "../mcp/index.js";
4
+ function parseCliOptions(argv) {
5
+ const { values } = parseArgs({
6
+ args: argv,
7
+ options: {
8
+ transport: { type: "string" },
9
+ host: { type: "string" },
10
+ port: { type: "string" },
11
+ path: { type: "string" },
12
+ "output-dir": { type: "string" },
13
+ "snapshot-mode": { type: "string" }
14
+ },
15
+ allowPositionals: false
16
+ });
17
+ const transport = (values.transport ?? "stdio");
18
+ if (transport !== "stdio" && transport !== "http") {
19
+ throw new Error(`Unsupported transport "${transport}". Expected "stdio" or "http".`);
20
+ }
21
+ const snapshotMode = values["snapshot-mode"];
22
+ if (snapshotMode !== undefined
23
+ && snapshotMode !== "full"
24
+ && snapshotMode !== "none") {
25
+ throw new Error(`Unsupported snapshot mode "${snapshotMode}". Expected "full" or "none".`);
26
+ }
27
+ const portValue = values.port;
28
+ const port = portValue === undefined ? undefined : Number.parseInt(portValue, 10);
29
+ if (portValue !== undefined && Number.isNaN(port)) {
30
+ throw new Error(`Invalid port "${portValue}". Expected an integer.`);
31
+ }
32
+ return {
33
+ transport,
34
+ ...(values.host !== undefined ? { host: values.host } : {}),
35
+ ...(port !== undefined ? { port } : {}),
36
+ ...(values.path !== undefined ? { path: values.path } : {}),
37
+ ...(values["output-dir"] !== undefined ? { outputDir: values["output-dir"] } : {}),
38
+ ...(snapshotMode !== undefined ? { snapshotMode: snapshotMode } : {})
39
+ };
40
+ }
41
+ function sharedOptions(options) {
42
+ return {
43
+ ...(options.outputDir !== undefined ? { outputDir: options.outputDir } : {}),
44
+ ...(options.snapshotMode !== undefined ? { snapshotMode: options.snapshotMode } : {})
45
+ };
46
+ }
47
+ async function main() {
48
+ const options = parseCliOptions(process.argv.slice(2));
49
+ if (options.transport === "http") {
50
+ const httpOptions = {
51
+ port: options.port ?? 3333,
52
+ ...(options.host !== undefined ? { host: options.host } : {}),
53
+ ...(options.path !== undefined ? { path: options.path } : {}),
54
+ ...sharedOptions(options)
55
+ };
56
+ const bundle = await startRoxyBrowserMcpHttp(httpOptions);
57
+ const host = httpOptions.host ?? "127.0.0.1";
58
+ const path = httpOptions.path ?? "/mcp";
59
+ console.error(`RoxyBrowser MCP HTTP server listening at http://${host}:${httpOptions.port}${path}`);
60
+ const close = async () => {
61
+ await bundle.close();
62
+ process.exitCode = 0;
63
+ };
64
+ process.once("SIGINT", () => void close());
65
+ process.once("SIGTERM", () => void close());
66
+ return;
67
+ }
68
+ await startRoxyBrowserMcpStdio(sharedOptions(options));
69
+ }
70
+ void main().catch((error) => {
4
71
  console.error(error instanceof Error ? error.message : String(error));
5
72
  process.exitCode = 1;
6
73
  });
@@ -1 +1 @@
1
- {"version":3,"file":"roxybrowser-mcp.js","sourceRoot":"","sources":["../../src/bin/roxybrowser-mcp.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,KAAK,wBAAwB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC9C,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"roxybrowser-mcp.js","sourceRoot":"","sources":["../../src/bin/roxybrowser-mcp.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ declare const _default: import("./tool.js").Tool<z.ZodObject<{
5
5
  firefox: "firefox";
6
6
  chrome: "chrome";
7
7
  }>>;
8
+ sessionId: z.ZodOptional<z.ZodString>;
8
9
  }, z.core.$strip>>[];
9
10
  export default _default;
10
11
  //# sourceMappingURL=connect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/mcp/backend/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;;;;;;;AAgCxB,wBAAyB"}
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/mcp/backend/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;;;;;;;;AAkCxB,wBAAyB"}
@@ -9,7 +9,8 @@ const connect = defineTool({
9
9
  description: "Attach to an existing browser and seed the active tab snapshot.",
10
10
  inputSchema: z.object({
11
11
  endpoint: z.string().min(1),
12
- browser: z.enum(["chrome", "firefox"]).default("chrome")
12
+ browser: z.enum(["chrome", "firefox"]).default("chrome"),
13
+ sessionId: z.string().min(1).optional()
13
14
  }),
14
15
  type: "action"
15
16
  },
@@ -18,7 +19,8 @@ const connect = defineTool({
18
19
  const result = await context.runtime.connect({
19
20
  protocol,
20
21
  endpoint: params.endpoint,
21
- browser: params.browser === "chrome" ? "chromium" : params.browser
22
+ browser: params.browser === "chrome" ? "chromium" : params.browser,
23
+ ...(params.sessionId ? { sessionId: params.sessionId } : {})
22
24
  });
23
25
  response.addTextResult(formatConnectResult({
24
26
  ...result,
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/mcp/backend/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,OAAO,GAAG,UAAU,CAAC;IACzB,UAAU,EAAE,QAAQ;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,iEAAiE;QAC9E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;SACzD,CAAC;QACF,IAAI,EAAE,QAAQ;KACf;IACD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAC3C,QAAQ;YACR,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO;SACnE,CAAC,CAAC;QACH,QAAQ,CAAC,aAAa,CACpB,mBAAmB,CAAC;YAClB,GAAG,MAAM;YACT,WAAW,EAAE,MAAM,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW;SAC/E,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,eAAe,CAAC,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/mcp/backend/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,OAAO,GAAG,UAAU,CAAC;IACzB,UAAU,EAAE,QAAQ;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,iEAAiE;QAC9E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;YACxD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;SACxC,CAAC;QACF,IAAI,EAAE,QAAQ;KACf;IACD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAC3C,QAAQ;YACR,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO;YAClE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC,CAAC;QACH,QAAQ,CAAC,aAAa,CACpB,mBAAmB,CAAC;YAClB,GAAG,MAAM;YACT,WAAW,EAAE,MAAM,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW;SAC/E,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,eAAe,CAAC,OAAO,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/mcp/backend/response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,qBAAa,QAAQ;IAiBjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAlB5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqE;IAC5F,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAON;IACd,OAAO,CAAC,OAAO,CAAS;gBAGL,OAAO,EAAE,OAAO,EACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAG5C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI;IAIxE,QAAQ,IAAI,IAAI;IAIhB,kBAAkB,IAAI,IAAI;IAI1B,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAU3F,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAmEnE"}
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/mcp/backend/response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,qBAAa,QAAQ;IAiBjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAlB5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqE;IAC5F,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAON;IACd,OAAO,CAAC,OAAO,CAAS;gBAGL,OAAO,EAAE,OAAO,EACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAG5C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI;IAIxE,QAAQ,IAAI,IAAI;IAIhB,kBAAkB,IAAI,IAAI;IAI1B,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAU3F,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAwFnE"}
@@ -61,18 +61,28 @@ export class Response {
61
61
  sections.push("### Code", "```js", ...this.code, "```");
62
62
  }
63
63
  if (this.includeSnapshot === "full") {
64
- const snapshot = await this.context.runtime.snapshot();
64
+ const snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot());
65
65
  if (sections.length) {
66
66
  sections.push("");
67
67
  }
68
68
  sections.push(formatSnapshot(snapshot));
69
69
  }
70
70
  if (this.fullSnapshot) {
71
- const snapshot = await this.context.runtime.snapshot({
71
+ let snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot({
72
72
  ...(this.fullSnapshot.target !== undefined ? { target: this.fullSnapshot.target } : {}),
73
73
  ...(this.fullSnapshot.depth !== undefined ? { depth: this.fullSnapshot.depth } : {}),
74
74
  ...(this.fullSnapshot.boxes !== undefined ? { boxes: this.fullSnapshot.boxes } : {})
75
- });
75
+ }));
76
+ if (!this.fullSnapshot.filename
77
+ && snapshot.text.trim().length === 0
78
+ && snapshot.url
79
+ && snapshot.url !== "about:blank") {
80
+ snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot({
81
+ ...(this.fullSnapshot.target !== undefined ? { target: this.fullSnapshot.target } : {}),
82
+ ...(this.fullSnapshot.depth !== undefined ? { depth: this.fullSnapshot.depth } : {}),
83
+ ...(this.fullSnapshot.boxes !== undefined ? { boxes: this.fullSnapshot.boxes } : {})
84
+ }));
85
+ }
76
86
  if (this.fullSnapshot.filename) {
77
87
  const resolvedFilename = await this.context.resolveOutputFile(this.fullSnapshot.filename);
78
88
  await writeFile(resolvedFilename, snapshot.text);
@@ -106,4 +116,16 @@ export class Response {
106
116
  };
107
117
  }
108
118
  }
119
+ async function reconcileSnapshotWithTabs(context, snapshot) {
120
+ const tabs = await context.runtime.listTabs();
121
+ const activeTab = tabs.find((tab) => tab.active);
122
+ if (!activeTab) {
123
+ return snapshot;
124
+ }
125
+ return {
126
+ ...snapshot,
127
+ title: activeTab.title || snapshot.title,
128
+ url: activeTab.url || snapshot.url
129
+ };
130
+ }
109
131
  //# sourceMappingURL=response.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/mcp/backend/response.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/mcp/backend/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1D,MAAM,OAAO,QAAQ;IAiBA;IACR;IACA;IAlBM,OAAO,GAAa,EAAE,CAAC;IACvB,MAAM,GAAa,EAAE,CAAC;IACtB,IAAI,GAAa,EAAE,CAAC;IACpB,MAAM,GAAkE,EAAE,CAAC;IACpF,eAAe,GAAoB,MAAM,CAAC;IAC1C,YAAY,CAON;IACN,OAAO,GAAG,KAAK,CAAC;IAExB,YACmB,OAAgB,EACxB,QAAgB,EAChB,QAAiC;QAFzB,YAAO,GAAP,OAAO,CAAS;QACxB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,aAAQ,GAAR,QAAQ,CAAyB;IACzC,CAAC;IAEJ,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,QAAoC;QAC/D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,IAAI,MAAM,CAAC;IACtE,CAAC;IAED,sBAAsB,CAAC,QAAiB,EAAE,MAAe,EAAE,KAAc,EAAE,KAAe;QACxF,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG;YAClB,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAC9C,IAAI,CAAC,OAAO,EACZ,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CACtC,CAAC;YACF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,QAAQ,GAAG,MAAM,yBAAyB,CAC5C,IAAI,CAAC,OAAO,EACZ,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACpC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvF,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpF,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACnF,CAAC,CACH,CAAC;YACF,IACE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ;mBACxB,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;mBACjC,QAAQ,CAAC,GAAG;mBACZ,QAAQ,CAAC,GAAG,KAAK,aAAa,EACjC,CAAC;gBACD,QAAQ,GAAG,MAAM,yBAAyB,CACxC,IAAI,CAAC,OAAO,EACZ,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;oBAClC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvF,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpF,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrF,CAAC,CACH,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAC/B,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAC1F,MAAM,SAAS,CAAC,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACjD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACpB,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,sBAAsB,gBAAgB,IAAI,CAAC,CAAC;YAC1E,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACnD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACpB,CAAC;gBACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;gBACtC,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC3C,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC7B,IAAI,EAAE,OAAgB;oBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;iBACzB,CAAC,CAAC;aACJ;YACD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjD,CAAC;IACJ,CAAC;CACF;AAED,KAAK,UAAU,yBAAyB,CACtC,OAAgB,EAChB,QAAyB;IAEzB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;QACxC,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG;KACnC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"connectedBrowser.d.ts","sourceRoot":"","sources":["../../src/mcp/connectedBrowser.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAOV,uBAAuB,EACvB,sBAAsB,EAOvB,MAAM,YAAY,CAAC;AAk0FpB,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,uBAAuB,CAAC,CAMlC"}
1
+ {"version":3,"file":"connectedBrowser.d.ts","sourceRoot":"","sources":["../../src/mcp/connectedBrowser.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAOV,uBAAuB,EACvB,sBAAsB,EAOvB,MAAM,YAAY,CAAC;AA85FpB,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,uBAAuB,CAAC,CAMlC"}
@@ -4,6 +4,7 @@ import * as cdpModule from "chrome-remote-interface";
4
4
  import { normalizeAriaSnapshotOptions, retryUntilReady } from "../ariaSnapshot.js";
5
5
  import { PLAYWRIGHT_ARIA_SNAPSHOT_EVALUATE_SOURCE as ARIA_SNAPSHOT_EVALUATE_SOURCE } from "../vendor/playwright/ariaSnapshotEvaluate.js";
6
6
  import { getBidiClientFactory } from "../protocol/bidi/client.js";
7
+ import { parseSerializedEvaluationResult, wrapWithSerializedEvaluationResult } from "../protocol/evaluationSerializer.js";
7
8
  import { McpToolError } from "./errors.js";
8
9
  import { ACTION_POINT_EVALUATE_SOURCE, ACTION_POINT_BY_SELECTOR_SOURCE } from "./snapshot.js";
9
10
  function delay(ms) {
@@ -351,7 +352,7 @@ async function evaluateBiDi(client, contextId, functionSource, arg) {
351
352
  ? `(${functionSource})()`
352
353
  : `(${functionSource})(${JSON.stringify(arg)})`;
353
354
  const response = (await client.scriptEvaluate({
354
- expression,
355
+ expression: wrapWithSerializedEvaluationResult(expression),
355
356
  target: {
356
357
  context: contextId
357
358
  },
@@ -361,7 +362,7 @@ async function evaluateBiDi(client, contextId, functionSource, arg) {
361
362
  if (response.type === "exception") {
362
363
  throw new Error(response.exceptionDetails?.text || "BiDi runtime evaluation failed.");
363
364
  }
364
- return response.result?.value;
365
+ return parseSerializedEvaluationResult(extractBiDiValue(response.result));
365
366
  }
366
367
  async function evaluateBiDiRef(client, contextId, functionSource, arg) {
367
368
  const expression = arg === undefined
@@ -389,6 +390,22 @@ async function evaluateBiDiRef(client, contextId, functionSource, arg) {
389
390
  ...(response.result?.value?.handle !== undefined ? { handle: response.result.value.handle } : {})
390
391
  };
391
392
  }
393
+ function extractBiDiValue(value) {
394
+ if (!value) {
395
+ return undefined;
396
+ }
397
+ if (value.type === "array" && Array.isArray(value.value)) {
398
+ return value.value.map((entry) => extractBiDiValue(entry));
399
+ }
400
+ if (value.type === "object" && Array.isArray(value.value)) {
401
+ const obj = {};
402
+ for (const [key, val] of value.value) {
403
+ obj[key] = extractBiDiValue(val);
404
+ }
405
+ return obj;
406
+ }
407
+ return value.value;
408
+ }
392
409
  function toAriaSnapshotPayload(request = {}) {
393
410
  return {
394
411
  options: normalizeAriaSnapshotOptions({
@@ -1384,6 +1401,7 @@ class BidiConnectedBrowserSession {
1384
1401
  bidiListeners = new Map();
1385
1402
  responseDataCollector;
1386
1403
  activeTabId;
1404
+ ownsSession = false;
1387
1405
  constructor(client) {
1388
1406
  this.client = client;
1389
1407
  }
@@ -1397,9 +1415,10 @@ class BidiConnectedBrowserSession {
1397
1415
  }
1398
1416
  const client = await getBidiClientFactory()({
1399
1417
  browserName: "firefox",
1400
- webSocketUrl: args.endpoint
1418
+ webSocketUrl: normalizeFirefoxBidiEndpoint(args.endpoint, args.sessionId)
1401
1419
  });
1402
1420
  const session = new BidiConnectedBrowserSession(client);
1421
+ session.ownsSession = await ensureMcpBiDiSession(client, args.endpoint, args.sessionId);
1403
1422
  await session.initialize();
1404
1423
  const tabs = await session.refreshTabs();
1405
1424
  if (tabs.length === 0) {
@@ -1462,7 +1481,7 @@ class BidiConnectedBrowserSession {
1462
1481
  }
1463
1482
  async snapshot(request = {}) {
1464
1483
  const tabId = await this.getActiveTabId();
1465
- const result = await evaluateBiDi(this.client, tabId, ARIA_SNAPSHOT_EVALUATE_SOURCE, toAriaSnapshotPayload(request));
1484
+ const result = await retryUntilReady(() => evaluateBiDi(this.client, tabId, ARIA_SNAPSHOT_EVALUATE_SOURCE, toAriaSnapshotPayload(request)));
1466
1485
  return toBrowserSnapshot(result, request, {
1467
1486
  console: this.consoleSummary(tabId),
1468
1487
  consoleLink: await this.takeConsoleLink(tabId)
@@ -1647,7 +1666,9 @@ class BidiConnectedBrowserSession {
1647
1666
  await this.client.networkRemoveDataCollector({ collector: this.responseDataCollector }).catch(() => { });
1648
1667
  this.responseDataCollector = undefined;
1649
1668
  }
1650
- await this.client.sessionEnd({}).catch(() => { });
1669
+ if (this.ownsSession) {
1670
+ await this.client.sessionEnd({}).catch(() => { });
1671
+ }
1651
1672
  this.client.close();
1652
1673
  }
1653
1674
  async navigate(url) {
@@ -2144,6 +2165,55 @@ class BidiConnectedBrowserSession {
2144
2165
  return `${relativePath}${lineRange}`;
2145
2166
  }
2146
2167
  }
2168
+ function normalizeFirefoxBidiEndpoint(endpoint, sessionId) {
2169
+ const url = new URL(endpoint);
2170
+ if (sessionId) {
2171
+ url.pathname = `/session/${sessionId}`;
2172
+ return url.toString();
2173
+ }
2174
+ if (url.pathname === "/" || url.pathname === "") {
2175
+ url.pathname = "/session";
2176
+ }
2177
+ return url.toString();
2178
+ }
2179
+ async function ensureMcpBiDiSession(client, endpoint, sessionId) {
2180
+ await client.sessionStatus({});
2181
+ if (sessionId || isSessionSpecificFirefoxBidiEndpoint(endpoint)) {
2182
+ return false;
2183
+ }
2184
+ try {
2185
+ await client.browsingContextGetTree({});
2186
+ return false;
2187
+ }
2188
+ catch (error) {
2189
+ const message = String(error instanceof Error ? error.message : error);
2190
+ if (!message.includes("session does not exist")
2191
+ && !message.includes("invalid session id")
2192
+ && !message.includes("not active")) {
2193
+ throw error;
2194
+ }
2195
+ }
2196
+ try {
2197
+ await client.sessionNew({
2198
+ capabilities: {
2199
+ alwaysMatch: {
2200
+ acceptInsecureCerts: true
2201
+ }
2202
+ }
2203
+ });
2204
+ return true;
2205
+ }
2206
+ catch (error) {
2207
+ const message = String(error instanceof Error ? error.message : error);
2208
+ if (message.includes("Maximum number of active sessions")) {
2209
+ throw new Error("Maximum number of active BiDi sessions. Reuse an existing one with sessionId or close the current session first.");
2210
+ }
2211
+ throw error;
2212
+ }
2213
+ }
2214
+ function isSessionSpecificFirefoxBidiEndpoint(endpoint) {
2215
+ return /^\/session\/[^/]+$/.test(new URL(endpoint).pathname);
2216
+ }
2147
2217
  export async function connectBrowserSession(args) {
2148
2218
  if (args.protocol === "cdp") {
2149
2219
  return CdpConnectedBrowserSession.connect(args);