ultimate-playwright-mcp 0.1.0

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 (131) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +286 -0
  3. package/dist/browser/cdp.d.ts +37 -0
  4. package/dist/browser/cdp.d.ts.map +1 -0
  5. package/dist/browser/cdp.helpers.d.ts +13 -0
  6. package/dist/browser/cdp.helpers.d.ts.map +1 -0
  7. package/dist/browser/cdp.helpers.js +38 -0
  8. package/dist/browser/cdp.helpers.js.map +1 -0
  9. package/dist/browser/cdp.js +77 -0
  10. package/dist/browser/cdp.js.map +1 -0
  11. package/dist/browser/chrome-tab-groups.d.ts +93 -0
  12. package/dist/browser/chrome-tab-groups.d.ts.map +1 -0
  13. package/dist/browser/chrome-tab-groups.js +458 -0
  14. package/dist/browser/chrome-tab-groups.js.map +1 -0
  15. package/dist/browser/chrome.d.ts +11 -0
  16. package/dist/browser/chrome.d.ts.map +1 -0
  17. package/dist/browser/chrome.js +74 -0
  18. package/dist/browser/chrome.js.map +1 -0
  19. package/dist/browser/pw-role-snapshot.d.ts +41 -0
  20. package/dist/browser/pw-role-snapshot.d.ts.map +1 -0
  21. package/dist/browser/pw-role-snapshot.js +346 -0
  22. package/dist/browser/pw-role-snapshot.js.map +1 -0
  23. package/dist/browser/pw-session.d.ts +145 -0
  24. package/dist/browser/pw-session.d.ts.map +1 -0
  25. package/dist/browser/pw-session.js +468 -0
  26. package/dist/browser/pw-session.js.map +1 -0
  27. package/dist/browser/pw-tools-activity.d.ts +27 -0
  28. package/dist/browser/pw-tools-activity.d.ts.map +1 -0
  29. package/dist/browser/pw-tools-activity.js +52 -0
  30. package/dist/browser/pw-tools-activity.js.map +1 -0
  31. package/dist/browser/pw-tools-downloads.d.ts +40 -0
  32. package/dist/browser/pw-tools-downloads.d.ts.map +1 -0
  33. package/dist/browser/pw-tools-downloads.js +191 -0
  34. package/dist/browser/pw-tools-downloads.js.map +1 -0
  35. package/dist/browser/pw-tools-interactions.d.ts +122 -0
  36. package/dist/browser/pw-tools-interactions.d.ts.map +1 -0
  37. package/dist/browser/pw-tools-interactions.js +434 -0
  38. package/dist/browser/pw-tools-interactions.js.map +1 -0
  39. package/dist/browser/pw-tools-responses.d.ts +19 -0
  40. package/dist/browser/pw-tools-responses.d.ts.map +1 -0
  41. package/dist/browser/pw-tools-responses.js +98 -0
  42. package/dist/browser/pw-tools-responses.js.map +1 -0
  43. package/dist/browser/pw-tools-shared.d.ts +12 -0
  44. package/dist/browser/pw-tools-shared.d.ts.map +1 -0
  45. package/dist/browser/pw-tools-shared.js +55 -0
  46. package/dist/browser/pw-tools-shared.js.map +1 -0
  47. package/dist/browser/pw-tools-snapshot.d.ts +70 -0
  48. package/dist/browser/pw-tools-snapshot.d.ts.map +1 -0
  49. package/dist/browser/pw-tools-snapshot.js +151 -0
  50. package/dist/browser/pw-tools-snapshot.js.map +1 -0
  51. package/dist/browser/pw-tools-state.d.ts +52 -0
  52. package/dist/browser/pw-tools-state.d.ts.map +1 -0
  53. package/dist/browser/pw-tools-state.js +159 -0
  54. package/dist/browser/pw-tools-state.js.map +1 -0
  55. package/dist/browser/pw-tools-storage.d.ts +53 -0
  56. package/dist/browser/pw-tools-storage.d.ts.map +1 -0
  57. package/dist/browser/pw-tools-storage.js +81 -0
  58. package/dist/browser/pw-tools-storage.js.map +1 -0
  59. package/dist/browser/pw-tools-trace.d.ts +18 -0
  60. package/dist/browser/pw-tools-trace.d.ts.map +1 -0
  61. package/dist/browser/pw-tools-trace.js +31 -0
  62. package/dist/browser/pw-tools-trace.js.map +1 -0
  63. package/dist/browser/tab-groups.d.ts +94 -0
  64. package/dist/browser/tab-groups.d.ts.map +1 -0
  65. package/dist/browser/tab-groups.js +303 -0
  66. package/dist/browser/tab-groups.js.map +1 -0
  67. package/dist/browser/target-id.d.ts +20 -0
  68. package/dist/browser/target-id.d.ts.map +1 -0
  69. package/dist/browser/target-id.js +29 -0
  70. package/dist/browser/target-id.js.map +1 -0
  71. package/dist/cli.d.ts +6 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +35 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/config.d.ts +32 -0
  76. package/dist/config.d.ts.map +1 -0
  77. package/dist/config.js +7 -0
  78. package/dist/config.js.map +1 -0
  79. package/dist/daemon/chrome-daemon.d.ts +7 -0
  80. package/dist/daemon/chrome-daemon.d.ts.map +1 -0
  81. package/dist/daemon/chrome-daemon.js +264 -0
  82. package/dist/daemon/chrome-daemon.js.map +1 -0
  83. package/dist/daemon/cli.d.ts +6 -0
  84. package/dist/daemon/cli.d.ts.map +1 -0
  85. package/dist/daemon/cli.js +110 -0
  86. package/dist/daemon/cli.js.map +1 -0
  87. package/dist/daemon/manager.d.ts +22 -0
  88. package/dist/daemon/manager.d.ts.map +1 -0
  89. package/dist/daemon/manager.js +89 -0
  90. package/dist/daemon/manager.js.map +1 -0
  91. package/dist/index.d.ts +9 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +9 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/mcp/server.d.ts +41 -0
  96. package/dist/mcp/server.d.ts.map +1 -0
  97. package/dist/mcp/server.js +122 -0
  98. package/dist/mcp/server.js.map +1 -0
  99. package/dist/mcp/tools/actions.d.ts +6 -0
  100. package/dist/mcp/tools/actions.d.ts.map +1 -0
  101. package/dist/mcp/tools/actions.js +214 -0
  102. package/dist/mcp/tools/actions.js.map +1 -0
  103. package/dist/mcp/tools/navigate.d.ts +6 -0
  104. package/dist/mcp/tools/navigate.d.ts.map +1 -0
  105. package/dist/mcp/tools/navigate.js +31 -0
  106. package/dist/mcp/tools/navigate.js.map +1 -0
  107. package/dist/mcp/tools/snapshot.d.ts +6 -0
  108. package/dist/mcp/tools/snapshot.d.ts.map +1 -0
  109. package/dist/mcp/tools/snapshot.js +26 -0
  110. package/dist/mcp/tools/snapshot.js.map +1 -0
  111. package/dist/mcp/tools/tab-group.d.ts +9 -0
  112. package/dist/mcp/tools/tab-group.d.ts.map +1 -0
  113. package/dist/mcp/tools/tab-group.js +173 -0
  114. package/dist/mcp/tools/tab-group.js.map +1 -0
  115. package/dist/mcp/tools/tabs.d.ts +6 -0
  116. package/dist/mcp/tools/tabs.d.ts.map +1 -0
  117. package/dist/mcp/tools/tabs.js +209 -0
  118. package/dist/mcp/tools/tabs.js.map +1 -0
  119. package/dist/utils/command-format.d.ts +6 -0
  120. package/dist/utils/command-format.d.ts.map +1 -0
  121. package/dist/utils/command-format.js +8 -0
  122. package/dist/utils/command-format.js.map +1 -0
  123. package/dist/utils/errors.d.ts +6 -0
  124. package/dist/utils/errors.d.ts.map +1 -0
  125. package/dist/utils/errors.js +22 -0
  126. package/dist/utils/errors.js.map +1 -0
  127. package/dist/utils/extension-installer.d.ts +16 -0
  128. package/dist/utils/extension-installer.d.ts.map +1 -0
  129. package/dist/utils/extension-installer.js +134 -0
  130. package/dist/utils/extension-installer.js.map +1 -0
  131. package/package.json +75 -0
@@ -0,0 +1,122 @@
1
+ /**
2
+ * MCP server implementation with Playwright browser control via CDP
3
+ */
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
7
+ import { DaemonManager } from "../daemon/manager.js";
8
+ import { registerBrowserTabsTool } from "./tools/tabs.js";
9
+ import { registerBrowserNavigateTool } from "./tools/navigate.js";
10
+ import { registerBrowserSnapshotTool } from "./tools/snapshot.js";
11
+ import { registerBrowserActionTools } from "./tools/actions.js";
12
+ import { registerBrowserTabGroupTool } from "./tools/tab-group.js";
13
+ import { warmupTabGrouper, seedExtensionIdFromPath } from "../browser/chrome-tab-groups.js";
14
+ import { existsSync } from "node:fs";
15
+ import { join, dirname } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ export async function createMCPServer(config) {
18
+ const server = new Server({
19
+ name: "ultimate-playwright-mcp",
20
+ version: "0.1.0",
21
+ }, {
22
+ capabilities: {
23
+ tools: {},
24
+ },
25
+ });
26
+ // Tool registry
27
+ const tools = new Map();
28
+ // Helper to register tools
29
+ function registerTool(name, description, inputSchema, handler) {
30
+ tools.set(name, { description, inputSchema, handler });
31
+ }
32
+ // Register all tools
33
+ registerBrowserTabGroupTool(registerTool, config);
34
+ registerBrowserTabsTool(registerTool, config);
35
+ registerBrowserNavigateTool(registerTool, config);
36
+ registerBrowserSnapshotTool(registerTool, config);
37
+ registerBrowserActionTools(registerTool, config);
38
+ // List tools handler
39
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
40
+ return {
41
+ tools: Array.from(tools.entries()).map(([name, tool]) => ({
42
+ name,
43
+ description: tool.description,
44
+ inputSchema: tool.inputSchema,
45
+ })),
46
+ };
47
+ });
48
+ // Call tool handler
49
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
50
+ const { name, arguments: args } = request.params;
51
+ const tool = tools.get(name);
52
+ if (!tool) {
53
+ throw new Error(`Unknown tool: ${name}`);
54
+ }
55
+ try {
56
+ const result = await tool.handler(args || {});
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2),
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ catch (error) {
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ return {
69
+ content: [
70
+ {
71
+ type: "text",
72
+ text: `Error: ${message}`,
73
+ },
74
+ ],
75
+ isError: true,
76
+ };
77
+ }
78
+ });
79
+ return server;
80
+ }
81
+ export async function runServer(config) {
82
+ // Ensure Chrome daemon is running (auto-start if needed)
83
+ if (!config.cdpEndpoint) {
84
+ await DaemonManager.ensureDaemonRunning({
85
+ chromeUserDataDir: config.chromeUserDataDir,
86
+ chromeExtensions: config.chromeExtensions,
87
+ chromeExecutable: config.chromeExecutable,
88
+ });
89
+ config.cdpEndpoint = DaemonManager.getCdpEndpoint();
90
+ }
91
+ const server = await createMCPServer(config);
92
+ const transport = new StdioServerTransport();
93
+ await server.connect(transport);
94
+ // Seed the companion extension ID so we can wake it when its SW goes dormant.
95
+ // Look for the bundled extension relative to this file, or in the configured extensions.
96
+ const __filename = fileURLToPath(import.meta.url);
97
+ const __dirname = dirname(__filename);
98
+ const bundledExtPath = join(__dirname, "..", "..", "extensions", "tab-grouper");
99
+ if (existsSync(bundledExtPath)) {
100
+ seedExtensionIdFromPath(bundledExtPath);
101
+ }
102
+ // Also check if it's in the configured extensions list
103
+ if (config.chromeExtensions) {
104
+ for (const ext of config.chromeExtensions) {
105
+ if (ext.includes("tab-grouper") && existsSync(ext)) {
106
+ seedExtensionIdFromPath(ext);
107
+ break;
108
+ }
109
+ }
110
+ }
111
+ // Warm up: discover companion extension while its SW is still alive
112
+ if (config.cdpEndpoint) {
113
+ warmupTabGrouper(config.cdpEndpoint).catch(() => { });
114
+ }
115
+ // Log to stderr so it doesn't interfere with stdio transport
116
+ console.error("Ultimate Playwright MCP server running on stdio");
117
+ if (config.agentId) {
118
+ console.error(`Agent ID: ${config.agentId}`);
119
+ }
120
+ console.error(`CDP Endpoint: ${config.cdpEndpoint}`);
121
+ }
122
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Browser action tools - click, type, hover, etc.
3
+ */
4
+ import type { ServerConfig } from "../../config.js";
5
+ export declare function registerBrowserActionTools(register: (name: string, description: string, schema: any, handler: (args: any) => Promise<any>) => void, config: ServerConfig): void;
6
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAWpD,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EACxG,MAAM,EAAE,YAAY,QAmQrB"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Browser action tools - click, type, hover, etc.
3
+ */
4
+ import { clickViaPlaywright, typeViaPlaywright, hoverViaPlaywright, pressKeyViaPlaywright, fillFormViaPlaywright, waitForViaPlaywright, } from "../../browser/pw-tools-interactions.js";
5
+ export function registerBrowserActionTools(register, config) {
6
+ // browser_click
7
+ register("browser_click", "Click an element by its ref (e1, e2, etc. from snapshot)", {
8
+ type: "object",
9
+ properties: {
10
+ ref: {
11
+ type: "string",
12
+ description: "Element reference from snapshot (e.g., 'e1', 'e2')",
13
+ },
14
+ targetId: {
15
+ type: "string",
16
+ description: "Target ID of the tab",
17
+ },
18
+ button: {
19
+ type: "string",
20
+ enum: ["left", "right", "middle"],
21
+ description: "Mouse button to click (default: left)",
22
+ },
23
+ doubleClick: {
24
+ type: "boolean",
25
+ description: "Perform a double-click",
26
+ },
27
+ },
28
+ required: ["ref"],
29
+ }, async (args) => {
30
+ if (!config.cdpEndpoint)
31
+ throw new Error("CDP endpoint not configured");
32
+ await clickViaPlaywright({
33
+ cdpUrl: config.cdpEndpoint,
34
+ targetId: args.targetId,
35
+ ref: args.ref,
36
+ button: args.button,
37
+ doubleClick: args.doubleClick,
38
+ });
39
+ return `**Clicked** element ${args.ref}`;
40
+ });
41
+ // browser_type
42
+ register("browser_type", "Type text into an element", {
43
+ type: "object",
44
+ properties: {
45
+ ref: {
46
+ type: "string",
47
+ description: "Element reference from snapshot",
48
+ },
49
+ text: {
50
+ type: "string",
51
+ description: "Text to type",
52
+ },
53
+ targetId: {
54
+ type: "string",
55
+ description: "Target ID of the tab",
56
+ },
57
+ submit: {
58
+ type: "boolean",
59
+ description: "Press Enter after typing",
60
+ },
61
+ },
62
+ required: ["ref", "text"],
63
+ }, async (args) => {
64
+ if (!config.cdpEndpoint)
65
+ throw new Error("CDP endpoint not configured");
66
+ await typeViaPlaywright({
67
+ cdpUrl: config.cdpEndpoint,
68
+ targetId: args.targetId,
69
+ ref: args.ref,
70
+ text: args.text,
71
+ submit: args.submit,
72
+ });
73
+ return `**Typed** "${args.text}" into ${args.ref}`;
74
+ });
75
+ // browser_hover
76
+ register("browser_hover", "Hover over an element", {
77
+ type: "object",
78
+ properties: {
79
+ ref: {
80
+ type: "string",
81
+ description: "Element reference from snapshot",
82
+ },
83
+ targetId: {
84
+ type: "string",
85
+ description: "Target ID of the tab",
86
+ },
87
+ },
88
+ required: ["ref"],
89
+ }, async (args) => {
90
+ if (!config.cdpEndpoint)
91
+ throw new Error("CDP endpoint not configured");
92
+ await hoverViaPlaywright({
93
+ cdpUrl: config.cdpEndpoint,
94
+ targetId: args.targetId,
95
+ ref: args.ref,
96
+ });
97
+ return `**Hovered** over ${args.ref}`;
98
+ });
99
+ // browser_press_key
100
+ register("browser_press_key", "Press a keyboard key", {
101
+ type: "object",
102
+ properties: {
103
+ key: {
104
+ type: "string",
105
+ description: "Key to press (e.g., 'Enter', 'Escape', 'ArrowDown')",
106
+ },
107
+ targetId: {
108
+ type: "string",
109
+ description: "Target ID of the tab",
110
+ },
111
+ },
112
+ required: ["key"],
113
+ }, async (args) => {
114
+ if (!config.cdpEndpoint)
115
+ throw new Error("CDP endpoint not configured");
116
+ await pressKeyViaPlaywright({
117
+ cdpUrl: config.cdpEndpoint,
118
+ targetId: args.targetId,
119
+ key: args.key,
120
+ });
121
+ return `**Pressed** key: ${args.key}`;
122
+ });
123
+ // browser_fill_form
124
+ register("browser_fill_form", "Fill multiple form fields at once", {
125
+ type: "object",
126
+ properties: {
127
+ fields: {
128
+ type: "array",
129
+ description: "Array of form fields to fill",
130
+ items: {
131
+ type: "object",
132
+ properties: {
133
+ ref: { type: "string" },
134
+ type: { type: "string" },
135
+ value: { type: ["string", "number", "boolean"] },
136
+ },
137
+ required: ["ref", "type"],
138
+ },
139
+ },
140
+ targetId: {
141
+ type: "string",
142
+ description: "Target ID of the tab",
143
+ },
144
+ },
145
+ required: ["fields"],
146
+ }, async (args) => {
147
+ if (!config.cdpEndpoint)
148
+ throw new Error("CDP endpoint not configured");
149
+ await fillFormViaPlaywright({
150
+ cdpUrl: config.cdpEndpoint,
151
+ targetId: args.targetId,
152
+ fields: args.fields,
153
+ });
154
+ return `**Filled** ${args.fields.length} form field(s)`;
155
+ });
156
+ // browser_wait_for
157
+ register("browser_wait_for", "Wait for a condition (text, selector, load state, time, etc.)", {
158
+ type: "object",
159
+ properties: {
160
+ text: {
161
+ type: "string",
162
+ description: "Wait for text to appear on page",
163
+ },
164
+ textGone: {
165
+ type: "string",
166
+ description: "Wait for text to disappear from page",
167
+ },
168
+ selector: {
169
+ type: "string",
170
+ description: "Wait for CSS selector",
171
+ },
172
+ url: {
173
+ type: "string",
174
+ description: "Wait for URL to match pattern",
175
+ },
176
+ loadState: {
177
+ type: "string",
178
+ enum: ["load", "domcontentloaded", "networkidle"],
179
+ description: "Wait for load state",
180
+ },
181
+ timeMs: {
182
+ type: "number",
183
+ description: "Wait for specific milliseconds",
184
+ },
185
+ targetId: {
186
+ type: "string",
187
+ description: "Target ID of the tab",
188
+ },
189
+ },
190
+ }, async (args) => {
191
+ if (!config.cdpEndpoint)
192
+ throw new Error("CDP endpoint not configured");
193
+ await waitForViaPlaywright({
194
+ cdpUrl: config.cdpEndpoint,
195
+ targetId: args.targetId,
196
+ text: args.text,
197
+ textGone: args.textGone,
198
+ selector: args.selector,
199
+ url: args.url,
200
+ loadState: args.loadState,
201
+ timeMs: args.timeMs,
202
+ });
203
+ const conditions = [
204
+ args.text && `text: "${args.text}"`,
205
+ args.textGone && `text gone: "${args.textGone}"`,
206
+ args.selector && `selector: ${args.selector}`,
207
+ args.url && `URL: ${args.url}`,
208
+ args.loadState && `load state: ${args.loadState}`,
209
+ args.timeMs && `${args.timeMs}ms`,
210
+ ].filter(Boolean);
211
+ return `**Wait completed** for ${conditions.join(", ")}`;
212
+ });
213
+ }
214
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/mcp/tools/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browser_navigate tool - navigate to URLs in specific tabs
3
+ */
4
+ import type { ServerConfig } from "../../config.js";
5
+ export declare function registerBrowserNavigateTool(register: (name: string, description: string, schema: any, handler: (args: any) => Promise<any>) => void, config: ServerConfig): void;
6
+ //# sourceMappingURL=navigate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/navigate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EACxG,MAAM,EAAE,YAAY,QAiCrB"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * browser_navigate tool - navigate to URLs in specific tabs
3
+ */
4
+ import { navigateViaPlaywright } from "../../browser/pw-tools-snapshot.js";
5
+ export function registerBrowserNavigateTool(register, config) {
6
+ register("browser_navigate", "Navigate to a URL in a specific tab. Use targetId from browser_tabs to specify which tab.", {
7
+ type: "object",
8
+ properties: {
9
+ url: {
10
+ type: "string",
11
+ description: "URL to navigate to",
12
+ },
13
+ targetId: {
14
+ type: "string",
15
+ description: "Target ID of the tab (from browser_tabs). If not provided, uses first available tab.",
16
+ },
17
+ },
18
+ required: ["url"],
19
+ }, async (args) => {
20
+ if (!config.cdpEndpoint) {
21
+ throw new Error("CDP endpoint not configured");
22
+ }
23
+ const result = await navigateViaPlaywright({
24
+ cdpUrl: config.cdpEndpoint,
25
+ targetId: args.targetId,
26
+ url: args.url,
27
+ });
28
+ return `**Navigation successful**\\nURL: ${result.url}`;
29
+ });
30
+ }
31
+ //# sourceMappingURL=navigate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../../src/mcp/tools/navigate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E,MAAM,UAAU,2BAA2B,CACzC,QAAwG,EACxG,MAAoB;IAEpB,QAAQ,CACN,kBAAkB,EAClB,2FAA2F,EAC3F;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oBAAoB;aAClC;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sFAAsF;aACpG;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;KAClB,EACD,KAAK,EAAE,IAAwC,EAAE,EAAE;QACjD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC;YACzC,MAAM,EAAE,MAAM,CAAC,WAAW;YAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAC;QAEH,OAAO,oCAAoC,MAAM,CAAC,GAAG,EAAE,CAAC;IAC1D,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browser_snapshot tool - capture accessibility tree snapshot with element refs
3
+ */
4
+ import type { ServerConfig } from "../../config.js";
5
+ export declare function registerBrowserSnapshotTool(register: (name: string, description: string, schema: any, handler: (args: any) => Promise<any>) => void, config: ServerConfig): void;
6
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/snapshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EACxG,MAAM,EAAE,YAAY,QA4BrB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * browser_snapshot tool - capture accessibility tree snapshot with element refs
3
+ */
4
+ import { snapshotRoleViaPlaywright } from "../../browser/pw-tools-snapshot.js";
5
+ export function registerBrowserSnapshotTool(register, config) {
6
+ register("browser_snapshot", "Capture accessibility tree snapshot of the current page. Returns element references (e1, e2, etc.) " +
7
+ "that can be used with other browser tools like click, type, etc.", {
8
+ type: "object",
9
+ properties: {
10
+ targetId: {
11
+ type: "string",
12
+ description: "Target ID of the tab (from browser_tabs). If not provided, uses first available tab.",
13
+ },
14
+ },
15
+ }, async (args) => {
16
+ if (!config.cdpEndpoint) {
17
+ throw new Error("CDP endpoint not configured");
18
+ }
19
+ const result = await snapshotRoleViaPlaywright({
20
+ cdpUrl: config.cdpEndpoint,
21
+ targetId: args.targetId,
22
+ });
23
+ return result.snapshot;
24
+ });
25
+ }
26
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/mcp/tools/snapshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAE/E,MAAM,UAAU,2BAA2B,CACzC,QAAwG,EACxG,MAAoB;IAEpB,QAAQ,CACN,kBAAkB,EAClB,qGAAqG;QACrG,kEAAkE,EAClE;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sFAAsF;aACpG;SACF;KACF,EACD,KAAK,EAAE,IAA2B,EAAE,EAAE;QACpC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC;YAC7C,MAAM,EAAE,MAAM,CAAC,WAAW;YAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * browser_tab_group tool — manage tab groups for multi-user isolation.
3
+ *
4
+ * Each session should create a tab group first, then use the groupId
5
+ * with browser_tabs and other tools to stay isolated.
6
+ */
7
+ import type { ServerConfig } from "../../config.js";
8
+ export declare function registerBrowserTabGroupTool(register: (name: string, description: string, schema: any, handler: (args: any) => Promise<any>) => void, config: ServerConfig): void;
9
+ //# sourceMappingURL=tab-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-group.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/tab-group.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmBpD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KACjC,IAAI,EACT,MAAM,EAAE,YAAY,QA6MrB"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * browser_tab_group tool — manage tab groups for multi-user isolation.
3
+ *
4
+ * Each session should create a tab group first, then use the groupId
5
+ * with browser_tabs and other tools to stay isolated.
6
+ */
7
+ import { createTabGroup, listTabGroups, deleteTabGroup, pruneStaleTargets, getTabGroup, } from "../../browser/tab-groups.js";
8
+ import { listPagesViaPlaywright, closePageByTargetIdViaPlaywright, } from "../../browser/pw-session.js";
9
+ import { isTabGrouperAvailable, ungroupTabsVisually, mapTargetIdsToChromeTabIds, listVisualTabGroups, } from "../../browser/chrome-tab-groups.js";
10
+ export function registerBrowserTabGroupTool(register, config) {
11
+ register("browser_tab_group", "Manage tab groups for session isolation. Multiple users/agents sharing one browser " +
12
+ "MUST create a tab group first, then pass the groupId to browser_tabs and other tools. " +
13
+ "This ensures each session only sees and controls its own tabs.\n\n" +
14
+ "Actions:\n" +
15
+ "- 'create': Create a new tab group. Returns a groupId to use with all other browser tools.\n" +
16
+ "- 'list': List all tab groups with tab counts.\n" +
17
+ "- 'delete': Delete a tab group and optionally close its tabs.\n\n" +
18
+ "⚡ IMPORTANT: Always create a tab group before opening tabs with browser_tabs.", {
19
+ type: "object",
20
+ properties: {
21
+ action: {
22
+ type: "string",
23
+ enum: ["create", "list", "delete"],
24
+ description: "Tab group action to perform",
25
+ },
26
+ name: {
27
+ type: "string",
28
+ description: "Human-readable name for the group (for 'create' action)",
29
+ },
30
+ color: {
31
+ type: "string",
32
+ enum: ["grey", "blue", "red", "yellow", "green", "pink", "purple", "cyan"],
33
+ description: "Visual color for the group (for 'create' action)",
34
+ },
35
+ groupId: {
36
+ type: "string",
37
+ description: "Group ID (for 'delete' action)",
38
+ },
39
+ closeTabs: {
40
+ type: "boolean",
41
+ description: "Whether to close all tabs in the group when deleting (default: true)",
42
+ },
43
+ },
44
+ required: ["action"],
45
+ }, async (args) => {
46
+ if (!config.cdpEndpoint) {
47
+ throw new Error("CDP endpoint not configured");
48
+ }
49
+ const { action } = args;
50
+ switch (action) {
51
+ case "create": {
52
+ if (!args.name) {
53
+ throw new Error("'name' is required for create action");
54
+ }
55
+ const group = createTabGroup({
56
+ name: args.name,
57
+ color: args.color,
58
+ });
59
+ // Check if visual grouping is available
60
+ let visualNote = "";
61
+ const hasExtension = await isTabGrouperAvailable(config.cdpEndpoint);
62
+ if (hasExtension) {
63
+ visualNote =
64
+ "\nVisual grouping: ✅ Tabs will appear in a Chrome tab group.";
65
+ }
66
+ else {
67
+ visualNote =
68
+ "\nVisual grouping: ⚠️ Companion extension not loaded. " +
69
+ "Tabs are logically isolated but won't show as a Chrome tab group. " +
70
+ "Load with: --chrome-extensions extensions/tab-grouper";
71
+ }
72
+ return (`**Tab group created**\n` +
73
+ `**groupId: ${group.groupId}** ← Use this with browser_tabs and other tools\n` +
74
+ `Name: ${group.name}\n` +
75
+ (group.color ? `Color: ${group.color}\n` : "") +
76
+ visualNote +
77
+ `\nNext step: Use browser_tabs with groupId="${group.groupId}" to create tabs in this group.`);
78
+ }
79
+ case "list": {
80
+ // Prune stale targets first
81
+ try {
82
+ const liveTabs = await listPagesViaPlaywright({
83
+ cdpUrl: config.cdpEndpoint,
84
+ });
85
+ const liveIds = new Set(liveTabs.map((t) => t.targetId));
86
+ pruneStaleTargets(liveIds);
87
+ }
88
+ catch {
89
+ // Pruning is best-effort
90
+ }
91
+ const groups = listTabGroups();
92
+ if (groups.length === 0) {
93
+ return "**No tab groups exist.**\nCreate one with browser_tab_group({ action: 'create', name: '...' })";
94
+ }
95
+ // Check for visual groups
96
+ let visualGroups = [];
97
+ try {
98
+ visualGroups = await listVisualTabGroups(config.cdpEndpoint);
99
+ }
100
+ catch {
101
+ // Extension not available
102
+ }
103
+ const output = groups
104
+ .map((g) => {
105
+ const visual = g.chromeGroupId
106
+ ? visualGroups.find((vg) => vg.id === g.chromeGroupId)
107
+ : null;
108
+ const visualLabel = visual
109
+ ? ` | Chrome group: ${visual.title} (${visual.color})`
110
+ : "";
111
+ return (`• **${g.name}** (${g.groupId})\n` +
112
+ ` Tabs: ${g.tabCount} | Color: ${g.color || "none"} | Created: ${new Date(g.createdAt).toISOString()}${visualLabel}`);
113
+ })
114
+ .join("\n\n");
115
+ return `**${groups.length} tab group(s)**\n\n${output}`;
116
+ }
117
+ case "delete": {
118
+ if (!args.groupId) {
119
+ throw new Error("'groupId' is required for delete action");
120
+ }
121
+ const closeTabs = args.closeTabs !== false; // default true
122
+ // Before deleting, try to ungroup tabs visually
123
+ const group = getTabGroup(args.groupId);
124
+ const { removedTargetIds } = deleteTabGroup(args.groupId);
125
+ if (closeTabs && removedTargetIds.length > 0) {
126
+ // Try visual ungrouping first (before closing)
127
+ if (group?.chromeGroupId) {
128
+ try {
129
+ const liveTabs = await listPagesViaPlaywright({
130
+ cdpUrl: config.cdpEndpoint,
131
+ });
132
+ const toUngroup = liveTabs.filter((t) => removedTargetIds.includes(t.targetId));
133
+ if (toUngroup.length > 0) {
134
+ const idMap = await mapTargetIdsToChromeTabIds(config.cdpEndpoint, toUngroup);
135
+ const chromeIds = [...idMap.values()];
136
+ if (chromeIds.length > 0) {
137
+ await ungroupTabsVisually(config.cdpEndpoint, chromeIds);
138
+ }
139
+ }
140
+ }
141
+ catch {
142
+ // Visual ungrouping is best-effort
143
+ }
144
+ }
145
+ const closeResults = [];
146
+ for (const targetId of removedTargetIds) {
147
+ try {
148
+ await closePageByTargetIdViaPlaywright({
149
+ cdpUrl: config.cdpEndpoint,
150
+ targetId,
151
+ });
152
+ closeResults.push(` ✓ Closed ${targetId}`);
153
+ }
154
+ catch {
155
+ closeResults.push(` ✗ Could not close ${targetId} (may already be closed)`);
156
+ }
157
+ }
158
+ return (`**Tab group deleted:** ${args.groupId}\n` +
159
+ `**${removedTargetIds.length} tab(s) removed:**\n` +
160
+ closeResults.join("\n"));
161
+ }
162
+ return (`**Tab group deleted:** ${args.groupId}\n` +
163
+ `Tabs removed from registry: ${removedTargetIds.length}` +
164
+ (!closeTabs && removedTargetIds.length > 0
165
+ ? " (tabs left open in browser)"
166
+ : ""));
167
+ }
168
+ default:
169
+ throw new Error(`Unknown action: ${action}. Use 'create', 'list', or 'delete'.`);
170
+ }
171
+ });
172
+ }
173
+ //# sourceMappingURL=tab-group.js.map