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 @@
1
+ {"version":3,"file":"tab-group.js","sourceRoot":"","sources":["../../../src/mcp/tools/tab-group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browser_tabs tool - manage browser tabs with targetId-based isolation and tab group support
3
+ */
4
+ import type { ServerConfig } from "../../config.js";
5
+ export declare function registerBrowserTabsTool(register: (name: string, description: string, schema: any, handler: (args: any) => Promise<any>) => void, config: ServerConfig): void;
6
+ //# sourceMappingURL=tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/tabs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAwBpD,wBAAgB,uBAAuB,CACrC,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,QAgQrB"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * browser_tabs tool - manage browser tabs with targetId-based isolation and tab group support
3
+ */
4
+ import { listPagesViaPlaywright, createPageViaPlaywright, closePageByTargetIdViaPlaywright, focusPageByTargetIdViaPlaywright, } from "../../browser/pw-session.js";
5
+ import { addTabToGroup, removeTabFromGroup, getTabsInGroup, getGroupForTab, getTabGroup, pruneStaleTargets, setChromeGroupId, getChromeTabId, } from "../../browser/tab-groups.js";
6
+ import { groupTabsVisually, isTabGrouperAvailable, createTabViaExtension, closeTabViaExtension, } from "../../browser/chrome-tab-groups.js";
7
+ export function registerBrowserTabsTool(register, config) {
8
+ register("browser_tabs", "Manage browser tabs. When using tab groups (recommended for multi-user), pass groupId to " +
9
+ "scope operations to your group's tabs only.\n\n" +
10
+ "Actions:\n" +
11
+ "- 'list': Show tabs. With groupId → only your group's tabs. Without → all tabs.\n" +
12
+ "- 'new': Create a tab. **Requires groupId** — tab is added to that group. Returns targetId.\n" +
13
+ "- 'close': Close a tab by index or targetId.\n" +
14
+ "- 'select': Focus a tab by index or targetId.\n\n" +
15
+ "⚡ IMPORTANT: Always create a tab group first with browser_tab_group, then use the groupId here.", {
16
+ type: "object",
17
+ properties: {
18
+ action: {
19
+ type: "string",
20
+ enum: ["list", "new", "close", "select"],
21
+ description: "Tab action to perform",
22
+ },
23
+ groupId: {
24
+ type: "string",
25
+ description: "Tab group ID to scope this operation to (from browser_tab_group). " +
26
+ "Recommended for multi-user isolation.",
27
+ },
28
+ url: {
29
+ type: "string",
30
+ description: "URL for 'new' action (defaults to about:blank)",
31
+ },
32
+ index: {
33
+ type: "number",
34
+ description: "Tab index for 'close' or 'select' actions (relative to group if groupId is set)",
35
+ },
36
+ targetId: {
37
+ type: "string",
38
+ description: "Target ID for 'close' or 'select' actions (alternative to index)",
39
+ },
40
+ },
41
+ required: ["action"],
42
+ }, async (args) => {
43
+ if (!config.cdpEndpoint) {
44
+ throw new Error("CDP endpoint not configured");
45
+ }
46
+ const { action, groupId, url, index, targetId } = args;
47
+ // Helper: get tabs scoped to group (or all tabs)
48
+ async function getScopedTabs() {
49
+ const allTabs = await listPagesViaPlaywright({ cdpUrl: config.cdpEndpoint });
50
+ // Prune stale entries from registry
51
+ const liveIds = new Set(allTabs.map((t) => t.targetId));
52
+ pruneStaleTargets(liveIds);
53
+ if (!groupId) {
54
+ return allTabs;
55
+ }
56
+ // Validate group exists
57
+ const group = getTabGroup(groupId);
58
+ if (!group) {
59
+ throw new Error(`Tab group not found: ${groupId}. Create one first with browser_tab_group.`);
60
+ }
61
+ const groupTargetIds = new Set(getTabsInGroup(groupId));
62
+ return allTabs.filter((t) => groupTargetIds.has(t.targetId));
63
+ }
64
+ // Helper: resolve target from index or targetId, respecting group scope
65
+ async function resolveTarget(scopedTabs) {
66
+ if (targetId) {
67
+ // If groupId set, verify this tab belongs to the group
68
+ if (groupId) {
69
+ const tabGroup = getGroupForTab(targetId);
70
+ if (tabGroup !== groupId) {
71
+ throw new Error(`Tab ${targetId} does not belong to group ${groupId}.`);
72
+ }
73
+ }
74
+ return targetId;
75
+ }
76
+ if (typeof index === "number") {
77
+ const tab = scopedTabs[index];
78
+ if (!tab) {
79
+ throw new Error(`No tab at index ${index}` +
80
+ (groupId ? ` in group ${groupId}` : ""));
81
+ }
82
+ return tab.targetId;
83
+ }
84
+ throw new Error("Either 'index' or 'targetId' is required");
85
+ }
86
+ switch (action) {
87
+ case "list": {
88
+ const tabs = await getScopedTabs();
89
+ if (tabs.length === 0) {
90
+ if (groupId) {
91
+ return `**No tabs in group ${groupId}.**\nCreate one with browser_tabs({ action: 'new', groupId: '${groupId}', url: '...' })`;
92
+ }
93
+ return "**No tabs open.**";
94
+ }
95
+ const output = tabs
96
+ .map((tab, i) => {
97
+ const groupLabel = !groupId ? (() => {
98
+ const g = getGroupForTab(tab.targetId);
99
+ const info = g ? getTabGroup(g) : null;
100
+ return info ? ` [${info.name}]` : " [ungrouped]";
101
+ })() : "";
102
+ return (`[${i}] **targetId: ${tab.targetId}**${groupLabel}\n` +
103
+ ` ${tab.title || "(no title)"}\n` +
104
+ ` ${tab.url}`);
105
+ })
106
+ .join("\n\n");
107
+ const label = groupId ? `in group ${groupId}` : "total";
108
+ return `**${tabs.length} tab(s)** ${label}\n\n${output}`;
109
+ }
110
+ case "new": {
111
+ // groupId is required for creating tabs
112
+ if (!groupId) {
113
+ throw new Error("groupId is required when creating new tabs. " +
114
+ "Create a tab group first with browser_tab_group, then pass the groupId here.");
115
+ }
116
+ const group = getTabGroup(groupId);
117
+ if (!group) {
118
+ throw new Error(`Tab group not found: ${groupId}. Create one first with browser_tab_group.`);
119
+ }
120
+ const tabUrl = url || "about:blank";
121
+ let resultTargetId;
122
+ let chromeTabId;
123
+ // Prefer creating via extension (gives us Chrome tab ID directly for reliable grouping)
124
+ const hasExtension = await isTabGrouperAvailable(config.cdpEndpoint);
125
+ if (hasExtension) {
126
+ try {
127
+ const extTab = await createTabViaExtension(config.cdpEndpoint, tabUrl);
128
+ resultTargetId = extTab.targetId;
129
+ chromeTabId = extTab.chromeTabId;
130
+ }
131
+ catch {
132
+ // Fall back to Playwright
133
+ const pwTab = await createPageViaPlaywright({
134
+ cdpUrl: config.cdpEndpoint,
135
+ url: tabUrl,
136
+ });
137
+ resultTargetId = pwTab.targetId;
138
+ }
139
+ }
140
+ else {
141
+ const pwTab = await createPageViaPlaywright({
142
+ cdpUrl: config.cdpEndpoint,
143
+ url: tabUrl,
144
+ });
145
+ resultTargetId = pwTab.targetId;
146
+ }
147
+ // Associate with group in registry (include Chrome tab ID if available)
148
+ addTabToGroup(resultTargetId, groupId, chromeTabId);
149
+ // Add to Chrome visual group
150
+ if (chromeTabId !== undefined) {
151
+ try {
152
+ const color = group.color || "grey";
153
+ const result = await groupTabsVisually(config.cdpEndpoint, [chromeTabId], group.name, color, group.chromeGroupId);
154
+ if (!group.chromeGroupId) {
155
+ setChromeGroupId(groupId, result.groupId);
156
+ }
157
+ }
158
+ catch {
159
+ // Visual grouping is best-effort
160
+ }
161
+ }
162
+ return (`**Tab created**\n` +
163
+ `**targetId: ${resultTargetId}** ← Use this with other browser tools\n` +
164
+ `Group: ${groupId}\n` +
165
+ `URL: ${tabUrl}`);
166
+ }
167
+ case "close": {
168
+ const tabs = await getScopedTabs();
169
+ const tid = await resolveTarget(tabs);
170
+ // Get stored Chrome tab ID for clean closure
171
+ const storedChromeTabId = getChromeTabId(tid);
172
+ // Close the tab — prefer extension if we have the Chrome tab ID
173
+ if (storedChromeTabId !== undefined) {
174
+ try {
175
+ await closeTabViaExtension(config.cdpEndpoint, storedChromeTabId);
176
+ }
177
+ catch {
178
+ // Fall back to Playwright
179
+ await closePageByTargetIdViaPlaywright({
180
+ cdpUrl: config.cdpEndpoint,
181
+ targetId: tid,
182
+ });
183
+ }
184
+ }
185
+ else {
186
+ await closePageByTargetIdViaPlaywright({
187
+ cdpUrl: config.cdpEndpoint,
188
+ targetId: tid,
189
+ });
190
+ }
191
+ // Remove from registry
192
+ removeTabFromGroup(tid);
193
+ return `**Tab closed:** ${tid}`;
194
+ }
195
+ case "select": {
196
+ const tabs = await getScopedTabs();
197
+ const tid = await resolveTarget(tabs);
198
+ await focusPageByTargetIdViaPlaywright({
199
+ cdpUrl: config.cdpEndpoint,
200
+ targetId: tid,
201
+ });
202
+ return `**Tab focused:** ${tid}`;
203
+ }
204
+ default:
205
+ throw new Error(`Unknown action: ${action}`);
206
+ }
207
+ });
208
+ }
209
+ //# sourceMappingURL=tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../../src/mcp/tools/tabs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Simplified command formatting (stub from OpenClaw's cli/command-format.ts)
3
+ * For ultimate-playwright-mcp, we just return the command as-is
4
+ */
5
+ export declare function formatCliCommand(command: string): string;
6
+ //# sourceMappingURL=command-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-format.d.ts","sourceRoot":"","sources":["../../src/utils/command-format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Simplified command formatting (stub from OpenClaw's cli/command-format.ts)
3
+ * For ultimate-playwright-mcp, we just return the command as-is
4
+ */
5
+ export function formatCliCommand(command) {
6
+ return command;
7
+ }
8
+ //# sourceMappingURL=command-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-format.js","sourceRoot":"","sources":["../../src/utils/command-format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Simplified error utilities extracted from OpenClaw
3
+ * Original: src/infra/errors.ts
4
+ */
5
+ export declare function formatErrorMessage(err: unknown): string;
6
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAevD"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Simplified error utilities extracted from OpenClaw
3
+ * Original: src/infra/errors.ts
4
+ */
5
+ export function formatErrorMessage(err) {
6
+ if (err instanceof Error) {
7
+ return err.message || err.name || "Error";
8
+ }
9
+ if (typeof err === "string") {
10
+ return err;
11
+ }
12
+ if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
13
+ return String(err);
14
+ }
15
+ try {
16
+ return JSON.stringify(err);
17
+ }
18
+ catch {
19
+ return Object.prototype.toString.call(err);
20
+ }
21
+ }
22
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC;IAC5C,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACnF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Chrome extension installer - Downloads and extracts extensions from Chrome Web Store
3
+ */
4
+ /**
5
+ * Check if a string is a Chrome Web Store extension ID (32 lowercase letters)
6
+ */
7
+ export declare function isChromeStoreId(str: string): boolean;
8
+ /**
9
+ * Get the local path for an extension (either downloaded or direct path)
10
+ */
11
+ export declare function resolveExtensionPath(extensionIdOrPath: string): Promise<string>;
12
+ /**
13
+ * Resolve multiple extensions (mix of IDs and paths)
14
+ */
15
+ export declare function resolveExtensions(extensionsIdOrPaths: string[]): Promise<string[]>;
16
+ //# sourceMappingURL=extension-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-installer.d.ts","sourceRoot":"","sources":["../../src/utils/extension-installer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AA+BD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAerF;AA2ED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,mBAAmB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAcxF"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Chrome extension installer - Downloads and extracts extensions from Chrome Web Store
3
+ */
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import os from "node:os";
7
+ import { pipeline } from "node:stream/promises";
8
+ import { createWriteStream } from "node:fs";
9
+ import AdmZip from "adm-zip";
10
+ const EXTENSIONS_DIR = path.join(os.homedir(), ".ultimate-playwright-mcp", "extensions");
11
+ const CHROME_VERSION = "120.0.0.0"; // Hardcoded version that works for most extensions
12
+ /**
13
+ * Check if a string is a Chrome Web Store extension ID (32 lowercase letters)
14
+ */
15
+ export function isChromeStoreId(str) {
16
+ return /^[a-z]{32}$/.test(str);
17
+ }
18
+ /**
19
+ * Strip CRX header from buffer to get the ZIP content
20
+ * CRX format: "Cr24" magic + version + header length + header + ZIP
21
+ */
22
+ function stripCrxHeader(crxBuffer) {
23
+ // Check for CRX magic number "Cr24"
24
+ if (crxBuffer.toString("utf8", 0, 4) !== "Cr24") {
25
+ throw new Error("Invalid CRX file: missing magic number");
26
+ }
27
+ // Read version (4 bytes at offset 4)
28
+ const version = crxBuffer.readUInt32LE(4);
29
+ if (version === 2) {
30
+ // CRX2 format: magic(4) + version(4) + pubkey_len(4) + sig_len(4) + pubkey + sig + ZIP
31
+ const pubkeyLen = crxBuffer.readUInt32LE(8);
32
+ const sigLen = crxBuffer.readUInt32LE(12);
33
+ const headerSize = 16 + pubkeyLen + sigLen;
34
+ return crxBuffer.subarray(headerSize);
35
+ }
36
+ else if (version === 3) {
37
+ // CRX3 format: magic(4) + version(4) + header_len(4) + header + ZIP
38
+ const headerLen = crxBuffer.readUInt32LE(8);
39
+ const headerSize = 12 + headerLen;
40
+ return crxBuffer.subarray(headerSize);
41
+ }
42
+ else {
43
+ throw new Error(`Unsupported CRX version: ${version}`);
44
+ }
45
+ }
46
+ /**
47
+ * Get the local path for an extension (either downloaded or direct path)
48
+ */
49
+ export async function resolveExtensionPath(extensionIdOrPath) {
50
+ // If it's a local path that exists, use it directly
51
+ if (fs.existsSync(extensionIdOrPath)) {
52
+ return extensionIdOrPath;
53
+ }
54
+ // If it's a Chrome Web Store ID, download it
55
+ if (isChromeStoreId(extensionIdOrPath)) {
56
+ return await downloadExtension(extensionIdOrPath);
57
+ }
58
+ throw new Error(`Invalid extension: "${extensionIdOrPath}". ` +
59
+ `Must be either a valid file path or a 32-character Chrome Web Store ID.`);
60
+ }
61
+ /**
62
+ * Download and extract a Chrome extension from the Web Store
63
+ */
64
+ async function downloadExtension(extensionId) {
65
+ // Ensure extensions directory exists
66
+ if (!fs.existsSync(EXTENSIONS_DIR)) {
67
+ fs.mkdirSync(EXTENSIONS_DIR, { recursive: true });
68
+ }
69
+ const extensionDir = path.join(EXTENSIONS_DIR, extensionId);
70
+ // If already downloaded, return the path
71
+ if (fs.existsSync(extensionDir)) {
72
+ console.error(`Extension ${extensionId} already downloaded`);
73
+ return extensionDir;
74
+ }
75
+ console.error(`Downloading extension ${extensionId} from Chrome Web Store...`);
76
+ // Build CRX download URL
77
+ const crxUrl = `https://clients2.google.com/service/update2/crx?` +
78
+ `response=redirect&prodversion=${CHROME_VERSION}&acceptformat=crx2,crx3&` +
79
+ `x=id%3D${extensionId}%26uc`;
80
+ try {
81
+ // Download CRX file
82
+ const response = await fetch(crxUrl);
83
+ if (!response.ok) {
84
+ throw new Error(`Failed to download: HTTP ${response.status}`);
85
+ }
86
+ // Save to temporary file
87
+ const tempCrxPath = path.join(EXTENSIONS_DIR, `${extensionId}.crx`);
88
+ const fileStream = createWriteStream(tempCrxPath);
89
+ if (!response.body) {
90
+ throw new Error("No response body");
91
+ }
92
+ await pipeline(response.body, fileStream);
93
+ // Extract CRX file (remove CRX header first)
94
+ console.error(`Extracting extension ${extensionId}...`);
95
+ const crxBuffer = fs.readFileSync(tempCrxPath);
96
+ const zipBuffer = stripCrxHeader(crxBuffer);
97
+ // Write stripped ZIP to temp file
98
+ const tempZipPath = path.join(EXTENSIONS_DIR, `${extensionId}.zip`);
99
+ fs.writeFileSync(tempZipPath, zipBuffer);
100
+ // Extract ZIP
101
+ const zip = new AdmZip(tempZipPath);
102
+ zip.extractAllTo(extensionDir, true);
103
+ // Clean up temp files
104
+ fs.unlinkSync(tempCrxPath);
105
+ fs.unlinkSync(tempZipPath);
106
+ console.error(`✓ Extension ${extensionId} installed to ${extensionDir}`);
107
+ return extensionDir;
108
+ }
109
+ catch (error) {
110
+ // Clean up on failure
111
+ if (fs.existsSync(extensionDir)) {
112
+ fs.rmSync(extensionDir, { recursive: true });
113
+ }
114
+ throw new Error(`Failed to download extension ${extensionId}: ${error instanceof Error ? error.message : String(error)}`);
115
+ }
116
+ }
117
+ /**
118
+ * Resolve multiple extensions (mix of IDs and paths)
119
+ */
120
+ export async function resolveExtensions(extensionsIdOrPaths) {
121
+ const resolved = [];
122
+ for (const item of extensionsIdOrPaths) {
123
+ try {
124
+ const path = await resolveExtensionPath(item);
125
+ resolved.push(path);
126
+ }
127
+ catch (error) {
128
+ console.error(`Warning: ${error instanceof Error ? error.message : String(error)}`);
129
+ // Continue with other extensions even if one fails
130
+ }
131
+ }
132
+ return resolved;
133
+ }
134
+ //# sourceMappingURL=extension-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-installer.js","sourceRoot":"","sources":["../../src/utils/extension-installer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "ultimate-playwright-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Multi-agent Playwright MCP server with tab isolation via targetId",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "ultimate-playwright-mcp": "./dist/cli.js",
10
+ "upmcp": "./dist/cli.js",
11
+ "upmcp-daemon": "./dist/daemon/cli.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "watch": "tsc --watch",
27
+ "lint": "eslint .",
28
+ "type-check": "tsc --noEmit",
29
+ "test": "playwright test",
30
+ "test:headed": "playwright test --headed",
31
+ "test:debug": "playwright test --debug",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "keywords": [
35
+ "mcp",
36
+ "playwright",
37
+ "browser",
38
+ "automation",
39
+ "multi-agent",
40
+ "tab-isolation",
41
+ "cdp"
42
+ ],
43
+ "author": "Patrick Menlove",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/pm990320/ultimate-playwright-mcp.git"
48
+ },
49
+ "homepage": "https://github.com/pm990320/ultimate-playwright-mcp#readme",
50
+ "bugs": {
51
+ "url": "https://github.com/pm990320/ultimate-playwright-mcp/issues"
52
+ },
53
+ "dependencies": {
54
+ "@modelcontextprotocol/sdk": "^1.0.4",
55
+ "adm-zip": "^0.5.16",
56
+ "commander": "^12.1.0",
57
+ "glob": "^13.0.1",
58
+ "playwright-core": "^1.49.1",
59
+ "ws": "^8.19.0"
60
+ },
61
+ "devDependencies": {
62
+ "@playwright/test": "^1.49.1",
63
+ "@types/adm-zip": "^0.5.7",
64
+ "@types/node": "^22.10.2",
65
+ "@types/ws": "^8.18.1",
66
+ "@typescript-eslint/eslint-plugin": "^8.18.2",
67
+ "@typescript-eslint/parser": "^8.18.2",
68
+ "eslint": "^9.17.0",
69
+ "globals": "^17.3.0",
70
+ "typescript": "^5.7.2"
71
+ },
72
+ "engines": {
73
+ "node": ">=18.0.0"
74
+ }
75
+ }