what-devtools-mcp 0.6.0 → 0.6.2
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/package.json +3 -3
- package/src/bridge.js +66 -2
- package/src/client-commands.js +1636 -7
- package/src/client.js +53 -12
- package/src/index.js +478 -0
- package/src/tools-agent.js +183 -2
- package/src/tools-extended.js +426 -10
- package/src/tools-interact.js +420 -0
- package/src/tools.js +110 -14
- package/src/vite-plugin.js +44 -6
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-devtools-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "MCP server bridging AI agents to live What Framework app state via WebSocket",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"what-devtools-mcp": "
|
|
7
|
+
"what-devtools-mcp": "src/index.js"
|
|
8
8
|
},
|
|
9
9
|
"exports": {
|
|
10
10
|
".": "./src/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"zod": "^3.25.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"what-devtools": "
|
|
23
|
+
"what-devtools": "^0.6.2"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"what-framework",
|
package/src/bridge.js
CHANGED
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { WebSocketServer } from 'ws';
|
|
8
|
+
import { randomBytes } from 'crypto';
|
|
9
|
+
import { createServer } from 'http';
|
|
10
|
+
import { writeFileSync, mkdirSync } from 'fs';
|
|
11
|
+
import { join } from 'path';
|
|
8
12
|
|
|
9
13
|
const MAX_EVENT_LOG = 1000;
|
|
10
14
|
const MAX_ERROR_LOG = 100;
|
|
11
15
|
|
|
12
|
-
export function createBridge({ port = 9229 } = {}) {
|
|
16
|
+
export function createBridge({ port = 9229, host = '127.0.0.1' } = {}) {
|
|
13
17
|
let latestSnapshot = null;
|
|
14
18
|
const eventLog = [];
|
|
15
19
|
const errorLog = [];
|
|
@@ -25,7 +29,64 @@ export function createBridge({ port = 9229 } = {}) {
|
|
|
25
29
|
// Baseline snapshot for diff tool
|
|
26
30
|
let baselineSnapshot = null;
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
// Use a fixed token from env if provided, otherwise generate a random one.
|
|
33
|
+
// Set WHAT_MCP_TOKEN to share the same token between bridge and Vite plugin.
|
|
34
|
+
const authToken = process.env.WHAT_MCP_TOKEN || randomBytes(24).toString('hex');
|
|
35
|
+
|
|
36
|
+
const wss = new WebSocketServer({ host, port, verifyClient: ({ req }) => {
|
|
37
|
+
// Require a valid token query parameter to connect
|
|
38
|
+
try {
|
|
39
|
+
const url = new URL(req.url, `http://${host}:${port}`);
|
|
40
|
+
return url.searchParams.get('token') === authToken;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}});
|
|
45
|
+
|
|
46
|
+
// --- Token Discovery ---
|
|
47
|
+
// Two mechanisms so the browser client can find the token automatically:
|
|
48
|
+
//
|
|
49
|
+
// 1. HTTP endpoint: GET http://localhost:{port+1}/__what_mcp_token returns the token
|
|
50
|
+
// The client fetches this on startup before connecting the WebSocket.
|
|
51
|
+
//
|
|
52
|
+
// 2. File: writes token to node_modules/.cache/what-devtools-mcp/token
|
|
53
|
+
// The Vite plugin reads this at transform time.
|
|
54
|
+
|
|
55
|
+
const discoveryPort = port + 1;
|
|
56
|
+
const httpServer = createServer((req, res) => {
|
|
57
|
+
// CORS headers so the browser can fetch from any origin
|
|
58
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
59
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET');
|
|
60
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
61
|
+
|
|
62
|
+
if (req.url === '/__what_mcp_token') {
|
|
63
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
64
|
+
res.end(JSON.stringify({ token: authToken, wsPort: port }));
|
|
65
|
+
} else {
|
|
66
|
+
res.writeHead(404);
|
|
67
|
+
res.end('Not found');
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
httpServer.listen(discoveryPort, host, () => {
|
|
72
|
+
console.error(`[what-devtools-mcp] Token discovery on http://${host}:${discoveryPort}/__what_mcp_token`);
|
|
73
|
+
});
|
|
74
|
+
httpServer.on('error', () => {
|
|
75
|
+
// Discovery port unavailable — not critical, file-based fallback still works
|
|
76
|
+
console.error(`[what-devtools-mcp] Token discovery port ${discoveryPort} unavailable (non-fatal)`);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Write token to a well-known file path for Vite plugin to read
|
|
80
|
+
try {
|
|
81
|
+
const cacheDir = join(process.cwd(), 'node_modules', '.cache', 'what-devtools-mcp');
|
|
82
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
83
|
+
writeFileSync(join(cacheDir, 'token'), JSON.stringify({ token: authToken, port, discoveryPort }));
|
|
84
|
+
} catch {
|
|
85
|
+
// Non-fatal — HTTP discovery is the primary mechanism
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.error(`[what-devtools-mcp] Bridge listening on ws://${host}:${port}`);
|
|
89
|
+
console.error(`[what-devtools-mcp] Auth token: ${authToken}`);
|
|
29
90
|
|
|
30
91
|
wss.on('connection', (ws) => {
|
|
31
92
|
browserSocket = ws;
|
|
@@ -130,6 +191,7 @@ export function createBridge({ port = 9229 } = {}) {
|
|
|
130
191
|
|
|
131
192
|
function saveBaseline() {
|
|
132
193
|
baselineSnapshot = latestSnapshot ? JSON.parse(JSON.stringify(latestSnapshot)) : null;
|
|
194
|
+
if (baselineSnapshot) baselineSnapshot._savedAt = Date.now();
|
|
133
195
|
return !!baselineSnapshot;
|
|
134
196
|
}
|
|
135
197
|
|
|
@@ -153,6 +215,7 @@ export function createBridge({ port = 9229 } = {}) {
|
|
|
153
215
|
pendingCommands.delete(id);
|
|
154
216
|
}
|
|
155
217
|
wss.close();
|
|
218
|
+
httpServer.close();
|
|
156
219
|
}
|
|
157
220
|
|
|
158
221
|
return {
|
|
@@ -167,5 +230,6 @@ export function createBridge({ port = 9229 } = {}) {
|
|
|
167
230
|
saveBaseline,
|
|
168
231
|
getBaseline,
|
|
169
232
|
close,
|
|
233
|
+
authToken,
|
|
170
234
|
};
|
|
171
235
|
}
|