@szymonrybczak/playwright-mcp 0.0.10 → 0.0.12

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
4
4
 
5
- const version = "0.0.10";
5
+ const version = "0.0.12";
6
6
  const json = {
7
7
  version};
8
8
 
@@ -31,14 +31,25 @@ const playwright__namespace = /*#__PURE__*/_interopNamespaceDefault(playwright);
31
31
 
32
32
  const testDebug = debugStub.default("pw:mcp:test");
33
33
  function contextFactory(browserConfig) {
34
- if (browserConfig.remoteEndpoint)
34
+ console.log("[contextFactory] START");
35
+ console.log("[contextFactory] browserConfig:", JSON.stringify(browserConfig, null, 2));
36
+ if (browserConfig.remoteEndpoint) {
37
+ console.log("[contextFactory] Using RemoteContextFactory");
35
38
  return new RemoteContextFactory(browserConfig);
36
- if (browserConfig.cdpEndpoint)
39
+ }
40
+ if (browserConfig.cdpEndpoint) {
41
+ console.log("[contextFactory] Using CdpContextFactory");
37
42
  return new CdpContextFactory(browserConfig);
38
- if (browserConfig.isolated)
43
+ }
44
+ if (browserConfig.isolated) {
45
+ console.log("[contextFactory] Using IsolatedContextFactory");
39
46
  return new IsolatedContextFactory(browserConfig);
40
- if (browserConfig.browserAgent)
47
+ }
48
+ if (browserConfig.browserAgent) {
49
+ console.log("[contextFactory] Using BrowserServerContextFactory");
41
50
  return new BrowserServerContextFactory(browserConfig);
51
+ }
52
+ console.log("[contextFactory] Using PersistentContextFactory");
42
53
  return new PersistentContextFactory(browserConfig);
43
54
  }
44
55
  class BaseContextFactory {
@@ -48,17 +59,26 @@ class BaseContextFactory {
48
59
  constructor(name, browserConfig) {
49
60
  this.name = name;
50
61
  this.browserConfig = browserConfig;
62
+ console.log(`[BaseContextFactory] Created factory: ${name}`);
51
63
  }
52
64
  async _obtainBrowser() {
53
- if (this._browserPromise)
65
+ console.log(`[BaseContextFactory._obtainBrowser] START (${this.name})`);
66
+ console.log(`[BaseContextFactory._obtainBrowser] _browserPromise exists:`, !!this._browserPromise);
67
+ if (this._browserPromise) {
68
+ console.log(`[BaseContextFactory._obtainBrowser] Returning existing promise`);
54
69
  return this._browserPromise;
70
+ }
55
71
  testDebug(`obtain browser (${this.name})`);
72
+ console.log(`[BaseContextFactory._obtainBrowser] Calling _doObtainBrowser...`);
56
73
  this._browserPromise = this._doObtainBrowser();
57
74
  void this._browserPromise.then((browser) => {
75
+ console.log(`[BaseContextFactory._obtainBrowser] Browser obtained successfully`);
58
76
  browser.on("disconnected", () => {
77
+ console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected`);
59
78
  this._browserPromise = void 0;
60
79
  });
61
- }).catch(() => {
80
+ }).catch((err) => {
81
+ console.log(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, err.message);
62
82
  this._browserPromise = void 0;
63
83
  });
64
84
  return this._browserPromise;
@@ -67,15 +87,22 @@ class BaseContextFactory {
67
87
  throw new Error("Not implemented");
68
88
  }
69
89
  async createContext() {
90
+ console.log(`[BaseContextFactory.createContext] START (${this.name})`);
70
91
  testDebug(`create browser context (${this.name})`);
92
+ console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser...`);
71
93
  const browser = await this._obtainBrowser();
94
+ console.log(`[BaseContextFactory.createContext] Got browser`);
95
+ console.log(`[BaseContextFactory.createContext] Calling _doCreateContext...`);
72
96
  const browserContext = await this._doCreateContext(browser);
97
+ console.log(`[BaseContextFactory.createContext] Got browserContext`);
98
+ console.log(`[BaseContextFactory.createContext] END`);
73
99
  return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
74
100
  }
75
101
  async _doCreateContext(browser) {
76
102
  throw new Error("Not implemented");
77
103
  }
78
104
  async _closeBrowserContext(browserContext, browser) {
105
+ console.log(`[BaseContextFactory._closeBrowserContext] START (${this.name})`);
79
106
  testDebug(`close browser context (${this.name})`);
80
107
  if (browser.contexts().length === 1)
81
108
  this._browserPromise = void 0;
@@ -86,6 +113,7 @@ class BaseContextFactory {
86
113
  await browser.close().catch(() => {
87
114
  });
88
115
  }
116
+ console.log(`[BaseContextFactory._closeBrowserContext] END`);
89
117
  }
90
118
  }
91
119
  class IsolatedContextFactory extends BaseContextFactory {
@@ -114,10 +142,41 @@ class CdpContextFactory extends BaseContextFactory {
114
142
  super("cdp", browserConfig);
115
143
  }
116
144
  async _doObtainBrowser() {
117
- return playwright__namespace.chromium.connectOverCDP(this.browserConfig.cdpEndpoint);
145
+ console.log("[CdpContextFactory._doObtainBrowser] START");
146
+ console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint:", this.browserConfig.cdpEndpoint);
147
+ console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint type:", typeof this.browserConfig.cdpEndpoint);
148
+ console.log("[CdpContextFactory._doObtainBrowser] playwright object keys:", Object.keys(playwright__namespace));
149
+ console.log("[CdpContextFactory._doObtainBrowser] playwright.chromium:", typeof playwright__namespace.chromium);
150
+ const endpoint = this.browserConfig.cdpEndpoint;
151
+ const isCloudfareFetcher = typeof endpoint !== "string";
152
+ console.log("[CdpContextFactory._doObtainBrowser] isCloudfareFetcher:", isCloudfareFetcher);
153
+ try {
154
+ let browser;
155
+ if (isCloudfareFetcher) {
156
+ console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connect() for Cloudflare Fetcher...");
157
+ browser = await playwright__namespace.chromium.connect(endpoint);
158
+ } else {
159
+ console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connectOverCDP() for CDP URL...");
160
+ browser = await playwright__namespace.chromium.connectOverCDP(endpoint);
161
+ }
162
+ console.log("[CdpContextFactory._doObtainBrowser] Connection completed");
163
+ return browser;
164
+ } catch (err) {
165
+ console.log("[CdpContextFactory._doObtainBrowser] ERROR:", err.message, err.stack);
166
+ throw err;
167
+ }
118
168
  }
119
169
  async _doCreateContext(browser) {
120
- return this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
170
+ console.log("[CdpContextFactory._doCreateContext] START");
171
+ console.log("[CdpContextFactory._doCreateContext] isolated:", this.browserConfig.isolated);
172
+ try {
173
+ const ctx = this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
174
+ console.log("[CdpContextFactory._doCreateContext] Got context");
175
+ return ctx;
176
+ } catch (err) {
177
+ console.log("[CdpContextFactory._doCreateContext] ERROR:", err.message, err.stack);
178
+ throw err;
179
+ }
121
180
  }
122
181
  }
123
182
  class RemoteContextFactory extends BaseContextFactory {
@@ -70,9 +70,29 @@ class Context {
70
70
  await this._currentTab.page.bringToFront();
71
71
  }
72
72
  async ensureTab() {
73
- const { browserContext } = await this._ensureBrowserContext();
74
- if (!this._currentTab)
75
- await browserContext.newPage();
73
+ console.log("[Context.ensureTab] START");
74
+ console.log("[Context.ensureTab] _currentTab exists:", !!this._currentTab);
75
+ console.log("[Context.ensureTab] Calling _ensureBrowserContext()...");
76
+ let browserContext;
77
+ try {
78
+ const result = await this._ensureBrowserContext();
79
+ browserContext = result.browserContext;
80
+ console.log("[Context.ensureTab] _ensureBrowserContext() completed");
81
+ } catch (err) {
82
+ console.log("[Context.ensureTab] ERROR in _ensureBrowserContext():", err.message, err.stack);
83
+ throw err;
84
+ }
85
+ if (!this._currentTab) {
86
+ console.log("[Context.ensureTab] No current tab, creating new page...");
87
+ try {
88
+ await browserContext.newPage();
89
+ console.log("[Context.ensureTab] New page created");
90
+ } catch (err) {
91
+ console.log("[Context.ensureTab] ERROR creating new page:", err.message, err.stack);
92
+ throw err;
93
+ }
94
+ }
95
+ console.log("[Context.ensureTab] END, returning tab");
76
96
  return this._currentTab;
77
97
  }
78
98
  async listTabsMarkdown() {
@@ -249,29 +269,51 @@ ${code.join("\n")}
249
269
  }
250
270
  }
251
271
  _ensureBrowserContext() {
272
+ console.log("[Context._ensureBrowserContext] START");
273
+ console.log("[Context._ensureBrowserContext] _browserContextPromise exists:", !!this._browserContextPromise);
252
274
  if (!this._browserContextPromise) {
275
+ console.log("[Context._ensureBrowserContext] Creating new browser context promise...");
253
276
  this._browserContextPromise = this._setupBrowserContext();
254
- this._browserContextPromise.catch(() => {
277
+ this._browserContextPromise.catch((err) => {
278
+ console.log("[Context._ensureBrowserContext] Promise rejected:", err.message);
255
279
  this._browserContextPromise = void 0;
256
280
  });
257
281
  }
282
+ console.log("[Context._ensureBrowserContext] END, returning promise");
258
283
  return this._browserContextPromise;
259
284
  }
260
285
  async _setupBrowserContext() {
261
- const result = await this._browserContextFactory.createContext();
286
+ console.log("[Context._setupBrowserContext] START");
287
+ console.log("[Context._setupBrowserContext] Calling _browserContextFactory.createContext()...");
288
+ let result;
289
+ try {
290
+ result = await this._browserContextFactory.createContext();
291
+ console.log("[Context._setupBrowserContext] createContext() completed");
292
+ } catch (err) {
293
+ console.log("[Context._setupBrowserContext] ERROR in createContext():", err.message, err.stack);
294
+ throw err;
295
+ }
262
296
  const { browserContext } = result;
297
+ console.log("[Context._setupBrowserContext] Got browserContext");
298
+ console.log("[Context._setupBrowserContext] Setting up request interception...");
263
299
  await this._setupRequestInterception(browserContext);
300
+ console.log("[Context._setupBrowserContext] Request interception done");
301
+ console.log("[Context._setupBrowserContext] Processing existing pages...");
264
302
  for (const page of browserContext.pages())
265
303
  this._onPageCreated(page);
266
304
  browserContext.on("page", (page) => this._onPageCreated(page));
305
+ console.log("[Context._setupBrowserContext] Pages processed");
267
306
  if (this.config.saveTrace) {
307
+ console.log("[Context._setupBrowserContext] Starting tracing...");
268
308
  await browserContext.tracing.start({
269
309
  name: "trace",
270
310
  screenshots: false,
271
311
  snapshots: true,
272
312
  sources: false
273
313
  });
314
+ console.log("[Context._setupBrowserContext] Tracing started");
274
315
  }
316
+ console.log("[Context._setupBrowserContext] END");
275
317
  return result;
276
318
  }
277
319
  }
@@ -50,24 +50,40 @@ class Tab {
50
50
  }));
51
51
  }
52
52
  async navigate(url) {
53
+ console.log("[Tab.navigate] START, url:", url);
54
+ console.log("[Tab.navigate] Clearing collected artifacts...");
53
55
  this._clearCollectedArtifacts();
56
+ console.log("[Tab.navigate] Artifacts cleared");
57
+ console.log("[Tab.navigate] Setting up download event listener...");
54
58
  const downloadEvent = utils.callOnPageNoTrace(this.page, (page) => page.waitForEvent("download").catch(() => {
55
59
  }));
60
+ console.log("[Tab.navigate] Download event listener ready");
56
61
  try {
62
+ console.log("[Tab.navigate] Calling page.goto()...");
57
63
  await this.page.goto(url, { waitUntil: "domcontentloaded" });
64
+ console.log("[Tab.navigate] page.goto() completed successfully");
58
65
  } catch (_e) {
59
66
  const e = _e;
67
+ console.log("[Tab.navigate] page.goto() threw error:", e.message);
60
68
  const mightBeDownload = e.message.includes("net::ERR_ABORTED") || e.message.includes("Download is starting");
61
- if (!mightBeDownload)
69
+ if (!mightBeDownload) {
70
+ console.log("[Tab.navigate] Not a download, re-throwing error");
62
71
  throw e;
72
+ }
73
+ console.log("[Tab.navigate] Might be download, waiting for download event...");
63
74
  const download = await Promise.race([
64
75
  downloadEvent,
65
76
  new Promise((resolve) => setTimeout(resolve, 1e3))
66
77
  ]);
67
- if (!download)
78
+ if (!download) {
79
+ console.log("[Tab.navigate] No download received, re-throwing error");
68
80
  throw e;
81
+ }
82
+ console.log("[Tab.navigate] Download detected");
69
83
  }
84
+ console.log("[Tab.navigate] Waiting for load state...");
70
85
  await this.waitForLoadState("load", { timeout: 5e3 });
86
+ console.log("[Tab.navigate] END");
71
87
  }
72
88
  hasSnapshot() {
73
89
  return !!this._snapshot;
@@ -5,6 +5,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5
5
  const zod = require('zod');
6
6
  const tool = require('./tool.js');
7
7
 
8
+ const log = (msg, data) => {
9
+ console.log(`[browser_navigate] ${msg}`, data !== void 0 ? JSON.stringify(data, null, 2) : "");
10
+ };
8
11
  const navigate = (captureSnapshot) => tool.defineTool({
9
12
  capability: "core",
10
13
  schema: {
@@ -17,17 +20,39 @@ const navigate = (captureSnapshot) => tool.defineTool({
17
20
  type: "destructive"
18
21
  },
19
22
  handle: async (context, params) => {
20
- const tab = await context.ensureTab();
21
- await tab.navigate(params.url);
23
+ log("=== NAVIGATE HANDLER START ===");
24
+ log("Params received:", params);
25
+ log("captureSnapshot:", captureSnapshot);
26
+ log("About to call context.ensureTab()...");
27
+ let tab;
28
+ try {
29
+ tab = await context.ensureTab();
30
+ log("context.ensureTab() completed successfully");
31
+ log("Tab page URL:", tab.page?.url?.());
32
+ } catch (err) {
33
+ log("ERROR in context.ensureTab():", { message: err.message, stack: err.stack });
34
+ throw err;
35
+ }
36
+ log(`About to call tab.navigate("${params.url}")...`);
37
+ try {
38
+ await tab.navigate(params.url);
39
+ log("tab.navigate() completed successfully");
40
+ } catch (err) {
41
+ log("ERROR in tab.navigate():", { message: err.message, stack: err.stack });
42
+ throw err;
43
+ }
22
44
  const code = [
23
45
  `// Navigate to ${params.url}`,
24
46
  `await page.goto('${params.url}');`
25
47
  ];
26
- return {
48
+ log("About to return result...");
49
+ const result = {
27
50
  code,
28
51
  captureSnapshot,
29
52
  waitForNetwork: false
30
53
  };
54
+ log("=== NAVIGATE HANDLER END ===");
55
+ return result;
31
56
  }
32
57
  });
33
58
  const goBack = (captureSnapshot) => tool.defineTool({
@@ -1,4 +1,4 @@
1
- const version = "0.0.10";
1
+ const version = "0.0.12";
2
2
  const json = {
3
3
  version};
4
4
 
@@ -8,14 +8,25 @@ import { userDataDir } from './fileUtils.js';
8
8
 
9
9
  const testDebug = createDebug("pw:mcp:test");
10
10
  function contextFactory(browserConfig) {
11
- if (browserConfig.remoteEndpoint)
11
+ console.log("[contextFactory] START");
12
+ console.log("[contextFactory] browserConfig:", JSON.stringify(browserConfig, null, 2));
13
+ if (browserConfig.remoteEndpoint) {
14
+ console.log("[contextFactory] Using RemoteContextFactory");
12
15
  return new RemoteContextFactory(browserConfig);
13
- if (browserConfig.cdpEndpoint)
16
+ }
17
+ if (browserConfig.cdpEndpoint) {
18
+ console.log("[contextFactory] Using CdpContextFactory");
14
19
  return new CdpContextFactory(browserConfig);
15
- if (browserConfig.isolated)
20
+ }
21
+ if (browserConfig.isolated) {
22
+ console.log("[contextFactory] Using IsolatedContextFactory");
16
23
  return new IsolatedContextFactory(browserConfig);
17
- if (browserConfig.browserAgent)
24
+ }
25
+ if (browserConfig.browserAgent) {
26
+ console.log("[contextFactory] Using BrowserServerContextFactory");
18
27
  return new BrowserServerContextFactory(browserConfig);
28
+ }
29
+ console.log("[contextFactory] Using PersistentContextFactory");
19
30
  return new PersistentContextFactory(browserConfig);
20
31
  }
21
32
  class BaseContextFactory {
@@ -25,17 +36,26 @@ class BaseContextFactory {
25
36
  constructor(name, browserConfig) {
26
37
  this.name = name;
27
38
  this.browserConfig = browserConfig;
39
+ console.log(`[BaseContextFactory] Created factory: ${name}`);
28
40
  }
29
41
  async _obtainBrowser() {
30
- if (this._browserPromise)
42
+ console.log(`[BaseContextFactory._obtainBrowser] START (${this.name})`);
43
+ console.log(`[BaseContextFactory._obtainBrowser] _browserPromise exists:`, !!this._browserPromise);
44
+ if (this._browserPromise) {
45
+ console.log(`[BaseContextFactory._obtainBrowser] Returning existing promise`);
31
46
  return this._browserPromise;
47
+ }
32
48
  testDebug(`obtain browser (${this.name})`);
49
+ console.log(`[BaseContextFactory._obtainBrowser] Calling _doObtainBrowser...`);
33
50
  this._browserPromise = this._doObtainBrowser();
34
51
  void this._browserPromise.then((browser) => {
52
+ console.log(`[BaseContextFactory._obtainBrowser] Browser obtained successfully`);
35
53
  browser.on("disconnected", () => {
54
+ console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected`);
36
55
  this._browserPromise = void 0;
37
56
  });
38
- }).catch(() => {
57
+ }).catch((err) => {
58
+ console.log(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, err.message);
39
59
  this._browserPromise = void 0;
40
60
  });
41
61
  return this._browserPromise;
@@ -44,15 +64,22 @@ class BaseContextFactory {
44
64
  throw new Error("Not implemented");
45
65
  }
46
66
  async createContext() {
67
+ console.log(`[BaseContextFactory.createContext] START (${this.name})`);
47
68
  testDebug(`create browser context (${this.name})`);
69
+ console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser...`);
48
70
  const browser = await this._obtainBrowser();
71
+ console.log(`[BaseContextFactory.createContext] Got browser`);
72
+ console.log(`[BaseContextFactory.createContext] Calling _doCreateContext...`);
49
73
  const browserContext = await this._doCreateContext(browser);
74
+ console.log(`[BaseContextFactory.createContext] Got browserContext`);
75
+ console.log(`[BaseContextFactory.createContext] END`);
50
76
  return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
51
77
  }
52
78
  async _doCreateContext(browser) {
53
79
  throw new Error("Not implemented");
54
80
  }
55
81
  async _closeBrowserContext(browserContext, browser) {
82
+ console.log(`[BaseContextFactory._closeBrowserContext] START (${this.name})`);
56
83
  testDebug(`close browser context (${this.name})`);
57
84
  if (browser.contexts().length === 1)
58
85
  this._browserPromise = void 0;
@@ -63,6 +90,7 @@ class BaseContextFactory {
63
90
  await browser.close().catch(() => {
64
91
  });
65
92
  }
93
+ console.log(`[BaseContextFactory._closeBrowserContext] END`);
66
94
  }
67
95
  }
68
96
  class IsolatedContextFactory extends BaseContextFactory {
@@ -91,10 +119,41 @@ class CdpContextFactory extends BaseContextFactory {
91
119
  super("cdp", browserConfig);
92
120
  }
93
121
  async _doObtainBrowser() {
94
- return playwright.chromium.connectOverCDP(this.browserConfig.cdpEndpoint);
122
+ console.log("[CdpContextFactory._doObtainBrowser] START");
123
+ console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint:", this.browserConfig.cdpEndpoint);
124
+ console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint type:", typeof this.browserConfig.cdpEndpoint);
125
+ console.log("[CdpContextFactory._doObtainBrowser] playwright object keys:", Object.keys(playwright));
126
+ console.log("[CdpContextFactory._doObtainBrowser] playwright.chromium:", typeof playwright.chromium);
127
+ const endpoint = this.browserConfig.cdpEndpoint;
128
+ const isCloudfareFetcher = typeof endpoint !== "string";
129
+ console.log("[CdpContextFactory._doObtainBrowser] isCloudfareFetcher:", isCloudfareFetcher);
130
+ try {
131
+ let browser;
132
+ if (isCloudfareFetcher) {
133
+ console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connect() for Cloudflare Fetcher...");
134
+ browser = await playwright.chromium.connect(endpoint);
135
+ } else {
136
+ console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connectOverCDP() for CDP URL...");
137
+ browser = await playwright.chromium.connectOverCDP(endpoint);
138
+ }
139
+ console.log("[CdpContextFactory._doObtainBrowser] Connection completed");
140
+ return browser;
141
+ } catch (err) {
142
+ console.log("[CdpContextFactory._doObtainBrowser] ERROR:", err.message, err.stack);
143
+ throw err;
144
+ }
95
145
  }
96
146
  async _doCreateContext(browser) {
97
- return this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
147
+ console.log("[CdpContextFactory._doCreateContext] START");
148
+ console.log("[CdpContextFactory._doCreateContext] isolated:", this.browserConfig.isolated);
149
+ try {
150
+ const ctx = this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
151
+ console.log("[CdpContextFactory._doCreateContext] Got context");
152
+ return ctx;
153
+ } catch (err) {
154
+ console.log("[CdpContextFactory._doCreateContext] ERROR:", err.message, err.stack);
155
+ throw err;
156
+ }
98
157
  }
99
158
  }
100
159
  class RemoteContextFactory extends BaseContextFactory {
@@ -66,9 +66,29 @@ class Context {
66
66
  await this._currentTab.page.bringToFront();
67
67
  }
68
68
  async ensureTab() {
69
- const { browserContext } = await this._ensureBrowserContext();
70
- if (!this._currentTab)
71
- await browserContext.newPage();
69
+ console.log("[Context.ensureTab] START");
70
+ console.log("[Context.ensureTab] _currentTab exists:", !!this._currentTab);
71
+ console.log("[Context.ensureTab] Calling _ensureBrowserContext()...");
72
+ let browserContext;
73
+ try {
74
+ const result = await this._ensureBrowserContext();
75
+ browserContext = result.browserContext;
76
+ console.log("[Context.ensureTab] _ensureBrowserContext() completed");
77
+ } catch (err) {
78
+ console.log("[Context.ensureTab] ERROR in _ensureBrowserContext():", err.message, err.stack);
79
+ throw err;
80
+ }
81
+ if (!this._currentTab) {
82
+ console.log("[Context.ensureTab] No current tab, creating new page...");
83
+ try {
84
+ await browserContext.newPage();
85
+ console.log("[Context.ensureTab] New page created");
86
+ } catch (err) {
87
+ console.log("[Context.ensureTab] ERROR creating new page:", err.message, err.stack);
88
+ throw err;
89
+ }
90
+ }
91
+ console.log("[Context.ensureTab] END, returning tab");
72
92
  return this._currentTab;
73
93
  }
74
94
  async listTabsMarkdown() {
@@ -245,29 +265,51 @@ ${code.join("\n")}
245
265
  }
246
266
  }
247
267
  _ensureBrowserContext() {
268
+ console.log("[Context._ensureBrowserContext] START");
269
+ console.log("[Context._ensureBrowserContext] _browserContextPromise exists:", !!this._browserContextPromise);
248
270
  if (!this._browserContextPromise) {
271
+ console.log("[Context._ensureBrowserContext] Creating new browser context promise...");
249
272
  this._browserContextPromise = this._setupBrowserContext();
250
- this._browserContextPromise.catch(() => {
273
+ this._browserContextPromise.catch((err) => {
274
+ console.log("[Context._ensureBrowserContext] Promise rejected:", err.message);
251
275
  this._browserContextPromise = void 0;
252
276
  });
253
277
  }
278
+ console.log("[Context._ensureBrowserContext] END, returning promise");
254
279
  return this._browserContextPromise;
255
280
  }
256
281
  async _setupBrowserContext() {
257
- const result = await this._browserContextFactory.createContext();
282
+ console.log("[Context._setupBrowserContext] START");
283
+ console.log("[Context._setupBrowserContext] Calling _browserContextFactory.createContext()...");
284
+ let result;
285
+ try {
286
+ result = await this._browserContextFactory.createContext();
287
+ console.log("[Context._setupBrowserContext] createContext() completed");
288
+ } catch (err) {
289
+ console.log("[Context._setupBrowserContext] ERROR in createContext():", err.message, err.stack);
290
+ throw err;
291
+ }
258
292
  const { browserContext } = result;
293
+ console.log("[Context._setupBrowserContext] Got browserContext");
294
+ console.log("[Context._setupBrowserContext] Setting up request interception...");
259
295
  await this._setupRequestInterception(browserContext);
296
+ console.log("[Context._setupBrowserContext] Request interception done");
297
+ console.log("[Context._setupBrowserContext] Processing existing pages...");
260
298
  for (const page of browserContext.pages())
261
299
  this._onPageCreated(page);
262
300
  browserContext.on("page", (page) => this._onPageCreated(page));
301
+ console.log("[Context._setupBrowserContext] Pages processed");
263
302
  if (this.config.saveTrace) {
303
+ console.log("[Context._setupBrowserContext] Starting tracing...");
264
304
  await browserContext.tracing.start({
265
305
  name: "trace",
266
306
  screenshots: false,
267
307
  snapshots: true,
268
308
  sources: false
269
309
  });
310
+ console.log("[Context._setupBrowserContext] Tracing started");
270
311
  }
312
+ console.log("[Context._setupBrowserContext] END");
271
313
  return result;
272
314
  }
273
315
  }
@@ -46,24 +46,40 @@ class Tab {
46
46
  }));
47
47
  }
48
48
  async navigate(url) {
49
+ console.log("[Tab.navigate] START, url:", url);
50
+ console.log("[Tab.navigate] Clearing collected artifacts...");
49
51
  this._clearCollectedArtifacts();
52
+ console.log("[Tab.navigate] Artifacts cleared");
53
+ console.log("[Tab.navigate] Setting up download event listener...");
50
54
  const downloadEvent = callOnPageNoTrace(this.page, (page) => page.waitForEvent("download").catch(() => {
51
55
  }));
56
+ console.log("[Tab.navigate] Download event listener ready");
52
57
  try {
58
+ console.log("[Tab.navigate] Calling page.goto()...");
53
59
  await this.page.goto(url, { waitUntil: "domcontentloaded" });
60
+ console.log("[Tab.navigate] page.goto() completed successfully");
54
61
  } catch (_e) {
55
62
  const e = _e;
63
+ console.log("[Tab.navigate] page.goto() threw error:", e.message);
56
64
  const mightBeDownload = e.message.includes("net::ERR_ABORTED") || e.message.includes("Download is starting");
57
- if (!mightBeDownload)
65
+ if (!mightBeDownload) {
66
+ console.log("[Tab.navigate] Not a download, re-throwing error");
58
67
  throw e;
68
+ }
69
+ console.log("[Tab.navigate] Might be download, waiting for download event...");
59
70
  const download = await Promise.race([
60
71
  downloadEvent,
61
72
  new Promise((resolve) => setTimeout(resolve, 1e3))
62
73
  ]);
63
- if (!download)
74
+ if (!download) {
75
+ console.log("[Tab.navigate] No download received, re-throwing error");
64
76
  throw e;
77
+ }
78
+ console.log("[Tab.navigate] Download detected");
65
79
  }
80
+ console.log("[Tab.navigate] Waiting for load state...");
66
81
  await this.waitForLoadState("load", { timeout: 5e3 });
82
+ console.log("[Tab.navigate] END");
67
83
  }
68
84
  hasSnapshot() {
69
85
  return !!this._snapshot;
@@ -1,6 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { defineTool } from './tool.js';
3
3
 
4
+ const log = (msg, data) => {
5
+ console.log(`[browser_navigate] ${msg}`, data !== void 0 ? JSON.stringify(data, null, 2) : "");
6
+ };
4
7
  const navigate = (captureSnapshot) => defineTool({
5
8
  capability: "core",
6
9
  schema: {
@@ -13,17 +16,39 @@ const navigate = (captureSnapshot) => defineTool({
13
16
  type: "destructive"
14
17
  },
15
18
  handle: async (context, params) => {
16
- const tab = await context.ensureTab();
17
- await tab.navigate(params.url);
19
+ log("=== NAVIGATE HANDLER START ===");
20
+ log("Params received:", params);
21
+ log("captureSnapshot:", captureSnapshot);
22
+ log("About to call context.ensureTab()...");
23
+ let tab;
24
+ try {
25
+ tab = await context.ensureTab();
26
+ log("context.ensureTab() completed successfully");
27
+ log("Tab page URL:", tab.page?.url?.());
28
+ } catch (err) {
29
+ log("ERROR in context.ensureTab():", { message: err.message, stack: err.stack });
30
+ throw err;
31
+ }
32
+ log(`About to call tab.navigate("${params.url}")...`);
33
+ try {
34
+ await tab.navigate(params.url);
35
+ log("tab.navigate() completed successfully");
36
+ } catch (err) {
37
+ log("ERROR in tab.navigate():", { message: err.message, stack: err.stack });
38
+ throw err;
39
+ }
18
40
  const code = [
19
41
  `// Navigate to ${params.url}`,
20
42
  `await page.goto('${params.url}');`
21
43
  ];
22
- return {
44
+ log("About to return result...");
45
+ const result = {
23
46
  code,
24
47
  captureSnapshot,
25
48
  waitForNetwork: false
26
49
  };
50
+ log("=== NAVIGATE HANDLER END ===");
51
+ return result;
27
52
  }
28
53
  });
29
54
  const goBack = (captureSnapshot) => defineTool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@szymonrybczak/playwright-mcp",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Cloudflare Playwright Tools for MCP",
5
5
  "type": "module",
6
6
  "repository": {