kibbutz-mcp 1.0.2 → 1.0.4

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 (2) hide show
  1. package/build/index.js +52 -20
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -9,14 +9,14 @@ import { spawn } from 'child_process';
9
9
  import fs from 'fs';
10
10
  import path from 'path';
11
11
  let mcpSocket = null;
12
- let socket = null;
12
+ let pingSocket = null;
13
13
  let token = null;
14
14
  let port = null;
15
15
  let wsPromise = null;
16
16
  const map = new Map();
17
17
  const server = new McpServer({
18
18
  name: 'kibbutz-mcp',
19
- version: '1.0.2',
19
+ version: '1.0.4',
20
20
  });
21
21
  function findChromeExecutable() {
22
22
  const platform = process.platform;
@@ -65,7 +65,7 @@ const sendAndWaitForReply = async (message, args) => {
65
65
  const timeout = setTimeout(() => {
66
66
  wsPromise = null;
67
67
  reject(new Error('Timeout waiting for MCP extension WebSocket connection'));
68
- }, 10000);
68
+ }, 2000);
69
69
  wsPromise = () => {
70
70
  clearTimeout(timeout);
71
71
  resolve();
@@ -75,19 +75,15 @@ const sendAndWaitForReply = async (message, args) => {
75
75
  }
76
76
  catch (error) { }
77
77
  }
78
- if (!mcpSocket || mcpSocket.readyState !== WebSocket.OPEN) {
78
+ if (!mcpSocket ||
79
+ !pingSocket ||
80
+ mcpSocket.readyState !== WebSocket.OPEN ||
81
+ pingSocket.readyState !== WebSocket.OPEN) {
79
82
  return Promise.resolve({
80
83
  content: [
81
84
  {
82
85
  type: 'text',
83
- text: `Connection failed: The MCP server cannot reach the Chrome extension.
84
-
85
- Please check the following:
86
- 1. Is the browser open?
87
- 2. Is the MCP switch inside the extension popup turned ON?
88
-
89
- If the issue persists, copy and paste this URL into your browser address bar:
90
- chrome-extension://bpfjmggaaiigpfahhmpmacfhlemnhhip/KIBBUTZ-MCP.html`,
86
+ text: `Connection failed: The MCP server cannot reach the Chrome extension. Open chrome-extension://bpfjmggaaiigpfahhmpmacfhlemnhhip/KIBBUTZ-MCP.html for troubleshooting.`,
91
87
  },
92
88
  ],
93
89
  isError: true,
@@ -145,6 +141,26 @@ server.registerTool('CLOSE_TABS_MCP', {
145
141
  .describe('List of specific tab identifiers (integers) to close.'),
146
142
  },
147
143
  }, (args) => sendAndWaitForReply('CLOSE_TABS_MCP', args));
144
+ server.registerTool('PIN_TABS_MCP', {
145
+ title: 'Pin tabs',
146
+ description: 'Pin specific browser tabs using their unique IDs.',
147
+ inputSchema: {
148
+ tabIds: z
149
+ .array(z.number())
150
+ .min(1)
151
+ .describe('List of specific tab identifiers (integers) to pin.'),
152
+ },
153
+ }, (args) => sendAndWaitForReply('PIN_TABS_MCP', args));
154
+ server.registerTool('UNPIN_TABS_MCP', {
155
+ title: 'Unpin tabs',
156
+ description: 'Unpin specific browser tabs using their unique IDs.',
157
+ inputSchema: {
158
+ tabIds: z
159
+ .array(z.number())
160
+ .min(1)
161
+ .describe('List of specific tab identifiers (integers) to unpin.'),
162
+ },
163
+ }, (args) => sendAndWaitForReply('UNPIN_TABS_MCP', args));
148
164
  server.registerTool('UNGROUP_TABS_MCP', {
149
165
  title: 'Ungroup tabs',
150
166
  description: 'Remove specific tabs from their assigned groups using their tab IDs. The tabs will become standalone.',
@@ -242,11 +258,19 @@ async function main() {
242
258
  const wss = new WebSocketServer({ noServer: true });
243
259
  const wssMcp = new WebSocketServer({ noServer: true });
244
260
  wss.on('connection', (ws) => {
245
- socket = ws;
261
+ pingSocket = ws;
246
262
  ws.on('error', console.error);
247
263
  ws.on('close', () => {
248
- if (socket === ws) {
249
- socket = null;
264
+ if (pingSocket === ws) {
265
+ pingSocket = null;
266
+ if (mcpSocket) {
267
+ wssMcp.clients.forEach((ws) => ws.terminate());
268
+ mcpSocket = null;
269
+ }
270
+ for (const { reject } of map.values()) {
271
+ reject(new Error('Extension WebSocket closed'));
272
+ }
273
+ map.clear();
250
274
  }
251
275
  });
252
276
  });
@@ -277,24 +301,32 @@ async function main() {
277
301
  });
278
302
  });
279
303
  httpServer.on('upgrade', (request, socket, head) => {
280
- if (request.headers['sec-websocket-protocol'] !== token) {
281
- socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
282
- socket.destroy();
283
- return;
284
- }
285
304
  const { pathname } = new URL(request.url || '', `wss:127.0.0.1:${port}`);
286
305
  if (pathname === '/ping') {
306
+ if (request.headers['sec-websocket-protocol'] !== token) {
307
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
308
+ socket.destroy();
309
+ return;
310
+ }
287
311
  wss.clients.forEach((ws) => ws.terminate());
288
312
  wss.handleUpgrade(request, socket, head, (ws) => {
289
313
  wss.emit('connection', ws, request);
290
314
  });
291
315
  }
292
316
  else if (pathname === '/mcp') {
317
+ if (pingSocket?.readyState !== WebSocket.OPEN) {
318
+ socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
319
+ socket.destroy();
320
+ return;
321
+ }
293
322
  wssMcp.clients.forEach((ws) => ws.terminate());
294
323
  wssMcp.handleUpgrade(request, socket, head, (ws) => {
295
324
  wssMcp.emit('connection', ws, request);
296
325
  });
297
326
  }
327
+ else {
328
+ socket.destroy();
329
+ }
298
330
  });
299
331
  httpServer.listen(0, () => {
300
332
  port = httpServer.address().port;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibbutz-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "scripts": {