@darkiceinteractive/mcp-conductor 1.1.0 → 3.0.0-beta.1

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 (293) hide show
  1. package/README.md +35 -5
  2. package/dist/bin/cli.d.ts +20 -0
  3. package/dist/bin/cli.d.ts.map +1 -0
  4. package/dist/bin/cli.js +260 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/bridge/http-server.d.ts +65 -1
  7. package/dist/bridge/http-server.d.ts.map +1 -1
  8. package/dist/bridge/http-server.js +192 -7
  9. package/dist/bridge/http-server.js.map +1 -1
  10. package/dist/bridge/index.d.ts +1 -0
  11. package/dist/bridge/index.d.ts.map +1 -1
  12. package/dist/bridge/index.js +1 -0
  13. package/dist/bridge/index.js.map +1 -1
  14. package/dist/bridge/pool.d.ts +95 -0
  15. package/dist/bridge/pool.d.ts.map +1 -0
  16. package/dist/bridge/pool.js +384 -0
  17. package/dist/bridge/pool.js.map +1 -0
  18. package/dist/bridge/session-registry.d.ts +64 -0
  19. package/dist/bridge/session-registry.d.ts.map +1 -0
  20. package/dist/bridge/session-registry.js +124 -0
  21. package/dist/bridge/session-registry.js.map +1 -0
  22. package/dist/cache/cache.d.ts +43 -0
  23. package/dist/cache/cache.d.ts.map +1 -0
  24. package/dist/cache/cache.js +167 -0
  25. package/dist/cache/cache.js.map +1 -0
  26. package/dist/cache/delta.d.ts +32 -0
  27. package/dist/cache/delta.d.ts.map +1 -0
  28. package/dist/cache/delta.js +131 -0
  29. package/dist/cache/delta.js.map +1 -0
  30. package/dist/cache/disk.d.ts +65 -0
  31. package/dist/cache/disk.d.ts.map +1 -0
  32. package/dist/cache/disk.js +238 -0
  33. package/dist/cache/disk.js.map +1 -0
  34. package/dist/cache/index.d.ts +53 -0
  35. package/dist/cache/index.d.ts.map +1 -0
  36. package/dist/cache/index.js +12 -0
  37. package/dist/cache/index.js.map +1 -0
  38. package/dist/cache/key.d.ts +44 -0
  39. package/dist/cache/key.d.ts.map +1 -0
  40. package/dist/cache/key.js +83 -0
  41. package/dist/cache/key.js.map +1 -0
  42. package/dist/cache/lru.d.ts +57 -0
  43. package/dist/cache/lru.d.ts.map +1 -0
  44. package/dist/cache/lru.js +112 -0
  45. package/dist/cache/lru.js.map +1 -0
  46. package/dist/cache/policy.d.ts +34 -0
  47. package/dist/cache/policy.d.ts.map +1 -0
  48. package/dist/cache/policy.js +95 -0
  49. package/dist/cache/policy.js.map +1 -0
  50. package/dist/cli/commands/doctor.d.ts +33 -0
  51. package/dist/cli/commands/doctor.d.ts.map +1 -0
  52. package/dist/cli/commands/doctor.js +135 -0
  53. package/dist/cli/commands/doctor.js.map +1 -0
  54. package/dist/cli/commands/export-servers.d.ts +22 -0
  55. package/dist/cli/commands/export-servers.d.ts.map +1 -0
  56. package/dist/cli/commands/export-servers.js +45 -0
  57. package/dist/cli/commands/export-servers.js.map +1 -0
  58. package/dist/cli/commands/import-servers.d.ts +57 -0
  59. package/dist/cli/commands/import-servers.d.ts.map +1 -0
  60. package/dist/cli/commands/import-servers.js +137 -0
  61. package/dist/cli/commands/import-servers.js.map +1 -0
  62. package/dist/cli/commands/routing.d.ts +34 -0
  63. package/dist/cli/commands/routing.d.ts.map +1 -0
  64. package/dist/cli/commands/routing.js +60 -0
  65. package/dist/cli/commands/routing.js.map +1 -0
  66. package/dist/cli/commands/test-server.d.ts +34 -0
  67. package/dist/cli/commands/test-server.d.ts.map +1 -0
  68. package/dist/cli/commands/test-server.js +86 -0
  69. package/dist/cli/commands/test-server.js.map +1 -0
  70. package/dist/cli/daemon.d.ts +60 -0
  71. package/dist/cli/daemon.d.ts.map +1 -0
  72. package/dist/cli/daemon.js +244 -0
  73. package/dist/cli/daemon.js.map +1 -0
  74. package/dist/cli/replay.d.ts +16 -0
  75. package/dist/cli/replay.d.ts.map +1 -0
  76. package/dist/cli/replay.js +89 -0
  77. package/dist/cli/replay.js.map +1 -0
  78. package/dist/cli/wizard/setup.d.ts +12 -0
  79. package/dist/cli/wizard/setup.d.ts.map +1 -0
  80. package/dist/cli/wizard/setup.js +71 -0
  81. package/dist/cli/wizard/setup.js.map +1 -0
  82. package/dist/config/defaults.d.ts +10 -0
  83. package/dist/config/defaults.d.ts.map +1 -1
  84. package/dist/config/defaults.js +14 -1
  85. package/dist/config/defaults.js.map +1 -1
  86. package/dist/config/schema.d.ts +34 -0
  87. package/dist/config/schema.d.ts.map +1 -1
  88. package/dist/daemon/client.d.ts +97 -0
  89. package/dist/daemon/client.d.ts.map +1 -0
  90. package/dist/daemon/client.js +279 -0
  91. package/dist/daemon/client.js.map +1 -0
  92. package/dist/daemon/discovery.d.ts +50 -0
  93. package/dist/daemon/discovery.d.ts.map +1 -0
  94. package/dist/daemon/discovery.js +104 -0
  95. package/dist/daemon/discovery.js.map +1 -0
  96. package/dist/daemon/index.d.ts +16 -0
  97. package/dist/daemon/index.d.ts.map +1 -0
  98. package/dist/daemon/index.js +11 -0
  99. package/dist/daemon/index.js.map +1 -0
  100. package/dist/daemon/sandbox-api.d.ts +45 -0
  101. package/dist/daemon/sandbox-api.d.ts.map +1 -0
  102. package/dist/daemon/sandbox-api.js +74 -0
  103. package/dist/daemon/sandbox-api.js.map +1 -0
  104. package/dist/daemon/server.d.ts +65 -0
  105. package/dist/daemon/server.d.ts.map +1 -0
  106. package/dist/daemon/server.js +351 -0
  107. package/dist/daemon/server.js.map +1 -0
  108. package/dist/daemon/shared-kv.d.ts +81 -0
  109. package/dist/daemon/shared-kv.d.ts.map +1 -0
  110. package/dist/daemon/shared-kv.js +215 -0
  111. package/dist/daemon/shared-kv.js.map +1 -0
  112. package/dist/daemon/shared-lock.d.ts +71 -0
  113. package/dist/daemon/shared-lock.d.ts.map +1 -0
  114. package/dist/daemon/shared-lock.js +119 -0
  115. package/dist/daemon/shared-lock.js.map +1 -0
  116. package/dist/hub/mcp-hub.d.ts +23 -0
  117. package/dist/hub/mcp-hub.d.ts.map +1 -1
  118. package/dist/hub/mcp-hub.js +34 -1
  119. package/dist/hub/mcp-hub.js.map +1 -1
  120. package/dist/index.js +19 -0
  121. package/dist/index.js.map +1 -1
  122. package/dist/observability/anomaly.d.ts +67 -0
  123. package/dist/observability/anomaly.d.ts.map +1 -0
  124. package/dist/observability/anomaly.js +141 -0
  125. package/dist/observability/anomaly.js.map +1 -0
  126. package/dist/observability/cost-predictor.d.ts +49 -0
  127. package/dist/observability/cost-predictor.d.ts.map +1 -0
  128. package/dist/observability/cost-predictor.js +145 -0
  129. package/dist/observability/cost-predictor.js.map +1 -0
  130. package/dist/observability/hot-path.d.ts +49 -0
  131. package/dist/observability/hot-path.d.ts.map +1 -0
  132. package/dist/observability/hot-path.js +125 -0
  133. package/dist/observability/hot-path.js.map +1 -0
  134. package/dist/observability/index.d.ts +10 -0
  135. package/dist/observability/index.d.ts.map +1 -0
  136. package/dist/observability/index.js +10 -0
  137. package/dist/observability/index.js.map +1 -0
  138. package/dist/observability/replay.d.ts +104 -0
  139. package/dist/observability/replay.d.ts.map +1 -0
  140. package/dist/observability/replay.js +239 -0
  141. package/dist/observability/replay.js.map +1 -0
  142. package/dist/registry/built-in-recommendations.d.ts +54 -0
  143. package/dist/registry/built-in-recommendations.d.ts.map +1 -0
  144. package/dist/registry/built-in-recommendations.js +65 -0
  145. package/dist/registry/built-in-recommendations.js.map +1 -0
  146. package/dist/registry/events.d.ts +26 -0
  147. package/dist/registry/events.d.ts.map +1 -0
  148. package/dist/registry/events.js +22 -0
  149. package/dist/registry/events.js.map +1 -0
  150. package/dist/registry/index.d.ts +159 -0
  151. package/dist/registry/index.d.ts.map +1 -0
  152. package/dist/registry/index.js +12 -0
  153. package/dist/registry/index.js.map +1 -0
  154. package/dist/registry/registry.d.ts +87 -0
  155. package/dist/registry/registry.d.ts.map +1 -0
  156. package/dist/registry/registry.js +294 -0
  157. package/dist/registry/registry.js.map +1 -0
  158. package/dist/registry/snapshot.d.ts +42 -0
  159. package/dist/registry/snapshot.d.ts.map +1 -0
  160. package/dist/registry/snapshot.js +71 -0
  161. package/dist/registry/snapshot.js.map +1 -0
  162. package/dist/registry/typegen.d.ts +48 -0
  163. package/dist/registry/typegen.d.ts.map +1 -0
  164. package/dist/registry/typegen.js +200 -0
  165. package/dist/registry/typegen.js.map +1 -0
  166. package/dist/registry/validator.d.ts +23 -0
  167. package/dist/registry/validator.d.ts.map +1 -0
  168. package/dist/registry/validator.js +50 -0
  169. package/dist/registry/validator.js.map +1 -0
  170. package/dist/reliability/breaker.d.ts +57 -0
  171. package/dist/reliability/breaker.d.ts.map +1 -0
  172. package/dist/reliability/breaker.js +130 -0
  173. package/dist/reliability/breaker.js.map +1 -0
  174. package/dist/reliability/errors.d.ts +78 -0
  175. package/dist/reliability/errors.d.ts.map +1 -0
  176. package/dist/reliability/errors.js +160 -0
  177. package/dist/reliability/errors.js.map +1 -0
  178. package/dist/reliability/gateway.d.ts +88 -0
  179. package/dist/reliability/gateway.d.ts.map +1 -0
  180. package/dist/reliability/gateway.js +180 -0
  181. package/dist/reliability/gateway.js.map +1 -0
  182. package/dist/reliability/index.d.ts +20 -0
  183. package/dist/reliability/index.d.ts.map +1 -0
  184. package/dist/reliability/index.js +16 -0
  185. package/dist/reliability/index.js.map +1 -0
  186. package/dist/reliability/profile.d.ts +49 -0
  187. package/dist/reliability/profile.d.ts.map +1 -0
  188. package/dist/reliability/profile.js +58 -0
  189. package/dist/reliability/profile.js.map +1 -0
  190. package/dist/reliability/retry.d.ts +39 -0
  191. package/dist/reliability/retry.d.ts.map +1 -0
  192. package/dist/reliability/retry.js +51 -0
  193. package/dist/reliability/retry.js.map +1 -0
  194. package/dist/reliability/timeout.d.ts +34 -0
  195. package/dist/reliability/timeout.d.ts.map +1 -0
  196. package/dist/reliability/timeout.js +53 -0
  197. package/dist/reliability/timeout.js.map +1 -0
  198. package/dist/runtime/executor.d.ts +12 -0
  199. package/dist/runtime/executor.d.ts.map +1 -1
  200. package/dist/runtime/executor.js +148 -16
  201. package/dist/runtime/executor.js.map +1 -1
  202. package/dist/runtime/findtool/embed.d.ts +28 -0
  203. package/dist/runtime/findtool/embed.d.ts.map +1 -0
  204. package/dist/runtime/findtool/embed.js +85 -0
  205. package/dist/runtime/findtool/embed.js.map +1 -0
  206. package/dist/runtime/findtool/index.d.ts +52 -0
  207. package/dist/runtime/findtool/index.d.ts.map +1 -0
  208. package/dist/runtime/findtool/index.js +78 -0
  209. package/dist/runtime/findtool/index.js.map +1 -0
  210. package/dist/runtime/findtool/vector-index.d.ts +53 -0
  211. package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
  212. package/dist/runtime/findtool/vector-index.js +71 -0
  213. package/dist/runtime/findtool/vector-index.js.map +1 -0
  214. package/dist/runtime/helpers/budget.d.ts +27 -0
  215. package/dist/runtime/helpers/budget.d.ts.map +1 -0
  216. package/dist/runtime/helpers/budget.js +103 -0
  217. package/dist/runtime/helpers/budget.js.map +1 -0
  218. package/dist/runtime/helpers/compact.d.ts +32 -0
  219. package/dist/runtime/helpers/compact.d.ts.map +1 -0
  220. package/dist/runtime/helpers/compact.js +93 -0
  221. package/dist/runtime/helpers/compact.js.map +1 -0
  222. package/dist/runtime/helpers/delta.d.ts +45 -0
  223. package/dist/runtime/helpers/delta.d.ts.map +1 -0
  224. package/dist/runtime/helpers/delta.js +116 -0
  225. package/dist/runtime/helpers/delta.js.map +1 -0
  226. package/dist/runtime/helpers/index.d.ts +16 -0
  227. package/dist/runtime/helpers/index.d.ts.map +1 -0
  228. package/dist/runtime/helpers/index.js +13 -0
  229. package/dist/runtime/helpers/index.js.map +1 -0
  230. package/dist/runtime/helpers/summarize.d.ts +24 -0
  231. package/dist/runtime/helpers/summarize.d.ts.map +1 -0
  232. package/dist/runtime/helpers/summarize.js +124 -0
  233. package/dist/runtime/helpers/summarize.js.map +1 -0
  234. package/dist/runtime/helpers/worker-preload.d.ts +25 -0
  235. package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
  236. package/dist/runtime/helpers/worker-preload.js +223 -0
  237. package/dist/runtime/helpers/worker-preload.js.map +1 -0
  238. package/dist/runtime/index.d.ts +1 -0
  239. package/dist/runtime/index.d.ts.map +1 -1
  240. package/dist/runtime/index.js +1 -0
  241. package/dist/runtime/index.js.map +1 -1
  242. package/dist/runtime/pool/index.d.ts +11 -0
  243. package/dist/runtime/pool/index.d.ts.map +1 -0
  244. package/dist/runtime/pool/index.js +8 -0
  245. package/dist/runtime/pool/index.js.map +1 -0
  246. package/dist/runtime/pool/recycle.d.ts +44 -0
  247. package/dist/runtime/pool/recycle.d.ts.map +1 -0
  248. package/dist/runtime/pool/recycle.js +50 -0
  249. package/dist/runtime/pool/recycle.js.map +1 -0
  250. package/dist/runtime/pool/worker-pool.d.ts +77 -0
  251. package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
  252. package/dist/runtime/pool/worker-pool.js +216 -0
  253. package/dist/runtime/pool/worker-pool.js.map +1 -0
  254. package/dist/runtime/pool/worker.d.ts +80 -0
  255. package/dist/runtime/pool/worker.d.ts.map +1 -0
  256. package/dist/runtime/pool/worker.js +324 -0
  257. package/dist/runtime/pool/worker.js.map +1 -0
  258. package/dist/server/mcp-server.d.ts +6 -0
  259. package/dist/server/mcp-server.d.ts.map +1 -1
  260. package/dist/server/mcp-server.js +610 -45
  261. package/dist/server/mcp-server.js.map +1 -1
  262. package/dist/server/passthrough-registrar.d.ts +73 -0
  263. package/dist/server/passthrough-registrar.d.ts.map +1 -0
  264. package/dist/server/passthrough-registrar.js +110 -0
  265. package/dist/server/passthrough-registrar.js.map +1 -0
  266. package/dist/skills/skills-engine.d.ts +9 -1
  267. package/dist/skills/skills-engine.d.ts.map +1 -1
  268. package/dist/skills/skills-engine.js +20 -3
  269. package/dist/skills/skills-engine.js.map +1 -1
  270. package/dist/utils/index.d.ts +3 -0
  271. package/dist/utils/index.d.ts.map +1 -1
  272. package/dist/utils/index.js +3 -0
  273. package/dist/utils/index.js.map +1 -1
  274. package/dist/utils/logger.d.ts.map +1 -1
  275. package/dist/utils/logger.js +5 -1
  276. package/dist/utils/logger.js.map +1 -1
  277. package/dist/utils/orphan-watch.d.ts +34 -0
  278. package/dist/utils/orphan-watch.d.ts.map +1 -0
  279. package/dist/utils/orphan-watch.js +54 -0
  280. package/dist/utils/orphan-watch.js.map +1 -0
  281. package/dist/utils/redact.d.ts +15 -0
  282. package/dist/utils/redact.d.ts.map +1 -0
  283. package/dist/utils/redact.js +48 -0
  284. package/dist/utils/redact.js.map +1 -0
  285. package/dist/utils/tokenize.d.ts +55 -0
  286. package/dist/utils/tokenize.d.ts.map +1 -0
  287. package/dist/utils/tokenize.js +205 -0
  288. package/dist/utils/tokenize.js.map +1 -0
  289. package/dist/version.d.ts +3 -3
  290. package/dist/version.d.ts.map +1 -1
  291. package/dist/version.js +3 -3
  292. package/dist/version.js.map +1 -1
  293. package/package.json +13 -3
@@ -29,7 +29,10 @@ export const DEFAULT_CONFIG = {
29
29
  sandbox: {
30
30
  maxMemoryMb: 128,
31
31
  allowedNetHosts: ['localhost'],
32
- maxConcurrentProcesses: 5,
32
+ // Bumped from 5 → 8 in v2.0.0-alpha.2 (X3 cleanup) per IBKR-side analysis
33
+ // finding #5. PRD Phase 4's worker pool further parameterises this with
34
+ // per-server overrides and warm-pool sizing.
35
+ maxConcurrentProcesses: 8,
33
36
  maxOutputBytes: 10 * 1024 * 1024, // 10MB
34
37
  },
35
38
  skills: {
@@ -95,6 +98,8 @@ export const DEFAULT_CONDUCTOR_CONFIG = {
95
98
  * - `STREAM_STUCK_TTL_MS` — `StreamManager` cleanup for hung running streams
96
99
  * - `STREAM_CLEANUP_INTERVAL_MS` — `StreamManager` tick rate for the sweep
97
100
  * - `MEMORY_LOG_INTERVAL_MS` — periodic heap/RSS log from the main entry point
101
+ * - `BRIDGE_SESSION_TTL_MS` — HTTP bridge session idle expiry (Mcp-Session-Id)
102
+ * - `BRIDGE_SESSION_CLEANUP_INTERVAL_MS` — sweep cadence for expired sessions
98
103
  */
99
104
  export const LIFECYCLE_TIMEOUTS = {
100
105
  SHUTDOWN_TIMEOUT_MS: 10_000,
@@ -104,5 +109,13 @@ export const LIFECYCLE_TIMEOUTS = {
104
109
  STREAM_STUCK_TTL_MS: 15 * 60_000,
105
110
  STREAM_CLEANUP_INTERVAL_MS: 60_000,
106
111
  MEMORY_LOG_INTERVAL_MS: 60_000,
112
+ BRIDGE_SESSION_TTL_MS: 30 * 60_000,
113
+ BRIDGE_SESSION_CLEANUP_INTERVAL_MS: 5 * 60_000,
114
+ ORPHAN_CHECK_INTERVAL_MS: 10_000,
107
115
  };
116
+ /**
117
+ * Cap on simultaneously tracked bridge sessions. Bounded to prevent the
118
+ * session registry from growing unbounded if a client keeps rotating IDs.
119
+ */
120
+ export const MAX_BRIDGE_SESSIONS = 1000;
108
121
  //# sourceMappingURL=defaults.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,EAAE,2DAA2D;QACpE,IAAI,EAAE,WAAW;KAClB;IACD,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,gBAAgB,EAAE,KAAK;QACvB,YAAY,EAAE,MAAM;QACpB,gBAAgB,EAAE,IAAI;KACvB;IACD,OAAO,EAAE;QACP,WAAW,EAAE,GAAG;QAChB,eAAe,EAAE,CAAC,WAAW,CAAC;QAC9B,sBAAsB,EAAE,CAAC;QACzB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;KAC1C;IACD,MAAM,EAAE;QACN,IAAI,EAAE,IAAI;QACV,eAAe,EAAE,IAAI;KACtB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,GAAG;KAChB;IACD,OAAO,EAAE;QACP,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI;KACd;IACD,OAAO,EAAE;QACP,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,sBAAsB;IAC/B,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,wBAAwB;IACnC,MAAM,EAAE,qBAAqB;IAC7B,aAAa,EAAE,4BAA4B;IAC3C,gBAAgB,EAAE,sBAAsB;IACxC,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,cAAc,EAAE,6BAA6B;IAC7C,eAAe,EAAE,8BAA8B;IAC/C,aAAa,EAAE,4BAA4B;CACnC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB,EAAE,MAAM;IAC3B,qBAAqB,EAAE,KAAK;IAC5B,mBAAmB,EAAE,CAAC,GAAG,MAAM;IAC/B,uBAAuB,EAAE,EAAE,GAAG,MAAM;IACpC,mBAAmB,EAAE,EAAE,GAAG,MAAM;IAChC,0BAA0B,EAAE,MAAM;IAClC,sBAAsB,EAAE,MAAM;CACtB,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,EAAE,2DAA2D;QACpE,IAAI,EAAE,WAAW;KAClB;IACD,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,gBAAgB,EAAE,KAAK;QACvB,YAAY,EAAE,MAAM;QACpB,gBAAgB,EAAE,IAAI;KACvB;IACD,OAAO,EAAE;QACP,WAAW,EAAE,GAAG;QAChB,eAAe,EAAE,CAAC,WAAW,CAAC;QAC9B,0EAA0E;QAC1E,wEAAwE;QACxE,6CAA6C;QAC7C,sBAAsB,EAAE,CAAC;QACzB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;KAC1C;IACD,MAAM,EAAE;QACN,IAAI,EAAE,IAAI;QACV,eAAe,EAAE,IAAI;KACtB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,GAAG;KAChB;IACD,OAAO,EAAE;QACP,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI;KACd;IACD,OAAO,EAAE;QACP,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,sBAAsB;IAC/B,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,wBAAwB;IACnC,MAAM,EAAE,qBAAqB;IAC7B,aAAa,EAAE,4BAA4B;IAC3C,gBAAgB,EAAE,sBAAsB;IACxC,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,cAAc,EAAE,6BAA6B;IAC7C,eAAe,EAAE,8BAA8B;IAC/C,aAAa,EAAE,4BAA4B;CACnC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB,EAAE,MAAM;IAC3B,qBAAqB,EAAE,KAAK;IAC5B,mBAAmB,EAAE,CAAC,GAAG,MAAM;IAC/B,uBAAuB,EAAE,EAAE,GAAG,MAAM;IACpC,mBAAmB,EAAE,EAAE,GAAG,MAAM;IAChC,0BAA0B,EAAE,MAAM;IAClC,sBAAsB,EAAE,MAAM;IAC9B,qBAAqB,EAAE,EAAE,GAAG,MAAM;IAClC,kCAAkC,EAAE,CAAC,GAAG,MAAM;IAC9C,wBAAwB,EAAE,MAAM;CACxB,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
@@ -92,4 +92,38 @@ export interface ConductorConfig {
92
92
  /** MCP servers that conductor will connect to internally */
93
93
  servers: Record<string, ConductorServerConfig>;
94
94
  }
95
+ /**
96
+ * Connection pool configuration for persistent stdio connections to MCP
97
+ * backend servers. Reduces cold-start latency by keeping connections alive
98
+ * and multiplexing JSON-RPC requests over the same stdio channel.
99
+ */
100
+ export interface ConnectionPoolConfig {
101
+ /** Minimum idle connections to keep per server (default: 1) */
102
+ minConnectionsPerServer?: number;
103
+ /** Maximum simultaneous connections per server (default: 4) */
104
+ maxConnectionsPerServer?: number;
105
+ /** Idle connection shutdown timeout in ms (default: 300000 = 5 min) */
106
+ idleTimeoutMs?: number;
107
+ /** Timeout for acquiring a connection from the pool (default: 5000) */
108
+ acquireTimeoutMs?: number;
109
+ }
110
+ /**
111
+ * Warm Deno worker pool configuration. Workers are pre-spawned at startup
112
+ * so the first execute_code call hits an already-warm sandbox.
113
+ */
114
+ export interface WorkerPoolConfig {
115
+ /** Number of warm workers to maintain (default: 4) */
116
+ size?: number;
117
+ /** Recycle a worker after this many jobs (default: 100) */
118
+ maxJobsPerWorker?: number;
119
+ /** Recycle a worker after this many ms since spawn (default: 600000 = 10 min) */
120
+ maxAgeMs?: number;
121
+ }
122
+ /**
123
+ * Phase 4 runtime pool configuration block (nested under `runtime` in conductor config).
124
+ */
125
+ export interface RuntimePoolConfig {
126
+ workerPool?: WorkerPoolConfig;
127
+ connectionPool?: ConnectionPoolConfig;
128
+ }
95
129
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,kDAAkD;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAChD"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * MCP Conductor Daemon Client.
3
+ *
4
+ * Thin agent-side bridge that connects to a running DaemonServer over a Unix
5
+ * socket or TCP and exposes a `callTool` interface compatible with the direct
6
+ * execution path. Authentication uses HMAC-SHA256 with the shared secret read
7
+ * from `~/.mcp-conductor/daemon-auth.json`.
8
+ *
9
+ * The sandbox `mcp.shared.*` API is built on top of this client.
10
+ *
11
+ * @module daemon/client
12
+ */
13
+ import type { KVSetOptions } from './shared-kv.js';
14
+ export interface DaemonClientOptions {
15
+ /** Unix socket path. Defaults to `~/.mcp-conductor/daemon.sock`. */
16
+ socketPath?: string;
17
+ /**
18
+ * TCP address of the daemon when connecting over Tailscale.
19
+ * Format: `"host:port"` e.g. `"100.64.0.1:9876"`.
20
+ */
21
+ tailscaleAddress?: string;
22
+ /** Auth configuration. */
23
+ auth?: {
24
+ sharedSecretPath?: string;
25
+ sharedSecret?: string;
26
+ };
27
+ /** Connection timeout in ms. Defaults to 5 000. */
28
+ connectTimeoutMs?: number;
29
+ }
30
+ /**
31
+ * Client-side bridge to the daemon.
32
+ *
33
+ * Usage:
34
+ * ```typescript
35
+ * const client = new DaemonClient();
36
+ * await client.connect();
37
+ * const result = await client.callTool('list_tools', {});
38
+ * await client.disconnect();
39
+ * ```
40
+ */
41
+ export declare class DaemonClient {
42
+ private readonly socketPath;
43
+ private readonly tailscaleAddress?;
44
+ private readonly sharedSecret;
45
+ private readonly connectTimeoutMs;
46
+ private socket;
47
+ private connected;
48
+ private readonly pending;
49
+ private buffer;
50
+ private nextId;
51
+ constructor(options?: DaemonClientOptions);
52
+ /**
53
+ * Connect to the daemon and complete the auth handshake.
54
+ */
55
+ connect(): Promise<void>;
56
+ /**
57
+ * Gracefully disconnect.
58
+ */
59
+ disconnect(): Promise<void>;
60
+ /**
61
+ * Call an MCP tool via the daemon.
62
+ */
63
+ callTool(name: string, args: unknown): Promise<unknown>;
64
+ /**
65
+ * Ping the daemon. Useful for health-checks.
66
+ */
67
+ ping(): Promise<void>;
68
+ /** Retrieve daemon statistics. */
69
+ stats(): Promise<unknown>;
70
+ kvGet<T>(key: string): Promise<T | null>;
71
+ kvSet<T>(key: string, value: T, options?: KVSetOptions): Promise<void>;
72
+ kvDelete(key: string): Promise<void>;
73
+ kvList(prefix?: string): Promise<string[]>;
74
+ lockAcquire(key: string, options?: {
75
+ timeoutMs?: number;
76
+ }): Promise<{
77
+ release: () => Promise<void>;
78
+ }>;
79
+ broadcast(channel: string, message: unknown): Promise<void>;
80
+ /**
81
+ * Subscribe to a channel. The handler is invoked for each push event
82
+ * received from the daemon. Returns an object with `unsubscribe()`.
83
+ */
84
+ subscribe(channel: string, handler: (msg: unknown) => void): {
85
+ unsubscribe: () => void;
86
+ };
87
+ private readonly pushListeners;
88
+ private loadSecret;
89
+ private openSocket;
90
+ private authenticate;
91
+ private waitForMessage;
92
+ private rpc;
93
+ private onData;
94
+ private handleResponse;
95
+ private rejectAllPending;
96
+ }
97
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkCnD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,IAAI,CAAC,EAAE;QACL,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,mBAAwB;IAiB7C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,kCAAkC;IAC5B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAQzB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIxC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ1C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IAarG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG;QAAE,WAAW,EAAE,MAAM,IAAI,CAAA;KAAE;IAiBxF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IAMnE,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,UAAU;YA4BJ,YAAY;IAU1B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,GAAG;IAoBX,OAAO,CAAC,MAAM;IAiBd,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,gBAAgB;CAMzB"}
@@ -0,0 +1,279 @@
1
+ /**
2
+ * MCP Conductor Daemon Client.
3
+ *
4
+ * Thin agent-side bridge that connects to a running DaemonServer over a Unix
5
+ * socket or TCP and exposes a `callTool` interface compatible with the direct
6
+ * execution path. Authentication uses HMAC-SHA256 with the shared secret read
7
+ * from `~/.mcp-conductor/daemon-auth.json`.
8
+ *
9
+ * The sandbox `mcp.shared.*` API is built on top of this client.
10
+ *
11
+ * @module daemon/client
12
+ */
13
+ import { createConnection } from 'node:net';
14
+ import { existsSync, readFileSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ import { homedir } from 'node:os';
17
+ import { createHmac } from 'node:crypto';
18
+ import { logger } from '../utils/logger.js';
19
+ const DEFAULT_SOCKET_PATH = join(homedir(), '.mcp-conductor', 'daemon.sock');
20
+ const DEFAULT_AUTH_PATH = join(homedir(), '.mcp-conductor', 'daemon-auth.json');
21
+ /**
22
+ * Client-side bridge to the daemon.
23
+ *
24
+ * Usage:
25
+ * ```typescript
26
+ * const client = new DaemonClient();
27
+ * await client.connect();
28
+ * const result = await client.callTool('list_tools', {});
29
+ * await client.disconnect();
30
+ * ```
31
+ */
32
+ export class DaemonClient {
33
+ socketPath;
34
+ tailscaleAddress;
35
+ sharedSecret;
36
+ connectTimeoutMs;
37
+ socket = null;
38
+ connected = false;
39
+ pending = new Map();
40
+ buffer = '';
41
+ nextId = 1;
42
+ constructor(options = {}) {
43
+ this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;
44
+ this.tailscaleAddress = options.tailscaleAddress;
45
+ this.connectTimeoutMs = options.connectTimeoutMs ?? 5_000;
46
+ const authPath = options.auth?.sharedSecretPath ?? DEFAULT_AUTH_PATH;
47
+ if (options.auth?.sharedSecret) {
48
+ this.sharedSecret = options.auth.sharedSecret;
49
+ }
50
+ else {
51
+ this.sharedSecret = this.loadSecret(authPath);
52
+ }
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Lifecycle
56
+ // ---------------------------------------------------------------------------
57
+ /**
58
+ * Connect to the daemon and complete the auth handshake.
59
+ */
60
+ async connect() {
61
+ if (this.connected)
62
+ return;
63
+ const socket = await this.openSocket();
64
+ this.socket = socket;
65
+ socket.setEncoding('utf-8');
66
+ socket.on('data', (chunk) => this.onData(chunk));
67
+ socket.on('close', () => {
68
+ this.connected = false;
69
+ this.rejectAllPending(new Error('DaemonClient: connection closed'));
70
+ });
71
+ socket.on('error', (err) => {
72
+ logger.debug('DaemonClient: socket error', { error: String(err) });
73
+ this.rejectAllPending(err);
74
+ });
75
+ // Complete challenge-response auth.
76
+ await this.authenticate();
77
+ this.connected = true;
78
+ logger.debug('DaemonClient: connected and authenticated');
79
+ }
80
+ /**
81
+ * Gracefully disconnect.
82
+ */
83
+ async disconnect() {
84
+ this.connected = false;
85
+ if (this.socket && !this.socket.destroyed) {
86
+ this.socket.end();
87
+ await new Promise((resolve) => {
88
+ this.socket.once('close', resolve);
89
+ setTimeout(resolve, 1000);
90
+ });
91
+ }
92
+ this.socket = null;
93
+ logger.debug('DaemonClient: disconnected');
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // Public RPC surface
97
+ // ---------------------------------------------------------------------------
98
+ /**
99
+ * Call an MCP tool via the daemon.
100
+ */
101
+ async callTool(name, args) {
102
+ return this.rpc('tool.call', { name, args });
103
+ }
104
+ /**
105
+ * Ping the daemon. Useful for health-checks.
106
+ */
107
+ async ping() {
108
+ await this.rpc('ping', {});
109
+ }
110
+ /** Retrieve daemon statistics. */
111
+ async stats() {
112
+ return this.rpc('stats', {});
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Shared KV API
116
+ // ---------------------------------------------------------------------------
117
+ async kvGet(key) {
118
+ return this.rpc('kv.get', { key });
119
+ }
120
+ async kvSet(key, value, options) {
121
+ await this.rpc('kv.set', { key, value, options });
122
+ }
123
+ async kvDelete(key) {
124
+ await this.rpc('kv.delete', { key });
125
+ }
126
+ async kvList(prefix) {
127
+ return this.rpc('kv.list', { prefix });
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Shared lock API
131
+ // ---------------------------------------------------------------------------
132
+ async lockAcquire(key, options) {
133
+ await this.rpc('lock.acquire', { key, timeoutMs: options?.timeoutMs });
134
+ return {
135
+ release: async () => {
136
+ await this.rpc('lock.release', { key });
137
+ },
138
+ };
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Pub/sub API
142
+ // ---------------------------------------------------------------------------
143
+ async broadcast(channel, message) {
144
+ await this.rpc('broadcast', { channel, message });
145
+ }
146
+ /**
147
+ * Subscribe to a channel. The handler is invoked for each push event
148
+ * received from the daemon. Returns an object with `unsubscribe()`.
149
+ */
150
+ subscribe(channel, handler) {
151
+ const listener = (msg) => {
152
+ const push = msg;
153
+ if (push.channel === channel) {
154
+ handler(push.message);
155
+ }
156
+ };
157
+ this.pushListeners.add(listener);
158
+ // Best-effort fire-and-forget notification to the server.
159
+ this.rpc('subscribe', { channel }).catch(() => { });
160
+ return {
161
+ unsubscribe: () => {
162
+ this.pushListeners.delete(listener);
163
+ },
164
+ };
165
+ }
166
+ pushListeners = new Set();
167
+ // ---------------------------------------------------------------------------
168
+ // Private helpers
169
+ // ---------------------------------------------------------------------------
170
+ loadSecret(authPath) {
171
+ if (!existsSync(authPath)) {
172
+ throw new Error(`DaemonClient: auth file not found at ${authPath}. ` +
173
+ 'Start the daemon first with `mcp-conductor-cli daemon start`.');
174
+ }
175
+ const raw = readFileSync(authPath, 'utf-8');
176
+ return JSON.parse(raw).sharedSecret;
177
+ }
178
+ openSocket() {
179
+ return new Promise((resolve, reject) => {
180
+ let socket;
181
+ const timer = setTimeout(() => {
182
+ socket?.destroy();
183
+ reject(new Error(`DaemonClient: connection timed out after ${this.connectTimeoutMs}ms`));
184
+ }, this.connectTimeoutMs);
185
+ if (this.tailscaleAddress) {
186
+ const [host, portStr] = this.tailscaleAddress.split(':');
187
+ const port = parseInt(portStr ?? '9876', 10);
188
+ socket = createConnection({ host, port });
189
+ }
190
+ else {
191
+ socket = createConnection({ path: this.socketPath });
192
+ }
193
+ socket.once('connect', () => {
194
+ clearTimeout(timer);
195
+ resolve(socket);
196
+ });
197
+ socket.once('error', (err) => {
198
+ clearTimeout(timer);
199
+ reject(err);
200
+ });
201
+ });
202
+ }
203
+ async authenticate() {
204
+ // Wait for the challenge from the server.
205
+ const challenge = await this.waitForMessage('__auth_challenge__');
206
+ const nonce = challenge.nonce;
207
+ // Compute HMAC token and send auth response.
208
+ const token = createHmac('sha256', this.sharedSecret).update(nonce).digest('hex');
209
+ await this.rpc('__auth__', { token });
210
+ }
211
+ waitForMessage(id) {
212
+ return new Promise((resolve, reject) => {
213
+ this.pending.set(id, { resolve, reject });
214
+ });
215
+ }
216
+ rpc(method, params) {
217
+ return new Promise((resolve, reject) => {
218
+ if (!this.socket || this.socket.destroyed) {
219
+ reject(new Error('DaemonClient: not connected'));
220
+ return;
221
+ }
222
+ const id = String(this.nextId++);
223
+ this.pending.set(id, { resolve, reject });
224
+ const msg = { id, method, params };
225
+ try {
226
+ this.socket.write(JSON.stringify(msg) + '\n');
227
+ }
228
+ catch (err) {
229
+ this.pending.delete(id);
230
+ reject(err);
231
+ }
232
+ });
233
+ }
234
+ onData(chunk) {
235
+ this.buffer += chunk;
236
+ const lines = this.buffer.split('\n');
237
+ this.buffer = lines.pop() ?? '';
238
+ for (const line of lines) {
239
+ const trimmed = line.trim();
240
+ if (!trimmed)
241
+ continue;
242
+ try {
243
+ const msg = JSON.parse(trimmed);
244
+ this.handleResponse(msg);
245
+ }
246
+ catch {
247
+ logger.warn('DaemonClient: malformed JSON from server');
248
+ }
249
+ }
250
+ }
251
+ handleResponse(msg) {
252
+ // Push events (id === '__push__') are delivered to pub/sub listeners.
253
+ if (msg.id === '__push__') {
254
+ for (const listener of this.pushListeners) {
255
+ listener(msg.result);
256
+ }
257
+ return;
258
+ }
259
+ const call = this.pending.get(msg.id);
260
+ if (!call) {
261
+ logger.warn('DaemonClient: received response for unknown id', { id: msg.id });
262
+ return;
263
+ }
264
+ this.pending.delete(msg.id);
265
+ if (msg.error) {
266
+ call.reject(new Error(`RPC error ${msg.error.code}: ${msg.error.message}`));
267
+ }
268
+ else {
269
+ call.resolve(msg.result);
270
+ }
271
+ }
272
+ rejectAllPending(err) {
273
+ for (const [id, call] of this.pending) {
274
+ this.pending.delete(id);
275
+ call.reject(err);
276
+ }
277
+ }
278
+ }
279
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAe,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA4B5C,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;AAC7E,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;AAuBhF;;;;;;;;;;GAUG;AACH,MAAM,OAAO,YAAY;IACN,UAAU,CAAS;IACnB,gBAAgB,CAAU;IAC1B,YAAY,CAAS;IACrB,gBAAgB,CAAS;IAElC,MAAM,GAAkB,IAAI,CAAC;IAC7B,SAAS,GAAG,KAAK,CAAC;IACT,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAClD,MAAM,GAAG,EAAE,CAAC;IACZ,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAY,UAA+B,EAAE;QAC3C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QACjD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC;QAE1D,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,gBAAgB,IAAI,iBAAiB,CAAC;QACrE,IAAI,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAE3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,oCAAoC;QACpC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YAClB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACpC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC7C,CAAC;IAED,8EAA8E;IAC9E,qBAAqB;IACrB,8EAA8E;IAE9E;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAAa;QACxC,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,kCAAkC;IAClC,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,8EAA8E;IAC9E,gBAAgB;IAChB,8EAA8E;IAE9E,KAAK,CAAC,KAAK,CAAI,GAAW;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAsB,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,KAAK,CAAI,GAAW,EAAE,KAAQ,EAAE,OAAsB;QAC1D,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAe;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAsB,CAAC;IAC9D,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,KAAK,CAAC,WAAW,CAAC,GAAW,EAAE,OAAgC;QAC7D,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACvE,OAAO;YACL,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1C,CAAC;SACF,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E,KAAK,CAAC,SAAS,CAAC,OAAe,EAAE,OAAgB;QAC/C,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,OAAe,EAAE,OAA+B;QACxD,MAAM,QAAQ,GAAG,CAAC,GAAY,EAAE,EAAE;YAChC,MAAM,IAAI,GAAG,GAA8C,CAAC;YAC5D,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,0DAA0D;QAC1D,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnD,OAAO;YACL,WAAW,EAAE,GAAG,EAAE;gBAChB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACtC,CAAC;SACF,CAAC;IACJ,CAAC;IAEgB,aAAa,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEnE,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAEtE,UAAU,CAAC,QAAgB;QACjC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,wCAAwC,QAAQ,IAAI;gBACpD,+DAA+D,CAChE,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC,YAAY,CAAC;IACpD,CAAC;IAEO,UAAU;QAChB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,MAAc,CAAC;YAEnB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,MAAM,EAAE,OAAO,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC;YAC3F,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAE1B,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC7C,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC1B,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,0CAA0C;QAC1C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;QAClE,MAAM,KAAK,GAAI,SAA+B,CAAC,KAAK,CAAC;QAErD,6CAA6C;QAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClF,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC;IAEO,cAAc,CAAC,EAAU;QAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,GAAG,CAAC,MAAc,EAAE,MAAgB;QAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBAC1C,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;gBACjD,OAAO;YACT,CAAC;YAED,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAE1C,MAAM,GAAG,GAAe,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAa;QAC1B,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;gBAC/C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,GAAgB;QACrC,sEAAsE;QACtE,IAAI,GAAG,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAC1B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBAC1C,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,gDAAgD,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9E,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE5B,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,GAAU;QACjC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Tailscale Peer Discovery for MCP Conductor Daemon.
3
+ *
4
+ * Provides helpers to resolve a daemon's address on the Tailscale mesh by
5
+ * hostname. The implementation queries the local Tailscale CLI (`tailscale
6
+ * status --json`) which must already be authenticated. No additional Tailscale
7
+ * API token is required — this works entirely through the local socket that
8
+ * the Tailscale daemon exposes.
9
+ *
10
+ * Cross-daemon mesh locking is deferred to v3.1; this module's v3.0 role is:
11
+ * 1. Resolve a Tailscale hostname → IP so DaemonClient can connect via TCP.
12
+ * 2. Detect whether Tailscale is available at all (graceful fallback to Unix
13
+ * socket when Tailscale is absent).
14
+ *
15
+ * @module daemon/discovery
16
+ */
17
+ export interface TailscalePeer {
18
+ hostname: string;
19
+ tailscaleIp: string;
20
+ online: boolean;
21
+ }
22
+ export interface TailscaleStatus {
23
+ available: boolean;
24
+ selfHostname?: string;
25
+ selfIp?: string;
26
+ peers: TailscalePeer[];
27
+ }
28
+ /**
29
+ * Resolves daemon addresses on the Tailscale mesh by querying the local
30
+ * Tailscale CLI.
31
+ */
32
+ export declare class TailscaleDiscovery {
33
+ private readonly tailscaleBin;
34
+ private readonly cacheTtlMs;
35
+ private cache;
36
+ /**
37
+ * Internal CLI runner — override in tests via `vi.spyOn(instance, '_runCli')`.
38
+ */
39
+ _runCli: (bin: string) => Promise<string>;
40
+ constructor(options?: {
41
+ tailscaleBin?: string;
42
+ cacheTtlMs?: number;
43
+ });
44
+ status(): Promise<TailscaleStatus>;
45
+ resolve(hostname: string): Promise<string | null>;
46
+ isAvailable(): Promise<boolean>;
47
+ invalidateCache(): void;
48
+ private queryTailscaleCli;
49
+ }
50
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/daemon/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AA4BD;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,KAAK,CAA+D;IAE5E;;OAEG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE9B,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO;IAMlE,MAAM,IAAI,OAAO,CAAC,eAAe,CAAC;IAUlC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcjD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKrC,eAAe,IAAI,IAAI;YAIT,iBAAiB;CA4BhC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Tailscale Peer Discovery for MCP Conductor Daemon.
3
+ *
4
+ * Provides helpers to resolve a daemon's address on the Tailscale mesh by
5
+ * hostname. The implementation queries the local Tailscale CLI (`tailscale
6
+ * status --json`) which must already be authenticated. No additional Tailscale
7
+ * API token is required — this works entirely through the local socket that
8
+ * the Tailscale daemon exposes.
9
+ *
10
+ * Cross-daemon mesh locking is deferred to v3.1; this module's v3.0 role is:
11
+ * 1. Resolve a Tailscale hostname → IP so DaemonClient can connect via TCP.
12
+ * 2. Detect whether Tailscale is available at all (graceful fallback to Unix
13
+ * socket when Tailscale is absent).
14
+ *
15
+ * @module daemon/discovery
16
+ */
17
+ import { execFile } from 'node:child_process';
18
+ import { logger } from '../utils/logger.js';
19
+ /**
20
+ * Runs the Tailscale CLI and returns its JSON output.
21
+ * Extracted so tests can override via `vi.spyOn(discovery, '_runCli')`.
22
+ */
23
+ async function runTailscaleCli(bin) {
24
+ return new Promise((resolve, reject) => {
25
+ execFile(bin, ['status', '--json'], { timeout: 5000 }, (err, stdout) => {
26
+ if (err)
27
+ reject(err);
28
+ else
29
+ resolve(stdout);
30
+ });
31
+ });
32
+ }
33
+ /**
34
+ * Resolves daemon addresses on the Tailscale mesh by querying the local
35
+ * Tailscale CLI.
36
+ */
37
+ export class TailscaleDiscovery {
38
+ tailscaleBin;
39
+ cacheTtlMs;
40
+ cache = null;
41
+ /**
42
+ * Internal CLI runner — override in tests via `vi.spyOn(instance, '_runCli')`.
43
+ */
44
+ _runCli;
45
+ constructor(options = {}) {
46
+ this.tailscaleBin = options.tailscaleBin ?? 'tailscale';
47
+ this.cacheTtlMs = options.cacheTtlMs ?? 10_000;
48
+ this._runCli = runTailscaleCli;
49
+ }
50
+ async status() {
51
+ if (this.cache && Date.now() < this.cache.expiresAt) {
52
+ return this.cache.status;
53
+ }
54
+ const result = await this.queryTailscaleCli();
55
+ this.cache = { expiresAt: Date.now() + this.cacheTtlMs, status: result };
56
+ return result;
57
+ }
58
+ async resolve(hostname) {
59
+ const st = await this.status();
60
+ if (!st.available)
61
+ return null;
62
+ if (st.selfHostname?.toLowerCase() === hostname.toLowerCase()) {
63
+ return st.selfIp ?? null;
64
+ }
65
+ const peer = st.peers.find((p) => p.hostname.toLowerCase() === hostname.toLowerCase());
66
+ return peer?.tailscaleIp ?? null;
67
+ }
68
+ async isAvailable() {
69
+ const st = await this.status();
70
+ return st.available;
71
+ }
72
+ invalidateCache() {
73
+ this.cache = null;
74
+ }
75
+ async queryTailscaleCli() {
76
+ try {
77
+ const stdout = await this._runCli(this.tailscaleBin);
78
+ const raw = JSON.parse(stdout);
79
+ const self = raw.Self;
80
+ const peers = [];
81
+ for (const peer of Object.values(raw.Peer ?? {})) {
82
+ const ip = peer.TailscaleIPs?.[0];
83
+ if (!ip || !peer.HostName)
84
+ continue;
85
+ peers.push({
86
+ hostname: peer.HostName,
87
+ tailscaleIp: ip,
88
+ online: peer.Online ?? false,
89
+ });
90
+ }
91
+ return {
92
+ available: true,
93
+ selfHostname: self?.HostName,
94
+ selfIp: self?.TailscaleIPs?.[0],
95
+ peers,
96
+ };
97
+ }
98
+ catch (err) {
99
+ logger.debug('TailscaleDiscovery: Tailscale CLI unavailable', { error: String(err) });
100
+ return { available: false, peers: [] };
101
+ }
102
+ }
103
+ }
104
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/daemon/discovery.ts"],"names":[],"mappings":"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"}