synapse-mcp 1.0.0 → 1.0.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 (413) hide show
  1. package/README.md +1820 -147
  2. package/dist/constants.d.ts +10 -4
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +18 -8
  5. package/dist/constants.js.map +1 -1
  6. package/dist/events/emitter.d.ts +63 -0
  7. package/dist/events/emitter.d.ts.map +1 -0
  8. package/dist/events/emitter.js +112 -0
  9. package/dist/events/emitter.js.map +1 -0
  10. package/dist/events/index.d.ts +3 -0
  11. package/dist/events/index.d.ts.map +1 -0
  12. package/dist/events/index.js +3 -0
  13. package/dist/events/index.js.map +1 -0
  14. package/dist/events/types.d.ts +51 -0
  15. package/dist/events/types.d.ts.map +1 -0
  16. package/dist/events/types.js +3 -0
  17. package/dist/events/types.js.map +1 -0
  18. package/dist/formatters/compose.d.ts +185 -0
  19. package/dist/formatters/compose.d.ts.map +1 -0
  20. package/dist/formatters/compose.js +397 -0
  21. package/dist/formatters/compose.js.map +1 -0
  22. package/dist/formatters/container.d.ts +84 -0
  23. package/dist/formatters/container.d.ts.map +1 -0
  24. package/dist/formatters/container.js +323 -0
  25. package/dist/formatters/container.js.map +1 -0
  26. package/dist/formatters/diagnostics.d.ts +20 -0
  27. package/dist/formatters/diagnostics.d.ts.map +1 -0
  28. package/dist/formatters/diagnostics.js +73 -0
  29. package/dist/formatters/diagnostics.js.map +1 -0
  30. package/dist/formatters/docker.d.ts +139 -0
  31. package/dist/formatters/docker.d.ts.map +1 -0
  32. package/dist/formatters/docker.js +216 -0
  33. package/dist/formatters/docker.js.map +1 -0
  34. package/dist/formatters/host.d.ts +137 -0
  35. package/dist/formatters/host.d.ts.map +1 -0
  36. package/dist/formatters/host.js +198 -0
  37. package/dist/formatters/host.js.map +1 -0
  38. package/dist/formatters/index.d.ts +17 -270
  39. package/dist/formatters/index.d.ts.map +1 -1
  40. package/dist/formatters/index.js +21 -456
  41. package/dist/formatters/index.js.map +1 -1
  42. package/dist/formatters/scout.d.ts +424 -0
  43. package/dist/formatters/scout.d.ts.map +1 -0
  44. package/dist/formatters/scout.js +687 -0
  45. package/dist/formatters/scout.js.map +1 -0
  46. package/dist/formatters/strategy.d.ts +105 -0
  47. package/dist/formatters/strategy.d.ts.map +1 -0
  48. package/dist/formatters/strategy.js +120 -0
  49. package/dist/formatters/strategy.js.map +1 -0
  50. package/dist/formatters/utils.d.ts +84 -0
  51. package/dist/formatters/utils.d.ts.map +1 -0
  52. package/dist/formatters/utils.js +129 -0
  53. package/dist/formatters/utils.js.map +1 -0
  54. package/dist/health-rate-limiter.d.ts +59 -0
  55. package/dist/health-rate-limiter.d.ts.map +1 -0
  56. package/dist/health-rate-limiter.js +159 -0
  57. package/dist/health-rate-limiter.js.map +1 -0
  58. package/dist/index.js +61 -100
  59. package/dist/index.js.map +1 -1
  60. package/dist/middleware/async-handler.d.ts +62 -0
  61. package/dist/middleware/async-handler.d.ts.map +1 -0
  62. package/dist/middleware/async-handler.js +58 -0
  63. package/dist/middleware/async-handler.js.map +1 -0
  64. package/dist/middleware/auth.d.ts +32 -0
  65. package/dist/middleware/auth.d.ts.map +1 -0
  66. package/dist/middleware/auth.js +63 -0
  67. package/dist/middleware/auth.js.map +1 -0
  68. package/dist/middleware/csrf-protection.d.ts +58 -0
  69. package/dist/middleware/csrf-protection.d.ts.map +1 -0
  70. package/dist/middleware/csrf-protection.js +123 -0
  71. package/dist/middleware/csrf-protection.js.map +1 -0
  72. package/dist/middleware/error-handler.d.ts +49 -0
  73. package/dist/middleware/error-handler.d.ts.map +1 -0
  74. package/dist/middleware/error-handler.js +90 -0
  75. package/dist/middleware/error-handler.js.map +1 -0
  76. package/dist/middleware/error-mapper.d.ts +44 -0
  77. package/dist/middleware/error-mapper.d.ts.map +1 -0
  78. package/dist/middleware/error-mapper.js +127 -0
  79. package/dist/middleware/error-mapper.js.map +1 -0
  80. package/dist/middleware/index.d.ts +13 -0
  81. package/dist/middleware/index.d.ts.map +1 -0
  82. package/dist/middleware/index.js +13 -0
  83. package/dist/middleware/index.js.map +1 -0
  84. package/dist/middleware/request-id.d.ts +22 -0
  85. package/dist/middleware/request-id.d.ts.map +1 -0
  86. package/dist/middleware/request-id.js +31 -0
  87. package/dist/middleware/request-id.js.map +1 -0
  88. package/dist/middleware/types.d.ts +33 -0
  89. package/dist/middleware/types.d.ts.map +1 -0
  90. package/dist/middleware/types.js +2 -0
  91. package/dist/middleware/types.js.map +1 -0
  92. package/dist/schemas/common.d.ts +205 -8
  93. package/dist/schemas/common.d.ts.map +1 -1
  94. package/dist/schemas/common.js +290 -17
  95. package/dist/schemas/common.js.map +1 -1
  96. package/dist/schemas/flux/compose.d.ts +307 -44
  97. package/dist/schemas/flux/compose.d.ts.map +1 -1
  98. package/dist/schemas/flux/compose.js +74 -48
  99. package/dist/schemas/flux/compose.js.map +1 -1
  100. package/dist/schemas/flux/container.d.ts +423 -56
  101. package/dist/schemas/flux/container.d.ts.map +1 -1
  102. package/dist/schemas/flux/container.js +83 -61
  103. package/dist/schemas/flux/container.js.map +1 -1
  104. package/dist/schemas/flux/docker.d.ts +254 -37
  105. package/dist/schemas/flux/docker.d.ts.map +1 -1
  106. package/dist/schemas/flux/docker.js +69 -39
  107. package/dist/schemas/flux/docker.js.map +1 -1
  108. package/dist/schemas/flux/host.d.ts +312 -29
  109. package/dist/schemas/flux/host.d.ts.map +1 -1
  110. package/dist/schemas/flux/host.js +74 -31
  111. package/dist/schemas/flux/host.js.map +1 -1
  112. package/dist/schemas/flux/index.d.ts +503 -11
  113. package/dist/schemas/flux/index.d.ts.map +1 -1
  114. package/dist/schemas/flux/index.js +34 -70
  115. package/dist/schemas/flux/index.js.map +1 -1
  116. package/dist/schemas/host-config.d.ts +76 -0
  117. package/dist/schemas/host-config.d.ts.map +1 -0
  118. package/dist/schemas/host-config.js +105 -0
  119. package/dist/schemas/host-config.js.map +1 -0
  120. package/dist/schemas/scout/index.d.ts +80 -23
  121. package/dist/schemas/scout/index.d.ts.map +1 -1
  122. package/dist/schemas/scout/index.js +26 -11
  123. package/dist/schemas/scout/index.js.map +1 -1
  124. package/dist/schemas/scout/logs.d.ts +17 -5
  125. package/dist/schemas/scout/logs.d.ts.map +1 -1
  126. package/dist/schemas/scout/logs.js +41 -31
  127. package/dist/schemas/scout/logs.js.map +1 -1
  128. package/dist/schemas/scout/simple.d.ts +126 -11
  129. package/dist/schemas/scout/simple.d.ts.map +1 -1
  130. package/dist/schemas/scout/simple.js +112 -57
  131. package/dist/schemas/scout/simple.js.map +1 -1
  132. package/dist/schemas/scout/zfs.d.ts +17 -5
  133. package/dist/schemas/scout/zfs.d.ts.map +1 -1
  134. package/dist/schemas/scout/zfs.js +34 -25
  135. package/dist/schemas/scout/zfs.js.map +1 -1
  136. package/dist/services/cache-layer.d.ts +160 -0
  137. package/dist/services/cache-layer.d.ts.map +1 -0
  138. package/dist/services/cache-layer.js +138 -0
  139. package/dist/services/cache-layer.js.map +1 -0
  140. package/dist/services/compose-cache.d.ts +75 -0
  141. package/dist/services/compose-cache.d.ts.map +1 -0
  142. package/dist/services/compose-cache.js +178 -0
  143. package/dist/services/compose-cache.js.map +1 -0
  144. package/dist/services/compose-discovery.d.ts +46 -0
  145. package/dist/services/compose-discovery.d.ts.map +1 -0
  146. package/dist/services/compose-discovery.js +219 -0
  147. package/dist/services/compose-discovery.js.map +1 -0
  148. package/dist/services/compose-project-lister.d.ts +27 -0
  149. package/dist/services/compose-project-lister.d.ts.map +1 -0
  150. package/dist/services/compose-project-lister.js +71 -0
  151. package/dist/services/compose-project-lister.js.map +1 -0
  152. package/dist/services/compose-scanner.d.ts +63 -0
  153. package/dist/services/compose-scanner.d.ts.map +1 -0
  154. package/dist/services/compose-scanner.js +253 -0
  155. package/dist/services/compose-scanner.js.map +1 -0
  156. package/dist/services/compose.d.ts +64 -28
  157. package/dist/services/compose.d.ts.map +1 -1
  158. package/dist/services/compose.js +220 -98
  159. package/dist/services/compose.js.map +1 -1
  160. package/dist/services/config-loader.d.ts +23 -0
  161. package/dist/services/config-loader.d.ts.map +1 -0
  162. package/dist/services/config-loader.js +124 -0
  163. package/dist/services/config-loader.js.map +1 -0
  164. package/dist/services/config-service.d.ts +38 -0
  165. package/dist/services/config-service.d.ts.map +1 -0
  166. package/dist/services/config-service.js +225 -0
  167. package/dist/services/config-service.js.map +1 -0
  168. package/dist/services/container-host-map-cache.d.ts +121 -0
  169. package/dist/services/container-host-map-cache.d.ts.map +1 -0
  170. package/dist/services/container-host-map-cache.js +188 -0
  171. package/dist/services/container-host-map-cache.js.map +1 -0
  172. package/dist/services/container.d.ts +194 -6
  173. package/dist/services/container.d.ts.map +1 -1
  174. package/dist/services/container.js +386 -11
  175. package/dist/services/container.js.map +1 -1
  176. package/dist/services/diagnostics.d.ts +57 -0
  177. package/dist/services/diagnostics.d.ts.map +1 -0
  178. package/dist/services/diagnostics.js +271 -0
  179. package/dist/services/diagnostics.js.map +1 -0
  180. package/dist/services/docker/container-service.d.ts +123 -0
  181. package/dist/services/docker/container-service.d.ts.map +1 -0
  182. package/dist/services/docker/container-service.js +347 -0
  183. package/dist/services/docker/container-service.js.map +1 -0
  184. package/dist/services/docker/image-service.d.ts +82 -0
  185. package/dist/services/docker/image-service.d.ts.map +1 -0
  186. package/dist/services/docker/image-service.js +193 -0
  187. package/dist/services/docker/image-service.js.map +1 -0
  188. package/dist/services/docker/index.d.ts +80 -0
  189. package/dist/services/docker/index.d.ts.map +1 -0
  190. package/dist/services/docker/index.js +103 -0
  191. package/dist/services/docker/index.js.map +1 -0
  192. package/dist/services/docker/network-service.d.ts +22 -0
  193. package/dist/services/docker/network-service.d.ts.map +1 -0
  194. package/dist/services/docker/network-service.js +43 -0
  195. package/dist/services/docker/network-service.js.map +1 -0
  196. package/dist/services/docker/system-service.d.ts +49 -0
  197. package/dist/services/docker/system-service.d.ts.map +1 -0
  198. package/dist/services/docker/system-service.js +215 -0
  199. package/dist/services/docker/system-service.js.map +1 -0
  200. package/dist/services/docker/utils/client-factory.d.ts +56 -0
  201. package/dist/services/docker/utils/client-factory.d.ts.map +1 -0
  202. package/dist/services/docker/utils/client-factory.js +139 -0
  203. package/dist/services/docker/utils/client-factory.js.map +1 -0
  204. package/dist/services/docker/utils/client-manager.d.ts +88 -0
  205. package/dist/services/docker/utils/client-manager.d.ts.map +1 -0
  206. package/dist/services/docker/utils/client-manager.js +124 -0
  207. package/dist/services/docker/utils/client-manager.js.map +1 -0
  208. package/dist/services/docker/utils/exec-handler.d.ts +94 -0
  209. package/dist/services/docker/utils/exec-handler.d.ts.map +1 -0
  210. package/dist/services/docker/utils/exec-handler.js +197 -0
  211. package/dist/services/docker/utils/exec-handler.js.map +1 -0
  212. package/dist/services/docker/utils/formatters.d.ts +13 -0
  213. package/dist/services/docker/utils/formatters.d.ts.map +1 -0
  214. package/dist/services/docker/utils/formatters.js +33 -0
  215. package/dist/services/docker/utils/formatters.js.map +1 -0
  216. package/dist/services/docker/utils/log-parser.d.ts +10 -0
  217. package/dist/services/docker/utils/log-parser.d.ts.map +1 -0
  218. package/dist/services/docker/utils/log-parser.js +48 -0
  219. package/dist/services/docker/utils/log-parser.js.map +1 -0
  220. package/dist/services/docker/utils/stats-calculator.d.ts +68 -0
  221. package/dist/services/docker/utils/stats-calculator.d.ts.map +1 -0
  222. package/dist/services/docker/utils/stats-calculator.js +61 -0
  223. package/dist/services/docker/utils/stats-calculator.js.map +1 -0
  224. package/dist/services/docker/volume-service.d.ts +22 -0
  225. package/dist/services/docker/volume-service.d.ts.map +1 -0
  226. package/dist/services/docker/volume-service.js +48 -0
  227. package/dist/services/docker/volume-service.js.map +1 -0
  228. package/dist/services/docker-interfaces.d.ts +283 -0
  229. package/dist/services/docker-interfaces.d.ts.map +1 -0
  230. package/dist/services/docker-interfaces.js +13 -0
  231. package/dist/services/docker-interfaces.js.map +1 -0
  232. package/dist/services/docker.d.ts +42 -5
  233. package/dist/services/docker.d.ts.map +1 -1
  234. package/dist/services/docker.js +335 -127
  235. package/dist/services/docker.js.map +1 -1
  236. package/dist/services/file-service.d.ts +6 -2
  237. package/dist/services/file-service.d.ts.map +1 -1
  238. package/dist/services/file-service.js +156 -52
  239. package/dist/services/file-service.js.map +1 -1
  240. package/dist/services/host-config-repository.d.ts +133 -0
  241. package/dist/services/host-config-repository.d.ts.map +1 -0
  242. package/dist/services/host-config-repository.js +323 -0
  243. package/dist/services/host-config-repository.js.map +1 -0
  244. package/dist/services/host-resolver.d.ts +49 -0
  245. package/dist/services/host-resolver.d.ts.map +1 -0
  246. package/dist/services/host-resolver.js +176 -0
  247. package/dist/services/host-resolver.js.map +1 -0
  248. package/dist/services/interfaces.d.ts +61 -194
  249. package/dist/services/interfaces.d.ts.map +1 -1
  250. package/dist/services/local-executor.d.ts +31 -0
  251. package/dist/services/local-executor.d.ts.map +1 -0
  252. package/dist/services/local-executor.js +71 -0
  253. package/dist/services/local-executor.js.map +1 -0
  254. package/dist/services/ssh-config-loader.d.ts +35 -0
  255. package/dist/services/ssh-config-loader.d.ts.map +1 -0
  256. package/dist/services/ssh-config-loader.js +218 -0
  257. package/dist/services/ssh-config-loader.js.map +1 -0
  258. package/dist/services/ssh-pool.d.ts +26 -1
  259. package/dist/services/ssh-pool.d.ts.map +1 -1
  260. package/dist/services/ssh-pool.js +165 -25
  261. package/dist/services/ssh-pool.js.map +1 -1
  262. package/dist/services/ssh-service.d.ts +3 -0
  263. package/dist/services/ssh-service.d.ts.map +1 -1
  264. package/dist/services/ssh-service.js +53 -31
  265. package/dist/services/ssh-service.js.map +1 -1
  266. package/dist/services/ssh.d.ts +2 -6
  267. package/dist/services/ssh.d.ts.map +1 -1
  268. package/dist/services/ssh.js +9 -40
  269. package/dist/services/ssh.js.map +1 -1
  270. package/dist/tools/definitions/flux.d.ts +13 -0
  271. package/dist/tools/definitions/flux.d.ts.map +1 -0
  272. package/dist/tools/definitions/flux.js +101 -0
  273. package/dist/tools/definitions/flux.js.map +1 -0
  274. package/dist/tools/definitions/index.d.ts +8 -0
  275. package/dist/tools/definitions/index.d.ts.map +1 -0
  276. package/dist/tools/definitions/index.js +8 -0
  277. package/dist/tools/definitions/index.js.map +1 -0
  278. package/dist/tools/definitions/scout.d.ts +13 -0
  279. package/dist/tools/definitions/scout.d.ts.map +1 -0
  280. package/dist/tools/definitions/scout.js +78 -0
  281. package/dist/tools/definitions/scout.js.map +1 -0
  282. package/dist/tools/flux.d.ts +16 -8
  283. package/dist/tools/flux.d.ts.map +1 -1
  284. package/dist/tools/flux.js +27 -66
  285. package/dist/tools/flux.js.map +1 -1
  286. package/dist/tools/handlers/base-handler.d.ts +172 -0
  287. package/dist/tools/handlers/base-handler.d.ts.map +1 -0
  288. package/dist/tools/handlers/base-handler.js +234 -0
  289. package/dist/tools/handlers/base-handler.js.map +1 -0
  290. package/dist/tools/handlers/compose-handlers.d.ts +108 -0
  291. package/dist/tools/handlers/compose-handlers.d.ts.map +1 -0
  292. package/dist/tools/handlers/compose-handlers.js +293 -0
  293. package/dist/tools/handlers/compose-handlers.js.map +1 -0
  294. package/dist/tools/handlers/compose-utils.d.ts +35 -0
  295. package/dist/tools/handlers/compose-utils.d.ts.map +1 -0
  296. package/dist/tools/handlers/compose-utils.js +76 -0
  297. package/dist/tools/handlers/compose-utils.js.map +1 -0
  298. package/dist/tools/handlers/compose.d.ts +23 -0
  299. package/dist/tools/handlers/compose.d.ts.map +1 -0
  300. package/dist/tools/handlers/compose.js +125 -0
  301. package/dist/tools/handlers/compose.js.map +1 -0
  302. package/dist/tools/handlers/container.d.ts +23 -0
  303. package/dist/tools/handlers/container.d.ts.map +1 -0
  304. package/dist/tools/handlers/container.js +333 -0
  305. package/dist/tools/handlers/container.js.map +1 -0
  306. package/dist/tools/handlers/docker.d.ts +24 -0
  307. package/dist/tools/handlers/docker.d.ts.map +1 -0
  308. package/dist/tools/handlers/docker.js +155 -0
  309. package/dist/tools/handlers/docker.js.map +1 -0
  310. package/dist/tools/handlers/host.d.ts +23 -0
  311. package/dist/tools/handlers/host.d.ts.map +1 -0
  312. package/dist/tools/handlers/host.js +196 -0
  313. package/dist/tools/handlers/host.js.map +1 -0
  314. package/dist/tools/handlers/scout-logs.d.ts +24 -0
  315. package/dist/tools/handlers/scout-logs.d.ts.map +1 -0
  316. package/dist/tools/handlers/scout-logs.js +119 -0
  317. package/dist/tools/handlers/scout-logs.js.map +1 -0
  318. package/dist/tools/handlers/scout-simple.d.ts +23 -0
  319. package/dist/tools/handlers/scout-simple.d.ts.map +1 -0
  320. package/dist/tools/handlers/scout-simple.js +286 -0
  321. package/dist/tools/handlers/scout-simple.js.map +1 -0
  322. package/dist/tools/handlers/scout-zfs.d.ts +23 -0
  323. package/dist/tools/handlers/scout-zfs.d.ts.map +1 -0
  324. package/dist/tools/handlers/scout-zfs.js +82 -0
  325. package/dist/tools/handlers/scout-zfs.js.map +1 -0
  326. package/dist/tools/index.d.ts +32 -2
  327. package/dist/tools/index.d.ts.map +1 -1
  328. package/dist/tools/index.js +41 -35
  329. package/dist/tools/index.js.map +1 -1
  330. package/dist/tools/registry.d.ts +135 -0
  331. package/dist/tools/registry.d.ts.map +1 -0
  332. package/dist/tools/registry.js +151 -0
  333. package/dist/tools/registry.js.map +1 -0
  334. package/dist/tools/scout.d.ts +16 -8
  335. package/dist/tools/scout.d.ts.map +1 -1
  336. package/dist/tools/scout.js +36 -78
  337. package/dist/tools/scout.js.map +1 -1
  338. package/dist/types.d.ts +627 -1
  339. package/dist/types.d.ts.map +1 -1
  340. package/dist/types.js.map +1 -1
  341. package/dist/utils/command-security.d.ts +82 -0
  342. package/dist/utils/command-security.d.ts.map +1 -0
  343. package/dist/utils/command-security.js +122 -0
  344. package/dist/utils/command-security.js.map +1 -0
  345. package/dist/utils/error-sanitization.d.ts +77 -0
  346. package/dist/utils/error-sanitization.d.ts.map +1 -0
  347. package/dist/utils/error-sanitization.js +107 -0
  348. package/dist/utils/error-sanitization.js.map +1 -0
  349. package/dist/utils/errors.d.ts +30 -6
  350. package/dist/utils/errors.d.ts.map +1 -1
  351. package/dist/utils/errors.js +91 -12
  352. package/dist/utils/errors.js.map +1 -1
  353. package/dist/utils/help-handler.d.ts +23 -0
  354. package/dist/utils/help-handler.d.ts.map +1 -0
  355. package/dist/utils/help-handler.js +21 -0
  356. package/dist/utils/help-handler.js.map +1 -0
  357. package/dist/utils/help.d.ts +1 -1
  358. package/dist/utils/help.d.ts.map +1 -1
  359. package/dist/utils/help.js +57 -16
  360. package/dist/utils/help.js.map +1 -1
  361. package/dist/utils/host-utils.d.ts +31 -0
  362. package/dist/utils/host-utils.d.ts.map +1 -0
  363. package/dist/utils/host-utils.js +80 -0
  364. package/dist/utils/host-utils.js.map +1 -0
  365. package/dist/utils/index.d.ts +8 -2
  366. package/dist/utils/index.d.ts.map +1 -1
  367. package/dist/utils/index.js +8 -2
  368. package/dist/utils/index.js.map +1 -1
  369. package/dist/utils/init-detection.d.ts +36 -0
  370. package/dist/utils/init-detection.d.ts.map +1 -0
  371. package/dist/utils/init-detection.js +79 -0
  372. package/dist/utils/init-detection.js.map +1 -0
  373. package/dist/utils/logger.d.ts +11 -0
  374. package/dist/utils/logger.d.ts.map +1 -0
  375. package/dist/utils/logger.js +32 -0
  376. package/dist/utils/logger.js.map +1 -0
  377. package/dist/utils/pagination.d.ts +20 -0
  378. package/dist/utils/pagination.d.ts.map +1 -0
  379. package/dist/utils/pagination.js +29 -0
  380. package/dist/utils/pagination.js.map +1 -0
  381. package/dist/utils/path-security.d.ts +132 -18
  382. package/dist/utils/path-security.d.ts.map +1 -1
  383. package/dist/utils/path-security.js +164 -35
  384. package/dist/utils/path-security.js.map +1 -1
  385. package/dist/utils/sorting.d.ts +33 -0
  386. package/dist/utils/sorting.d.ts.map +1 -0
  387. package/dist/utils/sorting.js +57 -0
  388. package/dist/utils/sorting.js.map +1 -0
  389. package/dist/utils/text-filters.d.ts +13 -0
  390. package/dist/utils/text-filters.d.ts.map +1 -0
  391. package/dist/utils/text-filters.js +18 -0
  392. package/dist/utils/text-filters.js.map +1 -0
  393. package/dist/utils/time.d.ts +11 -0
  394. package/dist/utils/time.d.ts.map +1 -0
  395. package/dist/utils/time.js +13 -0
  396. package/dist/utils/time.js.map +1 -0
  397. package/dist/utils/validation.d.ts +25 -0
  398. package/dist/utils/validation.d.ts.map +1 -0
  399. package/dist/utils/validation.js +56 -0
  400. package/dist/utils/validation.js.map +1 -0
  401. package/package.json +45 -19
  402. package/dist/schemas/discriminator.d.ts +0 -20
  403. package/dist/schemas/discriminator.d.ts.map +0 -1
  404. package/dist/schemas/discriminator.js +0 -25
  405. package/dist/schemas/discriminator.js.map +0 -1
  406. package/dist/schemas/unified.d.ts +0 -674
  407. package/dist/schemas/unified.d.ts.map +0 -1
  408. package/dist/schemas/unified.js +0 -453
  409. package/dist/schemas/unified.js.map +0 -1
  410. package/dist/tools/unified.d.ts +0 -7
  411. package/dist/tools/unified.d.ts.map +0 -1
  412. package/dist/tools/unified.js +0 -827
  413. package/dist/tools/unified.js.map +0 -1
package/README.md CHANGED
@@ -4,28 +4,77 @@ MCP (Model Context Protocol) server providing **Flux** (Docker management) and *
4
4
 
5
5
  Designed for use with Claude Code and other MCP-compatible clients.
6
6
 
7
+ ## Installation
8
+
9
+ ### Claude Code Plugin (Recommended)
10
+
11
+ ```bash
12
+ # Add the synapse marketplace
13
+ /plugin marketplace add jmagar/synapse-mcp
14
+
15
+ # Install the synapse-mcp plugin
16
+ /plugin install synapse-mcp@synapse
17
+ ```
18
+
19
+ **What you get:**
20
+
21
+ - ✅ `/flux` and `/scout` commands
22
+ - ✅ Auto-configured MCP server
23
+ - ✅ Complete documentation and examples
24
+ - ✅ SSH host auto-discovery
25
+
26
+ ### Usage
27
+
28
+ ```bash
29
+ # List Docker containers
30
+ /flux list containers
31
+
32
+ # Check SSH hosts
33
+ /scout list hosts
34
+
35
+ # Monitor system resources
36
+ /flux show resources
37
+ ```
38
+
39
+ ### Direct MCP Server Setup
40
+
41
+ For non-Claude Code MCP clients, see [Transport Quick Start](#transport-quick-start) below.
42
+
43
+ ## Transport Quick Start
44
+
45
+ Choose one:
46
+
47
+ 1. Local use: `stdio` (default)
48
+ 2. Secure remote with minimal setup: `stdio` over SSH
49
+ 3. Remote HTTP: API key auth and/or Tailscale Serve auth
50
+
51
+ See `docs/TRANSPORTS.md` for exact setup and configs for all transport modes.
52
+
7
53
  ## Features
8
54
 
9
55
  ### Flux Tool (Docker Infrastructure Management)
56
+
10
57
  - **Container lifecycle**: Start, stop, restart, pause/resume, pull, recreate, exec
11
58
  - **Docker Compose**: Full project management (up, down, restart, logs, build, pull, recreate)
12
59
  - **Image operations**: List, pull, build, remove Docker images
13
60
  - **Host operations**: Status checks, resource monitoring, systemd services, network info
14
- - **Log retrieval**: Advanced filtering with time ranges, grep, stream selection
61
+ - **Log retrieval**: Advanced filtering with time ranges, grep (safe patterns only), stream selection
15
62
  - **Resource monitoring**: Real-time CPU, memory, network, I/O statistics
16
63
  - **Smart search**: Find containers by name, image, or labels across all hosts
17
64
  - **Pagination & filtering**: All list operations support limits, offsets, and filtering
18
65
 
19
66
  ### Scout Tool (SSH Remote Operations)
67
+
20
68
  - **File operations**: Read files, directory trees, file transfer (beam), diff comparison
21
69
  - **Remote execution**: Execute commands with allowlist security
22
70
  - **Process monitoring**: List and filter processes by user, CPU, memory
23
71
  - **ZFS management**: Pools, datasets, snapshots with health monitoring
24
- - **System logs**: Access syslog, journald, dmesg, auth logs with filtering
72
+ - **System logs**: Access syslog, journald, dmesg, auth logs with filtering (safe grep patterns only)
25
73
  - **Disk monitoring**: Filesystem usage across all mounts
26
74
  - **Multi-host operations**: Execute commands or read files across multiple hosts (emit)
27
75
 
28
76
  ### Infrastructure
77
+
29
78
  - **Multi-host support**: Manage Docker and SSH across Unraid, Proxmox, bare metal
30
79
  - **Auto-detect local Docker**: Automatically adds local Docker socket if available
31
80
  - **Dual transport**: stdio for Claude Code, HTTP for remote access
@@ -36,105 +85,257 @@ Designed for use with Claude Code and other MCP-compatible clients.
36
85
 
37
86
  The server provides two powerful tools with discriminated union schemas for O(1) validation:
38
87
 
88
+ ### Available Tools
89
+
90
+ #### flux
91
+
92
+ Docker infrastructure management - container, compose, docker, and host operations
93
+
94
+ #### scout
95
+
96
+ SSH remote operations - file, process, and system inspection
97
+
98
+ ### Getting Help
99
+
100
+ Both tools include auto-generated help:
101
+
102
+ ```json
103
+ { "action": "help" }
104
+ { "action": "help", "topic": "container:resume" }
105
+ { "action": "help", "format": "json" }
106
+ ```
107
+
108
+ **Breaking change from V2:** The unified tool has been completely removed and replaced with `flux` and `scout`.
109
+
110
+ ---
111
+
39
112
  ### Tool 1: `flux` - Docker Infrastructure Management
40
113
 
41
- **4 actions, 39 subactions** - State changes, lifecycle control, destructive operations.
42
-
43
- #### Container Operations (`action: "container"`) - 14 subactions
44
-
45
- | Subaction | Description |
46
- | ---------|-------------|
47
- | `list` | List containers with filtering by state, name, image, labels |
48
- | `start` | Start a stopped container |
49
- | `stop` | Stop a running container |
50
- | `restart` | Restart a container |
51
- | `pause` | Pause a running container |
52
- | `resume` | Resume a paused container (was `unpause`) |
53
- | `logs` | Retrieve container logs with time and grep filters |
54
- | `stats` | Get real-time CPU, memory, network, I/O statistics |
55
- | `inspect` | Detailed container configuration and state (with summary mode) |
56
- | `search` | Search containers by name, image, or labels |
57
- | `pull` | Pull latest image for a container |
58
- | `recreate` | Recreate container with latest image |
59
- | `exec` | Execute command inside a container (allowlist validated) |
60
- | `top` | Show running processes in a container |
61
-
62
- #### Docker Compose Operations (`action: "compose"`) - 9 subactions
63
-
64
- | Subaction | Description |
65
- | ---------|-------------|
66
- | `list` | List Docker Compose projects on a host |
67
- | `status` | Get status of services in a project |
68
- | `up` | Start a compose project |
69
- | `down` | Stop a compose project |
70
- | `restart` | Restart a compose project |
71
- | `logs` | Get logs from compose project services |
72
- | `build` | Build images for a compose project |
73
- | `pull` | Pull images for a compose project |
74
- | `recreate` | Force recreate containers in a project |
75
-
76
- #### Docker System Operations (`action: "docker"`) - 9 subactions
77
-
78
- | Subaction | Description |
79
- | ---------|-------------|
80
- | `info` | Get Docker daemon information |
81
- | `df` | Get Docker disk usage (images, containers, volumes, cache) |
82
- | `prune` | Remove unused Docker resources (requires `force: true`) |
83
- | `images` | List Docker images on a host |
84
- | `pull` | Pull a Docker image |
85
- | `build` | Build a Docker image from Dockerfile |
86
- | `rmi` | Remove a Docker image |
87
- | `networks` | List Docker networks |
88
- | `volumes` | List Docker volumes |
89
-
90
- #### Host Operations (`action: "host"`) - 7 subactions
91
-
92
- | Subaction | Description |
93
- | ---------|-------------|
94
- | `status` | Check Docker connectivity to host |
95
- | `resources` | Get CPU, memory, disk usage via SSH |
96
- | `info` | Get OS, kernel, architecture, hostname |
97
- | `uptime` | Get system uptime |
98
- | `services` | Get systemd service status |
99
- | `network` | Get network interfaces and IP addresses |
100
- | `mounts` | Get mounted filesystems |
114
+ **43 operations across 5 actions** - Container lifecycle, compose orchestration, system management
115
+
116
+ ```
117
+ FLUX OPERATIONS:
118
+
119
+ Container (14 operations)
120
+ ● exec - Execute command inside a container
121
+ ● inspect - Get detailed container information
122
+ ● list - List containers with optional filtering
123
+ ● logs - Get container logs with optional filtering
124
+ pause - Pause a running container
125
+ ● pull - Pull latest image for a container
126
+ ⚠️ recreate - Recreate a container with optional image pull
127
+ ● restart - Restart a container
128
+ ● resume - Resume a paused container
129
+ search - Search containers by query string
130
+ ● start - Start a stopped container
131
+ ● stats - Get resource usage statistics
132
+ ● stop - Stop a running container
133
+ top - Show running processes in a container
134
+
135
+ Compose (10 operations)
136
+ ● build - Build Docker Compose project images
137
+ ⚠️ down - Stop a Docker Compose project
138
+ ● list - List all Docker Compose projects
139
+ ● logs - Get Docker Compose project logs
140
+ ● pull - Pull Docker Compose project images
141
+ ⚠️ recreate - Recreate Docker Compose project containers
142
+ ● refresh - Refresh compose project cache by scanning filesystem
143
+ restart - Restart a Docker Compose project
144
+ ● status - Get Docker Compose project status
145
+ ● up - Start a Docker Compose project
146
+
147
+ Docker (9 operations)
148
+ ● build - Build a Docker image
149
+ ● df - Get Docker disk usage information
150
+ ● images - List Docker images
151
+ ● info - Get Docker daemon information
152
+ ● networks - List Docker networks
153
+ ⚠️ prune - Remove unused Docker resources
154
+ ● pull - Pull a Docker image
155
+ ⚠️ rmi - Remove a Docker image
156
+ ● volumes - List Docker volumes
157
+
158
+ Host (9 operations)
159
+ ✓ doctor - Run diagnostic checks on host Docker configuration
160
+ ● info - Get OS, kernel, architecture, and hostname information
161
+ ● mounts - Get mounted filesystems
162
+ ● network - Get network interfaces and IP addresses
163
+ ● ports - List all port mappings for containers on a host
164
+ ● resources - Get CPU, memory, and disk usage via SSH
165
+ ● services - Get systemd service status
166
+ ✓ status - Check Docker connectivity to host
167
+ ● uptime - Get system uptime
168
+
169
+ ```
170
+
171
+ ---
101
172
 
102
173
  ---
103
174
 
104
175
  ### Tool 2: `scout` - SSH Remote Operations
105
176
 
106
- **11 actions, 16 operations** - Read-mostly remote file and system operations.
177
+ **16 operations across 11 actions** - File operations, process inspection, system logs
178
+
179
+ ```
180
+ SCOUT OPERATIONS:
181
+
182
+ Simple Actions (9 operations)
183
+ ● beam - File transfer between local and remote hosts
184
+ ● delta - Compare files or content between locations
185
+ ● df - Disk usage information for a remote host
186
+ ● emit - Multi-host operations
187
+ ● exec - Execute command on a remote host
188
+ ● find - Find files by glob pattern on a remote host
189
+ ● nodes - List all configured SSH hosts
190
+ ● peek - Read file or directory contents on a remote host
191
+ ● ps - List and search processes on a remote host
192
+
193
+ ZFS (3 operations)
194
+ ● pools - List ZFS storage pools
195
+ ● datasets - List ZFS datasets
196
+ ● snapshots - List ZFS snapshots
197
+
198
+ Logs (4 operations)
199
+ ● syslog - Access system log files (/var/log)
200
+ ● journal - Access systemd journal logs
201
+ ● dmesg - Access kernel ring buffer logs
202
+ ● auth - Access authentication logs
107
203
 
108
- #### Simple Actions (9)
204
+ ```
109
205
 
110
- | Action | Description |
111
- | ------|-------------|
112
- | `nodes` | List all configured SSH hosts |
113
- | `peek` | Read file or directory contents (with tree mode) |
114
- | `exec` | Execute command on remote host (allowlist validated) |
115
- | `find` | Find files by glob pattern |
116
- | `delta` | Compare files or content between locations |
117
- | `emit` | Multi-host operations (read files or execute commands) |
118
- | `beam` | File transfer between local/remote or remote/remote |
119
- | `ps` | List and search processes with filtering |
120
- | `df` | Disk usage information |
206
+ **Legend:**
207
+ - `●` State-changing operation
208
+ - `⚠️` Destructive operation (requires `force: true`)
209
+ - `✓` Diagnostic/health check
210
+ - `→` Port mapping notation (host→container/protocol)
211
+
212
+ ## Simple Actions (9)
213
+
214
+ | Action | Description |
215
+ | ------- | ------------------------------------------------------ |
216
+ | `nodes` | List all configured SSH hosts |
217
+ | `peek` | Read file or directory contents (with tree mode) |
218
+ | `exec` | Execute command on remote host (allowlist validated) |
219
+ | `find` | Find files by glob pattern |
220
+ | `delta` | Compare files or content between locations |
221
+ | `emit` | Multi-host operations (read files or execute commands) |
222
+ | `beam` | File transfer between local/remote or remote/remote |
223
+ | `ps` | List and search processes with filtering |
224
+ | `df` | Disk usage information |
121
225
 
122
226
  #### ZFS Operations (`action: "zfs"`) - 3 subactions
123
227
 
124
- | Subaction | Description |
125
- | ---------|-------------|
126
- | `pools` | List ZFS storage pools with health status |
127
- | `datasets` | List ZFS datasets (filesystems and volumes) |
128
- | `snapshots` | List ZFS snapshots |
228
+ | Subaction | Description |
229
+ | ----------- | ------------------------------------------- |
230
+ | `pools` | List ZFS storage pools with health status |
231
+ | `datasets` | List ZFS datasets (filesystems and volumes) |
232
+ | `snapshots` | List ZFS snapshots |
129
233
 
130
234
  #### Log Operations (`action: "logs"`) - 4 subactions
131
235
 
132
- | Subaction | Description |
133
- | ---------|-------------|
134
- | `syslog` | Access system log files (/var/log) |
236
+ | Subaction | Description |
237
+ | --------- | ----------------------------------------------- |
238
+ | `syslog` | Access system log files (/var/log) |
135
239
  | `journal` | Access systemd journal logs with unit filtering |
136
- | `dmesg` | Access kernel ring buffer logs |
137
- | `auth` | Access authentication logs |
240
+ | `dmesg` | Access kernel ring buffer logs |
241
+ | `auth` | Access authentication logs |
242
+
243
+ ---
244
+
245
+ ## Compose Auto-Discovery
246
+
247
+ The MCP server automatically discovers and caches Docker Compose project locations, eliminating the need to specify file paths for every operation.
248
+
249
+ ### How It Works
250
+
251
+ The discovery system uses a multi-layer approach:
252
+
253
+ 1. **Cache Check**: Looks up project in local cache (`.cache/compose-projects/`)
254
+ 2. **Docker List**: Queries `docker compose ls` for running projects
255
+ 3. **Filesystem Scan**: Scans configured search paths for compose files
256
+ 4. **Error**: Returns error if project not found in any layer
257
+
258
+ Discovery results are cached for 24 hours (configurable via `COMPOSE_CACHE_TTL_HOURS` environment variable).
259
+
260
+ ### Configuration
261
+
262
+ Add optional `composeSearchPaths` to your host configuration:
263
+
264
+ ```json
265
+ {
266
+ "hosts": [
267
+ {
268
+ "name": "my-host",
269
+ "host": "192.168.1.100",
270
+ "protocol": "ssh",
271
+ "composeSearchPaths": ["/opt/stacks", "/srv/docker"]
272
+ }
273
+ ]
274
+ }
275
+ ```
276
+
277
+ **Default search paths**: `["/compose", "/mnt/cache/compose", "/mnt/cache/code"]` if not specified.
278
+
279
+ ### Optional Host Parameter
280
+
281
+ Most compose operations accept an optional `host` parameter. When omitted, the system automatically searches all configured hosts in parallel to find the project:
282
+
283
+ ```json
284
+ // Explicit host (faster - no search needed)
285
+ { "action": "compose", "subaction": "up", "project": "plex", "host": "server1" }
286
+
287
+ // Auto-discover (searches all hosts in parallel)
288
+ { "action": "compose", "subaction": "up", "project": "plex" }
289
+ ```
290
+
291
+ Auto-discovery times out after 30 seconds if the project cannot be found on any host. If a project exists on multiple hosts, you'll receive an error asking you to specify the `host` parameter explicitly.
292
+
293
+ ### Cache Management
294
+
295
+ - **TTL**: 24 hours (default, configurable)
296
+ - **Storage**: `.cache/compose-projects/` directory (gitignored)
297
+ - **Invalidation**: Automatic when operations fail due to stale paths
298
+ - **Manual Refresh**: Use `compose:refresh` subaction
299
+
300
+ ### Manual Cache Refresh
301
+
302
+ Force a cache refresh by scanning the filesystem:
303
+
304
+ ```json
305
+ // Refresh all hosts
306
+ { "action": "compose", "subaction": "refresh" }
307
+
308
+ // Refresh specific host
309
+ { "action": "compose", "subaction": "refresh", "host": "server1" }
310
+ ```
311
+
312
+ Returns a list of discovered projects with their paths and discovery source (docker-ls or filesystem scan).
313
+
314
+ ### Architecture
315
+
316
+ ```
317
+ ┌─────────────┐
318
+ │ Handler │
319
+ └──────┬──────┘
320
+
321
+ v
322
+ ┌──────────────┐ ┌──────────────┐
323
+ │ HostResolver │─────>│ Discovery │
324
+ └──────────────┘ └──────┬───────┘
325
+
326
+ ┌────────┴────────┐
327
+ v v
328
+ ┌──────────┐ ┌──────────┐
329
+ │ Cache │ │ Scanner │
330
+ └──────────┘ └──────────┘
331
+ ```
332
+
333
+ **Components**:
334
+
335
+ - **HostResolver**: Finds which host contains the project (parallel search)
336
+ - **ComposeDiscovery**: Orchestrates cache, docker-ls, and filesystem scanning
337
+ - **ComposeProjectCache**: File-based cache with TTL validation
338
+ - **ComposeScanner**: Filesystem scanning for compose files (respects max depth of 3)
138
339
 
139
340
  ---
140
341
 
@@ -149,9 +350,15 @@ The server provides two powerful tools with discriminated union schemas for O(1)
149
350
  // Restart a container
150
351
  { "tool": "flux", "action": "container", "subaction": "restart", "container_id": "plex", "host": "tootie" }
151
352
 
152
- // Start a compose project
353
+ // Start a compose project (auto-discovers location and host)
354
+ { "tool": "flux", "action": "compose", "subaction": "up", "project": "media-stack" }
355
+
356
+ // Start a compose project on specific host
153
357
  { "tool": "flux", "action": "compose", "subaction": "up", "host": "tootie", "project": "media-stack" }
154
358
 
359
+ // Refresh compose project cache
360
+ { "tool": "flux", "action": "compose", "subaction": "refresh" }
361
+
155
362
  // Get host resources
156
363
  { "tool": "flux", "action": "host", "subaction": "resources", "host": "tootie" }
157
364
 
@@ -203,8 +410,45 @@ pnpm install
203
410
  pnpm run build
204
411
  ```
205
412
 
413
+ The server will create a `.cache/compose-projects/` directory for storing discovered project locations. This directory is automatically gitignored.
414
+
206
415
  ## Configuration
207
416
 
417
+ ### SSH Config Auto-Loading
418
+
419
+ **Zero configuration required!** Synapse-MCP automatically discovers hosts from your `~/.ssh/config` file.
420
+
421
+ All SSH hosts with a `HostName` directive are automatically available for Docker management via SSH tunneling to the remote Docker socket. Manual configuration is completely optional.
422
+
423
+ **Priority order:**
424
+
425
+ 1. Manual config file (highest) - `synapse.config.json`
426
+ 2. `SYNAPSE_HOSTS_CONFIG` environment variable
427
+ 3. **SSH config auto-discovery** - `~/.ssh/config`
428
+ 4. Local Docker socket (fallback)
429
+
430
+ **Example SSH config:**
431
+
432
+ ```ssh-config
433
+ Host production
434
+ HostName 192.168.1.100
435
+ User admin
436
+ Port 22
437
+ IdentityFile ~/.ssh/id_ed25519
438
+
439
+ Host staging
440
+ HostName 192.168.1.101
441
+ User deploy
442
+ Port 2222
443
+ IdentityFile ~/.ssh/staging_key
444
+ ```
445
+
446
+ Both hosts are immediately available as `flux` targets with SSH tunneling to `/var/run/docker.sock`. No additional configuration needed!
447
+
448
+ **Manual override:** If you create a `synapse.config.json` entry with the same name as an SSH host, the manual config completely replaces the SSH config (no merging).
449
+
450
+ ### Manual Configuration (Optional)
451
+
208
452
  Create a config file at one of these locations (checked in order):
209
453
 
210
454
  1. Path in `SYNAPSE_CONFIG_FILE` env var
@@ -218,70 +462,371 @@ Create a config file at one of these locations (checked in order):
218
462
  {
219
463
  "hosts": [
220
464
  {
221
- "name": "unraid",
222
- "host": "unraid.local",
223
- "port": 2375,
224
- "protocol": "http",
225
- "tags": ["media", "storage"]
465
+ "name": "local",
466
+ "host": "localhost",
467
+ "protocol": "ssh",
468
+ "dockerSocketPath": "/var/run/docker.sock",
469
+ "tags": ["development"]
226
470
  },
227
471
  {
228
- "name": "proxmox-docker",
472
+ "name": "production",
229
473
  "host": "192.168.1.100",
230
- "port": 2375,
231
- "protocol": "http",
232
- "tags": ["vms"]
474
+ "port": 22,
475
+ "protocol": "ssh",
476
+ "sshUser": "admin",
477
+ "sshKeyPath": "~/.ssh/id_rsa",
478
+ "tags": ["production"]
233
479
  },
234
480
  {
235
- "name": "local",
236
- "host": "localhost",
481
+ "name": "unraid",
482
+ "host": "unraid.local",
483
+ "port": 2375,
237
484
  "protocol": "http",
238
- "dockerSocketPath": "/var/run/docker.sock"
485
+ "tags": ["media", "storage"]
239
486
  }
240
487
  ]
241
488
  }
242
489
  ```
243
490
 
244
- Copy `synapse.config.example.json` as a starting point:
491
+ Copy `config/synapse.config.example.json` as a starting point:
492
+
245
493
  ```bash
246
- cp synapse.config.example.json ~/.config/synapse-mcp/config.json
494
+ cp config/synapse.config.example.json ~/.config/synapse-mcp/config.json
247
495
  # or
248
- cp synapse.config.example.json ~/.synapse-mcp.json
496
+ cp config/synapse.config.example.json ~/.synapse-mcp.json
249
497
  ```
250
498
 
251
499
  > **Note:** If `/var/run/docker.sock` exists and isn't already in your config, it will be automatically added as a host using your machine's hostname. This means the server works out-of-the-box for local Docker without any configuration.
252
500
 
253
501
  ### Host Configuration Options
254
502
 
255
- | Field | Type | Description |
256
- | ----- | ---- | ----------- |
257
- | `name` | `string` | Unique identifier for the host |
258
- | `host` | `string` | Hostname or IP address |
259
- | `port` | `number` | Docker API port (default: 2375) |
260
- | `protocol` | `"http"` / `"https"` / `"ssh"` | Connection protocol |
261
- | `dockerSocketPath` | `string` | Path to Docker socket (for local connections) |
262
- | `sshUser` | `string` | SSH username for remote connections (protocol: "ssh") |
263
- | `sshKeyPath` | `string` | Path to SSH private key for authentication |
264
- | `tags` | `string[]` | Optional tags for filtering |
503
+ | Field | Type | Description |
504
+ | ------------------ | ------------------------------ | ----------------------------------------------------- |
505
+ | `name` | `string` | Unique identifier for the host |
506
+ | `host` | `string` | Hostname or IP address |
507
+ | `port` | `number` | Docker API port (default: 2375) |
508
+ | `protocol` | `"http"` / `"https"` / `"ssh"` | Connection protocol |
509
+ | `dockerSocketPath` | `string` | Path to Docker socket (for local connections) |
510
+ | `sshUser` | `string` | SSH username for remote connections (protocol: "ssh") |
511
+ | `sshKeyPath` | `string` | Path to SSH private key for authentication |
512
+ | `tags` | `string[]` | Optional tags for filtering |
513
+
514
+ ### Environment Variables Reference
515
+
516
+ Complete reference for all environment variables that control server behavior.
517
+
518
+ #### Server Configuration
519
+
520
+ | Variable | Type | Default | Description |
521
+ | ---------------------- | ------------- | ------------ | ---------------------------------------------------------------------------------------------- |
522
+ | `SYNAPSE_CONFIG_FILE` | `string` | Auto-detect | Path to config file. Overrides default search paths. |
523
+ | `SYNAPSE_HOSTS_CONFIG` | `JSON string` | `undefined` | JSON config as environment variable. Fallback if no config file found. |
524
+ | `SYNAPSE_PORT` | `number` | `53000` | HTTP server port (only used with `--http` flag). |
525
+ | `SYNAPSE_HOST` | `string` | `127.0.0.1` | HTTP server bind address. Use `0.0.0.0` to expose to all interfaces (requires authentication). |
526
+ | `NODE_ENV` | `string` | `production` | Node environment. Affects stack traces and error verbosity. |
527
+
528
+ #### Performance Tuning
529
+
530
+ | Variable | Type | Default | Description |
531
+ | ----------------------------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------ |
532
+ | `SSH_POOL_MAX_CONNECTIONS` | `number` | `5` | Maximum SSH connections per host. Increase for high-concurrency workloads (10-20 for 100+ containers). |
533
+ | `SSH_POOL_IDLE_TIMEOUT_MS` | `number` | `60000` (60s) | Close idle connections after this duration. Reduce to save resources (30000 for low-usage). |
534
+ | `SSH_POOL_CONNECTION_TIMEOUT_MS` | `number` | `5000` (5s) | SSH connection timeout. Increase for slow networks (10000-15000). |
535
+ | `SSH_POOL_HEALTH_CHECK_INTERVAL_MS` | `number` | `30000` (30s) | Health check interval. Set to `0` to disable health checks. |
536
+ | `COMPOSE_CACHE_TTL_HOURS` | `number` | `24` | Compose project cache lifetime in hours. Lower for frequently changing projects (6-12 hours). |
537
+
538
+ #### Security Options
539
+
540
+ | Variable | Type | Default | Description | ⚠️ Security Impact |
541
+ | --------------------------- | --------- | ----------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
542
+ | `SYNAPSE_API_KEY` | `string` | `undefined` | Enables HTTP API key authentication when set. | If unset, `/mcp` does not require API key auth. Set this in all non-local deployments. |
543
+ | `SYNAPSE_ALLOWED_ORIGINS` | `string` | `undefined` | Comma-separated allowlist of trusted CORS origins for browser clients. | If unset, cross-origin browser access is blocked (`Access-Control-Allow-Origin: null`). |
544
+ | `SYNAPSE_ALLOW_ANY_COMMAND` | `boolean` | `false` | **DANGEROUS:** Disables command allowlist for `scout:exec`. | **CRITICAL:** Allows arbitrary command execution. Only use in trusted development environments. Never set in production. |
545
+
546
+ **Security Warning for `SYNAPSE_ALLOW_ANY_COMMAND`:**
547
+
548
+ When set to `true`, this variable completely bypasses the command allowlist, allowing execution of ANY command on managed hosts via `scout:exec`. This includes destructive commands like `rm -rf /`, privilege escalation, and backdoor installation.
549
+
550
+ **Default allowed commands** (when `false`):
551
+
552
+ - Read operations: `cat`, `head`, `tail`, `grep`, `rg`, `find`, `ls`, `tree`
553
+ - Info operations: `stat`, `file`, `du`, `df`, `pwd`, `hostname`, `uptime`, `whoami`
554
+ - Text processing: `wc`, `sort`, `uniq`, `diff`
555
+
556
+ **When to use `true`:**
557
+
558
+ - Local development only
559
+ - Single-user environments
560
+ - When you fully trust all MCP clients
561
+ - When `NODE_ENV=development`
562
+
563
+ **Detection:**
564
+
565
+ ```bash
566
+ # Check if variable is set
567
+ printenv | grep SYNAPSE_ALLOW_ANY_COMMAND
568
+
569
+ # Check systemd service
570
+ sudo grep SYNAPSE_ALLOW_ANY_COMMAND /etc/systemd/system/synapse-mcp.service
571
+
572
+ # Check Docker Compose
573
+ grep SYNAPSE_ALLOW_ANY_COMMAND docker-compose.yml
574
+ ```
575
+
576
+ #### Debug and Logging
577
+
578
+ | Variable | Type | Default | Description |
579
+ | ----------- | -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
580
+ | `DEBUG` | `string` | `undefined` | Enable debug logging. Set to `synapse:*` for all debug output or specific namespaces like `synapse:ssh`, `synapse:docker`. |
581
+ | `LOG_LEVEL` | `string` | `info` | Logging level: `error`, `warn`, `info`, `debug`, `trace`. |
582
+
583
+ #### Example Configurations
584
+
585
+ **Development (Local):**
586
+
587
+ ```bash
588
+ export NODE_ENV=development
589
+ export SYNAPSE_CONFIG_FILE=~/.config/synapse-mcp/config.json
590
+ export DEBUG=synapse:*
591
+ export SSH_POOL_HEALTH_CHECK_INTERVAL_MS=0 # Disable health checks
592
+ export LOG_LEVEL=debug
593
+ node dist/index.js
594
+ ```
595
+
596
+ **Production (HTTP Mode with High Concurrency):**
597
+
598
+ ```bash
599
+ export NODE_ENV=production
600
+ export SYNAPSE_PORT=53000
601
+ export SYNAPSE_HOST=127.0.0.1 # Localhost only, behind reverse proxy
602
+ export SSH_POOL_MAX_CONNECTIONS=10 # Higher concurrency
603
+ export COMPOSE_CACHE_TTL_HOURS=12 # Refresh more frequently
604
+ export LOG_LEVEL=info
605
+ node dist/index.js --http
606
+ ```
607
+
608
+ **Production (Stdio Mode for Claude Code):**
609
+
610
+ ```bash
611
+ export NODE_ENV=production
612
+ export SYNAPSE_CONFIG_FILE=/etc/synapse-mcp/config.json
613
+ export SSH_POOL_MAX_CONNECTIONS=5
614
+ export COMPOSE_CACHE_TTL_HOURS=24
615
+ export LOG_LEVEL=warn
616
+ node dist/index.js
617
+ ```
618
+
619
+ **High-Latency Network:**
620
+
621
+ ```bash
622
+ export SSH_POOL_CONNECTION_TIMEOUT_MS=15000 # 15s timeout
623
+ export SSH_POOL_IDLE_TIMEOUT_MS=120000 # 2min idle timeout
624
+ export SSH_POOL_HEALTH_CHECK_INTERVAL_MS=60000 # 1min health checks
625
+ node dist/index.js
626
+ ```
627
+
628
+ ### Local vs Remote Execution
629
+
630
+ The server automatically determines whether to use **local execution** or **SSH** based on your host configuration:
631
+
632
+ #### Local Execution (No SSH)
633
+
634
+ Commands run directly on localhost using Node.js for best performance:
635
+
636
+ ```json
637
+ {
638
+ "name": "local",
639
+ "host": "localhost",
640
+ "protocol": "ssh",
641
+ "dockerSocketPath": "/var/run/docker.sock"
642
+ }
643
+ ```
644
+
645
+ **Requirements**: Host must be `localhost`/`127.x.x.x`/`::1` AND no `sshUser` specified.
646
+
647
+ **Benefits**:
648
+
649
+ - ~10x faster than SSH for Compose and host operations
650
+ - No SSH key management needed
651
+ - Works out of the box
652
+
653
+ #### Remote Execution (SSH)
654
+
655
+ Commands run via SSH on remote hosts or when `sshUser` is specified:
656
+
657
+ ```json
658
+ {
659
+ "name": "production",
660
+ "host": "192.168.1.100",
661
+ "protocol": "ssh",
662
+ "sshUser": "admin",
663
+ "sshKeyPath": "~/.ssh/id_rsa"
664
+ }
665
+ ```
666
+
667
+ **When SSH is used**:
668
+
669
+ - Host is NOT localhost/127.x.x.x
670
+ - `sshUser` is specified (even for localhost)
671
+ - For all Scout operations (file operations always use SSH)
672
+
673
+ #### Docker API vs Command Execution
674
+
675
+ These are independent:
676
+
677
+ | Operation | Local Host | Remote Host |
678
+ | ---------------------------------- | ---------------- | ----------- |
679
+ | Docker API (container list, stats) | Unix socket | HTTP |
680
+ | Commands (compose, systemctl) | Local `execFile` | SSH |
681
+
682
+ See [.docs/local-vs-remote-execution.md](.docs/local-vs-remote-execution.md) for detailed architecture documentation.
265
683
 
266
684
  ### Resource Limits & Defaults
267
685
 
268
- | Setting | Value | Description |
269
- | -------|-------|-------------|
270
- | `CHARACTER_LIMIT` | 40,000 | Maximum response size (~12.5k tokens) |
271
- | `DEFAULT_LIMIT` | 20 | Default pagination limit for list operations |
272
- | `MAX_LIMIT` | 100 | Maximum pagination limit |
273
- | `DEFAULT_LOG_LINES` | 50 | Default number of log lines to fetch |
274
- | `MAX_LOG_LINES` | 500 | Maximum log lines allowed |
275
- | `API_TIMEOUT` | 30s | Docker API operation timeout |
276
- | `STATS_TIMEOUT` | 5s | Stats collection timeout |
686
+ | Setting | Value | Description |
687
+ | ------------------- | ------ | -------------------------------------------- |
688
+ | `CHARACTER_LIMIT` | 40,000 | Maximum response size (~12.5k tokens) |
689
+ | `DEFAULT_LIMIT` | 20 | Default pagination limit for list operations |
690
+ | `MAX_LIMIT` | 100 | Maximum pagination limit |
691
+ | `DEFAULT_LOG_LINES` | 50 | Default number of log lines to fetch |
692
+ | `MAX_LOG_LINES` | 500 | Maximum log lines allowed |
693
+ | `API_TIMEOUT` | 30s | Docker API operation timeout |
694
+ | `STATS_TIMEOUT` | 5s | Stats collection timeout |
695
+
696
+ ### Performance Characteristics
697
+
698
+ Understanding performance expectations helps optimize your usage and troubleshoot slow operations.
699
+
700
+ #### Response Time Expectations
701
+
702
+ | Operation Type | Expected Latency | Notes |
703
+ | ------------------------------ | ---------------- | --------------------------------------------------------------- |
704
+ | Single-host operations | 50-150ms | Container list, stats, logs, inspect |
705
+ | Multi-host container discovery | 100-500ms | Depends on host count and network latency |
706
+ | Compose auto-discovery | 1-500ms | Cache hit: 1ms, docker-ls: 50-100ms, filesystem scan: 200-500ms |
707
+ | SSH connection (warm) | <10ms | Connection pool hit |
708
+ | SSH connection (cold) | 200-300ms | New connection establishment |
709
+ | Container exec | 100ms-30s | Depends on command execution time |
710
+
711
+ #### Configuration Loading
712
+
713
+ - **Config files:** Loaded at server startup (synchronous read)
714
+ - **Config changes:** Require server restart (no hot reload)
715
+ - **SSH config:** Changes detected automatically on next operation
716
+ - **Cache:** Compose project cache has 24-hour TTL (configurable via `COMPOSE_CACHE_TTL_HOURS`)
717
+
718
+ #### Buffer and Output Limits
719
+
720
+ | Resource | Limit | Behavior on Exceed |
721
+ | ------------------------ | ------------------------------- | ------------------------------- |
722
+ | Response character limit | 40,000 chars (~12.5k tokens) | Truncated with warning |
723
+ | Container exec output | 10MB per stream (stdout/stderr) | Stream terminated with error |
724
+ | Log lines | 50 default, 500 maximum | Paginate with `lines` parameter |
725
+ | Find results | 100 default, 1000 maximum | Paginate with `limit` parameter |
726
+
727
+ #### Connection Pooling
728
+
729
+ | Setting | Default | Tuning |
730
+ | ------------------------ | ---------- | ----------------------------------- |
731
+ | SSH connections per host | 5 | `SSH_POOL_MAX_CONNECTIONS` |
732
+ | Idle timeout | 60 seconds | `SSH_POOL_IDLE_TIMEOUT_MS` |
733
+ | Connection timeout | 5 seconds | `SSH_POOL_CONNECTION_TIMEOUT_MS` |
734
+ | Health check interval | 30 seconds | `SSH_POOL_HEALTH_CHECK_INTERVAL_MS` |
735
+
736
+ **Performance Impact:**
737
+
738
+ - Warm connections: 20-30× faster than establishing new connections
739
+ - Pool exhaustion: Operations queue until connection available
740
+ - Health checks: Detect and remove stale connections automatically
741
+
742
+ #### Compose Discovery Cache
743
+
744
+ **Three-tier strategy:**
745
+
746
+ 1. **Cache check** (fastest, 0-1ms) - `.cache/compose-projects/`
747
+ 2. **docker compose ls** (medium, 50-100ms) - running projects only
748
+ 3. **Filesystem scan** (slowest, 200-500ms) - all projects
749
+
750
+ **Cache behavior:**
751
+
752
+ - TTL: 24 hours (default, configurable via `COMPOSE_CACHE_TTL_HOURS`)
753
+ - Invalidation: Automatic on stale path detection
754
+ - Storage: Local filesystem (`.cache/compose-projects/`)
755
+ - Refresh: Manual via `compose:refresh` or automatic on cache miss
756
+
757
+ #### Scaling Characteristics
758
+
759
+ **Host Count Impact:**
760
+
761
+ - **1-5 hosts:** Optimal performance, minimal latency
762
+ - **6-10 hosts:** Good performance, consider explicit `host` parameter for frequent operations
763
+ - **11-15 hosts:** Increased latency, recommend explicit `host` for all operations
764
+ - **16+ hosts:** Consider splitting into multiple MCP server instances
765
+
766
+ **Container Count Impact:**
767
+
768
+ - **1-50 containers:** No impact, all operations fast
769
+ - **51-100 containers:** Pagination recommended for list operations
770
+ - **101-500 containers:** Always paginate, avoid `state: "all"` without filters
771
+ - **500+ containers:** Use host-specific operations, increase `SSH_POOL_MAX_CONNECTIONS`
772
+
773
+ **Network Latency Impact:**
774
+
775
+ - Low latency (<10ms): Minimal impact on multi-host operations
776
+ - Medium latency (10-50ms): 2-3× slower for multi-host discovery
777
+ - High latency (>50ms): Explicitly specify `host` parameter to avoid discovery overhead
778
+
779
+ #### Tuning for Large Deployments
780
+
781
+ If managing 15+ hosts with 100+ containers:
782
+
783
+ ```bash
784
+ # Increase connection pool size
785
+ export SSH_POOL_MAX_CONNECTIONS=10
786
+
787
+ # Reduce cache TTL for frequently changing projects
788
+ export COMPOSE_CACHE_TTL_HOURS=12
789
+
790
+ # Disable health checks if connections are stable
791
+ export SSH_POOL_HEALTH_CHECK_INTERVAL_MS=0
792
+ ```
793
+
794
+ **Operational strategies:**
795
+
796
+ - **Always specify `host`:** Avoid auto-discovery overhead for known locations
797
+ - **Use pagination:** Set `limit: 20` for list operations
798
+ - **Batch operations:** Group related operations to reuse warm connections
799
+ - **Split by environment:** Run separate MCP instances for dev/staging/prod hosts
800
+
801
+ #### Performance Monitoring
802
+
803
+ **Monitor response times:**
804
+
805
+ ```bash
806
+ # Watch logs for slow operations
807
+ journalctl -u synapse-mcp.service | grep -E "took [0-9]{3,}ms"
808
+
809
+ # Check connection pool utilization
810
+ # (Low availability = need more connections)
811
+ ```
812
+
813
+ **Health check:**
814
+
815
+ ```bash
816
+ # Monitor server health
817
+ curl http://localhost:53000/health
818
+ ```
277
819
 
278
820
  ### Enabling Docker API on Hosts
279
821
 
280
822
  #### Unraid
823
+
281
824
  Docker API is typically available at port 2375 by default.
282
825
 
283
826
  #### Standard Docker (systemd)
827
+
284
828
  Edit `/etc/docker/daemon.json`:
829
+
285
830
  ```json
286
831
  {
287
832
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
@@ -289,9 +834,11 @@ Edit `/etc/docker/daemon.json`:
289
834
  ```
290
835
 
291
836
  Or override the systemd service:
837
+
292
838
  ```bash
293
839
  sudo systemctl edit docker.service
294
840
  ```
841
+
295
842
  ```ini
296
843
  [Service]
297
844
  ExecStart=
@@ -334,6 +881,7 @@ Or if your config is in one of the default locations, you can skip the env entir
334
881
  ```
335
882
 
336
883
  Then in Claude Code:
884
+
337
885
  ```
338
886
  > List all running containers on tootie (uses flux tool)
339
887
  > Restart the plex container (uses flux tool)
@@ -352,12 +900,13 @@ For remote access or multi-client scenarios:
352
900
  # Start HTTP server
353
901
  node dist/index.js --http
354
902
 
355
- # Server runs on http://127.0.0.1:3000/mcp
356
- # Health check: http://127.0.0.1:3000/health
903
+ # Server runs on http://127.0.0.1:53000/mcp
904
+ # Health check: http://127.0.0.1:53000/health
357
905
  ```
358
906
 
359
907
  Environment variables for HTTP mode:
360
- - `PORT`: Server port (default: 3000)
908
+
909
+ - `PORT`: Server port (default: 53000)
361
910
  - `HOST`: Bind address (default: 127.0.0.1)
362
911
 
363
912
  ### CLI Help
@@ -369,6 +918,7 @@ node dist/index.js --help
369
918
  ## Example Interactions
370
919
 
371
920
  ### Flux Tool - Container Management
921
+
372
922
  ```
373
923
  User: What containers are running on tootie?
374
924
 
@@ -383,6 +933,7 @@ I found 23 running containers on tootie:
383
933
  ```
384
934
 
385
935
  ### Flux Tool - Log Analysis
936
+
386
937
  ```
387
938
  User: Show me any errors from nginx in the last hour
388
939
 
@@ -394,6 +945,7 @@ Found 3 error entries in nginx logs:
394
945
  ```
395
946
 
396
947
  ### Scout Tool - Remote File Access
948
+
397
949
  ```
398
950
  User: Read the nginx config on tootie
399
951
 
@@ -407,6 +959,7 @@ worker_processes auto;
407
959
  ```
408
960
 
409
961
  ### Scout Tool - ZFS Health Check
962
+
410
963
  ```
411
964
  User: Check ZFS pool health on dookie
412
965
 
@@ -419,6 +972,7 @@ backup - ONLINE | Size: 12TB | Free: 5.1TB | Health: 100%
419
972
  ```
420
973
 
421
974
  ### Scout Tool - System Logs
975
+
422
976
  ```
423
977
  User: Show me Docker service errors from systemd journal
424
978
 
@@ -431,26 +985,785 @@ Recent errors from docker.service:
431
985
  [15:42:15] containerd: connection error: desc = "transport: error while dialing"
432
986
  ```
433
987
 
434
- ## Security
435
-
436
- ### Path Traversal Protection (CWE-22)
988
+ ## Troubleshooting
437
989
 
438
- The `image_build` tool implements strict path validation to prevent directory traversal attacks:
990
+ Common issues and their solutions. For additional help, see the operational runbooks in `docs/runbooks/`.
439
991
 
440
- - **Absolute paths required**: All paths (context, dockerfile) must start with `/`
441
- - **Traversal blocked**: Paths containing `..` or `.` components are rejected
442
- - **Character validation**: Only alphanumeric, dots (in filenames), hyphens, underscores, and forward slashes allowed
443
- - **Pre-execution validation**: Paths validated before SSH commands are executed
992
+ ### Service Won't Start
444
993
 
445
- Example of rejected paths:
446
- ```bash
447
- # Rejected: Directory traversal
448
- ../../../etc/passwd
449
- /app/../../../etc/passwd
994
+ #### Port Already in Use
450
995
 
451
- # Rejected: Relative paths
452
- ./build
453
- relative/path
996
+ **Symptom:**
997
+
998
+ ```
999
+ Error: listen EADDRINUSE: address already in use :::53000
1000
+ ```
1001
+
1002
+ **Cause:** Another process is using port 53000 (HTTP mode) or stdout/stdin are not available (stdio mode).
1003
+
1004
+ **Solution:**
1005
+
1006
+ **For HTTP mode:**
1007
+
1008
+ ```bash
1009
+ # Find process using port 53000
1010
+ lsof -i :53000
1011
+ # or
1012
+ ss -tulpn | grep :53000
1013
+
1014
+ # Kill the process or change port
1015
+ SYNAPSE_PORT=53001 node dist/index.js --http
1016
+
1017
+ # Or set permanently
1018
+ export SYNAPSE_PORT=53001
1019
+ ```
1020
+
1021
+ **For stdio mode:**
1022
+
1023
+ ```bash
1024
+ # Check if running in terminal (stdio requires parent process)
1025
+ # Don't run stdio mode directly in terminal - use via MCP client only
1026
+ ```
1027
+
1028
+ #### Missing Dependencies
1029
+
1030
+ **Symptom:**
1031
+
1032
+ ```
1033
+ Error: Cannot find module '@modelcontextprotocol/sdk'
1034
+ ```
1035
+
1036
+ **Cause:** Dependencies not installed or node_modules corrupted.
1037
+
1038
+ **Solution:**
1039
+
1040
+ ```bash
1041
+ # Reinstall dependencies
1042
+ rm -rf node_modules pnpm-lock.yaml
1043
+ pnpm install
1044
+
1045
+ # Rebuild
1046
+ pnpm run build
1047
+
1048
+ # Verify installation
1049
+ pnpm list @modelcontextprotocol/sdk
1050
+ ```
1051
+
1052
+ #### Permission Denied on Startup
1053
+
1054
+ **Symptom:**
1055
+
1056
+ ```
1057
+ Error: EACCES: permission denied, open '/var/run/docker.sock'
1058
+ ```
1059
+
1060
+ **Cause:** User not in `docker` group.
1061
+
1062
+ **Solution:**
1063
+
1064
+ ```bash
1065
+ # Add user to docker group
1066
+ sudo usermod -aG docker $USER
1067
+
1068
+ # Log out and back in for group change to take effect
1069
+ # Or use newgrp to activate immediately
1070
+ newgrp docker
1071
+
1072
+ # Verify docker access
1073
+ docker ps
1074
+ ```
1075
+
1076
+ ---
1077
+
1078
+ ### SSH Connection Failures
1079
+
1080
+ #### Host Key Verification Failed
1081
+
1082
+ **Symptom:**
1083
+
1084
+ ```
1085
+ [SSH] [Host: production] Permission denied (publickey)
1086
+ # or
1087
+ Host key verification failed
1088
+ ```
1089
+
1090
+ **Cause:** SSH key not in `~/.ssh/known_hosts` or key mismatch.
1091
+
1092
+ **Solution:**
1093
+
1094
+ **Option 1: Pre-seed known_hosts (Recommended)**
1095
+
1096
+ ```bash
1097
+ # Add host key to known_hosts
1098
+ ssh-keyscan -H hostname >> ~/.ssh/known_hosts
1099
+
1100
+ # For all configured hosts
1101
+ for host in production staging dev; do
1102
+ ssh-keyscan -H $host >> ~/.ssh/known_hosts
1103
+ done
1104
+ ```
1105
+
1106
+ **Option 2: Manual verification**
1107
+
1108
+ ```bash
1109
+ # Connect manually first to accept key
1110
+ ssh user@hostname
1111
+
1112
+ # Verify fingerprint matches (check console/IPMI)
1113
+ ssh-keygen -l -f ~/.ssh/known_hosts | grep hostname
1114
+ ```
1115
+
1116
+ **Option 3: Remove stale key (if host key changed)**
1117
+
1118
+ ```bash
1119
+ # Remove old key
1120
+ ssh-keygen -R hostname
1121
+
1122
+ # Re-add current key
1123
+ ssh-keyscan -H hostname >> ~/.ssh/known_hosts
1124
+ ```
1125
+
1126
+ #### SSH Key Permission Errors
1127
+
1128
+ **Symptom:**
1129
+
1130
+ ```
1131
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1132
+ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @
1133
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1134
+ Permissions 0644 for '/home/user/.ssh/id_rsa' are too open.
1135
+ ```
1136
+
1137
+ **Cause:** SSH private key has insecure permissions.
1138
+
1139
+ **Solution:**
1140
+
1141
+ ```bash
1142
+ # Fix key permissions (required: 600)
1143
+ chmod 600 ~/.ssh/id_rsa
1144
+ chmod 600 ~/.ssh/id_ed25519
1145
+
1146
+ # Fix directory permissions
1147
+ chmod 700 ~/.ssh
1148
+
1149
+ # Verify
1150
+ ls -la ~/.ssh/
1151
+ # Should show: -rw------- for keys
1152
+ ```
1153
+
1154
+ #### Connection Timeout
1155
+
1156
+ **Symptom:**
1157
+
1158
+ ```
1159
+ [SSH] [Host: production] SSH command timeout after 5000ms
1160
+ ```
1161
+
1162
+ **Cause:** Network latency, firewall blocking, or host unreachable.
1163
+
1164
+ **Solution:**
1165
+
1166
+ **Increase timeout:**
1167
+
1168
+ ```bash
1169
+ # Set longer connection timeout (15 seconds)
1170
+ export SSH_POOL_CONNECTION_TIMEOUT_MS=15000
1171
+ node dist/index.js
1172
+ ```
1173
+
1174
+ **Check network connectivity:**
1175
+
1176
+ ```bash
1177
+ # Test SSH access manually
1178
+ ssh -v user@hostname
1179
+
1180
+ # Check network latency
1181
+ ping hostname
1182
+
1183
+ # Check firewall rules
1184
+ sudo ufw status
1185
+ # or
1186
+ sudo iptables -L
1187
+ ```
1188
+
1189
+ **Verify host is reachable:**
1190
+
1191
+ ```bash
1192
+ # Test basic connectivity
1193
+ nc -zv hostname 22
1194
+
1195
+ # Check if SSH daemon is running
1196
+ ssh user@hostname 'systemctl status sshd'
1197
+ ```
1198
+
1199
+ #### SSH Agent Not Running
1200
+
1201
+ **Symptom:**
1202
+
1203
+ ```
1204
+ Could not open a connection to your authentication agent
1205
+ ```
1206
+
1207
+ **Cause:** SSH agent not started or key not added.
1208
+
1209
+ **Solution:**
1210
+
1211
+ ```bash
1212
+ # Start SSH agent
1213
+ eval $(ssh-agent)
1214
+
1215
+ # Add key to agent
1216
+ ssh-add ~/.ssh/id_rsa
1217
+
1218
+ # Verify key is loaded
1219
+ ssh-add -l
1220
+
1221
+ # Add to shell startup (~/.bashrc or ~/.zshrc)
1222
+ if [ -z "$SSH_AUTH_SOCK" ]; then
1223
+ eval $(ssh-agent)
1224
+ ssh-add ~/.ssh/id_rsa
1225
+ fi
1226
+ ```
1227
+
1228
+ ---
1229
+
1230
+ ### Docker API Connection Errors
1231
+
1232
+ #### Socket Permission Denied
1233
+
1234
+ **Symptom:**
1235
+
1236
+ ```
1237
+ Error: connect EACCES /var/run/docker.sock
1238
+ ```
1239
+
1240
+ **Cause:** User not in `docker` group or socket permissions incorrect.
1241
+
1242
+ **Solution:**
1243
+
1244
+ **Add user to docker group:**
1245
+
1246
+ ```bash
1247
+ # Add current user
1248
+ sudo usermod -aG docker $USER
1249
+
1250
+ # Log out and back in
1251
+ # Verify group membership
1252
+ groups | grep docker
1253
+
1254
+ # Test docker access
1255
+ docker ps
1256
+ ```
1257
+
1258
+ **Check socket permissions:**
1259
+
1260
+ ```bash
1261
+ # Socket should be owned by docker group
1262
+ ls -la /var/run/docker.sock
1263
+ # Should show: srw-rw---- root docker
1264
+
1265
+ # If permissions wrong, fix ownership
1266
+ sudo chown root:docker /var/run/docker.sock
1267
+ sudo chmod 660 /var/run/docker.sock
1268
+ ```
1269
+
1270
+ #### Connection Refused
1271
+
1272
+ **Symptom:**
1273
+
1274
+ ```
1275
+ Error: connect ECONNREFUSED 192.168.1.100:2375
1276
+ ```
1277
+
1278
+ **Cause:** Docker daemon not running, wrong port, or firewall blocking.
1279
+
1280
+ **Solution:**
1281
+
1282
+ **Check Docker daemon status:**
1283
+
1284
+ ```bash
1285
+ # On target host
1286
+ systemctl status docker
1287
+
1288
+ # Start if not running
1289
+ sudo systemctl start docker
1290
+ sudo systemctl enable docker
1291
+ ```
1292
+
1293
+ **Verify Docker API port:**
1294
+
1295
+ ```bash
1296
+ # Check if Docker listening on expected port
1297
+ ss -tulpn | grep 2375
1298
+
1299
+ # If not exposed, edit daemon config
1300
+ sudo vi /etc/docker/daemon.json
1301
+ # Add: {"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]}
1302
+
1303
+ sudo systemctl restart docker
1304
+ ```
1305
+
1306
+ **Check firewall:**
1307
+
1308
+ ```bash
1309
+ # Allow Docker API port (if using HTTP protocol)
1310
+ sudo ufw allow from 192.168.1.0/24 to any port 2375
1311
+
1312
+ # Or specific IP only (more secure)
1313
+ sudo ufw allow from 192.168.1.10 to any port 2375
1314
+ ```
1315
+
1316
+ #### Docker Daemon Not Ready
1317
+
1318
+ **Symptom:**
1319
+
1320
+ ```
1321
+ Cannot connect to the Docker daemon. Is the docker daemon running?
1322
+ ```
1323
+
1324
+ **Cause:** Docker service not started or crashed.
1325
+
1326
+ **Solution:**
1327
+
1328
+ ```bash
1329
+ # Check status
1330
+ systemctl status docker
1331
+
1332
+ # View logs
1333
+ journalctl -u docker.service -n 50
1334
+
1335
+ # Restart daemon
1336
+ sudo systemctl restart docker
1337
+
1338
+ # Check for errors
1339
+ docker info
1340
+ ```
1341
+
1342
+ ---
1343
+
1344
+ ### High Latency Issues
1345
+
1346
+ #### Slow Container Discovery
1347
+
1348
+ **Symptom:** Container operations taking 5-30 seconds across multiple hosts.
1349
+
1350
+ **Cause:** Sequential host scanning without explicit `host` parameter.
1351
+
1352
+ **Solution:**
1353
+
1354
+ **Always specify host when known:**
1355
+
1356
+ ```json
1357
+ // Instead of:
1358
+ { "action": "container", "subaction": "start", "container_id": "plex" }
1359
+
1360
+ // Use:
1361
+ { "action": "container", "subaction": "start", "container_id": "plex", "host": "production" }
1362
+ ```
1363
+
1364
+ **Reduce host count:**
1365
+
1366
+ ```bash
1367
+ # Split large deployments into multiple MCP instances
1368
+ # Production hosts: synapse-mcp-prod
1369
+ # Development hosts: synapse-mcp-dev
1370
+ ```
1371
+
1372
+ **Increase connection pool:**
1373
+
1374
+ ```bash
1375
+ export SSH_POOL_MAX_CONNECTIONS=10
1376
+ node dist/index.js
1377
+ ```
1378
+
1379
+ #### Slow Configuration Loading
1380
+
1381
+ **Symptom:** Every request takes 5-10ms longer than expected.
1382
+
1383
+ **Cause:** Config loaded synchronously on every request (PERF-C1).
1384
+
1385
+ **Solution:**
1386
+
1387
+ **Optimize config file size:**
1388
+
1389
+ ```bash
1390
+ # Keep config under 10KB
1391
+ # Split large host lists into multiple files
1392
+
1393
+ # Use SSH config auto-discovery instead
1394
+ # (parsed once at startup)
1395
+ ```
1396
+
1397
+ **Use SSH config auto-discovery:**
1398
+
1399
+ ```ssh-config
1400
+ # ~/.ssh/config
1401
+ Host production
1402
+ HostName 192.168.1.100
1403
+ User admin
1404
+ IdentityFile ~/.ssh/id_rsa
1405
+
1406
+ # No manual synapse.config.json needed
1407
+ ```
1408
+
1409
+ #### Network Latency
1410
+
1411
+ **Symptom:** Operations on remote hosts much slower than local.
1412
+
1413
+ **Cause:** High network latency (>50ms).
1414
+
1415
+ **Solution:**
1416
+
1417
+ **Increase timeouts for slow networks:**
1418
+
1419
+ ```bash
1420
+ export SSH_POOL_CONNECTION_TIMEOUT_MS=15000 # 15s
1421
+ export SSH_POOL_IDLE_TIMEOUT_MS=120000 # 2min
1422
+ ```
1423
+
1424
+ **Use local cache more aggressively:**
1425
+
1426
+ ```bash
1427
+ export COMPOSE_CACHE_TTL_HOURS=48 # 2 days
1428
+ ```
1429
+
1430
+ **Deploy MCP server closer to hosts:**
1431
+
1432
+ ```bash
1433
+ # Run synapse-mcp on same network segment as managed hosts
1434
+ # Or use VPN to reduce latency
1435
+ ```
1436
+
1437
+ ---
1438
+
1439
+ ### Container Not Found Errors
1440
+
1441
+ #### Container ID Too Short
1442
+
1443
+ **Symptom:**
1444
+
1445
+ ```
1446
+ Container "abc" not found on any host
1447
+ ```
1448
+
1449
+ **Cause:** Multiple containers match short prefix, or ID doesn't exist.
1450
+
1451
+ **Solution:**
1452
+
1453
+ **Use longer container ID:**
1454
+
1455
+ ```json
1456
+ // Instead of:
1457
+ { "container_id": "abc" }
1458
+
1459
+ // Use at least 8 characters:
1460
+ { "container_id": "abc12345" }
1461
+ ```
1462
+
1463
+ **Use container name:**
1464
+
1465
+ ```json
1466
+ { "container_id": "plex" }
1467
+ ```
1468
+
1469
+ **List all containers to find correct ID:**
1470
+
1471
+ ```json
1472
+ { "action": "container", "subaction": "list", "state": "all" }
1473
+ ```
1474
+
1475
+ #### Container on Unexpected Host
1476
+
1477
+ **Symptom:** Container exists but not found by auto-discovery.
1478
+
1479
+ **Cause:** Discovery timeout before reaching correct host.
1480
+
1481
+ **Solution:**
1482
+
1483
+ **Specify host explicitly:**
1484
+
1485
+ ```json
1486
+ {
1487
+ "action": "container",
1488
+ "subaction": "start",
1489
+ "container_id": "plex",
1490
+ "host": "media-server"
1491
+ }
1492
+ ```
1493
+
1494
+ **Increase discovery timeout:**
1495
+
1496
+ ```bash
1497
+ # Increase SSH connection timeout
1498
+ export SSH_POOL_CONNECTION_TIMEOUT_MS=10000
1499
+ ```
1500
+
1501
+ **Check host is reachable:**
1502
+
1503
+ ```bash
1504
+ ssh user@hostname docker ps
1505
+ ```
1506
+
1507
+ ---
1508
+
1509
+ ### Compose Project Not Detected
1510
+
1511
+ #### Project Not in Cache
1512
+
1513
+ **Symptom:**
1514
+
1515
+ ```
1516
+ Project "media-stack" not found on any configured host
1517
+ ```
1518
+
1519
+ **Cause:** Cache miss, project in non-standard location, or project name mismatch.
1520
+
1521
+ **Solution:**
1522
+
1523
+ **Refresh cache:**
1524
+
1525
+ ```json
1526
+ { "action": "compose", "subaction": "refresh" }
1527
+ ```
1528
+
1529
+ **Check actual project name:**
1530
+
1531
+ ```bash
1532
+ # SSH to host
1533
+ docker compose ls
1534
+
1535
+ # Or check compose.yaml
1536
+ cat /path/to/compose.yaml | grep "^name:"
1537
+ ```
1538
+
1539
+ **Add search path to host config:**
1540
+
1541
+ ```json
1542
+ {
1543
+ "name": "production",
1544
+ "host": "192.168.1.100",
1545
+ "protocol": "ssh",
1546
+ "sshUser": "admin",
1547
+ "composeSearchPaths": [
1548
+ "/compose",
1549
+ "/opt/stacks", // Add custom path
1550
+ "/srv/docker" // Add another path
1551
+ ]
1552
+ }
1553
+ ```
1554
+
1555
+ **Specify explicit path (bypass discovery):**
1556
+
1557
+ ```json
1558
+ {
1559
+ "action": "compose",
1560
+ "subaction": "up",
1561
+ "project": "media-stack",
1562
+ "host": "production",
1563
+ "path": "/opt/stacks/media" // Explicit path
1564
+ }
1565
+ ```
1566
+
1567
+ #### Stopped Project Not Found
1568
+
1569
+ **Symptom:** Project exists but not detected by `docker compose ls`.
1570
+
1571
+ **Cause:** `docker compose ls` only shows running projects.
1572
+
1573
+ **Solution:**
1574
+
1575
+ **Force filesystem scan:**
1576
+
1577
+ ```json
1578
+ // Refresh cache triggers full scan
1579
+ { "action": "compose", "subaction": "refresh" }
1580
+ ```
1581
+
1582
+ **Or use explicit path:**
1583
+
1584
+ ```json
1585
+ {
1586
+ "action": "compose",
1587
+ "subaction": "up",
1588
+ "path": "/path/to/project",
1589
+ "host": "production"
1590
+ }
1591
+ ```
1592
+
1593
+ #### Search Depth Too Shallow
1594
+
1595
+ **Symptom:** Deeply nested compose projects not found.
1596
+
1597
+ **Cause:** Default max depth is 3 levels.
1598
+
1599
+ **Solution:**
1600
+
1601
+ **Organize projects at shallower depth:**
1602
+
1603
+ ```bash
1604
+ # Instead of:
1605
+ /compose/apps/production/services/media/plex/
1606
+
1607
+ # Use:
1608
+ /compose/media-plex/
1609
+ ```
1610
+
1611
+ **Or manually add specific paths:**
1612
+
1613
+ ```json
1614
+ {
1615
+ "composeSearchPaths": ["/compose/apps/production/services/media/plex"]
1616
+ }
1617
+ ```
1618
+
1619
+ ---
1620
+
1621
+ ### Debug Logging
1622
+
1623
+ Enable detailed logging for troubleshooting:
1624
+
1625
+ **Enable all debug output:**
1626
+
1627
+ ```bash
1628
+ DEBUG=* node dist/index.js 2>debug.log
1629
+ ```
1630
+
1631
+ **Enable specific namespaces:**
1632
+
1633
+ ```bash
1634
+ # SSH operations only
1635
+ DEBUG=synapse:ssh node dist/index.js
1636
+
1637
+ # Docker operations only
1638
+ DEBUG=synapse:docker node dist/index.js
1639
+
1640
+ # Multiple namespaces
1641
+ DEBUG=synapse:ssh,synapse:docker node dist/index.js
1642
+ ```
1643
+
1644
+ **Increase log level:**
1645
+
1646
+ ```bash
1647
+ export LOG_LEVEL=debug
1648
+ node dist/index.js
1649
+ ```
1650
+
1651
+ **Monitor logs in real-time:**
1652
+
1653
+ ```bash
1654
+ # Systemd service
1655
+ journalctl -u synapse-mcp.service -f
1656
+
1657
+ # Or write to file
1658
+ node dist/index.js 2>&1 | tee -a synapse.log
1659
+ ```
1660
+
1661
+ ---
1662
+
1663
+ ### Getting Help
1664
+
1665
+ If you can't resolve the issue:
1666
+
1667
+ 1. **Check logs:**
1668
+
1669
+ ```bash
1670
+ journalctl -u synapse-mcp.service -n 100
1671
+ ```
1672
+
1673
+ 2. **Review runbooks:** See `docs/runbooks/` for detailed procedures
1674
+
1675
+ 3. **Check docs/SECURITY.md:** For security-related issues
1676
+
1677
+ 4. **Open GitHub issue:** Include:
1678
+ - Error message and full stack trace
1679
+ - Steps to reproduce
1680
+ - Environment details (Node version, OS, host count)
1681
+ - Relevant config (redact sensitive info)
1682
+
1683
+ 5. **Community support:** Tag maintainers in issues for faster response
1684
+
1685
+ ## Security
1686
+
1687
+ ### HTTP Transport Authentication
1688
+
1689
+ HTTP `POST /mcp` always requires the `X-Synapse-Client` header for CSRF protection.
1690
+ API key authentication is enabled only when `SYNAPSE_API_KEY` is set.
1691
+
1692
+ ```bash
1693
+ # Enable API key authentication
1694
+ export SYNAPSE_API_KEY="your-secret-key-here" # Recommended: 32+ characters
1695
+
1696
+ # Start server with HTTP transport
1697
+ node dist/index.js --transport http
1698
+ ```
1699
+
1700
+ If `SYNAPSE_API_KEY` is not set, requests are allowed without `X-API-Key` (local/dev behavior).
1701
+
1702
+ **Required Headers:**
1703
+
1704
+ - **X-Synapse-Client**: Always required (for CSRF protection)
1705
+ - **X-API-Key**: Required when `SYNAPSE_API_KEY` is configured
1706
+
1707
+ **Security Features:**
1708
+
1709
+ - Timing-safe comparison prevents timing attacks
1710
+ - CSRF protection blocks cross-origin requests without proper headers
1711
+ - 100KB body size limit prevents DoS attacks
1712
+
1713
+ **Example Request (API key enabled):**
1714
+
1715
+ ```bash
1716
+ curl -X POST "http://127.0.0.1:53000/mcp" \
1717
+ -H "Content-Type: application/json" \
1718
+ -H "X-Synapse-Client: mcp" \
1719
+ -H "X-API-Key: your-secret-key-here" \
1720
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
1721
+ ```
1722
+
1723
+ **Example Request (local/dev, no API key configured):**
1724
+
1725
+ ```bash
1726
+ unset SYNAPSE_API_KEY
1727
+ node dist/index.js --transport http
1728
+
1729
+ curl -X POST "http://127.0.0.1:53000/mcp" \
1730
+ -H "Content-Type: application/json" \
1731
+ -H "X-Synapse-Client: mcp" \
1732
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
1733
+ ```
1734
+
1735
+ ### Command Allowlist (CWE-78)
1736
+
1737
+ Scout `exec` operations are restricted to a curated allowlist of read-only commands:
1738
+
1739
+ **Allowed commands:** `df`, `uptime`, `hostname`, `uname`, `ps`, `free`, `top`, `htop`, `netstat`, `ss`, `lsof`, `systemctl status`, `journalctl`, `dmesg`, `tail`, `cat`, `grep` (and more - see `src/config/command-allowlist.json`)
1740
+
1741
+ **Security guarantees:**
1742
+
1743
+ - No destructive operations allowed
1744
+ - Shell argument escaping prevents injection
1745
+ - No environment variable bypass available
1746
+ - All commands validated before execution
1747
+
1748
+ ### Path Traversal Protection (CWE-22)
1749
+
1750
+ The `image_build` tool implements strict path validation to prevent directory traversal attacks:
1751
+
1752
+ - **Absolute paths required**: All paths (context, dockerfile) must start with `/`
1753
+ - **Traversal blocked**: Paths containing `..` or `.` components are rejected
1754
+ - **Character validation**: Only alphanumeric, dots (in filenames), hyphens, underscores, and forward slashes allowed
1755
+ - **Pre-execution validation**: Paths validated before SSH commands are executed
1756
+
1757
+ Example of rejected paths:
1758
+
1759
+ ```bash
1760
+ # Rejected: Directory traversal
1761
+ ../../../etc/passwd
1762
+ /app/../../../etc/passwd
1763
+
1764
+ # Rejected: Relative paths
1765
+ ./build
1766
+ relative/path
454
1767
 
455
1768
  # Accepted: Absolute paths without traversal
456
1769
  /home/user/docker/build
@@ -479,12 +1792,53 @@ pnpm test
479
1792
  # Run tests with coverage
480
1793
  pnpm run test:coverage
481
1794
 
1795
+ # Run performance benchmarks (opt-in)
1796
+ RUN_SSH_BENCHMARKS=true pnpm test src/services/ssh-pool.benchmark.test.ts
1797
+ RUN_CACHE_BENCHMARKS=true pnpm test src/services/cache-layer.benchmark.test.ts
1798
+
482
1799
  # Test with MCP Inspector
483
1800
  npx @modelcontextprotocol/inspector node dist/index.js
484
1801
  ```
485
1802
 
486
1803
  ## Architecture
487
1804
 
1805
+ ### Core Components
1806
+
1807
+ **Event System** (`src/events/`)
1808
+
1809
+ - Type-safe EventEmitter with discriminated unions
1810
+ - Events: `container_state_changed`, `cache_invalidated`
1811
+ - Decouples cross-cutting concerns (cache invalidation, audit trail, metrics)
1812
+
1813
+ **Lifecycle Management** (`src/services/container.ts`)
1814
+
1815
+ - State machine: `uninitialized` → `initializing` → `ready` → `shutting_down` → `shutdown`
1816
+ - Hooks: `initialize()`, `healthCheck()`, `shutdown()`
1817
+ - Graceful cleanup on process termination
1818
+
1819
+ **Tool Registry** (`src/tools/registry.ts`)
1820
+
1821
+ - Plugin-style tool registration
1822
+ - Zero modification required to add new tools
1823
+ - Declarative tool definitions in `src/tools/definitions/`
1824
+
1825
+ **Formatter Strategy** (`src/formatters/strategy.ts`)
1826
+
1827
+ - `IFormatter` interface for output formats
1828
+ - Implementations: `MarkdownFormatter`, `JSONFormatter`
1829
+ - `FormatterFactory` for format selection
1830
+ - Open/Closed Principle: Add formats without modifying handlers
1831
+
1832
+ **For detailed architecture documentation**, see:
1833
+
1834
+ - `src/services/LIFECYCLE.md` - Lifecycle management guide
1835
+ - `src/tools/EXTENDING.md` - Tool extension guide
1836
+ - `src/formatters/EXTENDING.md` - Formatter extension guide
1837
+ - `docs/HANDLERS.md` - Handler patterns and implementation guidance
1838
+ - `docs/TRANSPORTS.md` - Transport options (`stdio`, HTTP, SSH `stdio`, Tailscale Serve)
1839
+
1840
+ ### Directory Structure
1841
+
488
1842
  ```
489
1843
  synapse-mcp/
490
1844
  ├── src/
@@ -530,30 +1884,35 @@ synapse-mcp/
530
1884
  ### Key Architectural Decisions
531
1885
 
532
1886
  **V3 Schema Refactor - Two Tools Pattern**:
533
- - **Flux**: 4 actions (container, compose, docker, host) with 39 total subactions
1887
+
1888
+ - **Flux**: 5 actions (help, container, compose, docker, host) with 41 total subactions
534
1889
  - **Scout**: 11 actions (9 simple + 2 with subactions) for 16 total operations
535
1890
  - Clean separation: Flux = Docker/state changes, Scout = SSH/read operations
536
- - Total: 55 discriminator keys across both tools
1891
+ - Total: 57 operations across both tools
537
1892
 
538
1893
  **Discriminated Union for O(1) Validation**:
539
- - **Flux**: Composite `action_subaction` discriminator (`container:list`, `compose:up`, etc.)
1894
+
1895
+ - **Flux**: `action` + `subaction` fields with per-action nested discriminated unions
540
1896
  - **Scout**: Primary `action` discriminator with nested discriminators for `zfs` and `logs`
541
1897
  - Validation latency: <0.005ms average across all operations
542
1898
  - Zero performance degradation regardless of which operation is called
543
1899
 
544
1900
  **Help System**:
1901
+
545
1902
  - Auto-generated help handlers for both tools
546
1903
  - Introspects Zod schemas using `.describe()` metadata
547
1904
  - Supports topic-specific help (e.g., `flux help container:logs`)
548
1905
  - Available in markdown or JSON format
549
1906
 
550
1907
  **SSH Connection Pooling**:
1908
+
551
1909
  - 50× faster for repeated operations
552
1910
  - Automatic idle timeout and health checks
553
1911
  - Configurable pool size and connection reuse
554
1912
  - Transparent integration (no code changes required)
555
1913
 
556
1914
  **Test Coverage**:
1915
+
557
1916
  - Unit tests for all services, schemas, and tools
558
1917
  - Integration tests for end-to-end workflows
559
1918
  - Performance benchmarks for schema validation
@@ -563,15 +1922,13 @@ synapse-mcp/
563
1922
 
564
1923
  ### Schema Validation
565
1924
 
566
- Both Flux and Scout tools use Zod discriminated union for O(1) constant-time schema validation:
1925
+ Both Flux and Scout tools use Zod discriminated unions for constant-time schema dispatch:
567
1926
 
568
- - **Validation latency**: <0.005ms average across all 55 operations
569
- - **Flux optimization**: Composite `action_subaction` discriminator with preprocessor
1927
+ - **Validation latency**: <0.005ms average across all operations
1928
+ - **Flux optimization**: `action` + `subaction` with nested `subaction` discriminators
570
1929
  - **Scout optimization**: Primary `action` discriminator with nested discriminators for zfs/logs
571
1930
  - **Consistency**: All operations perform identically fast (no worst-case scenarios)
572
1931
 
573
- Flux inputs are automatically preprocessed to inject the `action_subaction` discriminator key.
574
-
575
1932
  ### SSH Connection Pooling
576
1933
 
577
1934
  All SSH operations use connection pooling for optimal performance:
@@ -584,6 +1941,7 @@ All SSH operations use connection pooling for optimal performance:
584
1941
  See [docs/ssh-connection-pooling.md](docs/ssh-connection-pooling.md) for details.
585
1942
 
586
1943
  **Key Benefits:**
1944
+
587
1945
  - Eliminate 250ms connection overhead per operation
588
1946
  - Support high-concurrency scenarios (configurable pool size)
589
1947
  - Automatic connection cleanup and health monitoring
@@ -598,10 +1956,325 @@ npm run test:bench
598
1956
  ```
599
1957
 
600
1958
  Expected results:
1959
+
601
1960
  - Worst-case validation: <0.005ms (0.003ms typical)
602
1961
  - Average-case validation: <0.005ms (0.003ms typical)
603
1962
  - Performance variance: <0.001ms (proves O(1) consistency)
604
1963
 
1964
+ ## Troubleshooting
1965
+
1966
+ ### Common Issues
1967
+
1968
+ #### "Cannot connect to Docker socket"
1969
+
1970
+ **Symptoms:**
1971
+
1972
+ - Error: `connect EACCES /var/run/docker.sock`
1973
+ - Error: `connect ENOENT /var/run/docker.sock`
1974
+
1975
+ **Solutions:**
1976
+
1977
+ 1. **Permissions** - Add your user to the docker group:
1978
+
1979
+ ```bash
1980
+ sudo usermod -aG docker $USER
1981
+ newgrp docker # Apply without logout
1982
+ ```
1983
+
1984
+ 2. **Socket path** - Check if Docker socket exists:
1985
+
1986
+ ```bash
1987
+ ls -la /var/run/docker.sock
1988
+ # If not found, Docker may not be installed or running
1989
+ sudo systemctl status docker
1990
+ ```
1991
+
1992
+ 3. **Docker not running** - Start Docker daemon:
1993
+ ```bash
1994
+ sudo systemctl start docker
1995
+ sudo systemctl enable docker # Start on boot
1996
+ ```
1997
+
1998
+ #### "SSH connection failed" / "All configured authentication methods failed"
1999
+
2000
+ **Symptoms:**
2001
+
2002
+ - Error: `HostOperationError: SSH connection failed`
2003
+ - Operations timeout on remote hosts
2004
+
2005
+ **Solutions:**
2006
+
2007
+ 1. **Test SSH manually** - Verify SSH access works:
2008
+
2009
+ ```bash
2010
+ ssh -i ~/.ssh/id_rsa user@hostname
2011
+ # Should connect without password prompt
2012
+ ```
2013
+
2014
+ 2. **Check SSH key permissions** - Keys must not be world-readable:
2015
+
2016
+ ```bash
2017
+ chmod 600 ~/.ssh/id_rsa
2018
+ chmod 644 ~/.ssh/id_rsa.pub
2019
+ ```
2020
+
2021
+ 3. **Verify host config** - Ensure `sshUser` and `sshKeyPath` are correct:
2022
+
2023
+ ```json
2024
+ {
2025
+ "name": "remote",
2026
+ "host": "192.168.1.100",
2027
+ "protocol": "ssh",
2028
+ "sshUser": "admin",
2029
+ "sshKeyPath": "~/.ssh/id_rsa" // or absolute: "/home/user/.ssh/id_rsa"
2030
+ }
2031
+ ```
2032
+
2033
+ 4. **SSH agent** - If using SSH agent, ensure key is loaded:
2034
+ ```bash
2035
+ ssh-add -l # List loaded keys
2036
+ ssh-add ~/.ssh/id_rsa # Add if missing
2037
+ ```
2038
+
2039
+ #### "Docker Compose project not found"
2040
+
2041
+ **Symptoms:**
2042
+
2043
+ - Error: `No Docker Compose projects found on host`
2044
+ - Expected projects don't appear in listings
2045
+
2046
+ **Solutions:**
2047
+
2048
+ 1. **Check search paths** - Add custom compose paths to config:
2049
+
2050
+ ```json
2051
+ {
2052
+ "name": "myhost",
2053
+ "composeSearchPaths": ["/opt/appdata", "/mnt/docker", "/home/user/compose"]
2054
+ }
2055
+ ```
2056
+
2057
+ 2. **Verify compose files exist** - SSH to host and check:
2058
+
2059
+ ```bash
2060
+ find /path/to/search -name "docker-compose.y*ml" -o -name "compose.y*ml"
2061
+ ```
2062
+
2063
+ 3. **Force cache refresh** - Use the refresh subaction:
2064
+
2065
+ ```json
2066
+ { "action": "compose", "subaction": "refresh", "host": "myhost" }
2067
+ ```
2068
+
2069
+ 4. **Check file permissions** - Ensure compose files are readable:
2070
+ ```bash
2071
+ ls -la /path/to/docker-compose.yml
2072
+ # Should show -rw-r--r-- (at minimum)
2073
+ ```
2074
+
2075
+ #### "Operation timed out"
2076
+
2077
+ **Symptoms:**
2078
+
2079
+ - Requests hang for 30+ seconds then fail
2080
+ - Stats collection fails intermittently
2081
+
2082
+ **Solutions:**
2083
+
2084
+ 1. **Check host connectivity** - Test network latency:
2085
+
2086
+ ```bash
2087
+ ping -c 4 hostname
2088
+ # Should show <50ms latency for local network
2089
+ ```
2090
+
2091
+ 2. **Docker daemon responsive** - Check if Docker is overloaded:
2092
+
2093
+ ```bash
2094
+ ssh user@host "docker ps" # Should respond in <1s
2095
+ ```
2096
+
2097
+ 3. **Reduce parallelism** - Query hosts sequentially instead of "all":
2098
+ ```json
2099
+ { "action": "container", "subaction": "list", "host": "specific-host" }
2100
+ ```
2101
+
2102
+ #### "Command not in allowed list"
2103
+
2104
+ **Symptoms:**
2105
+
2106
+ - Error: `Command 'X' not in allowed list`
2107
+ - Container exec or Scout commands fail
2108
+
2109
+ **Solutions:**
2110
+
2111
+ 1. **Use allowed commands only** - Check the allowlist:
2112
+
2113
+ <!-- prettier-ignore -->
2114
+ ```typescript
2115
+ // Allowed commands (src/constants.ts):
2116
+ [
2117
+ "docker",
2118
+ "docker-compose",
2119
+ "systemctl",
2120
+ "cat",
2121
+ "head",
2122
+ "tail",
2123
+ "grep",
2124
+ "rg",
2125
+ "find",
2126
+ "ls",
2127
+ "tree",
2128
+ "wc",
2129
+ "sort",
2130
+ "uniq",
2131
+ "diff",
2132
+ "stat",
2133
+ "file",
2134
+ "du",
2135
+ "df",
2136
+ "pwd",
2137
+ "hostname",
2138
+ "uptime",
2139
+ "whoami"
2140
+ ]
2141
+ ```
2142
+
2143
+ 2. **Development bypass** - For testing only (NOT production):
2144
+
2145
+ ```bash
2146
+ export NODE_ENV=development
2147
+ export SYNAPSE_ALLOW_ANY_COMMAND=true
2148
+ # Restart server
2149
+ ```
2150
+
2151
+ 3. **Request addition** - If command is needed, open an issue with:
2152
+ - Command name and purpose
2153
+ - Security justification
2154
+ - Example use cases
2155
+
2156
+ ### Diagnostic Steps
2157
+
2158
+ #### 1. Check MCP Server Logs
2159
+
2160
+ ```bash
2161
+ # If running via stdio
2162
+ tail -f ~/.mcp/logs/synapse-mcp.log
2163
+
2164
+ # If running via HTTP
2165
+ curl http://localhost:53001/health
2166
+ ```
2167
+
2168
+ #### 2. Test Host Configuration
2169
+
2170
+ ```bash
2171
+ # Test Docker API connection
2172
+ docker -H ssh://user@host ps
2173
+
2174
+ # Test SSH command execution
2175
+ ssh user@host "docker ps"
2176
+
2177
+ # Test Docker Compose
2178
+ ssh user@host "docker compose -f /path/to/compose.yml ps"
2179
+ ```
2180
+
2181
+ #### 3. Validate Configuration
2182
+
2183
+ ```bash
2184
+ # Check config file syntax
2185
+ cat ~/.config/synapse-mcp/config.json | jq .
2186
+
2187
+ # Verify paths exist
2188
+ ls -la ~/.ssh/id_rsa
2189
+ ls -la /var/run/docker.sock
2190
+ ```
2191
+
2192
+ #### 4. Enable Debug Logging
2193
+
2194
+ ```bash
2195
+ # Set environment variable
2196
+ export DEBUG=synapse:*
2197
+ # Or for specific modules
2198
+ export DEBUG=synapse:ssh,synapse:docker
2199
+
2200
+ # Restart server to see detailed logs
2201
+ ```
2202
+
2203
+ ### Recovery Procedures
2204
+
2205
+ #### Service Down
2206
+
2207
+ 1. **Check process** - Ensure server is running:
2208
+
2209
+ ```bash
2210
+ ps aux | grep synapse-mcp
2211
+ ```
2212
+
2213
+ 2. **Restart server** - Restart via your MCP client (Claude Code):
2214
+ - Restart Claude Code application
2215
+ - Or restart specific MCP server from settings
2216
+
2217
+ 3. **Check config** - Validate JSON syntax:
2218
+ ```bash
2219
+ jq . ~/.config/synapse-mcp/config.json
2220
+ # Should output formatted JSON (no errors)
2221
+ ```
2222
+
2223
+ #### High Error Rate
2224
+
2225
+ 1. **Check Docker health** - All hosts:
2226
+
2227
+ ```bash
2228
+ for host in host1 host2 host3; do
2229
+ ssh user@$host "docker info"
2230
+ done
2231
+ ```
2232
+
2233
+ 2. **Reduce load** - Limit concurrent operations:
2234
+ - Use specific host instead of "all"
2235
+ - Add delays between operations
2236
+ - Reduce pagination limits
2237
+
2238
+ 3. **Clear cache** - Force SSH connection pool reset:
2239
+ ```bash
2240
+ # Restart server (closes all connections)
2241
+ # Connections will be recreated on demand
2242
+ ```
2243
+
2244
+ #### Rollback Procedure
2245
+
2246
+ If an update causes issues:
2247
+
2248
+ 1. **Check version** - Note current version:
2249
+
2250
+ ```bash
2251
+ cd ~/path/to/synapse-mcp
2252
+ git log --oneline -1
2253
+ ```
2254
+
2255
+ 2. **Rollback** - Revert to previous working version:
2256
+
2257
+ ```bash
2258
+ git log --oneline -10 # Find last working commit
2259
+ git checkout <commit-hash>
2260
+ pnpm install
2261
+ pnpm run build
2262
+ ```
2263
+
2264
+ 3. **Restart** - Restart MCP server in Claude Code
2265
+
2266
+ 4. **Report issue** - Open GitHub issue with:
2267
+ - Version that failed
2268
+ - Error messages
2269
+ - Steps to reproduce
2270
+
2271
+ ### Getting Help
2272
+
2273
+ - **GitHub Issues**: https://github.com/anthropics/claude-code/issues
2274
+ - **Documentation**: See `.docs/` directory for detailed architecture docs
2275
+ - **Transport setup**: See `docs/TRANSPORTS.md` for secure local/remote connection patterns
2276
+ - **Logs**: Check `~/.mcp/logs/` for detailed error traces
2277
+
605
2278
  ## License
606
2279
 
607
2280
  MIT