@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.
- package/lib/mcp/browser/browserContextFactory.js +12 -12
- package/lib/mcp/browser/browserServerBackend.js +24 -12
- package/lib/mcp/browser/config.js +37 -7
- package/lib/mcp/browser/context.js +13 -61
- package/lib/mcp/browser/response.js +183 -251
- package/lib/mcp/browser/sessionLog.js +19 -104
- package/lib/mcp/browser/tab.js +49 -28
- package/lib/mcp/browser/tools/common.js +8 -9
- package/lib/mcp/browser/tools/console.js +20 -3
- package/lib/mcp/browser/tools/dialogs.js +2 -3
- package/lib/mcp/browser/tools/evaluate.js +8 -6
- package/lib/mcp/browser/tools/files.js +2 -2
- package/lib/mcp/browser/tools/form.js +2 -2
- package/lib/mcp/browser/tools/install.js +4 -1
- package/lib/mcp/browser/tools/keyboard.js +77 -10
- package/lib/mcp/browser/tools/mouse.js +59 -7
- package/lib/mcp/browser/tools/navigate.js +51 -8
- package/lib/mcp/browser/tools/network.js +21 -3
- package/lib/mcp/browser/tools/pdf.js +4 -3
- package/lib/mcp/browser/tools/runCode.js +8 -12
- package/lib/mcp/browser/tools/schema.js +31 -0
- package/lib/mcp/browser/tools/screenshot.js +10 -28
- package/lib/mcp/browser/tools/snapshot.js +40 -24
- package/lib/mcp/browser/tools/tabs.js +10 -10
- package/lib/mcp/browser/tools/tool.js +3 -6
- package/lib/mcp/browser/tools/tracing.js +3 -3
- package/lib/mcp/browser/tools/utils.js +2 -2
- package/lib/mcp/browser/tools/verify.js +9 -9
- package/lib/mcp/browser/tools/wait.js +3 -3
- package/lib/mcp/browser/tools.js +2 -2
- package/lib/mcp/extension/extensionContextFactory.js +2 -2
- package/lib/mcp/program.js +3 -2
- package/lib/mcp/terminal/cli.js +4 -216
- package/lib/mcp/terminal/command.js +56 -0
- package/lib/mcp/terminal/commands.js +528 -0
- package/lib/mcp/terminal/daemon.js +42 -25
- package/lib/mcp/terminal/helpGenerator.js +152 -0
- package/lib/mcp/terminal/program.js +434 -0
- package/lib/mcp/terminal/socketConnection.js +2 -4
- package/lib/mcpBundleImpl/index.js +44 -44
- package/lib/util.js +3 -6
- package/package.json +1 -1
package/lib/mcp/browser/tab.js
CHANGED
|
@@ -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.
|
|
40
|
+
this._lastHeader = { title: "about:blank", url: "about:blank", current: false };
|
|
40
41
|
this._consoleMessages = [];
|
|
41
|
-
this.
|
|
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.
|
|
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",
|
|
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.
|
|
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.
|
|
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
|
|
153
|
+
async headerSnapshot() {
|
|
154
|
+
let title;
|
|
140
155
|
await this._raceAgainstModalStates(async () => {
|
|
141
|
-
|
|
156
|
+
title = await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.title());
|
|
142
157
|
});
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
194
|
-
downloads: this._downloads
|
|
216
|
+
events: []
|
|
195
217
|
};
|
|
196
218
|
});
|
|
197
219
|
if (tabSnapshot) {
|
|
198
|
-
tabSnapshot.
|
|
199
|
-
this.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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.
|
|
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) =>
|
|
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
|
|
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:
|
|
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
|
|
28
|
-
const evaluateSchema =
|
|
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.
|
|
46
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
28
|
-
const
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
];
|