@everydaydevopsio/pilot 0.5.2 → 0.6.1
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/.mcp.json +9 -0
- package/AGENTS.md +9 -0
- package/CHANGELOG.md +64 -0
- package/CLAUDE.md +7 -7
- package/README.md +282 -69
- package/dist/browser/browser-manager.d.ts +60 -0
- package/dist/browser/browser-manager.d.ts.map +1 -0
- package/dist/browser/browser-manager.js +355 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/chrome-launcher.d.ts +31 -0
- package/dist/browser/chrome-launcher.d.ts.map +1 -0
- package/dist/browser/chrome-launcher.js +225 -0
- package/dist/browser/chrome-launcher.js.map +1 -0
- package/dist/browser/connection.d.ts +23 -0
- package/dist/browser/connection.d.ts.map +1 -0
- package/dist/browser/connection.js +53 -0
- package/dist/browser/connection.js.map +1 -0
- package/dist/browser/events.d.ts +9 -0
- package/dist/browser/events.d.ts.map +1 -0
- package/dist/browser/events.js +99 -0
- package/dist/browser/events.js.map +1 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/inspect/element-ref.d.ts +23 -0
- package/dist/browser/inspect/element-ref.d.ts.map +1 -0
- package/dist/browser/inspect/element-ref.js +52 -0
- package/dist/browser/inspect/element-ref.js.map +1 -0
- package/dist/browser/inspect/snapshot.d.ts +11 -0
- package/dist/browser/inspect/snapshot.d.ts.map +1 -0
- package/dist/browser/inspect/snapshot.js +282 -0
- package/dist/browser/inspect/snapshot.js.map +1 -0
- package/dist/browser/inspect/styles.d.ts +45 -0
- package/dist/browser/inspect/styles.d.ts.map +1 -0
- package/dist/browser/inspect/styles.js +190 -0
- package/dist/browser/inspect/styles.js.map +1 -0
- package/dist/browser/inspect/types.d.ts +35 -0
- package/dist/browser/inspect/types.d.ts.map +1 -0
- package/dist/browser/inspect/types.js +2 -0
- package/dist/browser/inspect/types.js.map +1 -0
- package/dist/browser/interaction/dialogs.d.ts +18 -0
- package/dist/browser/interaction/dialogs.d.ts.map +1 -0
- package/dist/browser/interaction/dialogs.js +35 -0
- package/dist/browser/interaction/dialogs.js.map +1 -0
- package/dist/browser/interaction/downloads.d.ts +23 -0
- package/dist/browser/interaction/downloads.d.ts.map +1 -0
- package/dist/browser/interaction/downloads.js +87 -0
- package/dist/browser/interaction/downloads.js.map +1 -0
- package/dist/browser/interaction/events.d.ts +17 -0
- package/dist/browser/interaction/events.d.ts.map +1 -0
- package/dist/browser/interaction/events.js +66 -0
- package/dist/browser/interaction/events.js.map +1 -0
- package/dist/browser/interaction/ref-resolver.d.ts +18 -0
- package/dist/browser/interaction/ref-resolver.d.ts.map +1 -0
- package/dist/browser/interaction/ref-resolver.js +32 -0
- package/dist/browser/interaction/ref-resolver.js.map +1 -0
- package/dist/browser/interaction/uploads.d.ts +4 -0
- package/dist/browser/interaction/uploads.d.ts.map +1 -0
- package/dist/browser/interaction/uploads.js +43 -0
- package/dist/browser/interaction/uploads.js.map +1 -0
- package/dist/browser/network/network-buffer.d.ts +19 -0
- package/dist/browser/network/network-buffer.d.ts.map +1 -0
- package/dist/browser/network/network-buffer.js +118 -0
- package/dist/browser/network/network-buffer.js.map +1 -0
- package/dist/browser/network/network-monitor.d.ts +8 -0
- package/dist/browser/network/network-monitor.d.ts.map +1 -0
- package/dist/browser/network/network-monitor.js +85 -0
- package/dist/browser/network/network-monitor.js.map +1 -0
- package/dist/browser/network/redaction.d.ts +3 -0
- package/dist/browser/network/redaction.d.ts.map +1 -0
- package/dist/browser/network/redaction.js +36 -0
- package/dist/browser/network/redaction.js.map +1 -0
- package/dist/browser/network/types.d.ts +45 -0
- package/dist/browser/network/types.d.ts.map +1 -0
- package/dist/browser/network/types.js +2 -0
- package/dist/browser/network/types.js.map +1 -0
- package/dist/browser/performance/analyze.d.ts +5 -0
- package/dist/browser/performance/analyze.d.ts.map +1 -0
- package/dist/browser/performance/analyze.js +230 -0
- package/dist/browser/performance/analyze.js.map +1 -0
- package/dist/browser/performance/trace.d.ts +10 -0
- package/dist/browser/performance/trace.d.ts.map +1 -0
- package/dist/browser/performance/trace.js +38 -0
- package/dist/browser/performance/trace.js.map +1 -0
- package/dist/browser/performance/types.d.ts +31 -0
- package/dist/browser/performance/types.d.ts.map +1 -0
- package/dist/browser/performance/types.js +2 -0
- package/dist/browser/performance/types.js.map +1 -0
- package/dist/browser/preflight.d.ts +20 -0
- package/dist/browser/preflight.d.ts.map +1 -0
- package/dist/browser/preflight.js +105 -0
- package/dist/browser/preflight.js.map +1 -0
- package/dist/browser/security/origins.d.ts +18 -0
- package/dist/browser/security/origins.d.ts.map +1 -0
- package/dist/browser/security/origins.js +84 -0
- package/dist/browser/security/origins.js.map +1 -0
- package/dist/browser/tabs.d.ts +15 -0
- package/dist/browser/tabs.d.ts.map +1 -0
- package/dist/browser/tabs.js +71 -0
- package/dist/browser/tabs.js.map +1 -0
- package/dist/browser/types.d.ts +32 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/browser.d.ts +2 -99
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -653
- package/dist/browser.js.map +1 -1
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +33 -48
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/linux-check.d.ts +2 -0
- package/dist/cli/linux-check.d.ts.map +1 -0
- package/dist/cli/linux-check.js +20 -0
- package/dist/cli/linux-check.js.map +1 -0
- package/dist/cli/skill-template.d.ts +1 -1
- package/dist/cli/skill-template.d.ts.map +1 -1
- package/dist/cli/skill-template.js +3 -113
- package/dist/cli/skill-template.js.map +1 -1
- package/dist/commands/check.d.ts +17 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +38 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/click.d.ts +3 -1
- package/dist/commands/click.d.ts.map +1 -1
- package/dist/commands/click.js +16 -4
- package/dist/commands/click.js.map +1 -1
- package/dist/commands/connect.d.ts +14 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +19 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/dialog.d.ts +19 -0
- package/dist/commands/dialog.d.ts.map +1 -0
- package/dist/commands/dialog.js +51 -0
- package/dist/commands/dialog.js.map +1 -0
- package/dist/commands/downloads.d.ts +30 -0
- package/dist/commands/downloads.d.ts.map +1 -0
- package/dist/commands/downloads.js +66 -0
- package/dist/commands/downloads.js.map +1 -0
- package/dist/commands/fill.d.ts +16 -0
- package/dist/commands/fill.d.ts.map +1 -0
- package/dist/commands/fill.js +15 -0
- package/dist/commands/fill.js.map +1 -0
- package/dist/commands/find.d.ts +14 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +26 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/hover.d.ts +13 -0
- package/dist/commands/hover.d.ts.map +1 -0
- package/dist/commands/hover.js +24 -0
- package/dist/commands/hover.js.map +1 -0
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +13 -0
- package/dist/commands/navigate.js.map +1 -1
- package/dist/commands/network.d.ts +33 -0
- package/dist/commands/network.d.ts.map +1 -0
- package/dist/commands/network.js +84 -0
- package/dist/commands/network.js.map +1 -0
- package/dist/commands/performance.d.ts +12 -0
- package/dist/commands/performance.d.ts.map +1 -0
- package/dist/commands/performance.js +26 -0
- package/dist/commands/performance.js.map +1 -0
- package/dist/commands/press_key.d.ts +10 -0
- package/dist/commands/press_key.d.ts.map +1 -0
- package/dist/commands/press_key.js +103 -0
- package/dist/commands/press_key.js.map +1 -0
- package/dist/commands/scroll.d.ts +21 -0
- package/dist/commands/scroll.d.ts.map +1 -0
- package/dist/commands/scroll.js +54 -0
- package/dist/commands/scroll.js.map +1 -0
- package/dist/commands/select.d.ts +18 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/select.js +53 -0
- package/dist/commands/select.js.map +1 -0
- package/dist/commands/snapshot.d.ts +9 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +7 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/styles.d.ts +13 -0
- package/dist/commands/styles.d.ts.map +1 -0
- package/dist/commands/styles.js +7 -0
- package/dist/commands/styles.js.map +1 -0
- package/dist/commands/type.d.ts +3 -1
- package/dist/commands/type.d.ts.map +1 -1
- package/dist/commands/type.js +11 -2
- package/dist/commands/type.js.map +1 -1
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +13 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/mcp/console-buffer.d.ts +9 -0
- package/dist/mcp/console-buffer.d.ts.map +1 -1
- package/dist/mcp/console-buffer.js.map +1 -1
- package/dist/mcp/index.js +20 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +63 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/browser.d.ts.map +1 -1
- package/dist/mcp/tools/browser.js +109 -11
- package/dist/mcp/tools/browser.js.map +1 -1
- package/dist/mcp/tools/connect.d.ts +5 -0
- package/dist/mcp/tools/connect.d.ts.map +1 -0
- package/dist/mcp/tools/connect.js +48 -0
- package/dist/mcp/tools/connect.js.map +1 -0
- package/dist/mcp/tools/files.d.ts +4 -0
- package/dist/mcp/tools/files.d.ts.map +1 -0
- package/dist/mcp/tools/files.js +85 -0
- package/dist/mcp/tools/files.js.map +1 -0
- package/dist/mcp/tools/interaction.d.ts +4 -0
- package/dist/mcp/tools/interaction.d.ts.map +1 -0
- package/dist/mcp/tools/interaction.js +176 -0
- package/dist/mcp/tools/interaction.js.map +1 -0
- package/dist/mcp/tools/names.d.ts +1 -1
- package/dist/mcp/tools/names.d.ts.map +1 -1
- package/dist/mcp/tools/names.js +19 -1
- package/dist/mcp/tools/names.js.map +1 -1
- package/dist/mcp/tools/network.d.ts +4 -0
- package/dist/mcp/tools/network.d.ts.map +1 -0
- package/dist/mcp/tools/network.js +68 -0
- package/dist/mcp/tools/network.js.map +1 -0
- package/dist/mcp/tools/performance.d.ts +4 -0
- package/dist/mcp/tools/performance.d.ts.map +1 -0
- package/dist/mcp/tools/performance.js +26 -0
- package/dist/mcp/tools/performance.js.map +1 -0
- package/dist/mcp/tools/runtime.d.ts +4 -0
- package/dist/mcp/tools/runtime.d.ts.map +1 -0
- package/dist/mcp/tools/runtime.js +128 -0
- package/dist/mcp/tools/runtime.js.map +1 -0
- package/dist/mcp/tools/snapshot.d.ts +4 -0
- package/dist/mcp/tools/snapshot.d.ts.map +1 -0
- package/dist/mcp/tools/snapshot.js +42 -0
- package/dist/mcp/tools/snapshot.js.map +1 -0
- package/dist/mcp/tools/styles.d.ts +4 -0
- package/dist/mcp/tools/styles.d.ts.map +1 -0
- package/dist/mcp/tools/styles.js +27 -0
- package/dist/mcp/tools/styles.js.map +1 -0
- package/dist/util/config.d.ts.map +1 -1
- package/dist/util/config.js +3 -2
- package/dist/util/config.js.map +1 -1
- package/package.json +5 -4
- package/skills/pilot/SKILL.md +48 -0
- package/src/browser/browser-manager.ts +465 -0
- package/src/browser/chrome-launcher.ts +282 -0
- package/src/browser/connection.ts +84 -0
- package/src/browser/events.ts +121 -0
- package/src/browser/index.ts +20 -0
- package/src/browser/inspect/element-ref.ts +68 -0
- package/src/browser/inspect/snapshot.ts +348 -0
- package/src/browser/inspect/styles.ts +258 -0
- package/src/browser/inspect/types.ts +37 -0
- package/src/browser/interaction/dialogs.ts +54 -0
- package/src/browser/interaction/downloads.ts +116 -0
- package/src/browser/interaction/events.ts +79 -0
- package/src/browser/interaction/ref-resolver.ts +53 -0
- package/src/browser/interaction/uploads.ts +60 -0
- package/src/browser/network/network-buffer.ts +133 -0
- package/src/browser/network/network-monitor.ts +107 -0
- package/src/browser/network/redaction.ts +42 -0
- package/src/browser/network/types.ts +47 -0
- package/src/browser/performance/analyze.ts +298 -0
- package/src/browser/performance/trace.ts +60 -0
- package/src/browser/performance/types.ts +34 -0
- package/src/browser/preflight.ts +144 -0
- package/src/browser/security/origins.ts +102 -0
- package/src/browser/tabs.ts +110 -0
- package/src/browser/types.ts +32 -0
- package/src/browser.ts +22 -798
- package/src/cli/init.ts +40 -49
- package/src/cli/linux-check.ts +23 -0
- package/src/cli/skill-template.ts +4 -113
- package/src/commands/check.ts +59 -0
- package/src/commands/click.ts +18 -4
- package/src/commands/connect.ts +40 -0
- package/src/commands/dialog.ts +79 -0
- package/src/commands/downloads.ts +111 -0
- package/src/commands/fill.ts +34 -0
- package/src/commands/find.ts +52 -0
- package/src/commands/hover.ts +42 -0
- package/src/commands/navigate.ts +20 -0
- package/src/commands/network.ts +141 -0
- package/src/commands/performance.ts +51 -0
- package/src/commands/press_key.ts +134 -0
- package/src/commands/scroll.ts +79 -0
- package/src/commands/select.ts +78 -0
- package/src/commands/snapshot.ts +18 -0
- package/src/commands/styles.ts +24 -0
- package/src/commands/type.ts +12 -2
- package/src/commands/upload.ts +36 -0
- package/src/mcp/console-buffer.ts +10 -0
- package/src/mcp/index.ts +24 -2
- package/src/mcp/server.ts +74 -2
- package/src/mcp/tools/browser.ts +125 -9
- package/src/mcp/tools/connect.ts +62 -0
- package/src/mcp/tools/files.ts +120 -0
- package/src/mcp/tools/interaction.ts +232 -0
- package/src/mcp/tools/names.ts +19 -1
- package/src/mcp/tools/network.ts +86 -0
- package/src/mcp/tools/performance.ts +40 -0
- package/src/mcp/tools/runtime.ts +164 -0
- package/src/mcp/tools/snapshot.ts +64 -0
- package/src/mcp/tools/styles.ts +41 -0
- package/src/util/config.ts +3 -2
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
export type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug';
|
|
2
2
|
|
|
3
|
+
export interface StackFrame {
|
|
4
|
+
url: string;
|
|
5
|
+
functionName: string;
|
|
6
|
+
lineNumber: number;
|
|
7
|
+
columnNumber: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
export interface ConsoleMessage {
|
|
4
11
|
level: ConsoleLevel;
|
|
5
12
|
text: string;
|
|
6
13
|
url: string;
|
|
7
14
|
lineNumber: number;
|
|
15
|
+
columnNumber?: number;
|
|
8
16
|
timestamp: number;
|
|
17
|
+
stackFrames?: StackFrame[];
|
|
18
|
+
isException?: boolean;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
export interface ConsoleFilter {
|
package/src/mcp/index.ts
CHANGED
|
@@ -28,8 +28,12 @@ async function run(): Promise<void> {
|
|
|
28
28
|
console.log('Usage: pilot [command] [options]');
|
|
29
29
|
console.log('');
|
|
30
30
|
console.log('Commands:');
|
|
31
|
+
console.log(' init [--agent claude|codex|both] [--force]');
|
|
31
32
|
console.log(
|
|
32
|
-
'
|
|
33
|
+
' Install the Pilot skill (default: claude)'
|
|
34
|
+
);
|
|
35
|
+
console.log(
|
|
36
|
+
' check Run Linux browser-launch preflight checks'
|
|
33
37
|
);
|
|
34
38
|
console.log(' (default) Start the MCP server on stdio');
|
|
35
39
|
console.log('');
|
|
@@ -74,7 +78,25 @@ async function run(): Promise<void> {
|
|
|
74
78
|
if (subcommand === 'init') {
|
|
75
79
|
const { runInit } = await import('../cli/init.js');
|
|
76
80
|
const force = args.includes('--force');
|
|
77
|
-
|
|
81
|
+
const agentArg = args.find((arg) => arg.startsWith('--agent='));
|
|
82
|
+
const agentIndex = args.indexOf('--agent');
|
|
83
|
+
const agent =
|
|
84
|
+
agentArg?.slice('--agent='.length) ??
|
|
85
|
+
(agentIndex >= 0 ? args[agentIndex + 1] : undefined) ??
|
|
86
|
+
'claude';
|
|
87
|
+
if (!['claude', 'codex', 'both'].includes(agent)) {
|
|
88
|
+
throw new Error('--agent must be one of: claude, codex, both');
|
|
89
|
+
}
|
|
90
|
+
await runInit({
|
|
91
|
+
force,
|
|
92
|
+
agent: agent as 'claude' | 'codex' | 'both'
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (subcommand === 'check') {
|
|
98
|
+
const { runCheck } = await import('../cli/linux-check.js');
|
|
99
|
+
await runCheck();
|
|
78
100
|
return;
|
|
79
101
|
}
|
|
80
102
|
|
package/src/mcp/server.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { BrowserManager } from '../browser.js';
|
|
3
|
+
import { ElementRefMap } from '../browser/inspect/element-ref.js';
|
|
4
|
+
import { resetCssState } from '../browser/inspect/styles.js';
|
|
5
|
+
import { DialogQueue } from '../browser/interaction/dialogs.js';
|
|
6
|
+
import { attachDialogHandler } from '../browser/interaction/dialogs.js';
|
|
7
|
+
import {
|
|
8
|
+
DownloadTracker,
|
|
9
|
+
enableDownloads,
|
|
10
|
+
attachDownloadHandler
|
|
11
|
+
} from '../browser/interaction/downloads.js';
|
|
12
|
+
import { NetworkBuffer } from '../browser/network/network-buffer.js';
|
|
13
|
+
import { attachNetworkMonitor } from '../browser/network/network-monitor.js';
|
|
3
14
|
import { loadConfig } from '../util/config.js';
|
|
4
15
|
import { ConsoleBuffer, type ConsoleMessage } from './console-buffer.js';
|
|
5
16
|
import { registerBrowserTools } from './tools/browser.js';
|
|
6
17
|
import { registerErrorTools } from './tools/errors.js';
|
|
18
|
+
import { registerSnapshotTools } from './tools/snapshot.js';
|
|
19
|
+
import { registerInteractionTools } from './tools/interaction.js';
|
|
20
|
+
import { registerNetworkTools } from './tools/network.js';
|
|
21
|
+
import { registerRuntimeTools } from './tools/runtime.js';
|
|
22
|
+
import { registerStylesTools } from './tools/styles.js';
|
|
23
|
+
import { registerFilesTools } from './tools/files.js';
|
|
24
|
+
import { createTraceState } from '../browser/performance/trace.js';
|
|
25
|
+
import { registerPerformanceTools } from './tools/performance.js';
|
|
26
|
+
import { registerConnectTools } from './tools/connect.js';
|
|
7
27
|
|
|
8
28
|
export interface McpConfig {
|
|
9
29
|
bufferSize: number;
|
|
@@ -14,6 +34,11 @@ export interface McpConfig {
|
|
|
14
34
|
export interface BrowserContext {
|
|
15
35
|
manager: BrowserManager | null;
|
|
16
36
|
consoleBuffer: ConsoleBuffer;
|
|
37
|
+
elementRefMap: ElementRefMap;
|
|
38
|
+
networkBuffer: NetworkBuffer;
|
|
39
|
+
dialogQueue: DialogQueue;
|
|
40
|
+
downloadTracker: DownloadTracker;
|
|
41
|
+
traceState: ReturnType<typeof createTraceState>;
|
|
17
42
|
baseConfig: McpConfig;
|
|
18
43
|
}
|
|
19
44
|
|
|
@@ -27,18 +52,57 @@ export async function createMcpServer(config: McpConfig): Promise<{
|
|
|
27
52
|
});
|
|
28
53
|
|
|
29
54
|
const consoleBuffer = new ConsoleBuffer(config.bufferSize);
|
|
55
|
+
const elementRefMap = new ElementRefMap();
|
|
56
|
+
const networkBuffer = new NetworkBuffer();
|
|
57
|
+
const dialogQueue = new DialogQueue();
|
|
58
|
+
const downloadTracker = new DownloadTracker();
|
|
59
|
+
const traceState = createTraceState();
|
|
30
60
|
|
|
31
61
|
const context: BrowserContext = {
|
|
32
62
|
manager: null,
|
|
33
63
|
consoleBuffer,
|
|
64
|
+
elementRefMap,
|
|
65
|
+
networkBuffer,
|
|
66
|
+
dialogQueue,
|
|
67
|
+
downloadTracker,
|
|
68
|
+
traceState,
|
|
34
69
|
baseConfig: config
|
|
35
70
|
};
|
|
36
71
|
|
|
37
|
-
function
|
|
72
|
+
function attachEventHandlers(manager: BrowserManager): void {
|
|
73
|
+
let monitoredClient: unknown = null;
|
|
74
|
+
|
|
75
|
+
function ensureMonitors(): void {
|
|
76
|
+
const client = manager.getClient();
|
|
77
|
+
if (client && client !== monitoredClient) {
|
|
78
|
+
attachNetworkMonitor(client, networkBuffer);
|
|
79
|
+
attachDialogHandler(client, dialogQueue);
|
|
80
|
+
attachDownloadHandler(client, downloadTracker);
|
|
81
|
+
void enableDownloads(client).catch(() => {
|
|
82
|
+
// Download behavior setup may fail in some environments
|
|
83
|
+
});
|
|
84
|
+
monitoredClient = client;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
38
88
|
manager.setEventCallback((event, data) => {
|
|
39
89
|
if (event === 'console_message') {
|
|
40
90
|
consoleBuffer.push(data as ConsoleMessage);
|
|
41
91
|
}
|
|
92
|
+
if (event === 'page_navigated') {
|
|
93
|
+
elementRefMap.invalidate();
|
|
94
|
+
}
|
|
95
|
+
if (event === 'browser_connected') {
|
|
96
|
+
ensureMonitors();
|
|
97
|
+
}
|
|
98
|
+
if (event === 'browser_disconnected') {
|
|
99
|
+
monitoredClient = null;
|
|
100
|
+
resetCssState();
|
|
101
|
+
dialogQueue.clear();
|
|
102
|
+
downloadTracker.clear();
|
|
103
|
+
}
|
|
104
|
+
// Reattach after tab switch (new client, no connect event)
|
|
105
|
+
ensureMonitors();
|
|
42
106
|
});
|
|
43
107
|
}
|
|
44
108
|
|
|
@@ -48,12 +112,20 @@ export async function createMcpServer(config: McpConfig): Promise<{
|
|
|
48
112
|
cdpHost: config.cdpHost
|
|
49
113
|
});
|
|
50
114
|
const manager = new BrowserManager(browserConfig);
|
|
51
|
-
|
|
115
|
+
attachEventHandlers(manager);
|
|
52
116
|
return manager;
|
|
53
117
|
}
|
|
54
118
|
|
|
55
119
|
registerBrowserTools(server, context, makeBrowserManager);
|
|
56
120
|
registerErrorTools(server, consoleBuffer);
|
|
121
|
+
registerSnapshotTools(server, context);
|
|
122
|
+
registerInteractionTools(server, context);
|
|
123
|
+
registerNetworkTools(server, context);
|
|
124
|
+
registerRuntimeTools(server, consoleBuffer);
|
|
125
|
+
registerStylesTools(server, context);
|
|
126
|
+
registerFilesTools(server, context);
|
|
127
|
+
registerPerformanceTools(server, context);
|
|
128
|
+
registerConnectTools(server, context, makeBrowserManager);
|
|
57
129
|
|
|
58
130
|
return {
|
|
59
131
|
server,
|
package/src/mcp/tools/browser.ts
CHANGED
|
@@ -57,6 +57,10 @@ const navigateShape = {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
const clickShape = {
|
|
60
|
+
ref: z
|
|
61
|
+
.string()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Element ref from browser_snapshot (e.g. "e3")'),
|
|
60
64
|
selector: z.string().optional().describe('CSS selector to click'),
|
|
61
65
|
x: z.number().optional().describe('Viewport X coordinate'),
|
|
62
66
|
y: z.number().optional().describe('Viewport Y coordinate'),
|
|
@@ -80,6 +84,10 @@ const clickShape = {
|
|
|
80
84
|
|
|
81
85
|
const typeShape = {
|
|
82
86
|
text: z.string().describe('Text to type'),
|
|
87
|
+
ref: z
|
|
88
|
+
.string()
|
|
89
|
+
.optional()
|
|
90
|
+
.describe('Element ref from browser_snapshot (e.g. "e3")'),
|
|
83
91
|
selector: z.string().optional().describe('CSS selector to focus first'),
|
|
84
92
|
clearFirst: z
|
|
85
93
|
.boolean()
|
|
@@ -128,7 +136,7 @@ const startShape = {
|
|
|
128
136
|
.boolean()
|
|
129
137
|
.optional()
|
|
130
138
|
.describe(
|
|
131
|
-
'Run Chrome headless. When omitted, falls back to PILOT_HEADLESS (default:
|
|
139
|
+
'Run Chrome headless. When omitted, falls back to PILOT_HEADLESS (accepts true/1 or false/0; default: false).'
|
|
132
140
|
),
|
|
133
141
|
chromePath: z
|
|
134
142
|
.string()
|
|
@@ -172,6 +180,14 @@ const startShape = {
|
|
|
172
180
|
.optional()
|
|
173
181
|
.describe(
|
|
174
182
|
'Responsive mode. When true, the page uses real window dimensions and reflows on resize (like a normal browser). Desktop presets default to true; mobile/tablet presets leave this unset (locked viewport). Set to false to lock the viewport with setDeviceMetricsOverride.'
|
|
183
|
+
),
|
|
184
|
+
startupTimeoutMs: z
|
|
185
|
+
.number()
|
|
186
|
+
.int()
|
|
187
|
+
.positive()
|
|
188
|
+
.default(30000)
|
|
189
|
+
.describe(
|
|
190
|
+
'Timeout waiting for Chrome DevTools to become ready, in milliseconds.'
|
|
175
191
|
)
|
|
176
192
|
};
|
|
177
193
|
|
|
@@ -190,6 +206,24 @@ const switchTabShape = {
|
|
|
190
206
|
targetId: z.string().describe('Target ID of the tab to switch to')
|
|
191
207
|
};
|
|
192
208
|
|
|
209
|
+
const tabsShape = {
|
|
210
|
+
action: z
|
|
211
|
+
.enum(['list', 'new', 'select', 'close'])
|
|
212
|
+
.describe(
|
|
213
|
+
'Action: list tabs, open new tab, select/switch tab, or close tab'
|
|
214
|
+
),
|
|
215
|
+
targetId: z
|
|
216
|
+
.string()
|
|
217
|
+
.optional()
|
|
218
|
+
.describe('Target ID (required for select and close actions)'),
|
|
219
|
+
url: z
|
|
220
|
+
.string()
|
|
221
|
+
.optional()
|
|
222
|
+
.describe(
|
|
223
|
+
'URL to open in the new tab (new action only, opens blank tab if omitted)'
|
|
224
|
+
)
|
|
225
|
+
};
|
|
226
|
+
|
|
193
227
|
const viewportResizeShape = {
|
|
194
228
|
width: z.number().int().positive().describe('New viewport width in pixels'),
|
|
195
229
|
height: z.number().int().positive().describe('New viewport height in pixels'),
|
|
@@ -237,7 +271,8 @@ export function registerBrowserTools(
|
|
|
237
271
|
viewportWidth,
|
|
238
272
|
viewportHeight,
|
|
239
273
|
deviceScaleFactor,
|
|
240
|
-
responsive
|
|
274
|
+
responsive,
|
|
275
|
+
startupTimeoutMs
|
|
241
276
|
}) => {
|
|
242
277
|
if (context.manager?.isConnected()) {
|
|
243
278
|
return {
|
|
@@ -265,7 +300,8 @@ export function registerBrowserTools(
|
|
|
265
300
|
viewportWidth,
|
|
266
301
|
viewportHeight,
|
|
267
302
|
deviceScaleFactor,
|
|
268
|
-
responsive
|
|
303
|
+
responsive,
|
|
304
|
+
startupTimeoutMs
|
|
269
305
|
});
|
|
270
306
|
context.manager = manager;
|
|
271
307
|
|
|
@@ -361,10 +397,11 @@ export function registerBrowserTools(
|
|
|
361
397
|
|
|
362
398
|
server.tool(
|
|
363
399
|
'browser_click',
|
|
364
|
-
'Click an element by
|
|
400
|
+
'Click an element by ref (from browser_snapshot), CSS selector, or coordinates.',
|
|
365
401
|
clickShape,
|
|
366
402
|
async (params) => {
|
|
367
403
|
if (
|
|
404
|
+
params.ref === undefined &&
|
|
368
405
|
params.selector === undefined &&
|
|
369
406
|
(params.x === undefined || params.y === undefined)
|
|
370
407
|
) {
|
|
@@ -372,7 +409,7 @@ export function registerBrowserTools(
|
|
|
372
409
|
content: [
|
|
373
410
|
{
|
|
374
411
|
type: 'text' as const,
|
|
375
|
-
text: 'Error: Either selector or x/y coordinates are required'
|
|
412
|
+
text: 'Error: Either ref, selector, or x/y coordinates are required'
|
|
376
413
|
}
|
|
377
414
|
],
|
|
378
415
|
isError: true
|
|
@@ -380,7 +417,7 @@ export function registerBrowserTools(
|
|
|
380
417
|
}
|
|
381
418
|
|
|
382
419
|
const { client } = requireClient(context);
|
|
383
|
-
const result = await executeClick(client, params);
|
|
420
|
+
const result = await executeClick(client, params, context.elementRefMap);
|
|
384
421
|
|
|
385
422
|
return {
|
|
386
423
|
content: [
|
|
@@ -395,17 +432,18 @@ export function registerBrowserTools(
|
|
|
395
432
|
|
|
396
433
|
server.tool(
|
|
397
434
|
'browser_type',
|
|
398
|
-
'Type text into the focused element or a
|
|
435
|
+
'Type text into the focused element, a ref (from browser_snapshot), or a CSS selector. Generates keystroke events (use browser_fill to replace a field value entirely).',
|
|
399
436
|
typeShape,
|
|
400
437
|
async (params) => {
|
|
401
438
|
const { client } = requireClient(context);
|
|
402
|
-
await executeType(client, params);
|
|
439
|
+
await executeType(client, params, context.elementRefMap);
|
|
403
440
|
|
|
441
|
+
const target = params.ref ?? params.selector;
|
|
404
442
|
return {
|
|
405
443
|
content: [
|
|
406
444
|
{
|
|
407
445
|
type: 'text' as const,
|
|
408
|
-
text: `Typed "${params.text}"${
|
|
446
|
+
text: `Typed "${params.text}"${target ? ` into ${target}` : ''}`
|
|
409
447
|
}
|
|
410
448
|
]
|
|
411
449
|
};
|
|
@@ -602,4 +640,82 @@ export function registerBrowserTools(
|
|
|
602
640
|
};
|
|
603
641
|
}
|
|
604
642
|
);
|
|
643
|
+
|
|
644
|
+
server.tool(
|
|
645
|
+
'browser_tabs',
|
|
646
|
+
'Manage browser tabs. Actions: "list" shows all tabs, "new" opens a tab (optional url), "select" switches to a tab (requires targetId), "close" closes a tab (requires targetId).',
|
|
647
|
+
tabsShape,
|
|
648
|
+
async ({ action, targetId, url }) => {
|
|
649
|
+
const { manager } = requireClient(context);
|
|
650
|
+
|
|
651
|
+
switch (action) {
|
|
652
|
+
case 'list': {
|
|
653
|
+
const tabs = await executeListTabs(manager);
|
|
654
|
+
return {
|
|
655
|
+
content: [
|
|
656
|
+
{ type: 'text' as const, text: JSON.stringify(tabs, null, 2) }
|
|
657
|
+
]
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
case 'new': {
|
|
662
|
+
const result = await executeNewTab(manager, url);
|
|
663
|
+
return {
|
|
664
|
+
content: [
|
|
665
|
+
{
|
|
666
|
+
type: 'text' as const,
|
|
667
|
+
text: `New tab opened (targetId: ${result.targetId}, url: ${result.url})`
|
|
668
|
+
}
|
|
669
|
+
]
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
case 'select': {
|
|
674
|
+
if (!targetId) {
|
|
675
|
+
return {
|
|
676
|
+
content: [
|
|
677
|
+
{
|
|
678
|
+
type: 'text' as const,
|
|
679
|
+
text: 'Error: targetId is required for select action'
|
|
680
|
+
}
|
|
681
|
+
],
|
|
682
|
+
isError: true
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
await executeSwitchTab(manager, targetId);
|
|
686
|
+
return {
|
|
687
|
+
content: [
|
|
688
|
+
{
|
|
689
|
+
type: 'text' as const,
|
|
690
|
+
text: `Switched to tab ${targetId}.`
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
case 'close': {
|
|
697
|
+
if (!targetId) {
|
|
698
|
+
return {
|
|
699
|
+
content: [
|
|
700
|
+
{
|
|
701
|
+
type: 'text' as const,
|
|
702
|
+
text: 'Error: targetId is required for close action'
|
|
703
|
+
}
|
|
704
|
+
],
|
|
705
|
+
isError: true
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
await executeCloseTab(manager, targetId);
|
|
709
|
+
return {
|
|
710
|
+
content: [
|
|
711
|
+
{
|
|
712
|
+
type: 'text' as const,
|
|
713
|
+
text: `Tab ${targetId} closed.`
|
|
714
|
+
}
|
|
715
|
+
]
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
);
|
|
605
721
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import type { BrowserContext } from '../server.js';
|
|
4
|
+
import type { BrowserManager } from '../../browser/browser-manager.js';
|
|
5
|
+
import { executeConnect, formatConnectResult } from '../../commands/connect.js';
|
|
6
|
+
|
|
7
|
+
const connectShape = {
|
|
8
|
+
host: z
|
|
9
|
+
.string()
|
|
10
|
+
.default('127.0.0.1')
|
|
11
|
+
.describe('Chrome debugging host (default: 127.0.0.1)'),
|
|
12
|
+
port: z
|
|
13
|
+
.number()
|
|
14
|
+
.int()
|
|
15
|
+
.min(1)
|
|
16
|
+
.max(65535)
|
|
17
|
+
.default(9222)
|
|
18
|
+
.describe('Chrome debugging port (default: 9222)')
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function registerConnectTools(
|
|
22
|
+
server: McpServer,
|
|
23
|
+
context: BrowserContext,
|
|
24
|
+
makeBrowserManager: () => BrowserManager
|
|
25
|
+
): void {
|
|
26
|
+
server.tool(
|
|
27
|
+
'browser_connect',
|
|
28
|
+
'Connect to an existing Chrome instance with remote debugging enabled. Start Chrome with --remote-debugging-port=PORT, then use this tool to connect. Lists available tabs after connecting. Use browser_switch_tab to select a specific tab.',
|
|
29
|
+
connectShape,
|
|
30
|
+
async ({ host, port }) => {
|
|
31
|
+
if (context.manager?.isConnected()) {
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: 'text' as const,
|
|
36
|
+
text: 'Already connected to a browser. Call browser_stop to disconnect first.'
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (context.manager) {
|
|
43
|
+
await context.manager.destroy();
|
|
44
|
+
context.manager = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const manager = makeBrowserManager();
|
|
48
|
+
try {
|
|
49
|
+
const result = await executeConnect(manager, { host, port });
|
|
50
|
+
context.manager = manager;
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{ type: 'text' as const, text: formatConnectResult(result) }
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
} catch (err) {
|
|
57
|
+
await manager.destroy();
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import type { BrowserContext } from '../server.js';
|
|
4
|
+
import { executeDialog, formatDialogResult } from '../../commands/dialog.js';
|
|
5
|
+
import { executeUpload } from '../../commands/upload.js';
|
|
6
|
+
import {
|
|
7
|
+
executeDownloads,
|
|
8
|
+
formatDownloadsResult
|
|
9
|
+
} from '../../commands/downloads.js';
|
|
10
|
+
|
|
11
|
+
const dialogShape = {
|
|
12
|
+
action: z
|
|
13
|
+
.enum(['list', 'accept', 'dismiss'])
|
|
14
|
+
.describe(
|
|
15
|
+
'Action: list pending dialogs, accept (OK/Yes), or dismiss (Cancel/No)'
|
|
16
|
+
),
|
|
17
|
+
promptText: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Text to enter for prompt dialogs (accept action only)')
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const uploadShape = {
|
|
24
|
+
ref: z
|
|
25
|
+
.string()
|
|
26
|
+
.describe('Element ref of a file input (from browser_snapshot)'),
|
|
27
|
+
files: z
|
|
28
|
+
.array(z.string())
|
|
29
|
+
.describe(
|
|
30
|
+
'File paths to upload. Must exist, be regular files, and be under PILOT_UPLOAD_ROOTS (default: cwd).'
|
|
31
|
+
)
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const downloadsShape = {
|
|
35
|
+
action: z
|
|
36
|
+
.enum(['list', 'wait', 'clear'])
|
|
37
|
+
.describe(
|
|
38
|
+
'Action: list tracked downloads, wait for one to complete, or clear'
|
|
39
|
+
),
|
|
40
|
+
guid: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Download GUID (required for wait action)'),
|
|
44
|
+
timeoutMs: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.positive()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Timeout for wait action in milliseconds (default: 30000)')
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function requireContext(context: BrowserContext) {
|
|
53
|
+
const manager = context.manager;
|
|
54
|
+
if (!manager || !manager.isConnected()) {
|
|
55
|
+
throw new Error('Browser not started. Call browser_start first.');
|
|
56
|
+
}
|
|
57
|
+
const client = manager.getClient()!;
|
|
58
|
+
return { client };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function registerFilesTools(
|
|
62
|
+
server: McpServer,
|
|
63
|
+
context: BrowserContext
|
|
64
|
+
): void {
|
|
65
|
+
server.tool(
|
|
66
|
+
'browser_dialog',
|
|
67
|
+
'Handle browser dialogs (alert, confirm, prompt). Use "list" to see pending dialogs, "accept" to click OK/Yes, or "dismiss" to click Cancel/No. For prompt dialogs, provide promptText with accept.',
|
|
68
|
+
dialogShape,
|
|
69
|
+
async ({ action, promptText }) => {
|
|
70
|
+
const { client } = requireContext(context);
|
|
71
|
+
const result = await executeDialog(client, context.dialogQueue, {
|
|
72
|
+
action,
|
|
73
|
+
promptText
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
content: [{ type: 'text' as const, text: formatDialogResult(result) }]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
server.tool(
|
|
82
|
+
'browser_upload',
|
|
83
|
+
'Upload files to a file input element by ref. Files must exist, be regular files, and be under allowed roots (PILOT_UPLOAD_ROOTS env, default: cwd). Use browser_snapshot to find file input refs.',
|
|
84
|
+
uploadShape,
|
|
85
|
+
async ({ ref, files }) => {
|
|
86
|
+
const { client } = requireContext(context);
|
|
87
|
+
const result = await executeUpload(client, context.elementRefMap, {
|
|
88
|
+
ref,
|
|
89
|
+
files
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text' as const,
|
|
95
|
+
text: `Uploaded ${result.files.length} file(s) to ${result.ref}`
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
server.tool(
|
|
103
|
+
'browser_downloads',
|
|
104
|
+
'Track file downloads. Actions: "list" shows tracked downloads with status/progress; "wait" blocks until a download (by GUID) completes; "clear" resets the tracker.',
|
|
105
|
+
downloadsShape,
|
|
106
|
+
async ({ action, guid, timeoutMs }) => {
|
|
107
|
+
requireContext(context);
|
|
108
|
+
const result = await executeDownloads(context.downloadTracker, {
|
|
109
|
+
action,
|
|
110
|
+
guid,
|
|
111
|
+
timeoutMs
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{ type: 'text' as const, text: formatDownloadsResult(result) }
|
|
116
|
+
]
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|