@szymonrybczak/playwright-mcp 0.0.2 → 0.0.4

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.
Files changed (115) hide show
  1. package/index.d.ts +21 -8
  2. package/lib/cjs/_virtual/_commonjsHelpers.js +9 -0
  3. package/lib/cjs/_virtual/browser.js +11 -0
  4. package/lib/cjs/_virtual/browser2.js +7 -0
  5. package/lib/cjs/cloudflare/package.json.js +10 -0
  6. package/lib/cjs/index.js +28 -0
  7. package/lib/cjs/node_modules/debug/src/browser.js +290 -0
  8. package/lib/cjs/node_modules/debug/src/common.js +307 -0
  9. package/lib/cjs/node_modules/ms/index.js +176 -0
  10. package/lib/cjs/package.js +9 -0
  11. package/lib/cjs/src/browserContextFactory.js +240 -0
  12. package/lib/cjs/src/config.js +77 -0
  13. package/lib/cjs/src/connection.js +74 -0
  14. package/lib/cjs/src/context.js +281 -0
  15. package/lib/cjs/src/fileUtils.js +25 -0
  16. package/lib/cjs/src/index.js +15 -0
  17. package/lib/cjs/src/javascript.js +41 -0
  18. package/lib/cjs/src/manualPromise.js +39 -0
  19. package/lib/cjs/src/pageSnapshot.js +35 -0
  20. package/lib/cjs/src/tab.js +91 -0
  21. package/lib/cjs/src/tools/common.js +60 -0
  22. package/lib/cjs/src/tools/console.js +36 -0
  23. package/lib/cjs/src/tools/dialogs.js +44 -0
  24. package/lib/cjs/src/tools/files.js +43 -0
  25. package/lib/cjs/src/tools/install.js +49 -0
  26. package/lib/cjs/src/tools/keyboard.js +38 -0
  27. package/lib/cjs/src/tools/navigate.js +85 -0
  28. package/lib/cjs/src/tools/network.js +43 -0
  29. package/lib/cjs/src/tools/pdf.js +42 -0
  30. package/lib/cjs/src/tools/screenshot.js +69 -0
  31. package/lib/cjs/src/tools/snapshot.js +195 -0
  32. package/lib/cjs/src/tools/tabs.js +110 -0
  33. package/lib/cjs/src/tools/testing.js +52 -0
  34. package/lib/cjs/src/tools/tool.js +9 -0
  35. package/lib/cjs/src/tools/utils.js +75 -0
  36. package/lib/cjs/src/tools/vision.js +181 -0
  37. package/lib/cjs/src/tools/wait.js +51 -0
  38. package/lib/cjs/src/tools.js +54 -0
  39. package/lib/esm/_virtual/_commonjsHelpers.js +5 -0
  40. package/lib/esm/_virtual/browser.js +7 -0
  41. package/lib/esm/_virtual/browser2.js +3 -0
  42. package/lib/esm/cloudflare/package.json.js +5 -0
  43. package/lib/esm/index.js +24 -0
  44. package/lib/esm/node_modules/debug/src/browser.js +286 -0
  45. package/lib/esm/node_modules/debug/src/common.js +303 -0
  46. package/lib/esm/node_modules/ms/index.js +172 -0
  47. package/lib/esm/package.js +5 -0
  48. package/lib/esm/src/browserContextFactory.js +216 -0
  49. package/lib/esm/src/config.js +72 -0
  50. package/lib/esm/src/connection.js +69 -0
  51. package/lib/esm/src/context.js +277 -0
  52. package/lib/esm/src/fileUtils.js +20 -0
  53. package/lib/esm/src/index.js +11 -0
  54. package/lib/esm/src/javascript.js +35 -0
  55. package/lib/esm/src/manualPromise.js +35 -0
  56. package/lib/esm/src/pageSnapshot.js +31 -0
  57. package/lib/esm/src/tab.js +87 -0
  58. package/lib/esm/src/tools/common.js +56 -0
  59. package/lib/esm/src/tools/console.js +32 -0
  60. package/lib/esm/src/tools/dialogs.js +40 -0
  61. package/lib/esm/src/tools/files.js +39 -0
  62. package/lib/esm/src/tools/install.js +45 -0
  63. package/lib/esm/src/tools/keyboard.js +34 -0
  64. package/lib/esm/src/tools/navigate.js +81 -0
  65. package/lib/esm/src/tools/network.js +39 -0
  66. package/lib/esm/src/tools/pdf.js +38 -0
  67. package/lib/esm/src/tools/screenshot.js +65 -0
  68. package/lib/esm/src/tools/snapshot.js +191 -0
  69. package/lib/esm/src/tools/tabs.js +106 -0
  70. package/lib/esm/src/tools/testing.js +48 -0
  71. package/lib/esm/src/tools/tool.js +5 -0
  72. package/lib/esm/src/tools/utils.js +68 -0
  73. package/lib/esm/src/tools/vision.js +177 -0
  74. package/lib/esm/src/tools/wait.js +47 -0
  75. package/lib/esm/src/tools.js +49 -0
  76. package/package.json +15 -44
  77. package/LICENSE +0 -202
  78. package/README.md +0 -508
  79. package/cli.js +0 -18
  80. package/config.d.ts +0 -128
  81. package/index.js +0 -19
  82. package/lib/browserContextFactory.js +0 -227
  83. package/lib/browserServer.js +0 -151
  84. package/lib/config.js +0 -189
  85. package/lib/connection.js +0 -82
  86. package/lib/context.js +0 -291
  87. package/lib/fileUtils.js +0 -32
  88. package/lib/httpServer.js +0 -201
  89. package/lib/index.js +0 -36
  90. package/lib/javascript.js +0 -49
  91. package/lib/manualPromise.js +0 -111
  92. package/lib/package.js +0 -20
  93. package/lib/pageSnapshot.js +0 -43
  94. package/lib/program.js +0 -72
  95. package/lib/server.js +0 -48
  96. package/lib/tab.js +0 -101
  97. package/lib/tools/common.js +0 -68
  98. package/lib/tools/console.js +0 -44
  99. package/lib/tools/dialogs.js +0 -52
  100. package/lib/tools/files.js +0 -51
  101. package/lib/tools/install.js +0 -57
  102. package/lib/tools/keyboard.js +0 -46
  103. package/lib/tools/navigate.js +0 -93
  104. package/lib/tools/network.js +0 -51
  105. package/lib/tools/pdf.js +0 -49
  106. package/lib/tools/screenshot.js +0 -77
  107. package/lib/tools/snapshot.js +0 -204
  108. package/lib/tools/tabs.js +0 -118
  109. package/lib/tools/testing.js +0 -60
  110. package/lib/tools/tool.js +0 -18
  111. package/lib/tools/utils.js +0 -80
  112. package/lib/tools/vision.js +0 -189
  113. package/lib/tools/wait.js +0 -59
  114. package/lib/tools.js +0 -61
  115. package/lib/transport.js +0 -133
@@ -0,0 +1,176 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ /**
6
+ * Helpers.
7
+ */
8
+
9
+ var ms;
10
+ var hasRequiredMs;
11
+
12
+ function requireMs () {
13
+ if (hasRequiredMs) return ms;
14
+ hasRequiredMs = 1;
15
+ var s = 1000;
16
+ var m = s * 60;
17
+ var h = m * 60;
18
+ var d = h * 24;
19
+ var w = d * 7;
20
+ var y = d * 365.25;
21
+
22
+ /**
23
+ * Parse or format the given `val`.
24
+ *
25
+ * Options:
26
+ *
27
+ * - `long` verbose formatting [false]
28
+ *
29
+ * @param {String|Number} val
30
+ * @param {Object} [options]
31
+ * @throws {Error} throw an error if val is not a non-empty string or a number
32
+ * @return {String|Number}
33
+ * @api public
34
+ */
35
+
36
+ ms = function (val, options) {
37
+ options = options || {};
38
+ var type = typeof val;
39
+ if (type === 'string' && val.length > 0) {
40
+ return parse(val);
41
+ } else if (type === 'number' && isFinite(val)) {
42
+ return options.long ? fmtLong(val) : fmtShort(val);
43
+ }
44
+ throw new Error(
45
+ 'val is not a non-empty string or a valid number. val=' +
46
+ JSON.stringify(val)
47
+ );
48
+ };
49
+
50
+ /**
51
+ * Parse the given `str` and return milliseconds.
52
+ *
53
+ * @param {String} str
54
+ * @return {Number}
55
+ * @api private
56
+ */
57
+
58
+ function parse(str) {
59
+ str = String(str);
60
+ if (str.length > 100) {
61
+ return;
62
+ }
63
+ var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
64
+ str
65
+ );
66
+ if (!match) {
67
+ return;
68
+ }
69
+ var n = parseFloat(match[1]);
70
+ var type = (match[2] || 'ms').toLowerCase();
71
+ switch (type) {
72
+ case 'years':
73
+ case 'year':
74
+ case 'yrs':
75
+ case 'yr':
76
+ case 'y':
77
+ return n * y;
78
+ case 'weeks':
79
+ case 'week':
80
+ case 'w':
81
+ return n * w;
82
+ case 'days':
83
+ case 'day':
84
+ case 'd':
85
+ return n * d;
86
+ case 'hours':
87
+ case 'hour':
88
+ case 'hrs':
89
+ case 'hr':
90
+ case 'h':
91
+ return n * h;
92
+ case 'minutes':
93
+ case 'minute':
94
+ case 'mins':
95
+ case 'min':
96
+ case 'm':
97
+ return n * m;
98
+ case 'seconds':
99
+ case 'second':
100
+ case 'secs':
101
+ case 'sec':
102
+ case 's':
103
+ return n * s;
104
+ case 'milliseconds':
105
+ case 'millisecond':
106
+ case 'msecs':
107
+ case 'msec':
108
+ case 'ms':
109
+ return n;
110
+ default:
111
+ return undefined;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Short format for `ms`.
117
+ *
118
+ * @param {Number} ms
119
+ * @return {String}
120
+ * @api private
121
+ */
122
+
123
+ function fmtShort(ms) {
124
+ var msAbs = Math.abs(ms);
125
+ if (msAbs >= d) {
126
+ return Math.round(ms / d) + 'd';
127
+ }
128
+ if (msAbs >= h) {
129
+ return Math.round(ms / h) + 'h';
130
+ }
131
+ if (msAbs >= m) {
132
+ return Math.round(ms / m) + 'm';
133
+ }
134
+ if (msAbs >= s) {
135
+ return Math.round(ms / s) + 's';
136
+ }
137
+ return ms + 'ms';
138
+ }
139
+
140
+ /**
141
+ * Long format for `ms`.
142
+ *
143
+ * @param {Number} ms
144
+ * @return {String}
145
+ * @api private
146
+ */
147
+
148
+ function fmtLong(ms) {
149
+ var msAbs = Math.abs(ms);
150
+ if (msAbs >= d) {
151
+ return plural(ms, msAbs, d, 'day');
152
+ }
153
+ if (msAbs >= h) {
154
+ return plural(ms, msAbs, h, 'hour');
155
+ }
156
+ if (msAbs >= m) {
157
+ return plural(ms, msAbs, m, 'minute');
158
+ }
159
+ if (msAbs >= s) {
160
+ return plural(ms, msAbs, s, 'second');
161
+ }
162
+ return ms + ' ms';
163
+ }
164
+
165
+ /**
166
+ * Pluralization helper.
167
+ */
168
+
169
+ function plural(ms, msAbs, n, name) {
170
+ var isPlural = msAbs >= n * 1.5;
171
+ return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
172
+ }
173
+ return ms;
174
+ }
175
+
176
+ exports.__require = requireMs;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const _package = require('./cloudflare/package.json.js');
6
+
7
+ const packageJSON = _package.default;
8
+
9
+ exports.packageJSON = packageJSON;
@@ -0,0 +1,240 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const fs = require('node:fs');
6
+ const net = require('node:net');
7
+ const path = require('node:path');
8
+ const os = require('node:os');
9
+ const browser = require('../_virtual/browser.js');
10
+ const playwright = require('@szymonrybczak/patchright');
11
+ const fileUtils = require('./fileUtils.js');
12
+
13
+ function _interopNamespaceDefault(e) {
14
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
15
+ if (e) {
16
+ for (const k in e) {
17
+ if (k !== 'default') {
18
+ const d = Object.getOwnPropertyDescriptor(e, k);
19
+ Object.defineProperty(n, k, d.get ? d : {
20
+ enumerable: true,
21
+ get: () => e[k]
22
+ });
23
+ }
24
+ }
25
+ }
26
+ n.default = e;
27
+ return Object.freeze(n);
28
+ }
29
+
30
+ const playwright__namespace = /*#__PURE__*/_interopNamespaceDefault(playwright);
31
+
32
+ const testDebug = browser.default("pw:mcp:test");
33
+ function contextFactory(browserConfig) {
34
+ if (browserConfig.remoteEndpoint)
35
+ return new RemoteContextFactory(browserConfig);
36
+ if (browserConfig.cdpEndpoint)
37
+ return new CdpContextFactory(browserConfig);
38
+ if (browserConfig.isolated)
39
+ return new IsolatedContextFactory(browserConfig);
40
+ if (browserConfig.browserAgent)
41
+ return new BrowserServerContextFactory(browserConfig);
42
+ return new PersistentContextFactory(browserConfig);
43
+ }
44
+ class BaseContextFactory {
45
+ browserConfig;
46
+ _browserPromise;
47
+ name;
48
+ constructor(name, browserConfig) {
49
+ this.name = name;
50
+ this.browserConfig = browserConfig;
51
+ }
52
+ async _obtainBrowser() {
53
+ if (this._browserPromise)
54
+ return this._browserPromise;
55
+ testDebug(`obtain browser (${this.name})`);
56
+ this._browserPromise = this._doObtainBrowser();
57
+ void this._browserPromise.then((browser) => {
58
+ browser.on("disconnected", () => {
59
+ this._browserPromise = void 0;
60
+ });
61
+ }).catch(() => {
62
+ this._browserPromise = void 0;
63
+ });
64
+ return this._browserPromise;
65
+ }
66
+ async _doObtainBrowser() {
67
+ throw new Error("Not implemented");
68
+ }
69
+ async createContext() {
70
+ testDebug(`create browser context (${this.name})`);
71
+ const browser = await this._obtainBrowser();
72
+ const browserContext = await this._doCreateContext(browser);
73
+ return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
74
+ }
75
+ async _doCreateContext(browser) {
76
+ throw new Error("Not implemented");
77
+ }
78
+ async _closeBrowserContext(browserContext, browser) {
79
+ testDebug(`close browser context (${this.name})`);
80
+ if (browser.contexts().length === 1)
81
+ this._browserPromise = void 0;
82
+ await browserContext.close().catch(() => {
83
+ });
84
+ if (browser.contexts().length === 0) {
85
+ testDebug(`close browser (${this.name})`);
86
+ await browser.close().catch(() => {
87
+ });
88
+ }
89
+ }
90
+ }
91
+ class IsolatedContextFactory extends BaseContextFactory {
92
+ constructor(browserConfig) {
93
+ super("isolated", browserConfig);
94
+ }
95
+ async _doObtainBrowser() {
96
+ await injectCdpPort(this.browserConfig);
97
+ const browserType = playwright__namespace[this.browserConfig.browserName];
98
+ return browserType.launch({
99
+ ...this.browserConfig.launchOptions,
100
+ handleSIGINT: false,
101
+ handleSIGTERM: false
102
+ }).catch((error) => {
103
+ if (error.message.includes("Executable doesn't exist"))
104
+ throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
105
+ throw error;
106
+ });
107
+ }
108
+ async _doCreateContext(browser) {
109
+ return browser.newContext(this.browserConfig.contextOptions);
110
+ }
111
+ }
112
+ class CdpContextFactory extends BaseContextFactory {
113
+ constructor(browserConfig) {
114
+ super("cdp", browserConfig);
115
+ }
116
+ async _doObtainBrowser() {
117
+ return playwright__namespace.chromium.connectOverCDP(this.browserConfig.cdpEndpoint);
118
+ }
119
+ async _doCreateContext(browser) {
120
+ return this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
121
+ }
122
+ }
123
+ class RemoteContextFactory extends BaseContextFactory {
124
+ constructor(browserConfig) {
125
+ super("remote", browserConfig);
126
+ }
127
+ async _doObtainBrowser() {
128
+ const url = new URL(this.browserConfig.remoteEndpoint);
129
+ url.searchParams.set("browser", this.browserConfig.browserName);
130
+ if (this.browserConfig.launchOptions)
131
+ url.searchParams.set("launch-options", JSON.stringify(this.browserConfig.launchOptions));
132
+ return playwright__namespace[this.browserConfig.browserName].connect(String(url));
133
+ }
134
+ async _doCreateContext(browser) {
135
+ return browser.newContext();
136
+ }
137
+ }
138
+ class PersistentContextFactory {
139
+ browserConfig;
140
+ _userDataDirs = /* @__PURE__ */ new Set();
141
+ constructor(browserConfig) {
142
+ this.browserConfig = browserConfig;
143
+ }
144
+ async createContext() {
145
+ await injectCdpPort(this.browserConfig);
146
+ testDebug("create browser context (persistent)");
147
+ const userDataDir2 = this.browserConfig.userDataDir ?? await this._createUserDataDir();
148
+ this._userDataDirs.add(userDataDir2);
149
+ testDebug("lock user data dir", userDataDir2);
150
+ const browserType = playwright__namespace[this.browserConfig.browserName];
151
+ for (let i = 0; i < 5; i++) {
152
+ try {
153
+ const browserContext = await browserType.launchPersistentContext(userDataDir2, {
154
+ ...this.browserConfig.launchOptions,
155
+ ...this.browserConfig.contextOptions,
156
+ handleSIGINT: false,
157
+ handleSIGTERM: false
158
+ });
159
+ const close = () => this._closeBrowserContext(browserContext, userDataDir2);
160
+ return { browserContext, close };
161
+ } catch (error) {
162
+ if (error.message.includes("Executable doesn't exist"))
163
+ throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
164
+ if (error.message.includes("ProcessSingleton") || error.message.includes("Invalid URL")) {
165
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
166
+ continue;
167
+ }
168
+ throw error;
169
+ }
170
+ }
171
+ throw new Error(`Browser is already in use for ${userDataDir2}, use --isolated to run multiple instances of the same browser`);
172
+ }
173
+ async _closeBrowserContext(browserContext, userDataDir2) {
174
+ testDebug("close browser context (persistent)");
175
+ testDebug("release user data dir", userDataDir2);
176
+ await browserContext.close().catch(() => {
177
+ });
178
+ this._userDataDirs.delete(userDataDir2);
179
+ testDebug("close browser context complete (persistent)");
180
+ }
181
+ async _createUserDataDir() {
182
+ let cacheDirectory;
183
+ if (process.platform === "linux")
184
+ cacheDirectory = process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache");
185
+ else if (process.platform === "darwin")
186
+ cacheDirectory = path.join(os.homedir(), "Library", "Caches");
187
+ else if (process.platform === "win32")
188
+ cacheDirectory = process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
189
+ else
190
+ throw new Error("Unsupported platform: " + process.platform);
191
+ const result = path.join(cacheDirectory, "ms-playwright", `mcp-${this.browserConfig.launchOptions?.channel ?? this.browserConfig?.browserName}-profile`);
192
+ await fs.promises.mkdir(result, { recursive: true });
193
+ return result;
194
+ }
195
+ }
196
+ class BrowserServerContextFactory extends BaseContextFactory {
197
+ constructor(browserConfig) {
198
+ super("persistent", browserConfig);
199
+ }
200
+ async _doObtainBrowser() {
201
+ const response = await fetch(new URL(`/json/launch`, this.browserConfig.browserAgent), {
202
+ method: "POST",
203
+ body: JSON.stringify({
204
+ browserType: this.browserConfig.browserName,
205
+ userDataDir: this.browserConfig.userDataDir ?? await this._createUserDataDir(),
206
+ launchOptions: this.browserConfig.launchOptions,
207
+ contextOptions: this.browserConfig.contextOptions
208
+ })
209
+ });
210
+ const info = await response.json();
211
+ if (info.error)
212
+ throw new Error(info.error);
213
+ return await playwright__namespace.chromium.connectOverCDP(`http://localhost:${info.cdpPort}/`);
214
+ }
215
+ async _doCreateContext(browser) {
216
+ return this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
217
+ }
218
+ async _createUserDataDir() {
219
+ const dir = await fileUtils.userDataDir(this.browserConfig);
220
+ await fs.promises.mkdir(dir, { recursive: true });
221
+ return dir;
222
+ }
223
+ }
224
+ async function injectCdpPort(browserConfig) {
225
+ if (browserConfig.browserName === "chromium")
226
+ browserConfig.launchOptions.cdpPort = await findFreePort();
227
+ }
228
+ async function findFreePort() {
229
+ return new Promise((resolve, reject) => {
230
+ const server = net.createServer();
231
+ server.listen(0, () => {
232
+ const { port } = server.address();
233
+ server.close(() => resolve(port));
234
+ });
235
+ server.on("error", reject);
236
+ });
237
+ }
238
+
239
+ exports.BrowserServerContextFactory = BrowserServerContextFactory;
240
+ exports.contextFactory = contextFactory;
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const fs = require('node:fs');
6
+ const os = require('node:os');
7
+ const path = require('node:path');
8
+ require('@szymonrybczak/patchright');
9
+ const utils = require('./tools/utils.js');
10
+
11
+ const defaultConfig = {
12
+ browser: {
13
+ browserName: "chromium",
14
+ launchOptions: {
15
+ channel: "chrome",
16
+ headless: os.platform() === "linux" && !process.env.DISPLAY,
17
+ chromiumSandbox: true
18
+ },
19
+ contextOptions: {
20
+ viewport: null
21
+ }
22
+ },
23
+ network: {
24
+ allowedOrigins: void 0,
25
+ blockedOrigins: void 0
26
+ },
27
+ server: {},
28
+ outputDir: path.join(os.tmpdir(), "playwright-mcp-output", utils.sanitizeForFilePath((/* @__PURE__ */ new Date()).toISOString()))
29
+ };
30
+ async function resolveConfig(config) {
31
+ return mergeConfig(defaultConfig, config);
32
+ }
33
+ async function outputFile(config, name) {
34
+ await fs.promises.mkdir(config.outputDir, { recursive: true });
35
+ const fileName = utils.sanitizeForFilePath(name);
36
+ return path.join(config.outputDir, fileName);
37
+ }
38
+ function pickDefined(obj) {
39
+ return Object.fromEntries(
40
+ Object.entries(obj ?? {}).filter(([_, v]) => v !== void 0)
41
+ );
42
+ }
43
+ function mergeConfig(base, overrides) {
44
+ const browser = {
45
+ ...pickDefined(base.browser),
46
+ ...pickDefined(overrides.browser),
47
+ browserName: overrides.browser?.browserName ?? base.browser?.browserName ?? "chromium",
48
+ isolated: overrides.browser?.isolated ?? base.browser?.isolated ?? false,
49
+ launchOptions: {
50
+ ...pickDefined(base.browser?.launchOptions),
51
+ ...pickDefined(overrides.browser?.launchOptions),
52
+ ...{ assistantMode: true }
53
+ },
54
+ contextOptions: {
55
+ ...pickDefined(base.browser?.contextOptions),
56
+ ...pickDefined(overrides.browser?.contextOptions)
57
+ }
58
+ };
59
+ if (browser.browserName !== "chromium" && browser.launchOptions)
60
+ delete browser.launchOptions.channel;
61
+ return {
62
+ ...pickDefined(base),
63
+ ...pickDefined(overrides),
64
+ browser,
65
+ network: {
66
+ ...pickDefined(base.network),
67
+ ...pickDefined(overrides.network)
68
+ },
69
+ server: {
70
+ ...pickDefined(base.server),
71
+ ...pickDefined(overrides.server)
72
+ }
73
+ };
74
+ }
75
+
76
+ exports.outputFile = outputFile;
77
+ exports.resolveConfig = resolveConfig;
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const index_js = require('@modelcontextprotocol/sdk/server/index.js');
6
+ const types_js = require('@modelcontextprotocol/sdk/types.js');
7
+ const zodToJsonSchema = require('zod-to-json-schema');
8
+ const context = require('./context.js');
9
+ const tools = require('./tools.js');
10
+ const _package = require('../package.js');
11
+
12
+ function createConnection(config, browserContextFactory) {
13
+ const allTools = config.vision ? tools.visionTools : tools.snapshotTools;
14
+ const tools$1 = allTools.filter((tool) => !config.capabilities || tool.capability === "core" || config.capabilities.includes(tool.capability));
15
+ const context$1 = new context.Context(tools$1, config, browserContextFactory);
16
+ const server = new index_js.Server({ name: "Playwright", version: _package.packageJSON.version }, {
17
+ capabilities: {
18
+ tools: {}
19
+ }
20
+ });
21
+ server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
22
+ return {
23
+ tools: tools$1.map((tool) => ({
24
+ name: tool.schema.name,
25
+ description: tool.schema.description,
26
+ inputSchema: zodToJsonSchema.zodToJsonSchema(tool.schema.inputSchema),
27
+ annotations: {
28
+ title: tool.schema.title,
29
+ readOnlyHint: tool.schema.type === "readOnly",
30
+ destructiveHint: tool.schema.type === "destructive",
31
+ openWorldHint: true
32
+ }
33
+ }))
34
+ };
35
+ });
36
+ server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
37
+ const errorResult = (...messages) => ({
38
+ content: [{ type: "text", text: messages.join("\n") }],
39
+ isError: true
40
+ });
41
+ const tool = tools$1.find((tool2) => tool2.schema.name === request.params.name);
42
+ if (!tool)
43
+ return errorResult(`Tool "${request.params.name}" not found`);
44
+ const modalStates = context$1.modalStates().map((state) => state.type);
45
+ if (tool.clearsModalState && !modalStates.includes(tool.clearsModalState))
46
+ return errorResult(`The tool "${request.params.name}" can only be used when there is related modal state present.`, ...context$1.modalStatesMarkdown());
47
+ if (!tool.clearsModalState && modalStates.length)
48
+ return errorResult(`Tool "${request.params.name}" does not handle the modal state.`, ...context$1.modalStatesMarkdown());
49
+ try {
50
+ return await context$1.run(tool, request.params.arguments);
51
+ } catch (error) {
52
+ return errorResult(String(error));
53
+ }
54
+ });
55
+ return new Connection(server, context$1);
56
+ }
57
+ class Connection {
58
+ server;
59
+ context;
60
+ constructor(server, context) {
61
+ this.server = server;
62
+ this.context = context;
63
+ this.server.oninitialized = () => {
64
+ this.context.clientVersion = this.server.getClientVersion();
65
+ };
66
+ }
67
+ async close() {
68
+ await this.server.close();
69
+ await this.context.close();
70
+ }
71
+ }
72
+
73
+ exports.Connection = Connection;
74
+ exports.createConnection = createConnection;