@playwright/mcp 0.0.36-alpha-2025-09-02 → 0.0.36-alpha-2025-09-04
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/README.md +1 -1
- package/cli.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +2 -2
- package/lib/{browserContextFactory.js → browser/browserContextFactory.js} +76 -36
- package/lib/{browserServerBackend.js → browser/browserServerBackend.js} +24 -22
- package/lib/{utils → browser}/codegen.js +8 -3
- package/lib/{config.js → browser/config.js} +43 -26
- package/lib/{context.js → browser/context.js} +27 -30
- package/lib/{response.js → browser/response.js} +14 -14
- package/lib/{sessionLog.js → browser/sessionLog.js} +23 -18
- package/lib/{tab.js → browser/tab.js} +29 -27
- package/lib/{tools → browser/tools}/common.js +11 -9
- package/lib/{tools → browser/tools}/console.js +7 -5
- package/lib/{tools → browser/tools}/dialogs.js +9 -7
- package/lib/browser/tools/evaluate.js +88 -0
- package/lib/{tools → browser/tools}/files.js +8 -6
- package/lib/browser/tools/form.js +92 -0
- package/lib/{tools → browser/tools}/install.js +18 -14
- package/lib/browser/tools/keyboard.js +113 -0
- package/lib/{tools → browser/tools}/mouse.js +18 -16
- package/lib/{tools → browser/tools}/navigate.js +10 -8
- package/lib/{tools → browser/tools}/network.js +7 -5
- package/lib/browser/tools/pdf.js +76 -0
- package/lib/browser/tools/screenshot.js +115 -0
- package/lib/browser/tools/snapshot.js +175 -0
- package/lib/{tools → browser/tools}/tabs.js +9 -7
- package/lib/{tools → browser/tools}/tool.js +6 -2
- package/lib/{tools → browser/tools}/utils.js +10 -5
- package/lib/{tools → browser/tools}/verify.js +59 -24
- package/lib/{tools → browser/tools}/wait.js +10 -8
- package/lib/browser/tools.js +61 -0
- package/lib/extension/cdpRelay.js +85 -48
- package/lib/extension/extensionContextFactory.js +48 -11
- package/lib/extension/protocol.js +4 -1
- package/lib/index.js +47 -12
- package/lib/{utils/log.js → log.js} +11 -4
- package/lib/{utils/package.js → package.js} +9 -5
- package/lib/program.js +68 -39
- package/lib/sdk/bundle.js +79 -0
- package/lib/{mcp → sdk}/http.js +57 -17
- package/lib/{mcp → sdk}/inProcessTransport.js +15 -20
- package/lib/{mcp → sdk}/manualPromise.js +11 -9
- package/lib/{mcp → sdk}/mdb.js +77 -38
- package/lib/{mcp → sdk}/proxyBackend.js +53 -16
- package/lib/sdk/server.js +164 -0
- package/lib/{mcp → sdk}/tool.js +8 -4
- package/lib/vscode/host.js +64 -35
- package/lib/vscode/main.js +48 -13
- package/package.json +6 -7
- package/lib/loop/loop.js +0 -69
- package/lib/loop/loopClaude.js +0 -152
- package/lib/loop/loopOpenAI.js +0 -141
- package/lib/loop/main.js +0 -60
- package/lib/loopTools/context.js +0 -67
- package/lib/loopTools/main.js +0 -54
- package/lib/loopTools/perform.js +0 -32
- package/lib/loopTools/snapshot.js +0 -29
- package/lib/loopTools/tool.js +0 -18
- package/lib/mcp/server.js +0 -123
- package/lib/tools/evaluate.js +0 -53
- package/lib/tools/form.js +0 -57
- package/lib/tools/keyboard.js +0 -78
- package/lib/tools/pdf.js +0 -40
- package/lib/tools/screenshot.js +0 -79
- package/lib/tools/snapshot.js +0 -139
- package/lib/tools.js +0 -54
- package/lib/utils/fileUtils.js +0 -36
- package/lib/utils/guid.js +0 -22
package/lib/{mcp → sdk}/mdb.js
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Copyright (c) Microsoft Corporation.
|
|
3
4
|
*
|
|
@@ -13,32 +14,67 @@
|
|
|
13
14
|
* See the License for the specific language governing permissions and
|
|
14
15
|
* limitations under the License.
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
51
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.MDBBackend = void 0;
|
|
55
|
+
exports.runMainBackend = runMainBackend;
|
|
56
|
+
exports.runOnPauseBackendLoop = runOnPauseBackendLoop;
|
|
57
|
+
const debug_1 = __importDefault(require("debug"));
|
|
58
|
+
const tool_1 = require("./tool");
|
|
59
|
+
const mcpBundle = __importStar(require("./bundle"));
|
|
60
|
+
const mcpServer = __importStar(require("./server"));
|
|
61
|
+
const mcpHttp = __importStar(require("./http"));
|
|
62
|
+
const server_1 = require("./server");
|
|
63
|
+
const manualPromise_1 = require("./manualPromise");
|
|
64
|
+
const mdbDebug = (0, debug_1.default)('pw:mcp:mdb');
|
|
65
|
+
const errorsDebug = (0, debug_1.default)('pw:mcp:errors');
|
|
66
|
+
const z = mcpBundle.z;
|
|
67
|
+
class MDBBackend {
|
|
34
68
|
constructor(topLevelBackend) {
|
|
69
|
+
this._stack = [];
|
|
70
|
+
this._initialized = false;
|
|
35
71
|
this._topLevelBackend = topLevelBackend;
|
|
36
72
|
}
|
|
37
73
|
async initialize(server) {
|
|
38
74
|
if (this._initialized)
|
|
39
75
|
return;
|
|
40
76
|
this._initialized = true;
|
|
41
|
-
const transport = await wrapInProcess(this._topLevelBackend);
|
|
77
|
+
const transport = await (0, server_1.wrapInProcess)(this._topLevelBackend);
|
|
42
78
|
await this._pushClient(transport);
|
|
43
79
|
}
|
|
44
80
|
async listTools() {
|
|
@@ -48,7 +84,7 @@ export class MDBBackend {
|
|
|
48
84
|
async callTool(name, args) {
|
|
49
85
|
if (name === pushToolsSchema.name)
|
|
50
86
|
return await this._pushTools(pushToolsSchema.inputSchema.parse(args || {}));
|
|
51
|
-
const interruptPromise = new ManualPromise();
|
|
87
|
+
const interruptPromise = new manualPromise_1.ManualPromise();
|
|
52
88
|
this._interruptPromise = interruptPromise;
|
|
53
89
|
let [entry] = this._stack;
|
|
54
90
|
// Pop the client while the tool is not found.
|
|
@@ -60,7 +96,7 @@ export class MDBBackend {
|
|
|
60
96
|
}
|
|
61
97
|
if (!entry)
|
|
62
98
|
throw new Error(`Tool ${name} not found in the tool stack`);
|
|
63
|
-
const resultPromise = new ManualPromise();
|
|
99
|
+
const resultPromise = new manualPromise_1.ManualPromise();
|
|
64
100
|
entry.resultPromise = resultPromise;
|
|
65
101
|
this._client().callTool({
|
|
66
102
|
name,
|
|
@@ -90,21 +126,22 @@ export class MDBBackend {
|
|
|
90
126
|
}
|
|
91
127
|
async _pushTools(params) {
|
|
92
128
|
mdbDebug('pushing tools to the stack', params.mcpUrl);
|
|
93
|
-
const transport = new StreamableHTTPClientTransport(new URL(params.mcpUrl));
|
|
129
|
+
const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(params.mcpUrl));
|
|
94
130
|
await this._pushClient(transport, params.introMessage);
|
|
95
131
|
return { content: [{ type: 'text', text: 'Tools pushed' }] };
|
|
96
132
|
}
|
|
97
133
|
async _pushClient(transport, introMessage) {
|
|
134
|
+
var _a;
|
|
98
135
|
mdbDebug('pushing client to the stack');
|
|
99
|
-
const client = new Client({ name: 'Internal client', version: '0.0.0' });
|
|
100
|
-
client.setRequestHandler(PingRequestSchema, () => ({}));
|
|
136
|
+
const client = new mcpBundle.Client({ name: 'Internal client', version: '0.0.0' });
|
|
137
|
+
client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
|
|
101
138
|
await client.connect(transport);
|
|
102
139
|
mdbDebug('connected to the new client');
|
|
103
140
|
const { tools } = await client.listTools();
|
|
104
141
|
this._stack.unshift({ client, toolNames: tools.map(tool => tool.name), resultPromise: undefined });
|
|
105
142
|
mdbDebug('new tools added to the stack:', tools.map(tool => tool.name));
|
|
106
143
|
mdbDebug('interrupting current call:', !!this._interruptPromise);
|
|
107
|
-
this._interruptPromise
|
|
144
|
+
(_a = this._interruptPromise) === null || _a === void 0 ? void 0 : _a.resolve({
|
|
108
145
|
content: [{
|
|
109
146
|
type: 'text',
|
|
110
147
|
text: introMessage || '',
|
|
@@ -114,7 +151,8 @@ export class MDBBackend {
|
|
|
114
151
|
return { content: [{ type: 'text', text: 'Tools pushed' }] };
|
|
115
152
|
}
|
|
116
153
|
}
|
|
117
|
-
|
|
154
|
+
exports.MDBBackend = MDBBackend;
|
|
155
|
+
const pushToolsSchema = (0, tool_1.defineToolSchema)({
|
|
118
156
|
name: 'mdb_push_tools',
|
|
119
157
|
title: 'Push MCP tools to the tools stack',
|
|
120
158
|
description: 'Push MCP tools to the tools stack',
|
|
@@ -124,21 +162,21 @@ const pushToolsSchema = defineToolSchema({
|
|
|
124
162
|
}),
|
|
125
163
|
type: 'readOnly',
|
|
126
164
|
});
|
|
127
|
-
|
|
165
|
+
async function runMainBackend(backendFactory, options) {
|
|
128
166
|
const mdbBackend = new MDBBackend(backendFactory.create());
|
|
129
167
|
// Start HTTP unconditionally.
|
|
130
168
|
const factory = {
|
|
131
169
|
...backendFactory,
|
|
132
170
|
create: () => mdbBackend
|
|
133
171
|
};
|
|
134
|
-
const url = await startAsHttp(factory, { port: options
|
|
172
|
+
const url = await startAsHttp(factory, { port: (options === null || options === void 0 ? void 0 : options.port) || 0 });
|
|
135
173
|
process.env.PLAYWRIGHT_DEBUGGER_MCP = url;
|
|
136
|
-
if (options
|
|
174
|
+
if ((options === null || options === void 0 ? void 0 : options.port) !== undefined)
|
|
137
175
|
return url;
|
|
138
176
|
// Start stdio conditionally.
|
|
139
|
-
await mcpServer.connect(factory, new StdioServerTransport(), false);
|
|
177
|
+
await mcpServer.connect(factory, new mcpBundle.StdioServerTransport(), false);
|
|
140
178
|
}
|
|
141
|
-
|
|
179
|
+
async function runOnPauseBackendLoop(mdbUrl, backend, introMessage) {
|
|
142
180
|
const wrappedBackend = new OnceTimeServerBackendWrapper(backend);
|
|
143
181
|
const factory = {
|
|
144
182
|
name: 'on-pause-backend',
|
|
@@ -149,9 +187,9 @@ export async function runOnPauseBackendLoop(mdbUrl, backend, introMessage) {
|
|
|
149
187
|
const httpServer = await mcpHttp.startHttpServer({ port: 0 });
|
|
150
188
|
await mcpHttp.installHttpTransport(httpServer, factory);
|
|
151
189
|
const url = mcpHttp.httpAddressToString(httpServer.address());
|
|
152
|
-
const client = new Client({ name: 'Internal client', version: '0.0.0' });
|
|
153
|
-
client.setRequestHandler(PingRequestSchema, () => ({}));
|
|
154
|
-
const transport = new StreamableHTTPClientTransport(new URL(mdbUrl));
|
|
190
|
+
const client = new mcpBundle.Client({ name: 'Internal client', version: '0.0.0' });
|
|
191
|
+
client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
|
|
192
|
+
const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(mdbUrl));
|
|
155
193
|
await client.connect(transport);
|
|
156
194
|
const pushToolsResult = await client.callTool({
|
|
157
195
|
name: pushToolsSchema.name,
|
|
@@ -173,14 +211,14 @@ async function startAsHttp(backendFactory, options) {
|
|
|
173
211
|
return mcpHttp.httpAddressToString(httpServer.address());
|
|
174
212
|
}
|
|
175
213
|
class OnceTimeServerBackendWrapper {
|
|
176
|
-
_backend;
|
|
177
|
-
_selfDestructPromise = new ManualPromise();
|
|
178
214
|
constructor(backend) {
|
|
215
|
+
this._selfDestructPromise = new manualPromise_1.ManualPromise();
|
|
179
216
|
this._backend = backend;
|
|
180
217
|
this._backend.requestSelfDestruct = () => this._selfDestructPromise.resolve();
|
|
181
218
|
}
|
|
182
219
|
async initialize(server, clientVersion, roots) {
|
|
183
|
-
|
|
220
|
+
var _a, _b;
|
|
221
|
+
await ((_b = (_a = this._backend).initialize) === null || _b === void 0 ? void 0 : _b.call(_a, server, clientVersion, roots));
|
|
184
222
|
}
|
|
185
223
|
async listTools() {
|
|
186
224
|
return this._backend.listTools();
|
|
@@ -189,7 +227,8 @@ class OnceTimeServerBackendWrapper {
|
|
|
189
227
|
return this._backend.callTool(name, args);
|
|
190
228
|
}
|
|
191
229
|
serverClosed(server) {
|
|
192
|
-
|
|
230
|
+
var _a, _b;
|
|
231
|
+
(_b = (_a = this._backend).serverClosed) === null || _b === void 0 ? void 0 : _b.call(_a, server);
|
|
193
232
|
this._selfDestructPromise.resolve();
|
|
194
233
|
}
|
|
195
234
|
async waitForClosed() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Copyright (c) Microsoft Corporation.
|
|
3
4
|
*
|
|
@@ -13,18 +14,51 @@
|
|
|
13
14
|
* See the License for the specific language governing permissions and
|
|
14
15
|
* limitations under the License.
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
51
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.ProxyBackend = void 0;
|
|
55
|
+
const debug_1 = __importDefault(require("debug"));
|
|
56
|
+
const mcpBundle = __importStar(require("./bundle"));
|
|
57
|
+
const errorsDebug = (0, debug_1.default)('pw:mcp:errors');
|
|
58
|
+
const { z, zodToJsonSchema } = mcpBundle;
|
|
59
|
+
class ProxyBackend {
|
|
27
60
|
constructor(mcpProviders) {
|
|
61
|
+
this._roots = [];
|
|
28
62
|
this._mcpProviders = mcpProviders;
|
|
29
63
|
this._contextSwitchTool = this._defineContextSwitchTool();
|
|
30
64
|
}
|
|
@@ -50,7 +84,8 @@ export class ProxyBackend {
|
|
|
50
84
|
});
|
|
51
85
|
}
|
|
52
86
|
serverClosed() {
|
|
53
|
-
|
|
87
|
+
var _a;
|
|
88
|
+
void ((_a = this._currentClient) === null || _a === void 0 ? void 0 : _a.close().catch(errorsDebug));
|
|
54
89
|
}
|
|
55
90
|
async _callContextSwitchTool(params) {
|
|
56
91
|
try {
|
|
@@ -87,18 +122,20 @@ export class ProxyBackend {
|
|
|
87
122
|
};
|
|
88
123
|
}
|
|
89
124
|
async _setCurrentClient(factory) {
|
|
90
|
-
|
|
125
|
+
var _a;
|
|
126
|
+
await ((_a = this._currentClient) === null || _a === void 0 ? void 0 : _a.close());
|
|
91
127
|
this._currentClient = undefined;
|
|
92
|
-
const client = new Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });
|
|
128
|
+
const client = new mcpBundle.Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });
|
|
93
129
|
client.registerCapabilities({
|
|
94
130
|
roots: {
|
|
95
131
|
listRoots: true,
|
|
96
132
|
},
|
|
97
133
|
});
|
|
98
|
-
client.setRequestHandler(ListRootsRequestSchema, () => ({ roots: this._roots }));
|
|
99
|
-
client.setRequestHandler(PingRequestSchema, () => ({}));
|
|
134
|
+
client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._roots }));
|
|
135
|
+
client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));
|
|
100
136
|
const transport = await factory.connect();
|
|
101
137
|
await client.connect(transport);
|
|
102
138
|
this._currentClient = client;
|
|
103
139
|
}
|
|
104
140
|
}
|
|
141
|
+
exports.ProxyBackend = ProxyBackend;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
51
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.connect = connect;
|
|
55
|
+
exports.wrapInProcess = wrapInProcess;
|
|
56
|
+
exports.createServer = createServer;
|
|
57
|
+
exports.start = start;
|
|
58
|
+
const debug_1 = __importDefault(require("debug"));
|
|
59
|
+
const mcpBundle = __importStar(require("./bundle"));
|
|
60
|
+
const http_1 = require("./http");
|
|
61
|
+
const inProcessTransport_1 = require("./inProcessTransport");
|
|
62
|
+
const serverDebug = (0, debug_1.default)('pw:mcp:server');
|
|
63
|
+
const errorsDebug = (0, debug_1.default)('pw:mcp:errors');
|
|
64
|
+
async function connect(factory, transport, runHeartbeat) {
|
|
65
|
+
const server = createServer(factory.name, factory.version, factory.create(), runHeartbeat);
|
|
66
|
+
await server.connect(transport);
|
|
67
|
+
}
|
|
68
|
+
async function wrapInProcess(backend) {
|
|
69
|
+
const server = createServer('Internal', '0.0.0', backend, false);
|
|
70
|
+
return new inProcessTransport_1.InProcessTransport(server);
|
|
71
|
+
}
|
|
72
|
+
function createServer(name, version, backend, runHeartbeat) {
|
|
73
|
+
let initializedPromiseResolve = () => { };
|
|
74
|
+
const initializedPromise = new Promise(resolve => initializedPromiseResolve = resolve);
|
|
75
|
+
const server = new mcpBundle.Server({ name, version }, {
|
|
76
|
+
capabilities: {
|
|
77
|
+
tools: {},
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
server.setRequestHandler(mcpBundle.ListToolsRequestSchema, async () => {
|
|
81
|
+
serverDebug('listTools');
|
|
82
|
+
await initializedPromise;
|
|
83
|
+
const tools = await backend.listTools();
|
|
84
|
+
return { tools };
|
|
85
|
+
});
|
|
86
|
+
let heartbeatRunning = false;
|
|
87
|
+
server.setRequestHandler(mcpBundle.CallToolRequestSchema, async (request) => {
|
|
88
|
+
serverDebug('callTool', request);
|
|
89
|
+
await initializedPromise;
|
|
90
|
+
if (runHeartbeat && !heartbeatRunning) {
|
|
91
|
+
heartbeatRunning = true;
|
|
92
|
+
startHeartbeat(server);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
return await backend.callTool(request.params.name, request.params.arguments || {});
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
content: [{ type: 'text', text: '### Result\n' + String(error) }],
|
|
100
|
+
isError: true,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
addServerListener(server, 'initialized', async () => {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
try {
|
|
107
|
+
const capabilities = server.getClientCapabilities();
|
|
108
|
+
let clientRoots = [];
|
|
109
|
+
if (capabilities === null || capabilities === void 0 ? void 0 : capabilities.roots) {
|
|
110
|
+
const { roots } = await server.listRoots(undefined, { timeout: 2000 }).catch(() => ({ roots: [] }));
|
|
111
|
+
clientRoots = roots;
|
|
112
|
+
}
|
|
113
|
+
const clientVersion = (_a = server.getClientVersion()) !== null && _a !== void 0 ? _a : { name: 'unknown', version: 'unknown' };
|
|
114
|
+
await ((_b = backend.initialize) === null || _b === void 0 ? void 0 : _b.call(backend, server, clientVersion, clientRoots));
|
|
115
|
+
initializedPromiseResolve();
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
errorsDebug(e);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
addServerListener(server, 'close', () => { var _a; return (_a = backend.serverClosed) === null || _a === void 0 ? void 0 : _a.call(backend, server); });
|
|
122
|
+
return server;
|
|
123
|
+
}
|
|
124
|
+
const startHeartbeat = (server) => {
|
|
125
|
+
const beat = () => {
|
|
126
|
+
Promise.race([
|
|
127
|
+
server.ping(),
|
|
128
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('ping timeout')), 5000)),
|
|
129
|
+
]).then(() => {
|
|
130
|
+
setTimeout(beat, 3000);
|
|
131
|
+
}).catch(() => {
|
|
132
|
+
void server.close();
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
beat();
|
|
136
|
+
};
|
|
137
|
+
function addServerListener(server, event, listener) {
|
|
138
|
+
const oldListener = server[`on${event}`];
|
|
139
|
+
server[`on${event}`] = () => {
|
|
140
|
+
oldListener === null || oldListener === void 0 ? void 0 : oldListener();
|
|
141
|
+
listener();
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
async function start(serverBackendFactory, options) {
|
|
145
|
+
if (options.port === undefined) {
|
|
146
|
+
await connect(serverBackendFactory, new mcpBundle.StdioServerTransport(), false);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const httpServer = await (0, http_1.startHttpServer)(options);
|
|
150
|
+
await (0, http_1.installHttpTransport)(httpServer, serverBackendFactory);
|
|
151
|
+
const url = (0, http_1.httpAddressToString)(httpServer.address());
|
|
152
|
+
const mcpConfig = { mcpServers: {} };
|
|
153
|
+
mcpConfig.mcpServers[serverBackendFactory.nameInConfig] = {
|
|
154
|
+
url: `${url}/mcp`
|
|
155
|
+
};
|
|
156
|
+
const message = [
|
|
157
|
+
`Listening on ${url}`,
|
|
158
|
+
'Put this in your client config:',
|
|
159
|
+
JSON.stringify(mcpConfig, undefined, 2),
|
|
160
|
+
'For legacy SSE transport support, you can use the /sse endpoint instead.',
|
|
161
|
+
].join('\n');
|
|
162
|
+
// eslint-disable-next-line no-console
|
|
163
|
+
console.error(message);
|
|
164
|
+
}
|
package/lib/{mcp → sdk}/tool.js
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Copyright (c) Microsoft Corporation.
|
|
3
4
|
*
|
|
@@ -13,12 +14,15 @@
|
|
|
13
14
|
* See the License for the specific language governing permissions and
|
|
14
15
|
* limitations under the License.
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.toMcpTool = toMcpTool;
|
|
19
|
+
exports.defineToolSchema = defineToolSchema;
|
|
20
|
+
const bundle_1 = require("../sdk/bundle");
|
|
21
|
+
function toMcpTool(tool) {
|
|
18
22
|
return {
|
|
19
23
|
name: tool.name,
|
|
20
24
|
description: tool.description,
|
|
21
|
-
inputSchema: zodToJsonSchema(tool.inputSchema, { strictUnions: true }),
|
|
25
|
+
inputSchema: (0, bundle_1.zodToJsonSchema)(tool.inputSchema, { strictUnions: true }),
|
|
22
26
|
annotations: {
|
|
23
27
|
title: tool.title,
|
|
24
28
|
readOnlyHint: tool.type === 'readOnly',
|
|
@@ -27,6 +31,6 @@ export function toMcpTool(tool) {
|
|
|
27
31
|
},
|
|
28
32
|
};
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
function defineToolSchema(tool) {
|
|
31
35
|
return tool;
|
|
32
36
|
}
|