@dolusoft/claude-collab 1.8.4 → 1.8.6

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/dist/mcp-main.js CHANGED
@@ -6,7 +6,7 @@ import { execFile, spawn } from 'child_process';
6
6
  import { unlinkSync } from 'fs';
7
7
  import { tmpdir } from 'os';
8
8
  import { join } from 'path';
9
- import { Bonjour } from 'bonjour-service';
9
+ import { createSocket } from 'dgram';
10
10
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
12
  import { z } from 'zod';
@@ -666,28 +666,48 @@ var HubServer = class {
666
666
  }
667
667
  }
668
668
  };
669
- var SERVICE_TYPE = "claude-collab";
670
- var MdnsAdvertiser = class {
671
- bonjour = null;
672
- start(port) {
673
- this.bonjour = new Bonjour();
674
- this.bonjour.publish({ name: "claude-collab-hub", type: SERVICE_TYPE, port });
675
- console.error(`[mdns] advertising hub on port ${port}`);
669
+ var DISCOVERY_PORT = 9998;
670
+ var BROADCAST_INTERVAL_MS = 3e3;
671
+ var BROADCAST_ADDRESS = "255.255.255.255";
672
+ var HubBroadcaster = class {
673
+ socket = null;
674
+ timer = null;
675
+ start(hubPort) {
676
+ if (this.socket) return;
677
+ const socket = createSocket("udp4");
678
+ this.socket = socket;
679
+ socket.on("error", (err) => {
680
+ console.error("[hub-broadcaster] error:", err.message);
681
+ });
682
+ socket.bind(0, () => {
683
+ socket.setBroadcast(true);
684
+ const send = () => {
685
+ if (!this.socket) return;
686
+ const msg = Buffer.from(JSON.stringify({ type: "claude-collab-hub", port: hubPort }));
687
+ socket.send(msg, 0, msg.length, DISCOVERY_PORT, BROADCAST_ADDRESS, (err) => {
688
+ if (err) console.error("[hub-broadcaster] send error:", err.message);
689
+ });
690
+ };
691
+ send();
692
+ this.timer = setInterval(send, BROADCAST_INTERVAL_MS);
693
+ });
676
694
  }
677
695
  stop() {
678
- if (!this.bonjour) return;
679
- this.bonjour.unpublishAll(() => {
680
- this.bonjour?.destroy();
681
- });
682
- this.bonjour = null;
683
- console.error("[mdns] stopped advertising");
696
+ if (this.timer) {
697
+ clearInterval(this.timer);
698
+ this.timer = null;
699
+ }
700
+ if (this.socket) {
701
+ this.socket.close();
702
+ this.socket = null;
703
+ }
684
704
  }
685
705
  };
686
706
 
687
707
  // src/infrastructure/hub/hub-manager.ts
688
708
  var HubManager = class {
689
709
  hubServer = null;
690
- advertiser = null;
710
+ broadcaster = null;
691
711
  currentPort = null;
692
712
  get isRunning() {
693
713
  return this.hubServer !== null;
@@ -701,9 +721,9 @@ var HubManager = class {
701
721
  server.start(port);
702
722
  this.hubServer = server;
703
723
  this.currentPort = port;
704
- const advertiser = new MdnsAdvertiser();
705
- advertiser.start(port);
706
- this.advertiser = advertiser;
724
+ const broadcaster = new HubBroadcaster();
725
+ broadcaster.start(port);
726
+ this.broadcaster = broadcaster;
707
727
  let firewallAdded = false;
708
728
  try {
709
729
  await addFirewallRule(port);
@@ -715,9 +735,9 @@ var HubManager = class {
715
735
  }
716
736
  async stop() {
717
737
  if (!this.isRunning) throw new Error("Hub is not running");
718
- if (this.advertiser) {
719
- this.advertiser.stop();
720
- this.advertiser = null;
738
+ if (this.broadcaster) {
739
+ this.broadcaster.stop();
740
+ this.broadcaster = null;
721
741
  }
722
742
  const port = this.currentPort;
723
743
  this.hubServer.stop();
@@ -1012,6 +1032,97 @@ function registerStopHubTool(server, hubManager) {
1012
1032
  }
1013
1033
  );
1014
1034
  }
1035
+ function discoverHub(timeoutMs = 1e4) {
1036
+ return new Promise((resolve) => {
1037
+ const socket = createSocket("udp4");
1038
+ let settled = false;
1039
+ const finish = (result) => {
1040
+ if (settled) return;
1041
+ settled = true;
1042
+ clearTimeout(timer);
1043
+ try {
1044
+ socket.close();
1045
+ } catch {
1046
+ }
1047
+ resolve(result);
1048
+ };
1049
+ const timer = setTimeout(() => finish(null), timeoutMs);
1050
+ socket.on("error", () => finish(null));
1051
+ socket.on("message", (msg, rinfo) => {
1052
+ try {
1053
+ const data = JSON.parse(msg.toString());
1054
+ if (data.type === "claude-collab-hub" && typeof data.port === "number") {
1055
+ finish({ host: rinfo.address, port: data.port });
1056
+ }
1057
+ } catch {
1058
+ }
1059
+ });
1060
+ socket.bind(DISCOVERY_PORT, "0.0.0.0");
1061
+ });
1062
+ }
1063
+ function watchForHub(onFound) {
1064
+ const socket = createSocket("udp4");
1065
+ socket.on("error", (err) => {
1066
+ console.error("[hub-listener] error:", err.message);
1067
+ });
1068
+ socket.on("message", (msg, rinfo) => {
1069
+ try {
1070
+ const data = JSON.parse(msg.toString());
1071
+ if (data.type === "claude-collab-hub" && typeof data.port === "number") {
1072
+ onFound({ host: rinfo.address, port: data.port });
1073
+ }
1074
+ } catch {
1075
+ }
1076
+ });
1077
+ socket.bind(DISCOVERY_PORT, "0.0.0.0");
1078
+ return () => {
1079
+ try {
1080
+ socket.close();
1081
+ } catch {
1082
+ }
1083
+ };
1084
+ }
1085
+
1086
+ // src/presentation/mcp/tools/connect.tool.ts
1087
+ function registerConnectTool(server, client) {
1088
+ server.tool(
1089
+ "connect",
1090
+ "Find and connect to the hub on the LAN automatically. No IP or port needed.",
1091
+ {},
1092
+ async () => {
1093
+ if (client.isConnected) {
1094
+ const info = client.getInfo();
1095
+ return {
1096
+ content: [{ type: "text", text: `Already connected to hub as "${info.teamName}".` }]
1097
+ };
1098
+ }
1099
+ const hub = await discoverHub(1e4);
1100
+ if (!hub) {
1101
+ return {
1102
+ content: [{
1103
+ type: "text",
1104
+ text: "No hub found on the LAN. Make sure someone has called start_hub on the host machine."
1105
+ }]
1106
+ };
1107
+ }
1108
+ try {
1109
+ await client.connectToHub(`ws://${hub.host}:${hub.port}`);
1110
+ const info = client.getInfo();
1111
+ return {
1112
+ content: [{
1113
+ type: "text",
1114
+ text: `Connected to hub at ${hub.host}:${hub.port} as "${info.teamName}".`
1115
+ }]
1116
+ };
1117
+ } catch (err) {
1118
+ const msg = err instanceof Error ? err.message : String(err);
1119
+ return {
1120
+ content: [{ type: "text", text: `Hub found at ${hub.host}:${hub.port} but connection failed: ${msg}` }]
1121
+ };
1122
+ }
1123
+ }
1124
+ );
1125
+ }
1015
1126
 
1016
1127
  // src/presentation/mcp/server.ts
1017
1128
  function createMcpServer(options) {
@@ -1026,6 +1137,7 @@ function createMcpServer(options) {
1026
1137
  registerHistoryTool(server, client);
1027
1138
  registerStartHubTool(server, client, hubManager);
1028
1139
  registerStopHubTool(server, hubManager);
1140
+ registerConnectTool(server, client);
1029
1141
  return server;
1030
1142
  }
1031
1143
  async function startMcpServer(options) {
@@ -1033,41 +1145,6 @@ async function startMcpServer(options) {
1033
1145
  const transport = new StdioServerTransport();
1034
1146
  await server.connect(transport);
1035
1147
  }
1036
- var SERVICE_TYPE2 = "claude-collab";
1037
- function resolveHost(svc) {
1038
- const ipv4 = svc.addresses?.find((a) => /^\d+\.\d+\.\d+\.\d+$/.test(a));
1039
- return ipv4 ?? svc.host;
1040
- }
1041
- function discoverHub(timeoutMs = 5e3) {
1042
- return new Promise((resolve) => {
1043
- const bonjour = new Bonjour();
1044
- const browser = bonjour.find({ type: SERVICE_TYPE2 });
1045
- let settled = false;
1046
- const finish = (result) => {
1047
- if (settled) return;
1048
- settled = true;
1049
- clearTimeout(timer);
1050
- browser.stop();
1051
- bonjour.destroy();
1052
- resolve(result);
1053
- };
1054
- const timer = setTimeout(() => finish(null), timeoutMs);
1055
- browser.on("up", (svc) => {
1056
- finish({ host: resolveHost(svc), port: svc.port });
1057
- });
1058
- });
1059
- }
1060
- function watchForHub(onFound) {
1061
- const bonjour = new Bonjour();
1062
- const browser = bonjour.find({ type: SERVICE_TYPE2 });
1063
- browser.on("up", (svc) => {
1064
- onFound({ host: resolveHost(svc), port: svc.port });
1065
- });
1066
- return () => {
1067
- browser.stop();
1068
- bonjour.destroy();
1069
- };
1070
- }
1071
1148
 
1072
1149
  // src/mcp-main.ts
1073
1150
  function getArg(flag) {