@cotestdev/mcp_playwright 0.0.35 → 0.0.37

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 (42) hide show
  1. package/lib/mcp/browser/browserContextFactory.js +12 -12
  2. package/lib/mcp/browser/browserServerBackend.js +24 -12
  3. package/lib/mcp/browser/config.js +37 -7
  4. package/lib/mcp/browser/context.js +13 -61
  5. package/lib/mcp/browser/response.js +183 -251
  6. package/lib/mcp/browser/sessionLog.js +19 -104
  7. package/lib/mcp/browser/tab.js +49 -28
  8. package/lib/mcp/browser/tools/common.js +8 -9
  9. package/lib/mcp/browser/tools/console.js +20 -3
  10. package/lib/mcp/browser/tools/dialogs.js +2 -3
  11. package/lib/mcp/browser/tools/evaluate.js +8 -6
  12. package/lib/mcp/browser/tools/files.js +2 -2
  13. package/lib/mcp/browser/tools/form.js +2 -2
  14. package/lib/mcp/browser/tools/install.js +4 -1
  15. package/lib/mcp/browser/tools/keyboard.js +77 -10
  16. package/lib/mcp/browser/tools/mouse.js +59 -7
  17. package/lib/mcp/browser/tools/navigate.js +51 -8
  18. package/lib/mcp/browser/tools/network.js +21 -3
  19. package/lib/mcp/browser/tools/pdf.js +4 -3
  20. package/lib/mcp/browser/tools/runCode.js +8 -12
  21. package/lib/mcp/browser/tools/schema.js +31 -0
  22. package/lib/mcp/browser/tools/screenshot.js +10 -28
  23. package/lib/mcp/browser/tools/snapshot.js +40 -24
  24. package/lib/mcp/browser/tools/tabs.js +10 -10
  25. package/lib/mcp/browser/tools/tool.js +3 -6
  26. package/lib/mcp/browser/tools/tracing.js +3 -3
  27. package/lib/mcp/browser/tools/utils.js +2 -2
  28. package/lib/mcp/browser/tools/verify.js +9 -9
  29. package/lib/mcp/browser/tools/wait.js +3 -3
  30. package/lib/mcp/browser/tools.js +2 -2
  31. package/lib/mcp/extension/extensionContextFactory.js +2 -2
  32. package/lib/mcp/program.js +3 -2
  33. package/lib/mcp/terminal/cli.js +4 -216
  34. package/lib/mcp/terminal/command.js +56 -0
  35. package/lib/mcp/terminal/commands.js +528 -0
  36. package/lib/mcp/terminal/daemon.js +42 -25
  37. package/lib/mcp/terminal/helpGenerator.js +152 -0
  38. package/lib/mcp/terminal/program.js +434 -0
  39. package/lib/mcp/terminal/socketConnection.js +2 -4
  40. package/lib/mcpBundleImpl/index.js +44 -44
  41. package/lib/util.js +3 -6
  42. package/package.json +1 -1
@@ -20,7 +20,8 @@ var tab_exports = {};
20
20
  __export(tab_exports, {
21
21
  Tab: () => Tab,
22
22
  TabEvents: () => TabEvents,
23
- renderModalStates: () => renderModalStates
23
+ renderModalStates: () => renderModalStates,
24
+ shouldIncludeMessage: () => shouldIncludeMessage
24
25
  });
25
26
  module.exports = __toCommonJS(tab_exports);
26
27
  var import_events = require("events");
@@ -36,26 +37,27 @@ const TabEvents = {
36
37
  class Tab extends import_events.EventEmitter {
37
38
  constructor(context, page, onPageClose) {
38
39
  super();
39
- this._lastTitle = "about:blank";
40
+ this._lastHeader = { title: "about:blank", url: "about:blank", current: false };
40
41
  this._consoleMessages = [];
41
- this._recentConsoleMessages = [];
42
+ this._downloads = [];
42
43
  this._requests = /* @__PURE__ */ new Set();
43
44
  this._modalStates = [];
44
- this._downloads = [];
45
45
  this._needsFullSnapshot = false;
46
+ this._eventEntries = [];
47
+ this._recentEventEntries = [];
46
48
  this.context = context;
47
49
  this.page = page;
48
50
  this._onPageClose = onPageClose;
49
51
  page.on("console", (event) => this._handleConsoleMessage(messageToConsoleMessage(event)));
50
52
  page.on("pageerror", (error) => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
51
- page.on("request", (request) => this._requests.add(request));
53
+ page.on("request", (request) => this._handleRequest(request));
52
54
  page.on("close", () => this._onClose());
53
55
  page.on("filechooser", (chooser) => {
54
56
  this.setModalState({
55
57
  type: "fileChooser",
56
58
  description: "File chooser",
57
59
  fileChooser: chooser,
58
- clearedBy: import_files.uploadFile.schema.name
60
+ clearedBy: { tool: import_files.uploadFile.schema.name, skill: "upload" }
59
61
  });
60
62
  });
61
63
  page.on("dialog", (dialog) => this._dialogShown(dialog));
@@ -110,39 +112,54 @@ class Tab extends import_events.EventEmitter {
110
112
  type: "dialog",
111
113
  description: `"${dialog.type()}" dialog with message "${dialog.message()}"`,
112
114
  dialog,
113
- clearedBy: import_dialogs.handleDialog.schema.name
115
+ clearedBy: { tool: import_dialogs.handleDialog.schema.name, skill: "dialog-accept or dialog-dismiss" }
114
116
  });
115
117
  }
116
118
  async _downloadStarted(download) {
117
119
  const entry = {
118
120
  download,
119
121
  finished: false,
120
- outputFile: await this.context.outputFile(download.suggestedFilename(), { origin: "web", reason: "Saving download" })
122
+ outputFile: await this.context.outputFile(download.suggestedFilename(), { origin: "web", title: "Saving download" })
121
123
  };
122
124
  this._downloads.push(entry);
125
+ this._addLogEntry({ type: "download-start", wallTime: Date.now(), download: entry });
123
126
  await download.saveAs(entry.outputFile);
124
127
  entry.finished = true;
128
+ this._addLogEntry({ type: "download-finish", wallTime: Date.now(), download: entry });
125
129
  }
126
130
  _clearCollectedArtifacts() {
127
131
  this._consoleMessages.length = 0;
128
- this._recentConsoleMessages.length = 0;
132
+ this._downloads.length = 0;
129
133
  this._requests.clear();
134
+ this._eventEntries.length = 0;
135
+ this._recentEventEntries.length = 0;
136
+ }
137
+ _handleRequest(request) {
138
+ this._requests.add(request);
139
+ this._addLogEntry({ type: "request", wallTime: Date.now(), request });
130
140
  }
131
141
  _handleConsoleMessage(message) {
132
142
  this._consoleMessages.push(message);
133
- this._recentConsoleMessages.push(message);
143
+ this._addLogEntry({ type: "console", wallTime: Date.now(), message });
144
+ }
145
+ _addLogEntry(entry) {
146
+ this._eventEntries.push(entry);
147
+ this._recentEventEntries.push(entry);
134
148
  }
135
149
  _onClose() {
136
150
  this._clearCollectedArtifacts();
137
151
  this._onPageClose(this);
138
152
  }
139
- async updateTitle() {
153
+ async headerSnapshot() {
154
+ let title;
140
155
  await this._raceAgainstModalStates(async () => {
141
- this._lastTitle = await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.title());
156
+ title = await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.title());
142
157
  });
143
- }
144
- lastTitle() {
145
- return this._lastTitle;
158
+ if (this._lastHeader.title !== title || this._lastHeader.url !== this.page.url() || this._lastHeader.current !== this.isCurrentTab()) {
159
+ this._lastHeader = { title: title ?? "", url: this.page.url(), current: this.isCurrentTab() };
160
+ return { ...this._lastHeader, changed: true };
161
+ }
162
+ return { ...this._lastHeader, changed: false };
146
163
  }
147
164
  isCurrentTab() {
148
165
  return this === this.context.currentTab();
@@ -175,37 +192,40 @@ class Tab extends import_events.EventEmitter {
175
192
  await this._initializedPromise;
176
193
  return this._consoleMessages.filter((message) => shouldIncludeMessage(level, message.type));
177
194
  }
195
+ async clearConsoleMessages() {
196
+ await this._initializedPromise;
197
+ this._consoleMessages.length = 0;
198
+ }
178
199
  async requests() {
179
200
  await this._initializedPromise;
180
201
  return this._requests;
181
202
  }
203
+ async clearRequests() {
204
+ await this._initializedPromise;
205
+ this._requests.clear();
206
+ }
182
207
  async captureSnapshot() {
183
208
  await this._initializedPromise;
184
209
  let tabSnapshot;
185
210
  const modalStates = await this._raceAgainstModalStates(async () => {
186
211
  const snapshot = await this.page._snapshotForAI({ track: "response" });
187
212
  tabSnapshot = {
188
- url: this.page.url(),
189
- title: await this.page.title(),
190
213
  ariaSnapshot: snapshot.full,
191
214
  ariaSnapshotDiff: this._needsFullSnapshot ? void 0 : snapshot.incremental,
192
215
  modalStates: [],
193
- consoleMessages: [],
194
- downloads: this._downloads
216
+ events: []
195
217
  };
196
218
  });
197
219
  if (tabSnapshot) {
198
- tabSnapshot.consoleMessages = this._recentConsoleMessages.filter((message) => shouldIncludeMessage(this.context.config.console.level, message.type));
199
- this._recentConsoleMessages = [];
220
+ tabSnapshot.events = this._recentEventEntries;
221
+ this._recentEventEntries = [];
200
222
  }
201
223
  this._needsFullSnapshot = !tabSnapshot;
202
224
  return tabSnapshot ?? {
203
- url: this.page.url(),
204
- title: "",
205
225
  ariaSnapshot: "",
226
+ ariaSnapshotDiff: "",
206
227
  modalStates,
207
- consoleMessages: [],
208
- downloads: []
228
+ events: []
209
229
  };
210
230
  }
211
231
  _javaScriptBlocked() {
@@ -279,12 +299,12 @@ function pageErrorToConsoleMessage(errorOrValue) {
279
299
  toString: () => String(errorOrValue)
280
300
  };
281
301
  }
282
- function renderModalStates(modalStates) {
302
+ function renderModalStates(config, modalStates) {
283
303
  const result = [];
284
304
  if (modalStates.length === 0)
285
305
  result.push("- There is no modal state present");
286
306
  for (const state of modalStates)
287
- result.push(`- [${state.description}]: can be handled by the "${state.clearedBy}" tool`);
307
+ result.push(`- [${state.description}]: can be handled by ${config.skillMode ? state.clearedBy.skill : state.clearedBy.tool}`);
288
308
  return result;
289
309
  }
290
310
  const consoleMessageLevels = ["error", "warning", "info", "debug"];
@@ -326,5 +346,6 @@ const tabSymbol = Symbol("tabSymbol");
326
346
  0 && (module.exports = {
327
347
  Tab,
328
348
  TabEvents,
329
- renderModalStates
349
+ renderModalStates,
350
+ shouldIncludeMessage
330
351
  });
@@ -18,15 +18,15 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var common_exports = {};
20
20
  __export(common_exports, {
21
- baseSchema: () => baseSchema,
21
+ baseSchema: () => import_schema2.baseSchema,
22
22
  default: () => common_default
23
23
  });
24
24
  module.exports = __toCommonJS(common_exports);
25
25
  var import_mcpBundle = require("../../../mcpBundle");
26
26
  var import_tool = require("./tool");
27
- const baseSchema = import_mcpBundle.z.object({
28
- toolText: import_mcpBundle.z.string().describe("A human-readable description of the action to perform by the tool.")
29
- });
27
+ var import_response = require("../response");
28
+ var import_schema = require("./schema");
29
+ var import_schema2 = require("./schema");
30
30
  const close = (0, import_tool.defineTool)({
31
31
  capability: "core",
32
32
  schema: {
@@ -38,7 +38,8 @@ const close = (0, import_tool.defineTool)({
38
38
  },
39
39
  handle: async (context, params, response) => {
40
40
  await context.closeBrowserContext();
41
- response.setIncludeTabs();
41
+ const result = (0, import_response.renderTabsMarkdown)([]);
42
+ response.addTextResult(result.join("\n"));
42
43
  response.addCode(`await page.close()`);
43
44
  }
44
45
  });
@@ -48,7 +49,7 @@ const resize = (0, import_tool.defineTabTool)({
48
49
  name: "browser_resize",
49
50
  title: "Resize browser window",
50
51
  description: "Resize the browser window",
51
- inputSchema: baseSchema.extend({
52
+ inputSchema: import_schema.baseSchema.extend({
52
53
  width: import_mcpBundle.z.number().describe("Width of the browser window"),
53
54
  height: import_mcpBundle.z.number().describe("Height of the browser window")
54
55
  }),
@@ -56,9 +57,7 @@ const resize = (0, import_tool.defineTabTool)({
56
57
  },
57
58
  handle: async (tab, params, response) => {
58
59
  response.addCode(`await page.setViewportSize({ width: ${params.width}, height: ${params.height} });`);
59
- await tab.waitForCompletion(async () => {
60
- await tab.page.setViewportSize({ width: params.width, height: params.height });
61
- });
60
+ await tab.page.setViewportSize({ width: params.width, height: params.height });
62
61
  }
63
62
  });
64
63
  var common_default = [
@@ -30,15 +30,32 @@ const console = (0, import_tool.defineTabTool)({
30
30
  title: "Get console messages",
31
31
  description: "Returns all console messages",
32
32
  inputSchema: import_mcpBundle.z.object({
33
- level: import_mcpBundle.z.enum(["error", "warning", "info", "debug"]).default("info").describe('Level of the console messages to return. Each level includes the messages of more severe levels. Defaults to "info".')
33
+ level: import_mcpBundle.z.enum(["error", "warning", "info", "debug"]).default("info").describe('Level of the console messages to return. Each level includes the messages of more severe levels. Defaults to "info".'),
34
+ filename: import_mcpBundle.z.string().optional().describe("Filename to save the console messages to. If not provided, messages are returned as text.")
34
35
  }),
35
36
  type: "readOnly"
36
37
  },
37
38
  handle: async (tab, params, response) => {
38
39
  const messages = await tab.consoleMessages(params.level);
39
- messages.map((message) => response.addResult(message.toString()));
40
+ const text = messages.map((message) => message.toString()).join("\n");
41
+ await response.addResult("Console", text, { prefix: "console", ext: "log", suggestedFilename: params.filename });
42
+ }
43
+ });
44
+ const consoleClear = (0, import_tool.defineTabTool)({
45
+ capability: "core",
46
+ skillOnly: true,
47
+ schema: {
48
+ name: "browser_console_clear",
49
+ title: "Clear console messages",
50
+ description: "Clear all console messages",
51
+ inputSchema: import_mcpBundle.z.object({}),
52
+ type: "readOnly"
53
+ },
54
+ handle: async (tab) => {
55
+ await tab.clearConsoleMessages();
40
56
  }
41
57
  });
42
58
  var console_default = [
43
- console
59
+ console,
60
+ consoleClear
44
61
  ];
@@ -24,21 +24,20 @@ __export(dialogs_exports, {
24
24
  module.exports = __toCommonJS(dialogs_exports);
25
25
  var import_mcpBundle = require("../../../mcpBundle");
26
26
  var import_tool = require("./tool");
27
- var import_common = require("./common");
27
+ var import_schema = require("./schema");
28
28
  const handleDialog = (0, import_tool.defineTabTool)({
29
29
  capability: "core",
30
30
  schema: {
31
31
  name: "browser_handle_dialog",
32
32
  title: "Handle a dialog",
33
33
  description: "Handle a dialog",
34
- inputSchema: import_common.baseSchema.extend({
34
+ inputSchema: import_schema.baseSchema.extend({
35
35
  accept: import_mcpBundle.z.boolean().describe("Whether to accept the dialog."),
36
36
  promptText: import_mcpBundle.z.string().optional().describe("The text of the prompt in case of a prompt dialog.")
37
37
  }),
38
38
  type: "action"
39
39
  },
40
40
  handle: async (tab, params, response) => {
41
- response.setIncludeSnapshot();
42
41
  const dialogState = tab.modalStates().find((state) => state.type === "dialog");
43
42
  if (!dialogState)
44
43
  throw new Error("No dialog visible");
@@ -24,8 +24,8 @@ module.exports = __toCommonJS(evaluate_exports);
24
24
  var import_mcpBundle = require("../../../mcpBundle");
25
25
  var import_utils = require("playwright-core/lib/utils");
26
26
  var import_tool = require("./tool");
27
- var import_common = require("./common");
28
- const evaluateSchema = import_common.baseSchema.extend({
27
+ var import_schema = require("./schema");
28
+ const evaluateSchema = import_schema.baseSchema.extend({
29
29
  function: import_mcpBundle.z.string().describe("() => { /* code */ } or (element) => { /* code */ } when element is provided"),
30
30
  element: import_mcpBundle.z.string().optional().describe("Human-readable element description used to obtain permission to interact with the element"),
31
31
  ref: import_mcpBundle.z.string().optional().describe("Exact target element reference from the page snapshot")
@@ -40,10 +40,11 @@ const evaluate = (0, import_tool.defineTabTool)({
40
40
  type: "action"
41
41
  },
42
42
  handle: async (tab, params, response) => {
43
- response.setIncludeSnapshot();
44
43
  let locator;
45
- if (params.ref && params.element) {
46
- locator = await tab.refLocator({ ref: params.ref, element: params.element });
44
+ if (!params.function.includes("=>"))
45
+ params.function = `() => (${params.function})`;
46
+ if (params.ref) {
47
+ locator = await tab.refLocator({ ref: params.ref, element: params.element || "element" });
47
48
  response.addCode(`await page.${locator.resolved}.evaluate(${(0, import_utils.escapeWithQuotes)(params.function)});`);
48
49
  } else {
49
50
  response.addCode(`await page.evaluate(${(0, import_utils.escapeWithQuotes)(params.function)});`);
@@ -51,7 +52,8 @@ const evaluate = (0, import_tool.defineTabTool)({
51
52
  await tab.waitForCompletion(async () => {
52
53
  const receiver = locator?.locator ?? tab.page;
53
54
  const result = await receiver._evaluateFunction(params.function);
54
- response.addResult(JSON.stringify(result, null, 2) || "undefined");
55
+ const text = JSON.stringify(result, null, 2) || "undefined";
56
+ response.addTextResult(text);
55
57
  });
56
58
  }
57
59
  });
@@ -24,14 +24,14 @@ __export(files_exports, {
24
24
  module.exports = __toCommonJS(files_exports);
25
25
  var import_mcpBundle = require("../../../mcpBundle");
26
26
  var import_tool = require("./tool");
27
- var import_common = require("./common");
27
+ var import_schema = require("./schema");
28
28
  const uploadFile = (0, import_tool.defineTabTool)({
29
29
  capability: "core",
30
30
  schema: {
31
31
  name: "browser_file_upload",
32
32
  title: "Upload files",
33
33
  description: "Upload one or multiple files",
34
- inputSchema: import_common.baseSchema.extend({
34
+ inputSchema: import_schema.baseSchema.extend({
35
35
  paths: import_mcpBundle.z.array(import_mcpBundle.z.string()).optional().describe("The absolute paths to the files to upload. Can be single file or multiple files. If omitted, file chooser is cancelled.")
36
36
  }),
37
37
  type: "action"
@@ -24,14 +24,14 @@ module.exports = __toCommonJS(form_exports);
24
24
  var import_mcpBundle = require("../../../mcpBundle");
25
25
  var import_utils = require("playwright-core/lib/utils");
26
26
  var import_tool = require("./tool");
27
- var import_common = require("./common");
27
+ var import_schema = require("./schema");
28
28
  const fillForm = (0, import_tool.defineTabTool)({
29
29
  capability: "core",
30
30
  schema: {
31
31
  name: "browser_fill_form",
32
32
  title: "Fill form",
33
33
  description: "Fill multiple form fields",
34
- inputSchema: import_common.baseSchema.extend({
34
+ inputSchema: import_schema.baseSchema.extend({
35
35
  fields: import_mcpBundle.z.array(import_mcpBundle.z.object({
36
36
  name: import_mcpBundle.z.string().describe("Human-readable field name"),
37
37
  type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the field"),
@@ -35,6 +35,7 @@ var import_child_process = require("child_process");
35
35
  var import_path = __toESM(require("path"));
36
36
  var import_mcpBundle = require("../../../mcpBundle");
37
37
  var import_tool = require("./tool");
38
+ var import_response = require("../response");
38
39
  const install = (0, import_tool.defineTool)({
39
40
  capability: "core-install",
40
41
  schema: {
@@ -61,7 +62,9 @@ const install = (0, import_tool.defineTool)({
61
62
  reject(new Error(`Failed to install browser: ${output.join("")}`));
62
63
  });
63
64
  });
64
- response.setIncludeTabs();
65
+ const tabHeaders = await Promise.all(context.tabs().map((tab) => tab.headerSnapshot()));
66
+ const result = (0, import_response.renderTabsMarkdown)(tabHeaders);
67
+ response.addTextResult(result.join("\n"));
65
68
  }
66
69
  });
67
70
  var install_default = [
@@ -24,25 +24,55 @@ module.exports = __toCommonJS(keyboard_exports);
24
24
  var import_mcpBundle = require("../../../mcpBundle");
25
25
  var import_tool = require("./tool");
26
26
  var import_snapshot = require("./snapshot");
27
- var import_common = require("./common");
28
- const pressKey = (0, import_tool.defineTabTool)({
29
- capability: "core",
27
+ var import_schema = require("./schema");
28
+ const press = (0, import_tool.defineTabTool)({
29
+ capability: "core-input",
30
30
  schema: {
31
31
  name: "browser_press_key",
32
32
  title: "Press a key",
33
33
  description: "Press a key on the keyboard",
34
- inputSchema: import_common.baseSchema.extend({
34
+ inputSchema: import_schema.baseSchema.extend({
35
35
  key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`")
36
36
  }),
37
37
  type: "input"
38
38
  },
39
39
  handle: async (tab, params, response) => {
40
- response.setIncludeSnapshot();
41
40
  response.addCode(`// Press ${params.key}`);
42
41
  response.addCode(`await page.keyboard.press('${params.key}');`);
43
- await tab.waitForCompletion(async () => {
42
+ if (params.key === "Enter") {
43
+ response.setIncludeSnapshot();
44
+ await tab.waitForCompletion(async () => {
45
+ await tab.page.keyboard.press("Enter");
46
+ });
47
+ } else {
44
48
  await tab.page.keyboard.press(params.key);
45
- });
49
+ }
50
+ }
51
+ });
52
+ const pressSequentially = (0, import_tool.defineTabTool)({
53
+ capability: "core-input",
54
+ skillOnly: true,
55
+ schema: {
56
+ name: "browser_press_sequentially",
57
+ title: "Type text key by key",
58
+ description: "Type text key by key on the keyboard",
59
+ inputSchema: import_schema.baseSchema.extend({
60
+ text: import_mcpBundle.z.string().describe("Text to type"),
61
+ submit: import_mcpBundle.z.boolean().optional().describe("Whether to submit entered text (press Enter after)")
62
+ }),
63
+ type: "input"
64
+ },
65
+ handle: async (tab, params, response) => {
66
+ response.addCode(`// Press ${params.text}`);
67
+ response.addCode(`await page.keyboard.type('${params.text}');`);
68
+ await tab.page.keyboard.type(params.text);
69
+ if (params.submit) {
70
+ response.addCode(`await page.keyboard.press('Enter');`);
71
+ response.setIncludeSnapshot();
72
+ await tab.waitForCompletion(async () => {
73
+ await tab.page.keyboard.press("Enter");
74
+ });
75
+ }
46
76
  }
47
77
  });
48
78
  const typeSchema = import_snapshot.elementSchema.extend({
@@ -51,7 +81,7 @@ const typeSchema = import_snapshot.elementSchema.extend({
51
81
  slowly: import_mcpBundle.z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
52
82
  });
53
83
  const type = (0, import_tool.defineTabTool)({
54
- capability: "core",
84
+ capability: "core-input",
55
85
  schema: {
56
86
  name: "browser_type",
57
87
  title: "Type text",
@@ -79,7 +109,44 @@ const type = (0, import_tool.defineTabTool)({
79
109
  });
80
110
  }
81
111
  });
112
+ const keydown = (0, import_tool.defineTabTool)({
113
+ capability: "core-input",
114
+ skillOnly: true,
115
+ schema: {
116
+ name: "browser_keydown",
117
+ title: "Press a key down",
118
+ description: "Press a key down on the keyboard",
119
+ inputSchema: import_schema.baseSchema.extend({
120
+ key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`")
121
+ }),
122
+ type: "input"
123
+ },
124
+ handle: async (tab, params, response) => {
125
+ response.addCode(`await page.keyboard.down('${params.key}');`);
126
+ await tab.page.keyboard.down(params.key);
127
+ }
128
+ });
129
+ const keyup = (0, import_tool.defineTabTool)({
130
+ capability: "core-input",
131
+ skillOnly: true,
132
+ schema: {
133
+ name: "browser_keyup",
134
+ title: "Press a key up",
135
+ description: "Press a key up on the keyboard",
136
+ inputSchema: import_schema.baseSchema.extend({
137
+ key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`")
138
+ }),
139
+ type: "input"
140
+ },
141
+ handle: async (tab, params, response) => {
142
+ response.addCode(`await page.keyboard.up('${params.key}');`);
143
+ await tab.page.keyboard.up(params.key);
144
+ }
145
+ });
82
146
  var keyboard_default = [
83
- pressKey,
84
- type
147
+ press,
148
+ type,
149
+ pressSequentially,
150
+ keydown,
151
+ keyup
85
152
  ];
@@ -23,16 +23,13 @@ __export(mouse_exports, {
23
23
  module.exports = __toCommonJS(mouse_exports);
24
24
  var import_mcpBundle = require("../../../mcpBundle");
25
25
  var import_tool = require("./tool");
26
- const elementSchema = import_mcpBundle.z.object({
27
- element: import_mcpBundle.z.string().describe("Human-readable element description used to obtain permission to interact with the element")
28
- });
29
26
  const mouseMove = (0, import_tool.defineTabTool)({
30
27
  capability: "vision",
31
28
  schema: {
32
29
  name: "browser_mouse_move_xy",
33
30
  title: "Move mouse",
34
31
  description: "Move mouse to a given position",
35
- inputSchema: elementSchema.extend({
32
+ inputSchema: import_mcpBundle.z.object({
36
33
  x: import_mcpBundle.z.number().describe("X coordinate"),
37
34
  y: import_mcpBundle.z.number().describe("Y coordinate")
38
35
  }),
@@ -46,13 +43,65 @@ const mouseMove = (0, import_tool.defineTabTool)({
46
43
  });
47
44
  }
48
45
  });
46
+ const mouseDown = (0, import_tool.defineTabTool)({
47
+ capability: "vision",
48
+ schema: {
49
+ name: "browser_mouse_down",
50
+ title: "Press mouse down",
51
+ description: "Press mouse down",
52
+ inputSchema: import_mcpBundle.z.object({
53
+ button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to press, defaults to left")
54
+ }),
55
+ type: "input"
56
+ },
57
+ handle: async (tab, params, response) => {
58
+ response.addCode(`// Press mouse down`);
59
+ response.addCode(`await page.mouse.down({ button: '${params.button}' });`);
60
+ await tab.page.mouse.down({ button: params.button });
61
+ }
62
+ });
63
+ const mouseUp = (0, import_tool.defineTabTool)({
64
+ capability: "vision",
65
+ schema: {
66
+ name: "browser_mouse_up",
67
+ title: "Press mouse up",
68
+ description: "Press mouse up",
69
+ inputSchema: import_mcpBundle.z.object({
70
+ button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to press, defaults to left")
71
+ }),
72
+ type: "input"
73
+ },
74
+ handle: async (tab, params, response) => {
75
+ response.addCode(`// Press mouse up`);
76
+ response.addCode(`await page.mouse.up({ button: '${params.button}' });`);
77
+ await tab.page.mouse.up({ button: params.button });
78
+ }
79
+ });
80
+ const mouseWheel = (0, import_tool.defineTabTool)({
81
+ capability: "vision",
82
+ schema: {
83
+ name: "browser_mouse_wheel",
84
+ title: "Scroll mouse wheel",
85
+ description: "Scroll mouse wheel",
86
+ inputSchema: import_mcpBundle.z.object({
87
+ deltaX: import_mcpBundle.z.number().default(0).describe("X delta"),
88
+ deltaY: import_mcpBundle.z.number().default(0).describe("Y delta")
89
+ }),
90
+ type: "input"
91
+ },
92
+ handle: async (tab, params, response) => {
93
+ response.addCode(`// Scroll mouse wheel`);
94
+ response.addCode(`await page.mouse.wheel(${params.deltaX}, ${params.deltaY});`);
95
+ await tab.page.mouse.wheel(params.deltaX, params.deltaY);
96
+ }
97
+ });
49
98
  const mouseClick = (0, import_tool.defineTabTool)({
50
99
  capability: "vision",
51
100
  schema: {
52
101
  name: "browser_mouse_click_xy",
53
102
  title: "Click",
54
103
  description: "Click left mouse button at a given position",
55
- inputSchema: elementSchema.extend({
104
+ inputSchema: import_mcpBundle.z.object({
56
105
  x: import_mcpBundle.z.number().describe("X coordinate"),
57
106
  y: import_mcpBundle.z.number().describe("Y coordinate")
58
107
  }),
@@ -77,7 +126,7 @@ const mouseDrag = (0, import_tool.defineTabTool)({
77
126
  name: "browser_mouse_drag_xy",
78
127
  title: "Drag mouse",
79
128
  description: "Drag left mouse button to a given position",
80
- inputSchema: elementSchema.extend({
129
+ inputSchema: import_mcpBundle.z.object({
81
130
  startX: import_mcpBundle.z.number().describe("Start X coordinate"),
82
131
  startY: import_mcpBundle.z.number().describe("Start Y coordinate"),
83
132
  endX: import_mcpBundle.z.number().describe("End X coordinate"),
@@ -103,5 +152,8 @@ const mouseDrag = (0, import_tool.defineTabTool)({
103
152
  var mouse_default = [
104
153
  mouseMove,
105
154
  mouseClick,
106
- mouseDrag
155
+ mouseDrag,
156
+ mouseDown,
157
+ mouseUp,
158
+ mouseWheel
107
159
  ];