@stablyai/internal-playwright 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 (297) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +168 -0
  4. package/ThirdPartyNotices.txt +6277 -0
  5. package/cli.js +19 -0
  6. package/index.d.ts +17 -0
  7. package/index.js +17 -0
  8. package/index.mjs +18 -0
  9. package/jsx-runtime.js +42 -0
  10. package/jsx-runtime.mjs +21 -0
  11. package/lib/agents/generateAgents.js +265 -0
  12. package/lib/agents/generator.md +102 -0
  13. package/lib/agents/healer.md +78 -0
  14. package/lib/agents/planner.md +135 -0
  15. package/lib/cli.js +274 -0
  16. package/lib/common/config.js +274 -0
  17. package/lib/common/config.js.map +7 -0
  18. package/lib/common/configLoader.js +377 -0
  19. package/lib/common/configLoader.js.map +7 -0
  20. package/lib/common/esmLoaderHost.js +102 -0
  21. package/lib/common/esmLoaderHost.js.map +7 -0
  22. package/lib/common/expectBundle.js +52 -0
  23. package/lib/common/expectBundle.js.map +7 -0
  24. package/lib/common/expectBundleImpl.js +389 -0
  25. package/lib/common/expectBundleImpl.js.map +7 -0
  26. package/lib/common/fixtures.js +302 -0
  27. package/lib/common/fixtures.js.map +7 -0
  28. package/lib/common/globals.js +58 -0
  29. package/lib/common/globals.js.map +7 -0
  30. package/lib/common/ipc.js +60 -0
  31. package/lib/common/ipc.js.map +7 -0
  32. package/lib/common/poolBuilder.js +85 -0
  33. package/lib/common/poolBuilder.js.map +7 -0
  34. package/lib/common/process.js +104 -0
  35. package/lib/common/process.js.map +7 -0
  36. package/lib/common/suiteUtils.js +140 -0
  37. package/lib/common/suiteUtils.js.map +7 -0
  38. package/lib/common/test.js +321 -0
  39. package/lib/common/test.js.map +7 -0
  40. package/lib/common/testLoader.js +100 -0
  41. package/lib/common/testLoader.js.map +7 -0
  42. package/lib/common/testType.js +310 -0
  43. package/lib/common/testType.js.map +7 -0
  44. package/lib/fsWatcher.js +67 -0
  45. package/lib/fsWatcher.js.map +7 -0
  46. package/lib/index.js +696 -0
  47. package/lib/index.js.map +7 -0
  48. package/lib/internalsForTest.js +42 -0
  49. package/lib/internalsForTest.js.map +7 -0
  50. package/lib/isomorphic/events.js +77 -0
  51. package/lib/isomorphic/events.js.map +7 -0
  52. package/lib/isomorphic/folders.js +30 -0
  53. package/lib/isomorphic/folders.js.map +7 -0
  54. package/lib/isomorphic/stringInternPool.js +69 -0
  55. package/lib/isomorphic/stringInternPool.js.map +7 -0
  56. package/lib/isomorphic/teleReceiver.js +507 -0
  57. package/lib/isomorphic/teleReceiver.js.map +7 -0
  58. package/lib/isomorphic/teleSuiteUpdater.js +137 -0
  59. package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
  60. package/lib/isomorphic/testServerConnection.js +211 -0
  61. package/lib/isomorphic/testServerConnection.js.map +7 -0
  62. package/lib/isomorphic/testServerInterface.js +16 -0
  63. package/lib/isomorphic/testServerInterface.js.map +7 -0
  64. package/lib/isomorphic/testTree.js +334 -0
  65. package/lib/isomorphic/testTree.js.map +7 -0
  66. package/lib/isomorphic/types.d.js +16 -0
  67. package/lib/isomorphic/types.d.js.map +7 -0
  68. package/lib/loader/loaderMain.js +59 -0
  69. package/lib/loader/loaderMain.js.map +7 -0
  70. package/lib/matchers/expect.js +325 -0
  71. package/lib/matchers/expect.js.map +7 -0
  72. package/lib/matchers/matcherHint.js +87 -0
  73. package/lib/matchers/matcherHint.js.map +7 -0
  74. package/lib/matchers/matchers.js +366 -0
  75. package/lib/matchers/matchers.js.map +7 -0
  76. package/lib/matchers/toBeTruthy.js +73 -0
  77. package/lib/matchers/toBeTruthy.js.map +7 -0
  78. package/lib/matchers/toEqual.js +99 -0
  79. package/lib/matchers/toEqual.js.map +7 -0
  80. package/lib/matchers/toHaveURL.js +102 -0
  81. package/lib/matchers/toHaveURL.js.map +7 -0
  82. package/lib/matchers/toMatchAriaSnapshot.js +159 -0
  83. package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
  84. package/lib/matchers/toMatchSnapshot.js +359 -0
  85. package/lib/matchers/toMatchSnapshot.js.map +7 -0
  86. package/lib/matchers/toMatchText.js +99 -0
  87. package/lib/matchers/toMatchText.js.map +7 -0
  88. package/lib/mcp/browser/actions.d.js +16 -0
  89. package/lib/mcp/browser/backend.js +93 -0
  90. package/lib/mcp/browser/backend.js.map +7 -0
  91. package/lib/mcp/browser/browserContextFactory.js +296 -0
  92. package/lib/mcp/browser/browserServerBackend.js +76 -0
  93. package/lib/mcp/browser/codegen.js +66 -0
  94. package/lib/mcp/browser/config.js +385 -0
  95. package/lib/mcp/browser/context.js +287 -0
  96. package/lib/mcp/browser/response.js +228 -0
  97. package/lib/mcp/browser/sessionLog.js +160 -0
  98. package/lib/mcp/browser/tab.js +277 -0
  99. package/lib/mcp/browser/tool.js +30 -0
  100. package/lib/mcp/browser/tool.js.map +7 -0
  101. package/lib/mcp/browser/tools/common.js +63 -0
  102. package/lib/mcp/browser/tools/console.js +44 -0
  103. package/lib/mcp/browser/tools/dialogs.js +60 -0
  104. package/lib/mcp/browser/tools/evaluate.js +70 -0
  105. package/lib/mcp/browser/tools/files.js +58 -0
  106. package/lib/mcp/browser/tools/form.js +74 -0
  107. package/lib/mcp/browser/tools/install.js +69 -0
  108. package/lib/mcp/browser/tools/keyboard.js +85 -0
  109. package/lib/mcp/browser/tools/mouse.js +107 -0
  110. package/lib/mcp/browser/tools/navigate.js +62 -0
  111. package/lib/mcp/browser/tools/network.js +54 -0
  112. package/lib/mcp/browser/tools/pdf.js +59 -0
  113. package/lib/mcp/browser/tools/screenshot.js +88 -0
  114. package/lib/mcp/browser/tools/snapshot.js +182 -0
  115. package/lib/mcp/browser/tools/tabs.js +67 -0
  116. package/lib/mcp/browser/tools/tool.js +49 -0
  117. package/lib/mcp/browser/tools/tracing.js +74 -0
  118. package/lib/mcp/browser/tools/utils.js +100 -0
  119. package/lib/mcp/browser/tools/verify.js +154 -0
  120. package/lib/mcp/browser/tools/wait.js +63 -0
  121. package/lib/mcp/browser/tools.js +80 -0
  122. package/lib/mcp/browser/tools.js.map +7 -0
  123. package/lib/mcp/browser/watchdog.js +44 -0
  124. package/lib/mcp/config.d.js +16 -0
  125. package/lib/mcp/extension/cdpRelay.js +351 -0
  126. package/lib/mcp/extension/extensionContextFactory.js +75 -0
  127. package/lib/mcp/extension/protocol.js +28 -0
  128. package/lib/mcp/index.js +61 -0
  129. package/lib/mcp/log.js +35 -0
  130. package/lib/mcp/program.js +96 -0
  131. package/lib/mcp/sdk/bundle.js +81 -0
  132. package/lib/mcp/sdk/bundle.js.map +7 -0
  133. package/lib/mcp/sdk/call.js +49 -0
  134. package/lib/mcp/sdk/call.js.map +7 -0
  135. package/lib/mcp/sdk/exports.js +32 -0
  136. package/lib/mcp/sdk/exports.js.map +7 -0
  137. package/lib/mcp/sdk/http.js +187 -0
  138. package/lib/mcp/sdk/http.js.map +7 -0
  139. package/lib/mcp/sdk/inProcessTransport.js +71 -0
  140. package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
  141. package/lib/mcp/sdk/mdb.js +206 -0
  142. package/lib/mcp/sdk/mdb.js.map +7 -0
  143. package/lib/mcp/sdk/proxyBackend.js +128 -0
  144. package/lib/mcp/sdk/proxyBackend.js.map +7 -0
  145. package/lib/mcp/sdk/server.js +189 -0
  146. package/lib/mcp/sdk/server.js.map +7 -0
  147. package/lib/mcp/sdk/tool.js +51 -0
  148. package/lib/mcp/sdk/tool.js.map +7 -0
  149. package/lib/mcp/test/backend.js +67 -0
  150. package/lib/mcp/test/backend.js.map +7 -0
  151. package/lib/mcp/test/browserBackend.js +98 -0
  152. package/lib/mcp/test/context.js +48 -0
  153. package/lib/mcp/test/context.js.map +7 -0
  154. package/lib/mcp/test/generatorTools.js +122 -0
  155. package/lib/mcp/test/plannerTools.js +46 -0
  156. package/lib/mcp/test/seed.js +72 -0
  157. package/lib/mcp/test/streams.js +39 -0
  158. package/lib/mcp/test/streams.js.map +7 -0
  159. package/lib/mcp/test/testBackend.js +97 -0
  160. package/lib/mcp/test/testContext.js +176 -0
  161. package/lib/mcp/test/testTool.js +30 -0
  162. package/lib/mcp/test/testTools.js +115 -0
  163. package/lib/mcp/test/tool.js +30 -0
  164. package/lib/mcp/test/tool.js.map +7 -0
  165. package/lib/mcp/test/tools.js +150 -0
  166. package/lib/mcp/test/tools.js.map +7 -0
  167. package/lib/mcp/vscode/host.js +187 -0
  168. package/lib/mcp/vscode/main.js +77 -0
  169. package/lib/mcpBundleImpl.js +41 -0
  170. package/lib/mcpBundleImpl.js.map +7 -0
  171. package/lib/plugins/gitCommitInfoPlugin.js +198 -0
  172. package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
  173. package/lib/plugins/index.js +28 -0
  174. package/lib/plugins/index.js.map +7 -0
  175. package/lib/plugins/webServerPlugin.js +209 -0
  176. package/lib/plugins/webServerPlugin.js.map +7 -0
  177. package/lib/program.js +412 -0
  178. package/lib/program.js.map +7 -0
  179. package/lib/reporters/base.js +609 -0
  180. package/lib/reporters/base.js.map +7 -0
  181. package/lib/reporters/blob.js +135 -0
  182. package/lib/reporters/blob.js.map +7 -0
  183. package/lib/reporters/dot.js +82 -0
  184. package/lib/reporters/dot.js.map +7 -0
  185. package/lib/reporters/empty.js +32 -0
  186. package/lib/reporters/empty.js.map +7 -0
  187. package/lib/reporters/github.js +128 -0
  188. package/lib/reporters/github.js.map +7 -0
  189. package/lib/reporters/html.js +644 -0
  190. package/lib/reporters/html.js.map +7 -0
  191. package/lib/reporters/internalReporter.js +130 -0
  192. package/lib/reporters/internalReporter.js.map +7 -0
  193. package/lib/reporters/json.js +254 -0
  194. package/lib/reporters/json.js.map +7 -0
  195. package/lib/reporters/junit.js +230 -0
  196. package/lib/reporters/junit.js.map +7 -0
  197. package/lib/reporters/line.js +113 -0
  198. package/lib/reporters/line.js.map +7 -0
  199. package/lib/reporters/list.js +235 -0
  200. package/lib/reporters/list.js.map +7 -0
  201. package/lib/reporters/listModeReporter.js +69 -0
  202. package/lib/reporters/listModeReporter.js.map +7 -0
  203. package/lib/reporters/markdown.js +144 -0
  204. package/lib/reporters/markdown.js.map +7 -0
  205. package/lib/reporters/merge.js +535 -0
  206. package/lib/reporters/merge.js.map +7 -0
  207. package/lib/reporters/multiplexer.js +104 -0
  208. package/lib/reporters/multiplexer.js.map +7 -0
  209. package/lib/reporters/reporterV2.js +102 -0
  210. package/lib/reporters/reporterV2.js.map +7 -0
  211. package/lib/reporters/teleEmitter.js +297 -0
  212. package/lib/reporters/teleEmitter.js.map +7 -0
  213. package/lib/reporters/versions/blobV1.js +16 -0
  214. package/lib/reporters/versions/blobV1.js.map +7 -0
  215. package/lib/runner/dispatcher.js +491 -0
  216. package/lib/runner/dispatcher.js.map +7 -0
  217. package/lib/runner/failureTracker.js +72 -0
  218. package/lib/runner/failureTracker.js.map +7 -0
  219. package/lib/runner/lastRun.js +77 -0
  220. package/lib/runner/lastRun.js.map +7 -0
  221. package/lib/runner/loadUtils.js +333 -0
  222. package/lib/runner/loadUtils.js.map +7 -0
  223. package/lib/runner/loaderHost.js +89 -0
  224. package/lib/runner/loaderHost.js.map +7 -0
  225. package/lib/runner/processHost.js +161 -0
  226. package/lib/runner/processHost.js.map +7 -0
  227. package/lib/runner/projectUtils.js +241 -0
  228. package/lib/runner/projectUtils.js.map +7 -0
  229. package/lib/runner/rebase.js +189 -0
  230. package/lib/runner/rebase.js.map +7 -0
  231. package/lib/runner/reporters.js +137 -0
  232. package/lib/runner/reporters.js.map +7 -0
  233. package/lib/runner/runner.js +173 -0
  234. package/lib/runner/sigIntWatcher.js +96 -0
  235. package/lib/runner/sigIntWatcher.js.map +7 -0
  236. package/lib/runner/taskRunner.js +127 -0
  237. package/lib/runner/taskRunner.js.map +7 -0
  238. package/lib/runner/tasks.js +410 -0
  239. package/lib/runner/tasks.js.map +7 -0
  240. package/lib/runner/testGroups.js +117 -0
  241. package/lib/runner/testGroups.js.map +7 -0
  242. package/lib/runner/testRunner.js +390 -0
  243. package/lib/runner/testRunner.js.map +7 -0
  244. package/lib/runner/testServer.js +264 -0
  245. package/lib/runner/testServer.js.map +7 -0
  246. package/lib/runner/uiMode.js +271 -0
  247. package/lib/runner/uiModeReporter.js +30 -0
  248. package/lib/runner/uiModeReporter.js.map +7 -0
  249. package/lib/runner/vcs.js +72 -0
  250. package/lib/runner/vcs.js.map +7 -0
  251. package/lib/runner/watchMode.js +395 -0
  252. package/lib/runner/watchMode.js.map +7 -0
  253. package/lib/runner/workerHost.js +95 -0
  254. package/lib/runner/workerHost.js.map +7 -0
  255. package/lib/store.js +98 -0
  256. package/lib/third_party/pirates.js +62 -0
  257. package/lib/third_party/pirates.js.map +7 -0
  258. package/lib/third_party/tsconfig-loader.js +103 -0
  259. package/lib/third_party/tsconfig-loader.js.map +7 -0
  260. package/lib/transform/babelBundle.js +43 -0
  261. package/lib/transform/babelBundle.js.map +7 -0
  262. package/lib/transform/babelBundleImpl.js +461 -0
  263. package/lib/transform/babelBundleImpl.js.map +7 -0
  264. package/lib/transform/compilationCache.js +272 -0
  265. package/lib/transform/compilationCache.js.map +7 -0
  266. package/lib/transform/esmLoader.js +104 -0
  267. package/lib/transform/esmLoader.js.map +7 -0
  268. package/lib/transform/esmUtils.js +32 -0
  269. package/lib/transform/portTransport.js +67 -0
  270. package/lib/transform/portTransport.js.map +7 -0
  271. package/lib/transform/transform.js +293 -0
  272. package/lib/transform/transform.js.map +7 -0
  273. package/lib/util.js +403 -0
  274. package/lib/util.js.map +7 -0
  275. package/lib/utilsBundle.js +43 -0
  276. package/lib/utilsBundle.js.map +7 -0
  277. package/lib/utilsBundleImpl.js +100 -0
  278. package/lib/utilsBundleImpl.js.map +7 -0
  279. package/lib/worker/fixtureRunner.js +258 -0
  280. package/lib/worker/fixtureRunner.js.map +7 -0
  281. package/lib/worker/stepContext.js +34 -0
  282. package/lib/worker/testInfo.js +508 -0
  283. package/lib/worker/testInfo.js.map +7 -0
  284. package/lib/worker/testTracing.js +344 -0
  285. package/lib/worker/testTracing.js.map +7 -0
  286. package/lib/worker/timeoutManager.js +174 -0
  287. package/lib/worker/timeoutManager.js.map +7 -0
  288. package/lib/worker/util.js +31 -0
  289. package/lib/worker/util.js.map +7 -0
  290. package/lib/worker/workerMain.js +520 -0
  291. package/lib/worker/workerMain.js.map +7 -0
  292. package/package.json +74 -0
  293. package/test.d.ts +18 -0
  294. package/test.js +24 -0
  295. package/test.mjs +33 -0
  296. package/types/test.d.ts +10217 -0
  297. package/types/testReporter.d.ts +816 -0
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var mdb_exports = {};
30
+ __export(mdb_exports, {
31
+ MDBBackend: () => MDBBackend,
32
+ runMainBackend: () => runMainBackend,
33
+ runOnPauseBackendLoop: () => runOnPauseBackendLoop
34
+ });
35
+ module.exports = __toCommonJS(mdb_exports);
36
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
37
+ var import_utils = require("playwright-core/lib/utils");
38
+ var import_tool = require("./tool");
39
+ var mcpBundle = __toESM(require("./bundle"));
40
+ var mcpServer = __toESM(require("./server"));
41
+ var mcpHttp = __toESM(require("./http"));
42
+ const mdbDebug = (0, import_utilsBundle.debug)("pw:mcp:mdb");
43
+ const errorsDebug = (0, import_utilsBundle.debug)("pw:mcp:errors");
44
+ const z = mcpBundle.z;
45
+ class MDBBackend {
46
+ constructor(mainBackend) {
47
+ this._progress = [];
48
+ this._mainBackend = mainBackend;
49
+ this._progressCallback = (params) => {
50
+ if (params.message)
51
+ this._progress.push({ type: "text", text: params.message });
52
+ };
53
+ }
54
+ async initialize(server, clientInfo) {
55
+ if (!this._clientInfo) {
56
+ this._clientInfo = clientInfo;
57
+ await this._mainBackend.initialize?.(server, clientInfo);
58
+ }
59
+ }
60
+ async listTools() {
61
+ return await this._mainBackend.listTools();
62
+ }
63
+ async callTool(name, args) {
64
+ if (name === pushToolsSchema.name) {
65
+ await this._createOnPauseClient(pushToolsSchema.inputSchema.parse(args || {}));
66
+ return { content: [{ type: "text", text: "Tools pushed" }] };
67
+ }
68
+ if (this._onPauseClient?.tools.find((tool) => tool.name === name)) {
69
+ const result2 = await this._onPauseClient.client.callTool({
70
+ name,
71
+ arguments: args
72
+ });
73
+ await this._mainBackend.afterCallTool?.(name, args, result2);
74
+ return result2;
75
+ }
76
+ await this._onPauseClient?.transport.terminateSession().catch(errorsDebug);
77
+ await this._onPauseClient?.client.close().catch(errorsDebug);
78
+ this._onPauseClient = void 0;
79
+ const resultPromise = new import_utils.ManualPromise();
80
+ const interruptPromise = new import_utils.ManualPromise();
81
+ this._interruptPromise = interruptPromise;
82
+ this._mainBackend.callTool(name, args, this._progressCallback).then((result2) => {
83
+ resultPromise.resolve(result2);
84
+ }).catch((e) => {
85
+ resultPromise.resolve({ content: [{ type: "text", text: String(e) }], isError: true });
86
+ });
87
+ const result = await Promise.race([interruptPromise, resultPromise]);
88
+ if (interruptPromise.isDone())
89
+ mdbDebug("client call intercepted", result);
90
+ else
91
+ mdbDebug("client call result", result);
92
+ result.content.unshift(...this._progress);
93
+ this._progress.length = 0;
94
+ return result;
95
+ }
96
+ async _createOnPauseClient(params) {
97
+ if (this._onPauseClient)
98
+ await this._onPauseClient.client.close().catch(errorsDebug);
99
+ this._onPauseClient = await this._createClient(params.mcpUrl);
100
+ this._interruptPromise?.resolve({
101
+ content: [{
102
+ type: "text",
103
+ text: params.introMessage || ""
104
+ }]
105
+ });
106
+ this._interruptPromise = void 0;
107
+ }
108
+ async _createClient(url) {
109
+ const client = new mcpBundle.Client({ name: "Interrupting client", version: "0.0.0" }, { capabilities: { roots: {} } });
110
+ client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));
111
+ client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
112
+ client.setNotificationHandler(mcpBundle.ProgressNotificationSchema, (notification) => {
113
+ if (notification.method === "notifications/progress") {
114
+ const { message } = notification.params;
115
+ if (message)
116
+ this._progress.push({ type: "text", text: message });
117
+ }
118
+ });
119
+ const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(url));
120
+ await client.connect(transport);
121
+ const { tools } = await client.listTools();
122
+ return { client, tools, transport };
123
+ }
124
+ }
125
+ const pushToolsSchema = (0, import_tool.defineToolSchema)({
126
+ name: "mdb_push_tools",
127
+ title: "Push MCP tools to the tools stack",
128
+ description: "Push MCP tools to the tools stack",
129
+ inputSchema: z.object({
130
+ mcpUrl: z.string(),
131
+ introMessage: z.string().optional()
132
+ }),
133
+ type: "readOnly"
134
+ });
135
+ async function runMainBackend(backendFactory, options) {
136
+ const mdbBackend = new MDBBackend(backendFactory.create());
137
+ const factory = {
138
+ ...backendFactory,
139
+ create: () => mdbBackend
140
+ };
141
+ const url = await startAsHttp(factory, { port: options?.port || 0 });
142
+ process.env.PLAYWRIGHT_DEBUGGER_MCP = url;
143
+ if (options?.port !== void 0)
144
+ return url;
145
+ await mcpServer.connect(factory, new mcpBundle.StdioServerTransport(), false);
146
+ }
147
+ async function runOnPauseBackendLoop(backend, introMessage) {
148
+ const wrappedBackend = new ServerBackendWithCloseListener(backend);
149
+ const factory = {
150
+ name: "on-pause-backend",
151
+ nameInConfig: "on-pause-backend",
152
+ version: "0.0.0",
153
+ create: () => wrappedBackend
154
+ };
155
+ const httpServer = await mcpHttp.startHttpServer({ port: 0 });
156
+ const url = await mcpHttp.installHttpTransport(httpServer, factory, true);
157
+ const client = new mcpBundle.Client({ name: "Pushing client", version: "0.0.0" });
158
+ client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
159
+ const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(process.env.PLAYWRIGHT_DEBUGGER_MCP));
160
+ await client.connect(transport);
161
+ const pushToolsResult = await client.callTool({
162
+ name: pushToolsSchema.name,
163
+ arguments: {
164
+ mcpUrl: url,
165
+ introMessage
166
+ }
167
+ });
168
+ if (pushToolsResult.isError)
169
+ errorsDebug("Failed to push tools", pushToolsResult.content);
170
+ await transport.terminateSession();
171
+ await client.close();
172
+ await wrappedBackend.waitForClosed();
173
+ httpServer.close();
174
+ }
175
+ async function startAsHttp(backendFactory, options) {
176
+ const httpServer = await mcpHttp.startHttpServer(options);
177
+ return await mcpHttp.installHttpTransport(httpServer, backendFactory, true);
178
+ }
179
+ class ServerBackendWithCloseListener {
180
+ constructor(backend) {
181
+ this._serverClosedPromise = new import_utils.ManualPromise();
182
+ this._backend = backend;
183
+ }
184
+ async initialize(server, clientInfo) {
185
+ await this._backend.initialize?.(server, clientInfo);
186
+ }
187
+ async listTools() {
188
+ return this._backend.listTools();
189
+ }
190
+ async callTool(name, args, progress) {
191
+ return this._backend.callTool(name, args, progress);
192
+ }
193
+ serverClosed(server) {
194
+ this._backend.serverClosed?.(server);
195
+ this._serverClosedPromise.resolve();
196
+ }
197
+ async waitForClosed() {
198
+ await this._serverClosedPromise;
199
+ }
200
+ }
201
+ // Annotate the CommonJS export names for ESM import in node:
202
+ 0 && (module.exports = {
203
+ MDBBackend,
204
+ runMainBackend,
205
+ runOnPauseBackendLoop
206
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/sdk/mdb.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\nimport { ManualPromise } from 'playwright-core/lib/utils';\n\nimport { PingRequestSchema, z } from './bundle.js';\nimport { StreamableHTTPClientTransport } from './bundle.js';\nimport * as mcpBundle from './bundle.js';\n\nimport { defineToolSchema } from './tool.js';\nimport * as mcpServer from './server.js';\nimport * as mcpHttp from './http.js';\nimport { wrapInProcess } from './server.js';\n\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\n\nconst mdbDebug = debug('pw:mcp:mdb');\nconst errorsDebug = debug('pw:mcp:errors');\n\nexport class MDBBackend implements mcpServer.ServerBackend {\n private _stack: { client: Client, toolNames: string[], resultPromise: ManualPromise<mcpServer.CallToolResult> | undefined }[] = [];\n private _interruptPromise: ManualPromise<mcpServer.CallToolResult> | undefined;\n private _topLevelBackend: mcpServer.ServerBackend;\n private _initialized = false;\n\n constructor(topLevelBackend: mcpServer.ServerBackend) {\n this._topLevelBackend = topLevelBackend;\n }\n\n async initialize(server: mcpServer.Server): Promise<void> {\n if (this._initialized)\n return;\n this._initialized = true;\n const transport = await wrapInProcess(this._topLevelBackend);\n await this._pushClient(transport);\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n const response = await this._client().listTools();\n return response.tools;\n }\n\n async callTool(name: string, args: mcpServer.CallToolRequest['params']['arguments']): Promise<mcpServer.CallToolResult> {\n if (name === pushToolsSchema.name)\n return await this._pushTools(pushToolsSchema.inputSchema.parse(args || {}));\n\n const interruptPromise = new ManualPromise<mcpServer.CallToolResult>();\n this._interruptPromise = interruptPromise;\n let [entry] = this._stack;\n\n // Pop the client while the tool is not found.\n while (entry && !entry.toolNames.includes(name)) {\n mdbDebug('popping client from stack for ', name);\n this._stack.shift();\n await entry.client.close();\n entry = this._stack[0];\n }\n\n const resultPromise = new ManualPromise<mcpServer.CallToolResult>();\n entry.resultPromise = resultPromise;\n\n this._client().callTool({\n name,\n arguments: args,\n }).then(result => {\n resultPromise.resolve(result as mcpServer.CallToolResult);\n }).catch(e => {\n mdbDebug('error in client call', e);\n if (this._stack.length < 2)\n throw e;\n this._stack.shift();\n const prevEntry = this._stack[0];\n void prevEntry.resultPromise!.then(result => resultPromise.resolve(result));\n });\n const result = await Promise.race([interruptPromise, resultPromise]);\n if (interruptPromise.isDone())\n mdbDebug('client call intercepted', result);\n else\n mdbDebug('client call result', result);\n return result;\n }\n\n private _client(): Client {\n const [entry] = this._stack;\n if (!entry)\n throw new Error('No debugging backend available');\n return entry.client;\n }\n\n private async _pushTools(params: { mcpUrl: string, introMessage?: string }): Promise<mcpServer.CallToolResult> {\n mdbDebug('pushing tools to the stack', params.mcpUrl);\n const transport = new StreamableHTTPClientTransport(new URL(params.mcpUrl));\n await this._pushClient(transport, params.introMessage);\n return { content: [{ type: 'text', text: 'Tools pushed' }] };\n }\n\n private async _pushClient(transport: Transport, introMessage?: string): Promise<mcpServer.CallToolResult> {\n mdbDebug('pushing client to the stack');\n const client = new mcpBundle.Client({ name: 'Internal client', version: '0.0.0' });\n client.setRequestHandler(PingRequestSchema, () => ({}));\n await client.connect(transport);\n mdbDebug('connected to the new client');\n const { tools } = await client.listTools();\n this._stack.unshift({ client, toolNames: tools.map(tool => tool.name), resultPromise: undefined });\n mdbDebug('new tools added to the stack:', tools.map(tool => tool.name));\n mdbDebug('interrupting current call:', !!this._interruptPromise);\n this._interruptPromise?.resolve({\n content: [{\n type: 'text',\n text: introMessage || '',\n }],\n });\n this._interruptPromise = undefined;\n return { content: [{ type: 'text', text: 'Tools pushed' }] };\n }\n}\n\nconst pushToolsSchema = defineToolSchema({\n name: 'mdb_push_tools',\n title: 'Push MCP tools to the tools stack',\n description: 'Push MCP tools to the tools stack',\n inputSchema: z.object({\n mcpUrl: z.string(),\n introMessage: z.string().optional(),\n }),\n type: 'readOnly',\n});\n\nexport type ServerBackendOnPause = mcpServer.ServerBackend & {\n requestSelfDestruct?: () => void;\n};\n\nexport async function runMainBackend(backendFactory: mcpServer.ServerBackendFactory, options?: { port?: number }): Promise<string | undefined> {\n const mdbBackend = new MDBBackend(backendFactory.create());\n // Start HTTP unconditionally.\n const factory: mcpServer.ServerBackendFactory = {\n ...backendFactory,\n create: () => mdbBackend\n };\n const url = await startAsHttp(factory, { port: options?.port || 0 });\n process.env.PLAYWRIGHT_MDB_URL = url;\n\n if (options?.port !== undefined)\n return url;\n\n // Start stdio conditionally.\n await mcpServer.connect(factory, new mcpBundle.StdioServerTransport(), false);\n}\n\nexport async function runOnPauseBackendLoop(mdbUrl: string, backend: ServerBackendOnPause, introMessage: string) {\n const wrappedBackend = new OnceTimeServerBackendWrapper(backend);\n\n const factory = {\n name: 'on-pause-backend',\n nameInConfig: 'on-pause-backend',\n version: '0.0.0',\n create: () => wrappedBackend,\n };\n\n const httpServer = await mcpHttp.startHttpServer({ port: 0 });\n await mcpHttp.installHttpTransport(httpServer, factory);\n const url = mcpHttp.httpAddressToString(httpServer.address());\n\n const client = new mcpBundle.Client({ name: 'Internal client', version: '0.0.0' });\n client.setRequestHandler(PingRequestSchema, () => ({}));\n const transport = new StreamableHTTPClientTransport(new URL(mdbUrl));\n await client.connect(transport);\n\n const pushToolsResult = await client.callTool({\n name: pushToolsSchema.name,\n arguments: {\n mcpUrl: url,\n introMessage,\n },\n });\n if (pushToolsResult.isError)\n errorsDebug('Failed to push tools', pushToolsResult.content);\n await transport.terminateSession();\n await client.close();\n\n await wrappedBackend.waitForClosed();\n httpServer.close();\n}\n\nasync function startAsHttp(backendFactory: mcpServer.ServerBackendFactory, options: { port: number }) {\n const httpServer = await mcpHttp.startHttpServer(options);\n await mcpHttp.installHttpTransport(httpServer, backendFactory);\n return mcpHttp.httpAddressToString(httpServer.address());\n}\n\n\nclass OnceTimeServerBackendWrapper implements mcpServer.ServerBackend {\n private _backend: ServerBackendOnPause;\n private _selfDestructPromise = new ManualPromise<void>();\n\n constructor(backend: ServerBackendOnPause) {\n this._backend = backend;\n this._backend.requestSelfDestruct = () => this._selfDestructPromise.resolve();\n }\n\n async initialize(server: mcpServer.Server, clientVersion: mcpServer.ClientVersion, roots: mcpServer.Root[]): Promise<void> {\n await this._backend.initialize?.(server, clientVersion, roots);\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n return this._backend.listTools();\n }\n\n async callTool(name: string, args: mcpServer.CallToolRequest['params']['arguments']): Promise<mcpServer.CallToolResult> {\n return this._backend.callTool(name, args);\n }\n\n serverClosed(server: mcpServer.Server) {\n this._backend.serverClosed?.(server);\n this._selfDestructPromise.resolve();\n }\n\n async waitForClosed() {\n await this._selfDestructPromise;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_bundle", "result"]
7
+ }
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var proxyBackend_exports = {};
30
+ __export(proxyBackend_exports, {
31
+ ProxyBackend: () => ProxyBackend
32
+ });
33
+ module.exports = __toCommonJS(proxyBackend_exports);
34
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
35
+ var mcpBundle = __toESM(require("./bundle"));
36
+ const errorsDebug = (0, import_utilsBundle.debug)("pw:mcp:errors");
37
+ const { z, zodToJsonSchema } = mcpBundle;
38
+ class ProxyBackend {
39
+ constructor(mcpProviders) {
40
+ this._mcpProviders = mcpProviders;
41
+ this._contextSwitchTool = this._defineContextSwitchTool();
42
+ }
43
+ async initialize(server, clientInfo) {
44
+ this._clientInfo = clientInfo;
45
+ }
46
+ async listTools() {
47
+ const currentClient = await this._ensureCurrentClient();
48
+ const response = await currentClient.listTools();
49
+ if (this._mcpProviders.length === 1)
50
+ return response.tools;
51
+ return [
52
+ ...response.tools,
53
+ this._contextSwitchTool
54
+ ];
55
+ }
56
+ async callTool(name, args) {
57
+ if (name === this._contextSwitchTool.name)
58
+ return this._callContextSwitchTool(args);
59
+ const currentClient = await this._ensureCurrentClient();
60
+ return await currentClient.callTool({
61
+ name,
62
+ arguments: args
63
+ });
64
+ }
65
+ serverClosed() {
66
+ void this._currentClient?.close().catch(errorsDebug);
67
+ }
68
+ async _callContextSwitchTool(params) {
69
+ try {
70
+ const factory = this._mcpProviders.find((factory2) => factory2.name === params.name);
71
+ if (!factory)
72
+ throw new Error("Unknown connection method: " + params.name);
73
+ await this._setCurrentClient(factory);
74
+ return {
75
+ content: [{ type: "text", text: "### Result\nSuccessfully changed connection method.\n" }]
76
+ };
77
+ } catch (error) {
78
+ return {
79
+ content: [{ type: "text", text: `### Result
80
+ Error: ${error}
81
+ ` }],
82
+ isError: true
83
+ };
84
+ }
85
+ }
86
+ _defineContextSwitchTool() {
87
+ return {
88
+ name: "browser_connect",
89
+ description: [
90
+ "Connect to a browser using one of the available methods:",
91
+ ...this._mcpProviders.map((factory) => `- "${factory.name}": ${factory.description}`)
92
+ ].join("\n"),
93
+ inputSchema: zodToJsonSchema(z.object({
94
+ name: z.enum(this._mcpProviders.map((factory) => factory.name)).default(this._mcpProviders[0].name).describe("The method to use to connect to the browser")
95
+ }), { strictUnions: true }),
96
+ annotations: {
97
+ title: "Connect to a browser context",
98
+ readOnlyHint: true,
99
+ openWorldHint: false
100
+ }
101
+ };
102
+ }
103
+ async _ensureCurrentClient() {
104
+ if (this._currentClient)
105
+ return this._currentClient;
106
+ return await this._setCurrentClient(this._mcpProviders[0]);
107
+ }
108
+ async _setCurrentClient(factory) {
109
+ await this._currentClient?.close();
110
+ this._currentClient = void 0;
111
+ const client = new mcpBundle.Client({ name: "Playwright MCP Proxy", version: "0.0.0" });
112
+ client.registerCapabilities({
113
+ roots: {
114
+ listRoots: true
115
+ }
116
+ });
117
+ client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));
118
+ client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
119
+ const transport = await factory.connect();
120
+ await client.connect(transport);
121
+ this._currentClient = client;
122
+ return client;
123
+ }
124
+ }
125
+ // Annotate the CommonJS export names for ESM import in node:
126
+ 0 && (module.exports = {
127
+ ProxyBackend
128
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/sdk/proxyBackend.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\nimport * as mcp from './bundle';\n\nimport type { ServerBackend, ClientVersion, Root, Server } from './server.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { Tool, CallToolResult, CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\n\nexport type MCPProvider = {\n name: string;\n description: string;\n connect(): Promise<Transport>;\n};\n\nconst errorsDebug = debug('pw:mcp:errors');\n\nexport class ProxyBackend implements ServerBackend {\n private _mcpProviders: MCPProvider[];\n private _currentClient: Client | undefined;\n private _contextSwitchTool: Tool;\n private _roots: Root[] = [];\n\n constructor(mcpProviders: MCPProvider[]) {\n this._mcpProviders = mcpProviders;\n this._contextSwitchTool = this._defineContextSwitchTool();\n }\n\n async initialize(server: Server, clientVersion: ClientVersion, roots: Root[]): Promise<void> {\n this._roots = roots;\n await this._setCurrentClient(this._mcpProviders[0]);\n }\n\n async listTools(): Promise<Tool[]> {\n const response = await this._currentClient!.listTools();\n if (this._mcpProviders.length === 1)\n return response.tools;\n return [\n ...response.tools,\n this._contextSwitchTool,\n ];\n }\n\n async callTool(name: string, args: CallToolRequest['params']['arguments']): Promise<CallToolResult> {\n if (name === this._contextSwitchTool.name)\n return this._callContextSwitchTool(args);\n return await this._currentClient!.callTool({\n name,\n arguments: args,\n }) as CallToolResult;\n }\n\n serverClosed?(): void {\n void this._currentClient?.close().catch(errorsDebug);\n }\n\n private async _callContextSwitchTool(params: any): Promise<CallToolResult> {\n try {\n const factory = this._mcpProviders.find(factory => factory.name === params.name);\n if (!factory)\n throw new Error('Unknown connection method: ' + params.name);\n\n await this._setCurrentClient(factory);\n return {\n content: [{ type: 'text', text: '### Result\\nSuccessfully changed connection method.\\n' }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `### Result\\nError: ${error}\\n` }],\n isError: true,\n };\n }\n }\n\n private _defineContextSwitchTool(): Tool {\n return {\n name: 'browser_connect',\n description: [\n 'Connect to a browser using one of the available methods:',\n ...this._mcpProviders.map(factory => `- \"${factory.name}\": ${factory.description}`),\n ].join('\\n'),\n inputSchema: mcp.zodToJsonSchema(mcp.z.object({\n name: mcp.z.enum(this._mcpProviders.map(factory => factory.name) as [string, ...string[]]).default(this._mcpProviders[0].name).describe('The method to use to connect to the browser'),\n }), { strictUnions: true }) as Tool['inputSchema'],\n annotations: {\n title: 'Connect to a browser context',\n readOnlyHint: true,\n openWorldHint: false,\n },\n };\n }\n\n private async _setCurrentClient(factory: MCPProvider) {\n await this._currentClient?.close();\n this._currentClient = undefined;\n\n const client = new mcp.Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });\n client.registerCapabilities({\n roots: {\n listRoots: true,\n },\n });\n client.setRequestHandler(mcp.ListRootsRequestSchema, () => ({ roots: this._roots }));\n client.setRequestHandler(mcp.PingRequestSchema, () => ({}));\n\n const transport = await factory.connect();\n await client.connect(transport);\n this._currentClient = client;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["factory"]
7
+ }
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var server_exports = {};
30
+ __export(server_exports, {
31
+ connect: () => connect,
32
+ createServer: () => createServer,
33
+ firstRootPath: () => firstRootPath,
34
+ start: () => start,
35
+ wrapInProcess: () => wrapInProcess
36
+ });
37
+ module.exports = __toCommonJS(server_exports);
38
+ var import_url = require("url");
39
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
40
+ var mcpBundle = __toESM(require("./bundle"));
41
+ var import_http = require("./http");
42
+ var import_inProcessTransport = require("./inProcessTransport");
43
+ const serverDebug = (0, import_utilsBundle.debug)("pw:mcp:server");
44
+ async function connect(factory, transport, runHeartbeat) {
45
+ const server = createServer(factory.name, factory.version, factory.create(), runHeartbeat);
46
+ await server.connect(transport);
47
+ }
48
+ async function wrapInProcess(backend) {
49
+ const server = createServer("Internal", "0.0.0", backend, false);
50
+ return new import_inProcessTransport.InProcessTransport(server);
51
+ }
52
+ function createServer(name, version, backend, runHeartbeat) {
53
+ const server = new mcpBundle.Server({ name, version }, {
54
+ capabilities: {
55
+ tools: {}
56
+ }
57
+ });
58
+ server.setRequestHandler(mcpBundle.ListToolsRequestSchema, async () => {
59
+ serverDebug("listTools");
60
+ const tools = await backend.listTools();
61
+ return { tools };
62
+ });
63
+ let initializePromise;
64
+ server.setRequestHandler(mcpBundle.CallToolRequestSchema, async (request, extra) => {
65
+ serverDebug("callTool", request);
66
+ const progressToken = request.params._meta?.progressToken;
67
+ let progressCounter = 0;
68
+ const progress = progressToken ? (params) => {
69
+ extra.sendNotification({
70
+ method: "notifications/progress",
71
+ params: {
72
+ progressToken,
73
+ progress: params.progress ?? ++progressCounter,
74
+ total: params.total,
75
+ message: params.message
76
+ }
77
+ }).catch(serverDebug);
78
+ } : () => {
79
+ };
80
+ try {
81
+ if (!initializePromise)
82
+ initializePromise = initializeServer(server, backend, runHeartbeat);
83
+ await initializePromise;
84
+ return mergeTextParts(await backend.callTool(request.params.name, request.params.arguments || {}, progress));
85
+ } catch (error) {
86
+ return {
87
+ content: [{ type: "text", text: "### Result\n" + String(error) }],
88
+ isError: true
89
+ };
90
+ }
91
+ });
92
+ addServerListener(server, "close", () => backend.serverClosed?.(server));
93
+ return server;
94
+ }
95
+ const initializeServer = async (server, backend, runHeartbeat) => {
96
+ const capabilities = server.getClientCapabilities();
97
+ let clientRoots = [];
98
+ if (capabilities?.roots) {
99
+ const { roots } = await server.listRoots().catch((e) => {
100
+ serverDebug(e);
101
+ return { roots: [] };
102
+ });
103
+ clientRoots = roots;
104
+ }
105
+ const clientInfo = {
106
+ name: server.getClientVersion()?.name ?? "unknown",
107
+ version: server.getClientVersion()?.version ?? "unknown",
108
+ roots: clientRoots,
109
+ timestamp: Date.now()
110
+ };
111
+ await backend.initialize?.(server, clientInfo);
112
+ if (runHeartbeat)
113
+ startHeartbeat(server);
114
+ };
115
+ const startHeartbeat = (server) => {
116
+ const beat = () => {
117
+ Promise.race([
118
+ server.ping(),
119
+ new Promise((_, reject) => setTimeout(() => reject(new Error("ping timeout")), 5e3))
120
+ ]).then(() => {
121
+ setTimeout(beat, 3e3);
122
+ }).catch(() => {
123
+ void server.close();
124
+ });
125
+ };
126
+ beat();
127
+ };
128
+ function addServerListener(server, event, listener) {
129
+ const oldListener = server[`on${event}`];
130
+ server[`on${event}`] = () => {
131
+ oldListener?.();
132
+ listener();
133
+ };
134
+ }
135
+ async function start(serverBackendFactory, options) {
136
+ if (options.port === void 0) {
137
+ await connect(serverBackendFactory, new mcpBundle.StdioServerTransport(), false);
138
+ return;
139
+ }
140
+ const httpServer = await (0, import_http.startHttpServer)(options);
141
+ const url = await (0, import_http.installHttpTransport)(httpServer, serverBackendFactory, false, options.allowedHosts);
142
+ const mcpConfig = { mcpServers: {} };
143
+ mcpConfig.mcpServers[serverBackendFactory.nameInConfig] = {
144
+ url: `${url}/mcp`
145
+ };
146
+ const message = [
147
+ `Listening on ${url}`,
148
+ "Put this in your client config:",
149
+ JSON.stringify(mcpConfig, void 0, 2),
150
+ "For legacy SSE transport support, you can use the /sse endpoint instead."
151
+ ].join("\n");
152
+ console.error(message);
153
+ }
154
+ function firstRootPath(clientInfo) {
155
+ if (clientInfo.roots.length === 0)
156
+ return void 0;
157
+ const firstRootUri = clientInfo.roots[0]?.uri;
158
+ const url = firstRootUri ? new URL(firstRootUri) : void 0;
159
+ return url ? (0, import_url.fileURLToPath)(url) : void 0;
160
+ }
161
+ function mergeTextParts(result) {
162
+ const content = [];
163
+ const testParts = [];
164
+ for (const part of result.content) {
165
+ if (part.type === "text") {
166
+ testParts.push(part.text);
167
+ continue;
168
+ }
169
+ if (testParts.length > 0) {
170
+ content.push({ type: "text", text: testParts.join("\n") });
171
+ testParts.length = 0;
172
+ }
173
+ content.push(part);
174
+ }
175
+ if (testParts.length > 0)
176
+ content.push({ type: "text", text: testParts.join("\n") });
177
+ return {
178
+ ...result,
179
+ content
180
+ };
181
+ }
182
+ // Annotate the CommonJS export names for ESM import in node:
183
+ 0 && (module.exports = {
184
+ connect,
185
+ createServer,
186
+ firstRootPath,
187
+ start,
188
+ wrapInProcess
189
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/sdk/server.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\n\nimport * as mcp from './bundle';\nimport { InProcessTransport } from './inProcessTransport';\nimport { httpAddressToString, installHttpTransport, startHttpServer } from './http';\n\nimport type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nexport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nexport type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js';\n\nconst serverDebug = debug('pw:mcp:server');\nconst errorsDebug = debug('pw:mcp:errors');\n\nexport type ClientVersion = { name: string, version: string };\nexport interface ServerBackend {\n initialize?(server: Server, clientVersion: ClientVersion, roots: Root[]): Promise<void>;\n listTools(): Promise<Tool[]>;\n callTool(name: string, args: CallToolRequest['params']['arguments']): Promise<CallToolResult>;\n serverClosed?(server: Server): void;\n}\n\nexport type ServerBackendFactory = {\n name: string;\n nameInConfig: string;\n version: string;\n create: () => ServerBackend;\n};\n\nexport async function connect(factory: ServerBackendFactory, transport: Transport, runHeartbeat: boolean) {\n const server = createServer(factory.name, factory.version, factory.create(), runHeartbeat);\n await server.connect(transport);\n}\n\nexport async function wrapInProcess(backend: ServerBackend): Promise<Transport> {\n const server = createServer('Internal', '0.0.0', backend, false);\n return new InProcessTransport(server);\n}\n\nexport function createServer(name: string, version: string, backend: ServerBackend, runHeartbeat: boolean): Server {\n let initializedPromiseResolve = () => {};\n const initializedPromise = new Promise<void>(resolve => initializedPromiseResolve = resolve);\n const server = new mcp.Server({ name, version }, {\n capabilities: {\n tools: {},\n }\n });\n\n server.setRequestHandler(mcp.ListToolsRequestSchema, async () => {\n serverDebug('listTools');\n await initializedPromise;\n const tools = await backend.listTools();\n return { tools };\n });\n\n let heartbeatRunning = false;\n server.setRequestHandler(mcp.CallToolRequestSchema, async request => {\n serverDebug('callTool', request);\n await initializedPromise;\n\n if (runHeartbeat && !heartbeatRunning) {\n heartbeatRunning = true;\n startHeartbeat(server);\n }\n\n try {\n return await backend.callTool(request.params.name, request.params.arguments || {});\n } catch (error) {\n return {\n content: [{ type: 'text', text: '### Result\\n' + String(error) }],\n isError: true,\n };\n }\n });\n addServerListener(server, 'initialized', async () => {\n try {\n const capabilities = server.getClientCapabilities();\n let clientRoots: Root[] = [];\n if (capabilities?.roots) {\n const { roots } = await server.listRoots(undefined, { timeout: 2_000 }).catch(() => ({ roots: [] }));\n clientRoots = roots;\n }\n const clientVersion = server.getClientVersion() ?? { name: 'unknown', version: 'unknown' };\n await backend.initialize?.(server, clientVersion, clientRoots);\n initializedPromiseResolve();\n } catch (e) {\n errorsDebug(e);\n }\n });\n addServerListener(server, 'close', () => backend.serverClosed?.(server));\n return server;\n}\n\nconst startHeartbeat = (server: Server) => {\n const beat = () => {\n Promise.race([\n server.ping(),\n new Promise((_, reject) => setTimeout(() => reject(new Error('ping timeout')), 5000)),\n ]).then(() => {\n setTimeout(beat, 3000);\n }).catch(() => {\n void server.close();\n });\n };\n\n beat();\n};\n\nfunction addServerListener(server: Server, event: 'close' | 'initialized', listener: () => void) {\n const oldListener = server[`on${event}`];\n server[`on${event}`] = () => {\n oldListener?.();\n listener();\n };\n}\n\nexport async function start(serverBackendFactory: ServerBackendFactory, options: { host?: string; port?: number }) {\n if (options.port === undefined) {\n await connect(serverBackendFactory, new mcp.StdioServerTransport(), false);\n return;\n }\n\n const httpServer = await startHttpServer(options);\n await installHttpTransport(httpServer, serverBackendFactory);\n const url = httpAddressToString(httpServer.address());\n\n const mcpConfig: any = { mcpServers: { } };\n mcpConfig.mcpServers[serverBackendFactory.nameInConfig] = {\n url: `${url}/mcp`\n };\n const message = [\n `Listening on ${url}`,\n 'Put this in your client config:',\n JSON.stringify(mcpConfig, undefined, 2),\n 'For legacy SSE transport support, you can use the /sse endpoint instead.',\n ].join('\\n');\n // eslint-disable-next-line no-console\n console.error(message);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var tool_exports = {};
20
+ __export(tool_exports, {
21
+ defineToolSchema: () => defineToolSchema,
22
+ toMcpTool: () => toMcpTool
23
+ });
24
+ module.exports = __toCommonJS(tool_exports);
25
+ var import_bundle = require("../sdk/bundle");
26
+ const typesWithIntent = ["action", "assertion", "input"];
27
+ function toMcpTool(tool, options) {
28
+ const inputSchema = options?.addIntent && typesWithIntent.includes(tool.type) ? tool.inputSchema.extend({
29
+ intent: import_bundle.z.string().describe("The intent of the call, for example the test step description plan idea")
30
+ }) : tool.inputSchema;
31
+ const readOnly = tool.type === "readOnly" || tool.type === "assertion";
32
+ return {
33
+ name: tool.name,
34
+ description: tool.description,
35
+ inputSchema: (0, import_bundle.zodToJsonSchema)(inputSchema, { strictUnions: true }),
36
+ annotations: {
37
+ title: tool.title,
38
+ readOnlyHint: readOnly,
39
+ destructiveHint: !readOnly,
40
+ openWorldHint: true
41
+ }
42
+ };
43
+ }
44
+ function defineToolSchema(tool) {
45
+ return tool;
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ defineToolSchema,
50
+ toMcpTool
51
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/sdk/tool.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { zodToJsonSchema } from './bundle.js';\n\nimport type { z } from 'zod';\nimport type * as mcpServer from './server.js';\n\nexport type ToolSchema<Input extends z.Schema> = {\n name: string;\n title: string;\n description: string;\n inputSchema: Input;\n type: 'readOnly' | 'destructive';\n};\n\nexport function toMcpTool(tool: ToolSchema<any>): mcpServer.Tool {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: zodToJsonSchema(tool.inputSchema, { strictUnions: true }) as mcpServer.Tool['inputSchema'],\n annotations: {\n title: tool.title,\n readOnlyHint: tool.type === 'readOnly',\n destructiveHint: tool.type === 'destructive',\n openWorldHint: true,\n },\n };\n}\n\nexport function defineToolSchema<Input extends z.Schema>(tool: ToolSchema<Input>): ToolSchema<Input> {\n return tool;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAgC;AAazB,SAAS,UAAU,MAAuC;AAC/D,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,iBAAa,+BAAgB,KAAK,aAAa,EAAE,cAAc,KAAK,CAAC;AAAA,IACrE,aAAa;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,cAAc,KAAK,SAAS;AAAA,MAC5B,iBAAiB,KAAK,SAAS;AAAA,MAC/B,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAEO,SAAS,iBAAyC,MAA4C;AACnG,SAAO;AACT;",
6
+ "names": []
7
+ }