mcp-accessibility-scanner 1.1.2 → 2.0.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 (110) hide show
  1. package/lib/browserContextFactory.js +83 -99
  2. package/lib/browserContextFactory.js.map +1 -1
  3. package/lib/browserServerBackend.js +78 -0
  4. package/lib/browserServerBackend.js.map +1 -0
  5. package/lib/config.js +77 -20
  6. package/lib/config.js.map +1 -1
  7. package/lib/context.js +109 -174
  8. package/lib/context.js.map +1 -1
  9. package/lib/extension/cdpRelay.js +359 -0
  10. package/lib/extension/cdpRelay.js.map +1 -0
  11. package/lib/extension/extensionContextFactory.js +57 -0
  12. package/lib/extension/extensionContextFactory.js.map +1 -0
  13. package/lib/extension/protocol.js +19 -0
  14. package/lib/extension/protocol.js.map +1 -0
  15. package/lib/index.js +7 -3
  16. package/lib/index.js.map +1 -1
  17. package/lib/{transport.js → mcp/http.js} +65 -63
  18. package/lib/mcp/http.js.map +1 -0
  19. package/lib/mcp/inProcessTransport.js +73 -0
  20. package/lib/mcp/inProcessTransport.js.map +1 -0
  21. package/lib/mcp/manualPromise.js.map +1 -0
  22. package/lib/mcp/mdb.js +199 -0
  23. package/lib/mcp/mdb.js.map +1 -0
  24. package/lib/mcp/proxyBackend.js +105 -0
  25. package/lib/mcp/proxyBackend.js.map +1 -0
  26. package/lib/mcp/server.js +124 -0
  27. package/lib/mcp/server.js.map +1 -0
  28. package/lib/mcp/tool.js +33 -0
  29. package/lib/mcp/tool.js.map +1 -0
  30. package/lib/program.js +81 -26
  31. package/lib/program.js.map +1 -1
  32. package/lib/response.js +166 -0
  33. package/lib/response.js.map +1 -0
  34. package/lib/sessionLog.js +122 -0
  35. package/lib/sessionLog.js.map +1 -0
  36. package/lib/tab.js +171 -23
  37. package/lib/tab.js.map +1 -1
  38. package/lib/tools/common.js +12 -25
  39. package/lib/tools/common.js.map +1 -1
  40. package/lib/tools/console.js +4 -15
  41. package/lib/tools/console.js.map +1 -1
  42. package/lib/tools/dialogs.js +14 -19
  43. package/lib/tools/dialogs.js.map +1 -1
  44. package/lib/tools/evaluate.js +54 -0
  45. package/lib/tools/evaluate.js.map +1 -0
  46. package/lib/tools/files.js +12 -19
  47. package/lib/tools/files.js.map +1 -1
  48. package/lib/tools/form.js +58 -0
  49. package/lib/tools/form.js.map +1 -0
  50. package/lib/tools/install.js +7 -10
  51. package/lib/tools/install.js.map +1 -1
  52. package/lib/tools/keyboard.js +49 -17
  53. package/lib/tools/keyboard.js.map +1 -1
  54. package/lib/tools/mouse.js +100 -0
  55. package/lib/tools/mouse.js.map +1 -0
  56. package/lib/tools/navigate.js +13 -52
  57. package/lib/tools/navigate.js.map +1 -1
  58. package/lib/tools/network.js +5 -15
  59. package/lib/tools/network.js.map +1 -1
  60. package/lib/tools/pdf.js +8 -17
  61. package/lib/tools/pdf.js.map +1 -1
  62. package/lib/tools/screenshot.js +36 -34
  63. package/lib/tools/screenshot.js.map +1 -1
  64. package/lib/tools/snapshot.js +103 -154
  65. package/lib/tools/snapshot.js.map +1 -1
  66. package/lib/tools/tabs.js +34 -93
  67. package/lib/tools/tabs.js.map +1 -1
  68. package/lib/tools/tool.js +15 -0
  69. package/lib/tools/tool.js.map +1 -1
  70. package/lib/tools/utils.js +7 -13
  71. package/lib/tools/utils.js.map +1 -1
  72. package/lib/tools/verify.js +138 -0
  73. package/lib/tools/verify.js.map +1 -0
  74. package/lib/tools/wait.js +11 -15
  75. package/lib/tools/wait.js.map +1 -1
  76. package/lib/tools.js +19 -23
  77. package/lib/tools.js.map +1 -1
  78. package/lib/{javascript.js → utils/codegen.js} +2 -2
  79. package/lib/utils/codegen.js.map +1 -0
  80. package/lib/{fileUtils.js → utils/fileUtils.js} +6 -2
  81. package/lib/utils/fileUtils.js.map +1 -0
  82. package/lib/utils/guid.js +23 -0
  83. package/lib/utils/guid.js.map +1 -0
  84. package/lib/utils/log.js +22 -0
  85. package/lib/utils/log.js.map +1 -0
  86. package/lib/{package.js → utils/package.js} +4 -4
  87. package/lib/utils/package.js.map +1 -0
  88. package/lib/vscode/host.js +129 -0
  89. package/lib/vscode/host.js.map +1 -0
  90. package/lib/vscode/main.js +63 -0
  91. package/lib/vscode/main.js.map +1 -0
  92. package/package.json +20 -20
  93. package/lib/browserServer.js +0 -152
  94. package/lib/browserServer.js.map +0 -1
  95. package/lib/connection.js +0 -83
  96. package/lib/connection.js.map +0 -1
  97. package/lib/fileUtils.js.map +0 -1
  98. package/lib/httpServer.js +0 -202
  99. package/lib/httpServer.js.map +0 -1
  100. package/lib/javascript.js.map +0 -1
  101. package/lib/manualPromise.js.map +0 -1
  102. package/lib/package.js.map +0 -1
  103. package/lib/pageSnapshot.js +0 -44
  104. package/lib/pageSnapshot.js.map +0 -1
  105. package/lib/server.js +0 -49
  106. package/lib/server.js.map +0 -1
  107. package/lib/tools/vision.js +0 -190
  108. package/lib/tools/vision.js.map +0 -1
  109. package/lib/transport.js.map +0 -1
  110. /package/lib/{manualPromise.js → mcp/manualPromise.js} +0 -0
@@ -13,18 +13,53 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import http from 'node:http';
17
- import assert from 'node:assert';
18
- import crypto from 'node:crypto';
16
+ import assert from 'assert';
17
+ import http from 'http';
18
+ import crypto from 'crypto';
19
19
  import debug from 'debug';
20
20
  import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
21
21
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
22
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
23
- export async function startStdioTransport(server) {
24
- await server.createConnection(new StdioServerTransport());
25
- }
22
+ import * as mcpServer from './server.js';
26
23
  const testDebug = debug('pw:mcp:test');
27
- async function handleSSE(server, req, res, url, sessions) {
24
+ export async function startHttpServer(config, abortSignal) {
25
+ const { host, port } = config;
26
+ const httpServer = http.createServer();
27
+ decorateServer(httpServer);
28
+ await new Promise((resolve, reject) => {
29
+ httpServer.on('error', reject);
30
+ abortSignal?.addEventListener('abort', () => {
31
+ httpServer.close();
32
+ reject(new Error('Aborted'));
33
+ });
34
+ httpServer.listen(port, host, () => {
35
+ resolve();
36
+ httpServer.removeListener('error', reject);
37
+ });
38
+ });
39
+ return httpServer;
40
+ }
41
+ export function httpAddressToString(address) {
42
+ assert(address, 'Could not bind server socket');
43
+ if (typeof address === 'string')
44
+ return address;
45
+ const resolvedPort = address.port;
46
+ let resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
47
+ if (resolvedHost === '0.0.0.0' || resolvedHost === '[::]')
48
+ resolvedHost = 'localhost';
49
+ return `http://${resolvedHost}:${resolvedPort}`;
50
+ }
51
+ export async function installHttpTransport(httpServer, serverBackendFactory) {
52
+ const sseSessions = new Map();
53
+ const streamableSessions = new Map();
54
+ httpServer.on('request', async (req, res) => {
55
+ const url = new URL(`http://localhost${req.url}`);
56
+ if (url.pathname.startsWith('/sse'))
57
+ await handleSSE(serverBackendFactory, req, res, url, sseSessions);
58
+ else
59
+ await handleStreamable(serverBackendFactory, req, res, streamableSessions);
60
+ });
61
+ }
62
+ async function handleSSE(serverBackendFactory, req, res, url, sessions) {
28
63
  if (req.method === 'POST') {
29
64
  const sessionId = url.searchParams.get('sessionId');
30
65
  if (!sessionId) {
@@ -42,19 +77,17 @@ async function handleSSE(server, req, res, url, sessions) {
42
77
  const transport = new SSEServerTransport('/sse', res);
43
78
  sessions.set(transport.sessionId, transport);
44
79
  testDebug(`create SSE session: ${transport.sessionId}`);
45
- const connection = await server.createConnection(transport);
80
+ await mcpServer.connect(serverBackendFactory, transport, false);
46
81
  res.on('close', () => {
47
82
  testDebug(`delete SSE session: ${transport.sessionId}`);
48
83
  sessions.delete(transport.sessionId);
49
- // eslint-disable-next-line no-console
50
- void connection.close().catch(e => console.error(e));
51
84
  });
52
85
  return;
53
86
  }
54
87
  res.statusCode = 405;
55
88
  res.end('Method not allowed');
56
89
  }
57
- async function handleStreamable(server, req, res, sessions) {
90
+ async function handleStreamable(serverBackendFactory, req, res, sessions) {
58
91
  const sessionId = req.headers['mcp-session-id'];
59
92
  if (sessionId) {
60
93
  const transport = sessions.get(sessionId);
@@ -68,67 +101,36 @@ async function handleStreamable(server, req, res, sessions) {
68
101
  if (req.method === 'POST') {
69
102
  const transport = new StreamableHTTPServerTransport({
70
103
  sessionIdGenerator: () => crypto.randomUUID(),
71
- onsessioninitialized: sessionId => {
104
+ onsessioninitialized: async (sessionId) => {
105
+ testDebug(`create http session: ${transport.sessionId}`);
106
+ await mcpServer.connect(serverBackendFactory, transport, true);
72
107
  sessions.set(sessionId, transport);
73
108
  }
74
109
  });
75
110
  transport.onclose = () => {
76
- if (transport.sessionId)
77
- sessions.delete(transport.sessionId);
111
+ if (!transport.sessionId)
112
+ return;
113
+ sessions.delete(transport.sessionId);
114
+ testDebug(`delete http session: ${transport.sessionId}`);
78
115
  };
79
- await server.createConnection(transport);
80
116
  await transport.handleRequest(req, res);
81
117
  return;
82
118
  }
83
119
  res.statusCode = 400;
84
120
  res.end('Invalid request');
85
121
  }
86
- export async function startHttpServer(config) {
87
- const { host, port } = config;
88
- const httpServer = http.createServer();
89
- await new Promise((resolve, reject) => {
90
- httpServer.on('error', reject);
91
- httpServer.listen(port, host, () => {
92
- resolve();
93
- httpServer.removeListener('error', reject);
94
- });
122
+ function decorateServer(server) {
123
+ const sockets = new Set();
124
+ server.on('connection', socket => {
125
+ sockets.add(socket);
126
+ socket.once('close', () => sockets.delete(socket));
95
127
  });
96
- return httpServer;
97
- }
98
- export function startHttpTransport(httpServer, mcpServer) {
99
- const sseSessions = new Map();
100
- const streamableSessions = new Map();
101
- httpServer.on('request', async (req, res) => {
102
- const url = new URL(`http://localhost${req.url}`);
103
- if (url.pathname.startsWith('/mcp'))
104
- await handleStreamable(mcpServer, req, res, streamableSessions);
105
- else
106
- await handleSSE(mcpServer, req, res, url, sseSessions);
107
- });
108
- const url = httpAddressToString(httpServer.address());
109
- const message = [
110
- `Listening on ${url}`,
111
- 'Put this in your client config:',
112
- JSON.stringify({
113
- 'mcpServers': {
114
- 'playwright': {
115
- 'url': `${url}/sse`
116
- }
117
- }
118
- }, undefined, 2),
119
- 'If your client supports streamable HTTP, you can use the /mcp endpoint instead.',
120
- ].join('\n');
121
- // eslint-disable-next-line no-console
122
- console.error(message);
123
- }
124
- export function httpAddressToString(address) {
125
- assert(address, 'Could not bind server socket');
126
- if (typeof address === 'string')
127
- return address;
128
- const resolvedPort = address.port;
129
- let resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
130
- if (resolvedHost === '0.0.0.0' || resolvedHost === '[::]')
131
- resolvedHost = 'localhost';
132
- return `http://${resolvedHost}:${resolvedPort}`;
128
+ const close = server.close;
129
+ server.close = (callback) => {
130
+ for (const socket of sockets)
131
+ socket.destroy();
132
+ sockets.clear();
133
+ return close.call(server, callback);
134
+ };
133
135
  }
134
- //# sourceMappingURL=transport.js.map
136
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export class InProcessTransport {
17
+ _server;
18
+ _serverTransport;
19
+ _connected = false;
20
+ constructor(server) {
21
+ this._server = server;
22
+ this._serverTransport = new InProcessServerTransport(this);
23
+ }
24
+ async start() {
25
+ if (this._connected)
26
+ throw new Error('InprocessTransport already started!');
27
+ await this._server.connect(this._serverTransport);
28
+ this._connected = true;
29
+ }
30
+ async send(message, options) {
31
+ if (!this._connected)
32
+ throw new Error('Transport not connected');
33
+ this._serverTransport._receiveFromClient(message);
34
+ }
35
+ async close() {
36
+ if (this._connected) {
37
+ this._connected = false;
38
+ this.onclose?.();
39
+ this._serverTransport.onclose?.();
40
+ }
41
+ }
42
+ onclose;
43
+ onerror;
44
+ onmessage;
45
+ sessionId;
46
+ setProtocolVersion;
47
+ _receiveFromServer(message, extra) {
48
+ this.onmessage?.(message, extra);
49
+ }
50
+ }
51
+ class InProcessServerTransport {
52
+ _clientTransport;
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
+ onclose;
65
+ onerror;
66
+ onmessage;
67
+ sessionId;
68
+ setProtocolVersion;
69
+ _receiveFromClient(message) {
70
+ this.onmessage?.(message);
71
+ }
72
+ }
73
+ //# sourceMappingURL=inProcessTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inProcessTransport.js","sourceRoot":"","sources":["../../src/mcp/inProcessTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,OAAO,kBAAkB;IACrB,OAAO,CAAS;IAChB,gBAAgB,CAA2B;IAC3C,UAAU,GAAY,KAAK,CAAC;IAEpC,YAAY,MAAc;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,gBAAgB,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,UAAU;YACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAEzD,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAuB,EAAE,OAA8B;QAChE,IAAI,CAAC,IAAI,CAAC,UAAU;YAClB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAG7C,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,CAA4B;IACnC,OAAO,CAAwC;IAC/C,SAAS,CAA6E;IACtF,SAAS,CAAsB;IAC/B,kBAAkB,CAA2C;IAE7D,kBAAkB,CAAC,OAAuB,EAAE,KAAwB;QAClE,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;CACF;AAED,MAAM,wBAAwB;IACpB,gBAAgB,CAAqB;IAE7C,YAAY,eAAmC;QAC7C,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK;IACX,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAuB,EAAE,OAA8B;QAChE,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IACnB,CAAC;IAED,OAAO,CAA4B;IACnC,OAAO,CAAwC;IAC/C,SAAS,CAA6E;IACtF,SAAS,CAAsB;IAC/B,kBAAkB,CAA2C;IAC7D,kBAAkB,CAAC,OAAuB;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manualPromise.js","sourceRoot":"","sources":["../../src/mcp/manualPromise.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,OAAO,aAAwB,SAAQ,OAAU;IAC7C,QAAQ,CAAkB;IAC1B,OAAO,CAAsB;IAC7B,OAAO,CAAU;IAEzB;QACE,IAAI,OAAuB,CAAC;QAC5B,IAAI,MAA0B,CAAC;QAC/B,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,OAAO,GAAG,CAAC,CAAC;YACZ,MAAM,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,OAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,MAAO,CAAC;IACzB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,OAAO,CAAC,CAAI;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,CAAQ;QACb,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAc,CAAC,MAAM,CAAC,OAAO,CAAC;QAClC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAa,CAAC,MAAM,CAAC,WAAW,CAAC;QAC/B,OAAO,eAAe,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,iBAAiB;IACpB,eAAe,CAAoB;IACnC,WAAW,CAAoB;IAC/B,kBAAkB,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC/D,SAAS,GAAG,KAAK,CAAC;IAE1B,MAAM,CAAC,KAAY;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE;YAC5C,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,KAAY;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,kBAAkB;YAC/C,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAI,MAA2B,EAAE,OAAmB;QAC3E,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,OAAkC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,CAAe,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,OAAmB,EAAE,YAAgB;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,QAAwB,EAAE,IAAa,EAAE,YAAkB;QAC7E,MAAM,gBAAgB,GAAG,IAAI,aAAa,EAAS,CAAC;QACpD,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,eAAe;YACtB,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,WAAW;YAClB,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;gBACxB,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACnE,GAAG,QAAQ;aACZ,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF;AAED,SAAS,UAAU,CAAC,KAAY,EAAE,MAAgB;IAChD,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;IAC1B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,KAAK,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;IAC9C,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;IAChC,KAAK,CAAC,eAAe,GAAG,eAAe,CAAC;IACxC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
package/lib/mcp/mdb.js ADDED
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import debug from 'debug';
17
+ import { z } from 'zod';
18
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
19
+ import { PingRequestSchema } from '@modelcontextprotocol/sdk/types.js';
20
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
21
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
22
+ import { defineToolSchema } from './tool.js';
23
+ import * as mcpServer from './server.js';
24
+ import * as mcpHttp from './http.js';
25
+ import { wrapInProcess } from './server.js';
26
+ import { ManualPromise } from './manualPromise.js';
27
+ const mdbDebug = debug('pw:mcp:mdb');
28
+ const errorsDebug = debug('pw:mcp:errors');
29
+ export class MDBBackend {
30
+ _stack = [];
31
+ _interruptPromise;
32
+ _topLevelBackend;
33
+ _initialized = false;
34
+ constructor(topLevelBackend) {
35
+ this._topLevelBackend = topLevelBackend;
36
+ }
37
+ async initialize(server) {
38
+ if (this._initialized)
39
+ return;
40
+ this._initialized = true;
41
+ const transport = await wrapInProcess(this._topLevelBackend);
42
+ await this._pushClient(transport);
43
+ }
44
+ async listTools() {
45
+ const response = await this._client().listTools();
46
+ return response.tools;
47
+ }
48
+ async callTool(name, args) {
49
+ if (name === pushToolsSchema.name)
50
+ return await this._pushTools(pushToolsSchema.inputSchema.parse(args || {}));
51
+ const interruptPromise = new ManualPromise();
52
+ this._interruptPromise = interruptPromise;
53
+ let [entry] = this._stack;
54
+ // Pop the client while the tool is not found.
55
+ while (entry && !entry.toolNames.includes(name)) {
56
+ mdbDebug('popping client from stack for ', name);
57
+ this._stack.shift();
58
+ await entry.client.close();
59
+ entry = this._stack[0];
60
+ }
61
+ if (!entry)
62
+ throw new Error(`Tool ${name} not found in the tool stack`);
63
+ const resultPromise = new ManualPromise();
64
+ entry.resultPromise = resultPromise;
65
+ this._client().callTool({
66
+ name,
67
+ arguments: args,
68
+ }).then(result => {
69
+ resultPromise.resolve(result);
70
+ }).catch(e => {
71
+ mdbDebug('error in client call', e);
72
+ if (this._stack.length < 2)
73
+ throw e;
74
+ this._stack.shift();
75
+ const prevEntry = this._stack[0];
76
+ void prevEntry.resultPromise.then(result => resultPromise.resolve(result));
77
+ });
78
+ const result = await Promise.race([interruptPromise, resultPromise]);
79
+ if (interruptPromise.isDone())
80
+ mdbDebug('client call intercepted', result);
81
+ else
82
+ mdbDebug('client call result', result);
83
+ return result;
84
+ }
85
+ _client() {
86
+ const [entry] = this._stack;
87
+ if (!entry)
88
+ throw new Error('No debugging backend available');
89
+ return entry.client;
90
+ }
91
+ async _pushTools(params) {
92
+ mdbDebug('pushing tools to the stack', params.mcpUrl);
93
+ const transport = new StreamableHTTPClientTransport(new URL(params.mcpUrl));
94
+ await this._pushClient(transport, params.introMessage);
95
+ return { content: [{ type: 'text', text: 'Tools pushed' }] };
96
+ }
97
+ async _pushClient(transport, introMessage) {
98
+ mdbDebug('pushing client to the stack');
99
+ const client = new Client({ name: 'Internal client', version: '0.0.0' });
100
+ client.setRequestHandler(PingRequestSchema, () => ({}));
101
+ await client.connect(transport);
102
+ mdbDebug('connected to the new client');
103
+ const { tools } = await client.listTools();
104
+ this._stack.unshift({ client, toolNames: tools.map(tool => tool.name), resultPromise: undefined });
105
+ mdbDebug('new tools added to the stack:', tools.map(tool => tool.name));
106
+ mdbDebug('interrupting current call:', !!this._interruptPromise);
107
+ this._interruptPromise?.resolve({
108
+ content: [{
109
+ type: 'text',
110
+ text: introMessage || '',
111
+ }],
112
+ });
113
+ this._interruptPromise = undefined;
114
+ return { content: [{ type: 'text', text: 'Tools pushed' }] };
115
+ }
116
+ }
117
+ const pushToolsSchema = defineToolSchema({
118
+ name: 'mdb_push_tools',
119
+ title: 'Push MCP tools to the tools stack',
120
+ description: 'Push MCP tools to the tools stack',
121
+ inputSchema: z.object({
122
+ mcpUrl: z.string(),
123
+ introMessage: z.string().optional(),
124
+ }),
125
+ type: 'readOnly',
126
+ });
127
+ export async function runMainBackend(backendFactory, options) {
128
+ const mdbBackend = new MDBBackend(backendFactory.create());
129
+ // Start HTTP unconditionally.
130
+ const factory = {
131
+ ...backendFactory,
132
+ create: () => mdbBackend
133
+ };
134
+ const url = await startAsHttp(factory, { port: options?.port || 0 });
135
+ process.env.PLAYWRIGHT_DEBUGGER_MCP = url;
136
+ if (options?.port !== undefined)
137
+ return url;
138
+ // Start stdio conditionally.
139
+ await mcpServer.connect(factory, new StdioServerTransport(), false);
140
+ }
141
+ export async function runOnPauseBackendLoop(mdbUrl, backend, introMessage) {
142
+ const wrappedBackend = new OnceTimeServerBackendWrapper(backend);
143
+ const factory = {
144
+ name: 'on-pause-backend',
145
+ nameInConfig: 'on-pause-backend',
146
+ version: '0.0.0',
147
+ create: () => wrappedBackend,
148
+ };
149
+ const httpServer = await mcpHttp.startHttpServer({ port: 0 });
150
+ await mcpHttp.installHttpTransport(httpServer, factory);
151
+ 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));
155
+ await client.connect(transport);
156
+ const pushToolsResult = await client.callTool({
157
+ name: pushToolsSchema.name,
158
+ arguments: {
159
+ mcpUrl: url,
160
+ introMessage,
161
+ },
162
+ });
163
+ if (pushToolsResult.isError)
164
+ errorsDebug('Failed to push tools', pushToolsResult.content);
165
+ await transport.terminateSession();
166
+ await client.close();
167
+ await wrappedBackend.waitForClosed();
168
+ httpServer.close();
169
+ }
170
+ async function startAsHttp(backendFactory, options) {
171
+ const httpServer = await mcpHttp.startHttpServer(options);
172
+ await mcpHttp.installHttpTransport(httpServer, backendFactory);
173
+ return mcpHttp.httpAddressToString(httpServer.address());
174
+ }
175
+ class OnceTimeServerBackendWrapper {
176
+ _backend;
177
+ _selfDestructPromise = new ManualPromise();
178
+ constructor(backend) {
179
+ this._backend = backend;
180
+ this._backend.requestSelfDestruct = () => this._selfDestructPromise.resolve();
181
+ }
182
+ async initialize(server, clientVersion, roots) {
183
+ await this._backend.initialize?.(server, clientVersion, roots);
184
+ }
185
+ async listTools() {
186
+ return this._backend.listTools();
187
+ }
188
+ async callTool(name, args) {
189
+ return this._backend.callTool(name, args);
190
+ }
191
+ serverClosed(server) {
192
+ this._backend.serverClosed?.(server);
193
+ this._selfDestructPromise.resolve();
194
+ }
195
+ async waitForClosed() {
196
+ await this._selfDestructPromise;
197
+ }
198
+ }
199
+ //# sourceMappingURL=mdb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdb.js","sourceRoot":"","sources":["../../src/mcp/mdb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import debug from 'debug';
17
+ import { z } from 'zod';
18
+ import { zodToJsonSchema } from 'zod-to-json-schema';
19
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
20
+ import { ListRootsRequestSchema, PingRequestSchema } from '@modelcontextprotocol/sdk/types.js';
21
+ const errorsDebug = debug('pw:mcp:errors');
22
+ export class ProxyBackend {
23
+ _mcpProviders;
24
+ _currentClient;
25
+ _contextSwitchTool;
26
+ _roots = [];
27
+ constructor(mcpProviders) {
28
+ this._mcpProviders = mcpProviders;
29
+ this._contextSwitchTool = this._defineContextSwitchTool();
30
+ }
31
+ async initialize(server, clientVersion, roots) {
32
+ this._roots = roots;
33
+ await this._setCurrentClient(this._mcpProviders[0]);
34
+ }
35
+ async listTools() {
36
+ const response = await this._currentClient.listTools();
37
+ if (this._mcpProviders.length === 1)
38
+ return response.tools;
39
+ return [
40
+ ...response.tools,
41
+ this._contextSwitchTool,
42
+ ];
43
+ }
44
+ async callTool(name, args) {
45
+ if (name === this._contextSwitchTool.name)
46
+ return this._callContextSwitchTool(args);
47
+ return await this._currentClient.callTool({
48
+ name,
49
+ arguments: args,
50
+ });
51
+ }
52
+ serverClosed() {
53
+ void this._currentClient?.close().catch(errorsDebug);
54
+ }
55
+ async _callContextSwitchTool(params) {
56
+ try {
57
+ const factory = this._mcpProviders.find(factory => factory.name === params.name);
58
+ if (!factory)
59
+ throw new Error('Unknown connection method: ' + params.name);
60
+ await this._setCurrentClient(factory);
61
+ return {
62
+ content: [{ type: 'text', text: '### Result\nSuccessfully changed connection method.\n' }],
63
+ };
64
+ }
65
+ catch (error) {
66
+ return {
67
+ content: [{ type: 'text', text: `### Result\nError: ${error}\n` }],
68
+ isError: true,
69
+ };
70
+ }
71
+ }
72
+ _defineContextSwitchTool() {
73
+ return {
74
+ name: 'browser_connect',
75
+ description: [
76
+ 'Connect to a browser using one of the available methods:',
77
+ ...this._mcpProviders.map(factory => `- "${factory.name}": ${factory.description}`),
78
+ ].join('\n'),
79
+ inputSchema: zodToJsonSchema(z.object({
80
+ name: z.enum(this._mcpProviders.map(factory => factory.name)).default(this._mcpProviders[0].name).describe('The method to use to connect to the browser'),
81
+ }), { strictUnions: true }),
82
+ annotations: {
83
+ title: 'Connect to a browser context',
84
+ readOnlyHint: true,
85
+ openWorldHint: false,
86
+ },
87
+ };
88
+ }
89
+ async _setCurrentClient(factory) {
90
+ await this._currentClient?.close();
91
+ this._currentClient = undefined;
92
+ const client = new Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });
93
+ client.registerCapabilities({
94
+ roots: {
95
+ listRoots: true,
96
+ },
97
+ });
98
+ client.setRequestHandler(ListRootsRequestSchema, () => ({ roots: this._roots }));
99
+ client.setRequestHandler(PingRequestSchema, () => ({}));
100
+ const transport = await factory.connect();
101
+ await client.connect(transport);
102
+ this._currentClient = client;
103
+ }
104
+ }
105
+ //# sourceMappingURL=proxyBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxyBackend.js","sourceRoot":"","sources":["../../src/mcp/proxyBackend.ts"],"names":[],"mappings":"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"}