@one2x/playwright 1.57.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +168 -0
- package/ThirdPartyNotices.txt +6277 -0
- package/cli.js +19 -0
- package/index.d.ts +17 -0
- package/index.js +17 -0
- package/index.mjs +18 -0
- package/jsx-runtime.js +42 -0
- package/jsx-runtime.mjs +21 -0
- package/lib/agents/copilot-setup-steps.yml +34 -0
- package/lib/agents/generateAgents.js +394 -0
- package/lib/agents/generateAgents.js.map +7 -0
- package/lib/agents/playwright-test-coverage.prompt.md +31 -0
- package/lib/agents/playwright-test-generate.prompt.md +8 -0
- package/lib/agents/playwright-test-generator.agent.md +88 -0
- package/lib/agents/playwright-test-heal.prompt.md +6 -0
- package/lib/agents/playwright-test-healer.agent.md +55 -0
- package/lib/agents/playwright-test-plan.prompt.md +9 -0
- package/lib/agents/playwright-test-planner.agent.md +117 -0
- package/lib/common/config.js +280 -0
- package/lib/common/config.js.map +7 -0
- package/lib/common/configLoader.js +344 -0
- package/lib/common/configLoader.js.map +7 -0
- package/lib/common/esmLoaderHost.js +102 -0
- package/lib/common/esmLoaderHost.js.map +7 -0
- package/lib/common/expectBundle.js +52 -0
- package/lib/common/expectBundle.js.map +7 -0
- package/lib/common/expectBundleImpl.js +389 -0
- package/lib/common/expectBundleImpl.js.map +7 -0
- package/lib/common/fixtures.js +302 -0
- package/lib/common/fixtures.js.map +7 -0
- package/lib/common/globals.js +58 -0
- package/lib/common/globals.js.map +7 -0
- package/lib/common/ipc.js +60 -0
- package/lib/common/ipc.js.map +7 -0
- package/lib/common/poolBuilder.js +85 -0
- package/lib/common/poolBuilder.js.map +7 -0
- package/lib/common/process.js +104 -0
- package/lib/common/process.js.map +7 -0
- package/lib/common/suiteUtils.js +140 -0
- package/lib/common/suiteUtils.js.map +7 -0
- package/lib/common/test.js +321 -0
- package/lib/common/test.js.map +7 -0
- package/lib/common/testLoader.js +101 -0
- package/lib/common/testLoader.js.map +7 -0
- package/lib/common/testType.js +298 -0
- package/lib/common/testType.js.map +7 -0
- package/lib/common/validators.js +68 -0
- package/lib/common/validators.js.map +7 -0
- package/lib/fsWatcher.js +67 -0
- package/lib/fsWatcher.js.map +7 -0
- package/lib/index.js +682 -0
- package/lib/index.js.map +7 -0
- package/lib/internalsForTest.js +42 -0
- package/lib/internalsForTest.js.map +7 -0
- package/lib/isomorphic/events.js +77 -0
- package/lib/isomorphic/events.js.map +7 -0
- package/lib/isomorphic/folders.js +30 -0
- package/lib/isomorphic/folders.js.map +7 -0
- package/lib/isomorphic/stringInternPool.js +69 -0
- package/lib/isomorphic/stringInternPool.js.map +7 -0
- package/lib/isomorphic/teleReceiver.js +508 -0
- package/lib/isomorphic/teleReceiver.js.map +7 -0
- package/lib/isomorphic/teleSuiteUpdater.js +137 -0
- package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
- package/lib/isomorphic/testServerConnection.js +211 -0
- package/lib/isomorphic/testServerConnection.js.map +7 -0
- package/lib/isomorphic/testServerInterface.js +16 -0
- package/lib/isomorphic/testServerInterface.js.map +7 -0
- package/lib/isomorphic/testTree.js +334 -0
- package/lib/isomorphic/testTree.js.map +7 -0
- package/lib/isomorphic/types.d.js +16 -0
- package/lib/isomorphic/types.d.js.map +7 -0
- package/lib/loader/loaderMain.js +59 -0
- package/lib/loader/loaderMain.js.map +7 -0
- package/lib/matchers/expect.js +325 -0
- package/lib/matchers/expect.js.map +7 -0
- package/lib/matchers/matcherHint.js +87 -0
- package/lib/matchers/matcherHint.js.map +7 -0
- package/lib/matchers/matchers.js +366 -0
- package/lib/matchers/matchers.js.map +7 -0
- package/lib/matchers/toBeTruthy.js +73 -0
- package/lib/matchers/toBeTruthy.js.map +7 -0
- package/lib/matchers/toEqual.js +99 -0
- package/lib/matchers/toEqual.js.map +7 -0
- package/lib/matchers/toHaveURL.js +102 -0
- package/lib/matchers/toHaveURL.js.map +7 -0
- package/lib/matchers/toMatchAriaSnapshot.js +159 -0
- package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
- package/lib/matchers/toMatchSnapshot.js +341 -0
- package/lib/matchers/toMatchSnapshot.js.map +7 -0
- package/lib/matchers/toMatchText.js +99 -0
- package/lib/matchers/toMatchText.js.map +7 -0
- package/lib/mcp/browser/actions.d.js +16 -0
- package/lib/mcp/browser/actions.d.js.map +7 -0
- package/lib/mcp/browser/browserContextFactory.js +357 -0
- package/lib/mcp/browser/browserContextFactory.js.map +7 -0
- package/lib/mcp/browser/browserServerBackend.js +76 -0
- package/lib/mcp/browser/browserServerBackend.js.map +7 -0
- package/lib/mcp/browser/codegen.js +66 -0
- package/lib/mcp/browser/codegen.js.map +7 -0
- package/lib/mcp/browser/config.js +425 -0
- package/lib/mcp/browser/config.js.map +7 -0
- package/lib/mcp/browser/context.js +287 -0
- package/lib/mcp/browser/context.js.map +7 -0
- package/lib/mcp/browser/response.js +228 -0
- package/lib/mcp/browser/response.js.map +7 -0
- package/lib/mcp/browser/sessionLog.js +160 -0
- package/lib/mcp/browser/sessionLog.js.map +7 -0
- package/lib/mcp/browser/tab.js +280 -0
- package/lib/mcp/browser/tab.js.map +7 -0
- package/lib/mcp/browser/tools/actionRetry.js +40 -0
- package/lib/mcp/browser/tools/actionRetry.js.map +7 -0
- package/lib/mcp/browser/tools/common.js +63 -0
- package/lib/mcp/browser/tools/common.js.map +7 -0
- package/lib/mcp/browser/tools/console.js +44 -0
- package/lib/mcp/browser/tools/console.js.map +7 -0
- package/lib/mcp/browser/tools/dialogs.js +60 -0
- package/lib/mcp/browser/tools/dialogs.js.map +7 -0
- package/lib/mcp/browser/tools/evaluate.js +69 -0
- package/lib/mcp/browser/tools/evaluate.js.map +7 -0
- package/lib/mcp/browser/tools/files.js +58 -0
- package/lib/mcp/browser/tools/files.js.map +7 -0
- package/lib/mcp/browser/tools/form.js +79 -0
- package/lib/mcp/browser/tools/form.js.map +7 -0
- package/lib/mcp/browser/tools/install.js +69 -0
- package/lib/mcp/browser/tools/install.js.map +7 -0
- package/lib/mcp/browser/tools/keyboard.js +84 -0
- package/lib/mcp/browser/tools/keyboard.js.map +7 -0
- package/lib/mcp/browser/tools/mouse.js +107 -0
- package/lib/mcp/browser/tools/mouse.js.map +7 -0
- package/lib/mcp/browser/tools/navigate.js +62 -0
- package/lib/mcp/browser/tools/navigate.js.map +7 -0
- package/lib/mcp/browser/tools/network.js +54 -0
- package/lib/mcp/browser/tools/network.js.map +7 -0
- package/lib/mcp/browser/tools/pdf.js +59 -0
- package/lib/mcp/browser/tools/pdf.js.map +7 -0
- package/lib/mcp/browser/tools/screenshot.js +106 -0
- package/lib/mcp/browser/tools/screenshot.js.map +7 -0
- package/lib/mcp/browser/tools/snapshot.js +312 -0
- package/lib/mcp/browser/tools/snapshot.js.map +7 -0
- package/lib/mcp/browser/tools/tabs.js +67 -0
- package/lib/mcp/browser/tools/tabs.js.map +7 -0
- package/lib/mcp/browser/tools/tool.js +49 -0
- package/lib/mcp/browser/tools/tool.js.map +7 -0
- package/lib/mcp/browser/tools/tracing.js +74 -0
- package/lib/mcp/browser/tools/tracing.js.map +7 -0
- package/lib/mcp/browser/tools/utils.js +96 -0
- package/lib/mcp/browser/tools/utils.js.map +7 -0
- package/lib/mcp/browser/tools/verify.js +153 -0
- package/lib/mcp/browser/tools/verify.js.map +7 -0
- package/lib/mcp/browser/tools/wait.js +63 -0
- package/lib/mcp/browser/tools/wait.js.map +7 -0
- package/lib/mcp/browser/tools.js +80 -0
- package/lib/mcp/browser/tools.js.map +7 -0
- package/lib/mcp/browser/watchdog.js +44 -0
- package/lib/mcp/browser/watchdog.js.map +7 -0
- package/lib/mcp/config.d.js +16 -0
- package/lib/mcp/config.d.js.map +7 -0
- package/lib/mcp/extension/cdpRelay.js +351 -0
- package/lib/mcp/extension/cdpRelay.js.map +7 -0
- package/lib/mcp/extension/extensionContextFactory.js +75 -0
- package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
- package/lib/mcp/extension/protocol.js +28 -0
- package/lib/mcp/extension/protocol.js.map +7 -0
- package/lib/mcp/index.js +61 -0
- package/lib/mcp/index.js.map +7 -0
- package/lib/mcp/log.js +35 -0
- package/lib/mcp/log.js.map +7 -0
- package/lib/mcp/program.js +118 -0
- package/lib/mcp/program.js.map +7 -0
- package/lib/mcp/sdk/bundle.js +81 -0
- package/lib/mcp/sdk/bundle.js.map +7 -0
- package/lib/mcp/sdk/exports.js +32 -0
- package/lib/mcp/sdk/exports.js.map +7 -0
- package/lib/mcp/sdk/http.js +276 -0
- package/lib/mcp/sdk/http.js.map +7 -0
- package/lib/mcp/sdk/inProcessTransport.js +71 -0
- package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
- package/lib/mcp/sdk/mdb.js +208 -0
- package/lib/mcp/sdk/mdb.js.map +7 -0
- package/lib/mcp/sdk/proxyBackend.js +128 -0
- package/lib/mcp/sdk/proxyBackend.js.map +7 -0
- package/lib/mcp/sdk/server.js +190 -0
- package/lib/mcp/sdk/server.js.map +7 -0
- package/lib/mcp/sdk/tool.js +51 -0
- package/lib/mcp/sdk/tool.js.map +7 -0
- package/lib/mcp/test/browserBackend.js +98 -0
- package/lib/mcp/test/browserBackend.js.map +7 -0
- package/lib/mcp/test/generatorTools.js +122 -0
- package/lib/mcp/test/generatorTools.js.map +7 -0
- package/lib/mcp/test/plannerTools.js +46 -0
- package/lib/mcp/test/plannerTools.js.map +7 -0
- package/lib/mcp/test/seed.js +82 -0
- package/lib/mcp/test/seed.js.map +7 -0
- package/lib/mcp/test/streams.js +41 -0
- package/lib/mcp/test/streams.js.map +7 -0
- package/lib/mcp/test/testBackend.js +97 -0
- package/lib/mcp/test/testBackend.js.map +7 -0
- package/lib/mcp/test/testContext.js +216 -0
- package/lib/mcp/test/testContext.js.map +7 -0
- package/lib/mcp/test/testTool.js +30 -0
- package/lib/mcp/test/testTool.js.map +7 -0
- package/lib/mcp/test/testTools.js +111 -0
- package/lib/mcp/test/testTools.js.map +7 -0
- package/lib/mcpBundleImpl.js +41 -0
- package/lib/mcpBundleImpl.js.map +7 -0
- package/lib/plugins/gitCommitInfoPlugin.js +198 -0
- package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
- package/lib/plugins/index.js +28 -0
- package/lib/plugins/index.js.map +7 -0
- package/lib/plugins/webServerPlugin.js +233 -0
- package/lib/plugins/webServerPlugin.js.map +7 -0
- package/lib/program.js +412 -0
- package/lib/program.js.map +7 -0
- package/lib/reporters/base.js +609 -0
- package/lib/reporters/base.js.map +7 -0
- package/lib/reporters/blob.js +135 -0
- package/lib/reporters/blob.js.map +7 -0
- package/lib/reporters/dot.js +82 -0
- package/lib/reporters/dot.js.map +7 -0
- package/lib/reporters/empty.js +32 -0
- package/lib/reporters/empty.js.map +7 -0
- package/lib/reporters/github.js +128 -0
- package/lib/reporters/github.js.map +7 -0
- package/lib/reporters/html.js +623 -0
- package/lib/reporters/html.js.map +7 -0
- package/lib/reporters/internalReporter.js +130 -0
- package/lib/reporters/internalReporter.js.map +7 -0
- package/lib/reporters/json.js +254 -0
- package/lib/reporters/json.js.map +7 -0
- package/lib/reporters/junit.js +232 -0
- package/lib/reporters/junit.js.map +7 -0
- package/lib/reporters/line.js +113 -0
- package/lib/reporters/line.js.map +7 -0
- package/lib/reporters/list.js +231 -0
- package/lib/reporters/list.js.map +7 -0
- package/lib/reporters/listModeReporter.js +69 -0
- package/lib/reporters/listModeReporter.js.map +7 -0
- package/lib/reporters/markdown.js +144 -0
- package/lib/reporters/markdown.js.map +7 -0
- package/lib/reporters/merge.js +541 -0
- package/lib/reporters/merge.js.map +7 -0
- package/lib/reporters/multiplexer.js +104 -0
- package/lib/reporters/multiplexer.js.map +7 -0
- package/lib/reporters/reporterV2.js +102 -0
- package/lib/reporters/reporterV2.js.map +7 -0
- package/lib/reporters/teleEmitter.js +298 -0
- package/lib/reporters/teleEmitter.js.map +7 -0
- package/lib/reporters/versions/blobV1.js +16 -0
- package/lib/reporters/versions/blobV1.js.map +7 -0
- package/lib/runner/dispatcher.js +491 -0
- package/lib/runner/dispatcher.js.map +7 -0
- package/lib/runner/failureTracker.js +72 -0
- package/lib/runner/failureTracker.js.map +7 -0
- package/lib/runner/lastRun.js +77 -0
- package/lib/runner/lastRun.js.map +7 -0
- package/lib/runner/loadUtils.js +334 -0
- package/lib/runner/loadUtils.js.map +7 -0
- package/lib/runner/loaderHost.js +89 -0
- package/lib/runner/loaderHost.js.map +7 -0
- package/lib/runner/processHost.js +161 -0
- package/lib/runner/processHost.js.map +7 -0
- package/lib/runner/projectUtils.js +241 -0
- package/lib/runner/projectUtils.js.map +7 -0
- package/lib/runner/rebase.js +189 -0
- package/lib/runner/rebase.js.map +7 -0
- package/lib/runner/reporters.js +138 -0
- package/lib/runner/reporters.js.map +7 -0
- package/lib/runner/runner.js +110 -0
- package/lib/runner/sigIntWatcher.js +96 -0
- package/lib/runner/sigIntWatcher.js.map +7 -0
- package/lib/runner/taskRunner.js +127 -0
- package/lib/runner/taskRunner.js.map +7 -0
- package/lib/runner/tasks.js +410 -0
- package/lib/runner/tasks.js.map +7 -0
- package/lib/runner/testGroups.js +117 -0
- package/lib/runner/testGroups.js.map +7 -0
- package/lib/runner/testRunner.js +390 -0
- package/lib/runner/testRunner.js.map +7 -0
- package/lib/runner/testServer.js +267 -0
- package/lib/runner/testServer.js.map +7 -0
- package/lib/runner/uiModeReporter.js +30 -0
- package/lib/runner/uiModeReporter.js.map +7 -0
- package/lib/runner/vcs.js +72 -0
- package/lib/runner/vcs.js.map +7 -0
- package/lib/runner/watchMode.js +395 -0
- package/lib/runner/watchMode.js.map +7 -0
- package/lib/runner/workerHost.js +95 -0
- package/lib/runner/workerHost.js.map +7 -0
- package/lib/third_party/pirates.js +62 -0
- package/lib/third_party/pirates.js.map +7 -0
- package/lib/third_party/tsconfig-loader.js +103 -0
- package/lib/third_party/tsconfig-loader.js.map +7 -0
- package/lib/transform/babelBundle.js +43 -0
- package/lib/transform/babelBundle.js.map +7 -0
- package/lib/transform/babelBundleImpl.js +461 -0
- package/lib/transform/babelBundleImpl.js.map +7 -0
- package/lib/transform/compilationCache.js +272 -0
- package/lib/transform/compilationCache.js.map +7 -0
- package/lib/transform/esmLoader.js +104 -0
- package/lib/transform/esmLoader.js.map +7 -0
- package/lib/transform/portTransport.js +67 -0
- package/lib/transform/portTransport.js.map +7 -0
- package/lib/transform/transform.js +293 -0
- package/lib/transform/transform.js.map +7 -0
- package/lib/util.js +403 -0
- package/lib/util.js.map +7 -0
- package/lib/utilsBundle.js +43 -0
- package/lib/utilsBundle.js.map +7 -0
- package/lib/utilsBundleImpl.js +100 -0
- package/lib/utilsBundleImpl.js.map +7 -0
- package/lib/worker/fixtureRunner.js +258 -0
- package/lib/worker/fixtureRunner.js.map +7 -0
- package/lib/worker/testInfo.js +514 -0
- package/lib/worker/testInfo.js.map +7 -0
- package/lib/worker/testTracing.js +344 -0
- package/lib/worker/testTracing.js.map +7 -0
- package/lib/worker/timeoutManager.js +174 -0
- package/lib/worker/timeoutManager.js.map +7 -0
- package/lib/worker/util.js +31 -0
- package/lib/worker/util.js.map +7 -0
- package/lib/worker/workerMain.js +520 -0
- package/lib/worker/workerMain.js.map +7 -0
- package/package.json +74 -0
- package/test.d.ts +18 -0
- package/test.js +24 -0
- package/test.mjs +33 -0
- package/types/test.d.ts +10196 -0
- package/types/testReporter.d.ts +821 -0
|
@@ -0,0 +1,71 @@
|
|
|
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 inProcessTransport_exports = {};
|
|
20
|
+
__export(inProcessTransport_exports, {
|
|
21
|
+
InProcessTransport: () => InProcessTransport
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(inProcessTransport_exports);
|
|
24
|
+
class InProcessTransport {
|
|
25
|
+
constructor(server) {
|
|
26
|
+
this._connected = false;
|
|
27
|
+
this._server = server;
|
|
28
|
+
this._serverTransport = new InProcessServerTransport(this);
|
|
29
|
+
}
|
|
30
|
+
async start() {
|
|
31
|
+
if (this._connected)
|
|
32
|
+
throw new Error("InprocessTransport already started!");
|
|
33
|
+
await this._server.connect(this._serverTransport);
|
|
34
|
+
this._connected = true;
|
|
35
|
+
}
|
|
36
|
+
async send(message, options) {
|
|
37
|
+
if (!this._connected)
|
|
38
|
+
throw new Error("Transport not connected");
|
|
39
|
+
this._serverTransport._receiveFromClient(message);
|
|
40
|
+
}
|
|
41
|
+
async close() {
|
|
42
|
+
if (this._connected) {
|
|
43
|
+
this._connected = false;
|
|
44
|
+
this.onclose?.();
|
|
45
|
+
this._serverTransport.onclose?.();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
_receiveFromServer(message, extra) {
|
|
49
|
+
this.onmessage?.(message, extra);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
class InProcessServerTransport {
|
|
53
|
+
constructor(clientTransport) {
|
|
54
|
+
this._clientTransport = clientTransport;
|
|
55
|
+
}
|
|
56
|
+
async start() {
|
|
57
|
+
}
|
|
58
|
+
async send(message, options) {
|
|
59
|
+
this._clientTransport._receiveFromServer(message);
|
|
60
|
+
}
|
|
61
|
+
async close() {
|
|
62
|
+
this.onclose?.();
|
|
63
|
+
}
|
|
64
|
+
_receiveFromClient(message) {
|
|
65
|
+
this.onmessage?.(message);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
69
|
+
0 && (module.exports = {
|
|
70
|
+
InProcessTransport
|
|
71
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/mcp/sdk/inProcessTransport.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 type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport type { Transport, TransportSendOptions } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { JSONRPCMessage, MessageExtraInfo } from '@modelcontextprotocol/sdk/types.js';\n\nexport class InProcessTransport implements Transport {\n private _server: Server;\n private _serverTransport: InProcessServerTransport;\n private _connected: boolean = false;\n\n constructor(server: Server) {\n this._server = server;\n this._serverTransport = new InProcessServerTransport(this);\n }\n\n async start(): Promise<void> {\n if (this._connected)\n throw new Error('InprocessTransport already started!');\n\n await this._server.connect(this._serverTransport);\n this._connected = true;\n }\n\n async send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void> {\n if (!this._connected)\n throw new Error('Transport not connected');\n\n\n this._serverTransport._receiveFromClient(message);\n }\n\n async close(): Promise<void> {\n if (this._connected) {\n this._connected = false;\n this.onclose?.();\n this._serverTransport.onclose?.();\n }\n }\n\n onclose?: (() => void) | undefined;\n onerror?: ((error: Error) => void) | undefined;\n onmessage?: ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined;\n sessionId?: string | undefined;\n setProtocolVersion?: ((version: string) => void) | undefined;\n\n _receiveFromServer(message: JSONRPCMessage, extra?: MessageExtraInfo): void {\n this.onmessage?.(message, extra);\n }\n}\n\nclass InProcessServerTransport implements Transport {\n private _clientTransport: InProcessTransport;\n\n constructor(clientTransport: InProcessTransport) {\n this._clientTransport = clientTransport;\n }\n\n async start(): Promise<void> {\n }\n\n async send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void> {\n this._clientTransport._receiveFromServer(message);\n }\n\n async close(): Promise<void> {\n this.onclose?.();\n }\n\n onclose?: (() => void) | undefined;\n onerror?: ((error: Error) => void) | undefined;\n onmessage?: ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined;\n sessionId?: string | undefined;\n setProtocolVersion?: ((version: string) => void) | undefined;\n _receiveFromClient(message: JSONRPCMessage): void {\n this.onmessage?.(message);\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBO,MAAM,mBAAwC;AAAA,EAKnD,YAAY,QAAgB;AAF5B,SAAQ,aAAsB;AAG5B,SAAK,UAAU;AACf,SAAK,mBAAmB,IAAI,yBAAyB,IAAI;AAAA,EAC3D;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK;AACP,YAAM,IAAI,MAAM,qCAAqC;AAEvD,UAAM,KAAK,QAAQ,QAAQ,KAAK,gBAAgB;AAChD,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,KAAK,SAAyB,SAA+C;AACjF,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,yBAAyB;AAG3C,SAAK,iBAAiB,mBAAmB,OAAO;AAAA,EAClD;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,YAAY;AACnB,WAAK,aAAa;AAClB,WAAK,UAAU;AACf,WAAK,iBAAiB,UAAU;AAAA,IAClC;AAAA,EACF;AAAA,EAQA,mBAAmB,SAAyB,OAAgC;AAC1E,SAAK,YAAY,SAAS,KAAK;AAAA,EACjC;AACF;AAEA,MAAM,yBAA8C;AAAA,EAGlD,YAAY,iBAAqC;AAC/C,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAM,QAAuB;AAAA,EAC7B;AAAA,EAEA,MAAM,KAAK,SAAyB,SAA+C;AACjF,SAAK,iBAAiB,mBAAmB,OAAO;AAAA,EAClD;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,UAAU;AAAA,EACjB;AAAA,EAOA,mBAAmB,SAA+B;AAChD,SAAK,YAAY,OAAO;AAAA,EAC1B;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
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(backendFactory.config));
|
|
137
|
+
const factory = {
|
|
138
|
+
...backendFactory,
|
|
139
|
+
create: (cfg) => 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
|
+
config: {},
|
|
154
|
+
// MDB doesn't use config
|
|
155
|
+
create: () => wrappedBackend
|
|
156
|
+
};
|
|
157
|
+
const httpServer = await mcpHttp.startHttpServer({ port: 0 });
|
|
158
|
+
const url = await mcpHttp.installHttpTransport(httpServer, factory, true);
|
|
159
|
+
const client = new mcpBundle.Client({ name: "Pushing client", version: "0.0.0" });
|
|
160
|
+
client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
|
|
161
|
+
const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(process.env.PLAYWRIGHT_DEBUGGER_MCP));
|
|
162
|
+
await client.connect(transport);
|
|
163
|
+
const pushToolsResult = await client.callTool({
|
|
164
|
+
name: pushToolsSchema.name,
|
|
165
|
+
arguments: {
|
|
166
|
+
mcpUrl: url,
|
|
167
|
+
introMessage
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
if (pushToolsResult.isError)
|
|
171
|
+
errorsDebug("Failed to push tools", pushToolsResult.content);
|
|
172
|
+
await transport.terminateSession();
|
|
173
|
+
await client.close();
|
|
174
|
+
await wrappedBackend.waitForClosed();
|
|
175
|
+
httpServer.close();
|
|
176
|
+
}
|
|
177
|
+
async function startAsHttp(backendFactory, options) {
|
|
178
|
+
const httpServer = await mcpHttp.startHttpServer(options);
|
|
179
|
+
return await mcpHttp.installHttpTransport(httpServer, backendFactory, true);
|
|
180
|
+
}
|
|
181
|
+
class ServerBackendWithCloseListener {
|
|
182
|
+
constructor(backend) {
|
|
183
|
+
this._serverClosedPromise = new import_utils.ManualPromise();
|
|
184
|
+
this._backend = backend;
|
|
185
|
+
}
|
|
186
|
+
async initialize(server, clientInfo) {
|
|
187
|
+
await this._backend.initialize?.(server, clientInfo);
|
|
188
|
+
}
|
|
189
|
+
async listTools() {
|
|
190
|
+
return this._backend.listTools();
|
|
191
|
+
}
|
|
192
|
+
async callTool(name, args, progress) {
|
|
193
|
+
return this._backend.callTool(name, args, progress);
|
|
194
|
+
}
|
|
195
|
+
serverClosed(server) {
|
|
196
|
+
this._backend.serverClosed?.(server);
|
|
197
|
+
this._serverClosedPromise.resolve();
|
|
198
|
+
}
|
|
199
|
+
async waitForClosed() {
|
|
200
|
+
await this._serverClosedPromise;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
204
|
+
0 && (module.exports = {
|
|
205
|
+
MDBBackend,
|
|
206
|
+
runMainBackend,
|
|
207
|
+
runOnPauseBackendLoop
|
|
208
|
+
});
|
|
@@ -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 { defineToolSchema } from './tool';\nimport * as mcpBundle from './bundle';\nimport * as mcpServer from './server';\nimport * as mcpHttp from './http';\n\nimport type { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\n\nconst mdbDebug = debug('pw:mcp:mdb');\nconst errorsDebug = debug('pw:mcp:errors');\nconst z = mcpBundle.z;\n\nexport class MDBBackend implements mcpServer.ServerBackend {\n private _onPauseClient: { client: Client, tools: mcpServer.Tool[], transport: StreamableHTTPClientTransport } | undefined;\n private _interruptPromise: ManualPromise<mcpServer.CallToolResult> | undefined;\n private _mainBackend: mcpServer.ServerBackend;\n private _clientInfo: mcpServer.ClientInfo | undefined;\n private _progress: mcpServer.CallToolResult['content'] = [];\n private _progressCallback: mcpServer.ProgressCallback;\n\n constructor(mainBackend: mcpServer.ServerBackend) {\n this._mainBackend = mainBackend;\n this._progressCallback = (params: mcpServer.ProgressParams) => {\n if (params.message)\n this._progress.push({ type: 'text', text: params.message });\n };\n }\n\n async initialize(server: mcpServer.Server, clientInfo: mcpServer.ClientInfo): Promise<void> {\n if (!this._clientInfo) {\n this._clientInfo = clientInfo;\n await this._mainBackend.initialize?.(server, clientInfo);\n }\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n return await this._mainBackend.listTools();\n }\n\n async callTool(name: string, args: mcpServer.CallToolRequest['params']['arguments']): Promise<mcpServer.CallToolResult> {\n if (name === pushToolsSchema.name) {\n await this._createOnPauseClient(pushToolsSchema.inputSchema.parse(args || {}));\n return { content: [{ type: 'text', text: 'Tools pushed' }] };\n }\n\n if (this._onPauseClient?.tools.find(tool => tool.name === name)) {\n const result = await this._onPauseClient.client.callTool({\n name,\n arguments: args,\n }) as mcpServer.CallToolResult;\n await this._mainBackend.afterCallTool?.(name, args, result);\n return result;\n }\n\n await this._onPauseClient?.transport.terminateSession().catch(errorsDebug);\n await this._onPauseClient?.client.close().catch(errorsDebug);\n this._onPauseClient = undefined;\n\n const resultPromise = new ManualPromise<mcpServer.CallToolResult>();\n const interruptPromise = new ManualPromise<mcpServer.CallToolResult>();\n this._interruptPromise = interruptPromise;\n\n this._mainBackend.callTool(name, args, this._progressCallback).then(result => {\n resultPromise.resolve(result as mcpServer.CallToolResult);\n }).catch(e => {\n resultPromise.resolve({ content: [{ type: 'text', text: String(e) }], isError: true });\n });\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 result.content.unshift(...this._progress);\n this._progress.length = 0;\n return result;\n }\n\n private async _createOnPauseClient(params: { mcpUrl: string, introMessage?: string }) {\n if (this._onPauseClient)\n await this._onPauseClient.client.close().catch(errorsDebug);\n\n this._onPauseClient = await this._createClient(params.mcpUrl);\n\n this._interruptPromise?.resolve({\n content: [{\n type: 'text',\n text: params.introMessage || '',\n }],\n });\n this._interruptPromise = undefined;\n }\n\n private async _createClient(url: string): Promise<{ client: Client, tools: mcpServer.Tool[], transport: StreamableHTTPClientTransport }> {\n const client = new mcpBundle.Client({ name: 'Interrupting client', version: '0.0.0' }, { capabilities: { roots: {} } });\n client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n client.setNotificationHandler(mcpBundle.ProgressNotificationSchema, notification => {\n if (notification.method === 'notifications/progress') {\n const { message } = notification.params;\n if (message)\n this._progress.push({ type: 'text', text: message });\n }\n });\n const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(url));\n await client.connect(transport);\n const { tools } = await client.listTools();\n return { client, tools, transport };\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 async function runMainBackend(backendFactory: mcpServer.ServerBackendFactory, options?: { port?: number }): Promise<string | undefined> {\n const mdbBackend = new MDBBackend(backendFactory.create(backendFactory.config));\n // Start HTTP unconditionally.\n const factory: mcpServer.ServerBackendFactory = {\n ...backendFactory,\n create: (cfg) => mdbBackend\n };\n const url = await startAsHttp(factory, { port: options?.port || 0 });\n process.env.PLAYWRIGHT_DEBUGGER_MCP = 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(backend: mcpServer.ServerBackend, introMessage: string) {\n const wrappedBackend = new ServerBackendWithCloseListener(backend);\n\n const factory: mcpServer.ServerBackendFactory = {\n name: 'on-pause-backend',\n nameInConfig: 'on-pause-backend',\n version: '0.0.0',\n config: {} as any, // MDB doesn't use config\n create: () => wrappedBackend,\n };\n\n const httpServer = await mcpHttp.startHttpServer({ port: 0 });\n const url = await mcpHttp.installHttpTransport(httpServer, factory, true);\n\n const client = new mcpBundle.Client({ name: 'Pushing client', version: '0.0.0' });\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(process.env.PLAYWRIGHT_DEBUGGER_MCP!));\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 return await mcpHttp.installHttpTransport(httpServer, backendFactory, true);\n}\n\n\nclass ServerBackendWithCloseListener implements mcpServer.ServerBackend {\n private _backend: mcpServer.ServerBackend;\n private _serverClosedPromise = new ManualPromise<void>();\n\n constructor(backend: mcpServer.ServerBackend) {\n this._backend = backend;\n }\n\n async initialize(server: mcpServer.Server, clientInfo: mcpServer.ClientInfo): Promise<void> {\n await this._backend.initialize?.(server, clientInfo);\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'], progress: mcpServer.ProgressCallback): Promise<mcpServer.CallToolResult> {\n return this._backend.callTool(name, args, progress);\n }\n\n serverClosed(server: mcpServer.Server) {\n this._backend.serverClosed?.(server);\n this._serverClosedPromise.resolve();\n }\n\n async waitForClosed() {\n await this._serverClosedPromise;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["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';\n\nimport * as mcpBundle from './bundle';\n\nimport type { ServerBackend, ClientInfo, Server } from './server';\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');\nconst { z, zodToJsonSchema } = mcpBundle;\n\nexport class ProxyBackend implements ServerBackend {\n private _mcpProviders: MCPProvider[];\n private _currentClient: Client | undefined;\n private _contextSwitchTool: Tool;\n private _clientInfo: ClientInfo | undefined;\n\n constructor(mcpProviders: MCPProvider[]) {\n this._mcpProviders = mcpProviders;\n this._contextSwitchTool = this._defineContextSwitchTool();\n }\n\n async initialize(server: Server, clientInfo: ClientInfo): Promise<void> {\n this._clientInfo = clientInfo;\n }\n\n async listTools(): Promise<Tool[]> {\n const currentClient = await this._ensureCurrentClient();\n const response = await 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 const currentClient = await this._ensureCurrentClient();\n return await 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: zodToJsonSchema(z.object({\n name: 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 _ensureCurrentClient(): Promise<Client> {\n if (this._currentClient)\n return this._currentClient;\n return await this._setCurrentClient(this._mcpProviders[0]);\n }\n\n private async _setCurrentClient(factory: MCPProvider) {\n await this._currentClient?.close();\n this._currentClient = undefined;\n\n const client = new mcpBundle.Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });\n client.registerCapabilities({\n roots: {\n listRoots: true,\n },\n });\n client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n\n const transport = await factory.connect();\n await client.connect(transport);\n this._currentClient = client;\n return client;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["factory"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
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, config) {
|
|
45
|
+
const backend = factory.create(config || factory.config);
|
|
46
|
+
const server = createServer(factory.name, factory.version, backend, runHeartbeat);
|
|
47
|
+
await server.connect(transport);
|
|
48
|
+
}
|
|
49
|
+
async function wrapInProcess(backend) {
|
|
50
|
+
const server = createServer("Internal", "0.0.0", backend, false);
|
|
51
|
+
return new import_inProcessTransport.InProcessTransport(server);
|
|
52
|
+
}
|
|
53
|
+
function createServer(name, version, backend, runHeartbeat) {
|
|
54
|
+
const server = new mcpBundle.Server({ name, version }, {
|
|
55
|
+
capabilities: {
|
|
56
|
+
tools: {}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
server.setRequestHandler(mcpBundle.ListToolsRequestSchema, async () => {
|
|
60
|
+
serverDebug("listTools");
|
|
61
|
+
const tools = await backend.listTools();
|
|
62
|
+
return { tools };
|
|
63
|
+
});
|
|
64
|
+
let initializePromise;
|
|
65
|
+
server.setRequestHandler(mcpBundle.CallToolRequestSchema, async (request, extra) => {
|
|
66
|
+
serverDebug("callTool", request);
|
|
67
|
+
const progressToken = request.params._meta?.progressToken;
|
|
68
|
+
let progressCounter = 0;
|
|
69
|
+
const progress = progressToken ? (params) => {
|
|
70
|
+
extra.sendNotification({
|
|
71
|
+
method: "notifications/progress",
|
|
72
|
+
params: {
|
|
73
|
+
progressToken,
|
|
74
|
+
progress: params.progress ?? ++progressCounter,
|
|
75
|
+
total: params.total,
|
|
76
|
+
message: params.message
|
|
77
|
+
}
|
|
78
|
+
}).catch(serverDebug);
|
|
79
|
+
} : () => {
|
|
80
|
+
};
|
|
81
|
+
try {
|
|
82
|
+
if (!initializePromise)
|
|
83
|
+
initializePromise = initializeServer(server, backend, runHeartbeat);
|
|
84
|
+
await initializePromise;
|
|
85
|
+
return mergeTextParts(await backend.callTool(request.params.name, request.params.arguments || {}, progress));
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text", text: "### Result\n" + String(error) }],
|
|
89
|
+
isError: true
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
addServerListener(server, "close", () => backend.serverClosed?.(server));
|
|
94
|
+
return server;
|
|
95
|
+
}
|
|
96
|
+
const initializeServer = async (server, backend, runHeartbeat) => {
|
|
97
|
+
const capabilities = server.getClientCapabilities();
|
|
98
|
+
let clientRoots = [];
|
|
99
|
+
if (capabilities?.roots) {
|
|
100
|
+
const { roots } = await server.listRoots().catch((e) => {
|
|
101
|
+
serverDebug(e);
|
|
102
|
+
return { roots: [] };
|
|
103
|
+
});
|
|
104
|
+
clientRoots = roots;
|
|
105
|
+
}
|
|
106
|
+
const clientInfo = {
|
|
107
|
+
name: server.getClientVersion()?.name ?? "unknown",
|
|
108
|
+
version: server.getClientVersion()?.version ?? "unknown",
|
|
109
|
+
roots: clientRoots,
|
|
110
|
+
timestamp: Date.now()
|
|
111
|
+
};
|
|
112
|
+
await backend.initialize?.(server, clientInfo);
|
|
113
|
+
if (runHeartbeat)
|
|
114
|
+
startHeartbeat(server);
|
|
115
|
+
};
|
|
116
|
+
const startHeartbeat = (server) => {
|
|
117
|
+
const beat = () => {
|
|
118
|
+
Promise.race([
|
|
119
|
+
server.ping(),
|
|
120
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("ping timeout")), 5e3))
|
|
121
|
+
]).then(() => {
|
|
122
|
+
setTimeout(beat, 3e3);
|
|
123
|
+
}).catch(() => {
|
|
124
|
+
void server.close();
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
beat();
|
|
128
|
+
};
|
|
129
|
+
function addServerListener(server, event, listener) {
|
|
130
|
+
const oldListener = server[`on${event}`];
|
|
131
|
+
server[`on${event}`] = () => {
|
|
132
|
+
oldListener?.();
|
|
133
|
+
listener();
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async function start(serverBackendFactory, options) {
|
|
137
|
+
if (options.port === void 0) {
|
|
138
|
+
await connect(serverBackendFactory, new mcpBundle.StdioServerTransport(), false);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const httpServer = await (0, import_http.startHttpServer)(options);
|
|
142
|
+
const url = await (0, import_http.installHttpTransport)(httpServer, serverBackendFactory, false, options.allowedHosts);
|
|
143
|
+
const mcpConfig = { mcpServers: {} };
|
|
144
|
+
mcpConfig.mcpServers[serverBackendFactory.nameInConfig] = {
|
|
145
|
+
url: `${url}/mcp`
|
|
146
|
+
};
|
|
147
|
+
const message = [
|
|
148
|
+
`Listening on ${url}`,
|
|
149
|
+
"Put this in your client config:",
|
|
150
|
+
JSON.stringify(mcpConfig, void 0, 2),
|
|
151
|
+
"For legacy SSE transport support, you can use the /sse endpoint instead."
|
|
152
|
+
].join("\n");
|
|
153
|
+
console.error(message);
|
|
154
|
+
}
|
|
155
|
+
function firstRootPath(clientInfo) {
|
|
156
|
+
if (clientInfo.roots.length === 0)
|
|
157
|
+
return void 0;
|
|
158
|
+
const firstRootUri = clientInfo.roots[0]?.uri;
|
|
159
|
+
const url = firstRootUri ? new URL(firstRootUri) : void 0;
|
|
160
|
+
return url ? (0, import_url.fileURLToPath)(url) : void 0;
|
|
161
|
+
}
|
|
162
|
+
function mergeTextParts(result) {
|
|
163
|
+
const content = [];
|
|
164
|
+
const testParts = [];
|
|
165
|
+
for (const part of result.content) {
|
|
166
|
+
if (part.type === "text") {
|
|
167
|
+
testParts.push(part.text);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (testParts.length > 0) {
|
|
171
|
+
content.push({ type: "text", text: testParts.join("\n") });
|
|
172
|
+
testParts.length = 0;
|
|
173
|
+
}
|
|
174
|
+
content.push(part);
|
|
175
|
+
}
|
|
176
|
+
if (testParts.length > 0)
|
|
177
|
+
content.push({ type: "text", text: testParts.join("\n") });
|
|
178
|
+
return {
|
|
179
|
+
...result,
|
|
180
|
+
content
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
184
|
+
0 && (module.exports = {
|
|
185
|
+
connect,
|
|
186
|
+
createServer,
|
|
187
|
+
firstRootPath,
|
|
188
|
+
start,
|
|
189
|
+
wrapInProcess
|
|
190
|
+
});
|