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.
- package/README.md +1820 -147
- package/dist/constants.d.ts +10 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +18 -8
- package/dist/constants.js.map +1 -1
- package/dist/events/emitter.d.ts +63 -0
- package/dist/events/emitter.d.ts.map +1 -0
- package/dist/events/emitter.js +112 -0
- package/dist/events/emitter.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +51 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +3 -0
- package/dist/events/types.js.map +1 -0
- package/dist/formatters/compose.d.ts +185 -0
- package/dist/formatters/compose.d.ts.map +1 -0
- package/dist/formatters/compose.js +397 -0
- package/dist/formatters/compose.js.map +1 -0
- package/dist/formatters/container.d.ts +84 -0
- package/dist/formatters/container.d.ts.map +1 -0
- package/dist/formatters/container.js +323 -0
- package/dist/formatters/container.js.map +1 -0
- package/dist/formatters/diagnostics.d.ts +20 -0
- package/dist/formatters/diagnostics.d.ts.map +1 -0
- package/dist/formatters/diagnostics.js +73 -0
- package/dist/formatters/diagnostics.js.map +1 -0
- package/dist/formatters/docker.d.ts +139 -0
- package/dist/formatters/docker.d.ts.map +1 -0
- package/dist/formatters/docker.js +216 -0
- package/dist/formatters/docker.js.map +1 -0
- package/dist/formatters/host.d.ts +137 -0
- package/dist/formatters/host.d.ts.map +1 -0
- package/dist/formatters/host.js +198 -0
- package/dist/formatters/host.js.map +1 -0
- package/dist/formatters/index.d.ts +17 -270
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +21 -456
- package/dist/formatters/index.js.map +1 -1
- package/dist/formatters/scout.d.ts +424 -0
- package/dist/formatters/scout.d.ts.map +1 -0
- package/dist/formatters/scout.js +687 -0
- package/dist/formatters/scout.js.map +1 -0
- package/dist/formatters/strategy.d.ts +105 -0
- package/dist/formatters/strategy.d.ts.map +1 -0
- package/dist/formatters/strategy.js +120 -0
- package/dist/formatters/strategy.js.map +1 -0
- package/dist/formatters/utils.d.ts +84 -0
- package/dist/formatters/utils.d.ts.map +1 -0
- package/dist/formatters/utils.js +129 -0
- package/dist/formatters/utils.js.map +1 -0
- package/dist/health-rate-limiter.d.ts +59 -0
- package/dist/health-rate-limiter.d.ts.map +1 -0
- package/dist/health-rate-limiter.js +159 -0
- package/dist/health-rate-limiter.js.map +1 -0
- package/dist/index.js +61 -100
- package/dist/index.js.map +1 -1
- package/dist/middleware/async-handler.d.ts +62 -0
- package/dist/middleware/async-handler.d.ts.map +1 -0
- package/dist/middleware/async-handler.js +58 -0
- package/dist/middleware/async-handler.js.map +1 -0
- package/dist/middleware/auth.d.ts +32 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +63 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/csrf-protection.d.ts +58 -0
- package/dist/middleware/csrf-protection.d.ts.map +1 -0
- package/dist/middleware/csrf-protection.js +123 -0
- package/dist/middleware/csrf-protection.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +49 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +90 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/error-mapper.d.ts +44 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -0
- package/dist/middleware/error-mapper.js +127 -0
- package/dist/middleware/error-mapper.js.map +1 -0
- package/dist/middleware/index.d.ts +13 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +13 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/request-id.d.ts +22 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +31 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/types.d.ts +33 -0
- package/dist/middleware/types.d.ts.map +1 -0
- package/dist/middleware/types.js +2 -0
- package/dist/middleware/types.js.map +1 -0
- package/dist/schemas/common.d.ts +205 -8
- package/dist/schemas/common.d.ts.map +1 -1
- package/dist/schemas/common.js +290 -17
- package/dist/schemas/common.js.map +1 -1
- package/dist/schemas/flux/compose.d.ts +307 -44
- package/dist/schemas/flux/compose.d.ts.map +1 -1
- package/dist/schemas/flux/compose.js +74 -48
- package/dist/schemas/flux/compose.js.map +1 -1
- package/dist/schemas/flux/container.d.ts +423 -56
- package/dist/schemas/flux/container.d.ts.map +1 -1
- package/dist/schemas/flux/container.js +83 -61
- package/dist/schemas/flux/container.js.map +1 -1
- package/dist/schemas/flux/docker.d.ts +254 -37
- package/dist/schemas/flux/docker.d.ts.map +1 -1
- package/dist/schemas/flux/docker.js +69 -39
- package/dist/schemas/flux/docker.js.map +1 -1
- package/dist/schemas/flux/host.d.ts +312 -29
- package/dist/schemas/flux/host.d.ts.map +1 -1
- package/dist/schemas/flux/host.js +74 -31
- package/dist/schemas/flux/host.js.map +1 -1
- package/dist/schemas/flux/index.d.ts +503 -11
- package/dist/schemas/flux/index.d.ts.map +1 -1
- package/dist/schemas/flux/index.js +34 -70
- package/dist/schemas/flux/index.js.map +1 -1
- package/dist/schemas/host-config.d.ts +76 -0
- package/dist/schemas/host-config.d.ts.map +1 -0
- package/dist/schemas/host-config.js +105 -0
- package/dist/schemas/host-config.js.map +1 -0
- package/dist/schemas/scout/index.d.ts +80 -23
- package/dist/schemas/scout/index.d.ts.map +1 -1
- package/dist/schemas/scout/index.js +26 -11
- package/dist/schemas/scout/index.js.map +1 -1
- package/dist/schemas/scout/logs.d.ts +17 -5
- package/dist/schemas/scout/logs.d.ts.map +1 -1
- package/dist/schemas/scout/logs.js +41 -31
- package/dist/schemas/scout/logs.js.map +1 -1
- package/dist/schemas/scout/simple.d.ts +126 -11
- package/dist/schemas/scout/simple.d.ts.map +1 -1
- package/dist/schemas/scout/simple.js +112 -57
- package/dist/schemas/scout/simple.js.map +1 -1
- package/dist/schemas/scout/zfs.d.ts +17 -5
- package/dist/schemas/scout/zfs.d.ts.map +1 -1
- package/dist/schemas/scout/zfs.js +34 -25
- package/dist/schemas/scout/zfs.js.map +1 -1
- package/dist/services/cache-layer.d.ts +160 -0
- package/dist/services/cache-layer.d.ts.map +1 -0
- package/dist/services/cache-layer.js +138 -0
- package/dist/services/cache-layer.js.map +1 -0
- package/dist/services/compose-cache.d.ts +75 -0
- package/dist/services/compose-cache.d.ts.map +1 -0
- package/dist/services/compose-cache.js +178 -0
- package/dist/services/compose-cache.js.map +1 -0
- package/dist/services/compose-discovery.d.ts +46 -0
- package/dist/services/compose-discovery.d.ts.map +1 -0
- package/dist/services/compose-discovery.js +219 -0
- package/dist/services/compose-discovery.js.map +1 -0
- package/dist/services/compose-project-lister.d.ts +27 -0
- package/dist/services/compose-project-lister.d.ts.map +1 -0
- package/dist/services/compose-project-lister.js +71 -0
- package/dist/services/compose-project-lister.js.map +1 -0
- package/dist/services/compose-scanner.d.ts +63 -0
- package/dist/services/compose-scanner.d.ts.map +1 -0
- package/dist/services/compose-scanner.js +253 -0
- package/dist/services/compose-scanner.js.map +1 -0
- package/dist/services/compose.d.ts +64 -28
- package/dist/services/compose.d.ts.map +1 -1
- package/dist/services/compose.js +220 -98
- package/dist/services/compose.js.map +1 -1
- package/dist/services/config-loader.d.ts +23 -0
- package/dist/services/config-loader.d.ts.map +1 -0
- package/dist/services/config-loader.js +124 -0
- package/dist/services/config-loader.js.map +1 -0
- package/dist/services/config-service.d.ts +38 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +225 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/container-host-map-cache.d.ts +121 -0
- package/dist/services/container-host-map-cache.d.ts.map +1 -0
- package/dist/services/container-host-map-cache.js +188 -0
- package/dist/services/container-host-map-cache.js.map +1 -0
- package/dist/services/container.d.ts +194 -6
- package/dist/services/container.d.ts.map +1 -1
- package/dist/services/container.js +386 -11
- package/dist/services/container.js.map +1 -1
- package/dist/services/diagnostics.d.ts +57 -0
- package/dist/services/diagnostics.d.ts.map +1 -0
- package/dist/services/diagnostics.js +271 -0
- package/dist/services/diagnostics.js.map +1 -0
- package/dist/services/docker/container-service.d.ts +123 -0
- package/dist/services/docker/container-service.d.ts.map +1 -0
- package/dist/services/docker/container-service.js +347 -0
- package/dist/services/docker/container-service.js.map +1 -0
- package/dist/services/docker/image-service.d.ts +82 -0
- package/dist/services/docker/image-service.d.ts.map +1 -0
- package/dist/services/docker/image-service.js +193 -0
- package/dist/services/docker/image-service.js.map +1 -0
- package/dist/services/docker/index.d.ts +80 -0
- package/dist/services/docker/index.d.ts.map +1 -0
- package/dist/services/docker/index.js +103 -0
- package/dist/services/docker/index.js.map +1 -0
- package/dist/services/docker/network-service.d.ts +22 -0
- package/dist/services/docker/network-service.d.ts.map +1 -0
- package/dist/services/docker/network-service.js +43 -0
- package/dist/services/docker/network-service.js.map +1 -0
- package/dist/services/docker/system-service.d.ts +49 -0
- package/dist/services/docker/system-service.d.ts.map +1 -0
- package/dist/services/docker/system-service.js +215 -0
- package/dist/services/docker/system-service.js.map +1 -0
- package/dist/services/docker/utils/client-factory.d.ts +56 -0
- package/dist/services/docker/utils/client-factory.d.ts.map +1 -0
- package/dist/services/docker/utils/client-factory.js +139 -0
- package/dist/services/docker/utils/client-factory.js.map +1 -0
- package/dist/services/docker/utils/client-manager.d.ts +88 -0
- package/dist/services/docker/utils/client-manager.d.ts.map +1 -0
- package/dist/services/docker/utils/client-manager.js +124 -0
- package/dist/services/docker/utils/client-manager.js.map +1 -0
- package/dist/services/docker/utils/exec-handler.d.ts +94 -0
- package/dist/services/docker/utils/exec-handler.d.ts.map +1 -0
- package/dist/services/docker/utils/exec-handler.js +197 -0
- package/dist/services/docker/utils/exec-handler.js.map +1 -0
- package/dist/services/docker/utils/formatters.d.ts +13 -0
- package/dist/services/docker/utils/formatters.d.ts.map +1 -0
- package/dist/services/docker/utils/formatters.js +33 -0
- package/dist/services/docker/utils/formatters.js.map +1 -0
- package/dist/services/docker/utils/log-parser.d.ts +10 -0
- package/dist/services/docker/utils/log-parser.d.ts.map +1 -0
- package/dist/services/docker/utils/log-parser.js +48 -0
- package/dist/services/docker/utils/log-parser.js.map +1 -0
- package/dist/services/docker/utils/stats-calculator.d.ts +68 -0
- package/dist/services/docker/utils/stats-calculator.d.ts.map +1 -0
- package/dist/services/docker/utils/stats-calculator.js +61 -0
- package/dist/services/docker/utils/stats-calculator.js.map +1 -0
- package/dist/services/docker/volume-service.d.ts +22 -0
- package/dist/services/docker/volume-service.d.ts.map +1 -0
- package/dist/services/docker/volume-service.js +48 -0
- package/dist/services/docker/volume-service.js.map +1 -0
- package/dist/services/docker-interfaces.d.ts +283 -0
- package/dist/services/docker-interfaces.d.ts.map +1 -0
- package/dist/services/docker-interfaces.js +13 -0
- package/dist/services/docker-interfaces.js.map +1 -0
- package/dist/services/docker.d.ts +42 -5
- package/dist/services/docker.d.ts.map +1 -1
- package/dist/services/docker.js +335 -127
- package/dist/services/docker.js.map +1 -1
- package/dist/services/file-service.d.ts +6 -2
- package/dist/services/file-service.d.ts.map +1 -1
- package/dist/services/file-service.js +156 -52
- package/dist/services/file-service.js.map +1 -1
- package/dist/services/host-config-repository.d.ts +133 -0
- package/dist/services/host-config-repository.d.ts.map +1 -0
- package/dist/services/host-config-repository.js +323 -0
- package/dist/services/host-config-repository.js.map +1 -0
- package/dist/services/host-resolver.d.ts +49 -0
- package/dist/services/host-resolver.d.ts.map +1 -0
- package/dist/services/host-resolver.js +176 -0
- package/dist/services/host-resolver.js.map +1 -0
- package/dist/services/interfaces.d.ts +61 -194
- package/dist/services/interfaces.d.ts.map +1 -1
- package/dist/services/local-executor.d.ts +31 -0
- package/dist/services/local-executor.d.ts.map +1 -0
- package/dist/services/local-executor.js +71 -0
- package/dist/services/local-executor.js.map +1 -0
- package/dist/services/ssh-config-loader.d.ts +35 -0
- package/dist/services/ssh-config-loader.d.ts.map +1 -0
- package/dist/services/ssh-config-loader.js +218 -0
- package/dist/services/ssh-config-loader.js.map +1 -0
- package/dist/services/ssh-pool.d.ts +26 -1
- package/dist/services/ssh-pool.d.ts.map +1 -1
- package/dist/services/ssh-pool.js +165 -25
- package/dist/services/ssh-pool.js.map +1 -1
- package/dist/services/ssh-service.d.ts +3 -0
- package/dist/services/ssh-service.d.ts.map +1 -1
- package/dist/services/ssh-service.js +53 -31
- package/dist/services/ssh-service.js.map +1 -1
- package/dist/services/ssh.d.ts +2 -6
- package/dist/services/ssh.d.ts.map +1 -1
- package/dist/services/ssh.js +9 -40
- package/dist/services/ssh.js.map +1 -1
- package/dist/tools/definitions/flux.d.ts +13 -0
- package/dist/tools/definitions/flux.d.ts.map +1 -0
- package/dist/tools/definitions/flux.js +101 -0
- package/dist/tools/definitions/flux.js.map +1 -0
- package/dist/tools/definitions/index.d.ts +8 -0
- package/dist/tools/definitions/index.d.ts.map +1 -0
- package/dist/tools/definitions/index.js +8 -0
- package/dist/tools/definitions/index.js.map +1 -0
- package/dist/tools/definitions/scout.d.ts +13 -0
- package/dist/tools/definitions/scout.d.ts.map +1 -0
- package/dist/tools/definitions/scout.js +78 -0
- package/dist/tools/definitions/scout.js.map +1 -0
- package/dist/tools/flux.d.ts +16 -8
- package/dist/tools/flux.d.ts.map +1 -1
- package/dist/tools/flux.js +27 -66
- package/dist/tools/flux.js.map +1 -1
- package/dist/tools/handlers/base-handler.d.ts +172 -0
- package/dist/tools/handlers/base-handler.d.ts.map +1 -0
- package/dist/tools/handlers/base-handler.js +234 -0
- package/dist/tools/handlers/base-handler.js.map +1 -0
- package/dist/tools/handlers/compose-handlers.d.ts +108 -0
- package/dist/tools/handlers/compose-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/compose-handlers.js +293 -0
- package/dist/tools/handlers/compose-handlers.js.map +1 -0
- package/dist/tools/handlers/compose-utils.d.ts +35 -0
- package/dist/tools/handlers/compose-utils.d.ts.map +1 -0
- package/dist/tools/handlers/compose-utils.js +76 -0
- package/dist/tools/handlers/compose-utils.js.map +1 -0
- package/dist/tools/handlers/compose.d.ts +23 -0
- package/dist/tools/handlers/compose.d.ts.map +1 -0
- package/dist/tools/handlers/compose.js +125 -0
- package/dist/tools/handlers/compose.js.map +1 -0
- package/dist/tools/handlers/container.d.ts +23 -0
- package/dist/tools/handlers/container.d.ts.map +1 -0
- package/dist/tools/handlers/container.js +333 -0
- package/dist/tools/handlers/container.js.map +1 -0
- package/dist/tools/handlers/docker.d.ts +24 -0
- package/dist/tools/handlers/docker.d.ts.map +1 -0
- package/dist/tools/handlers/docker.js +155 -0
- package/dist/tools/handlers/docker.js.map +1 -0
- package/dist/tools/handlers/host.d.ts +23 -0
- package/dist/tools/handlers/host.d.ts.map +1 -0
- package/dist/tools/handlers/host.js +196 -0
- package/dist/tools/handlers/host.js.map +1 -0
- package/dist/tools/handlers/scout-logs.d.ts +24 -0
- package/dist/tools/handlers/scout-logs.d.ts.map +1 -0
- package/dist/tools/handlers/scout-logs.js +119 -0
- package/dist/tools/handlers/scout-logs.js.map +1 -0
- package/dist/tools/handlers/scout-simple.d.ts +23 -0
- package/dist/tools/handlers/scout-simple.d.ts.map +1 -0
- package/dist/tools/handlers/scout-simple.js +286 -0
- package/dist/tools/handlers/scout-simple.js.map +1 -0
- package/dist/tools/handlers/scout-zfs.d.ts +23 -0
- package/dist/tools/handlers/scout-zfs.d.ts.map +1 -0
- package/dist/tools/handlers/scout-zfs.js +82 -0
- package/dist/tools/handlers/scout-zfs.js.map +1 -0
- package/dist/tools/index.d.ts +32 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +41 -35
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +135 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/scout.d.ts +16 -8
- package/dist/tools/scout.d.ts.map +1 -1
- package/dist/tools/scout.js +36 -78
- package/dist/tools/scout.js.map +1 -1
- package/dist/types.d.ts +627 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/command-security.d.ts +82 -0
- package/dist/utils/command-security.d.ts.map +1 -0
- package/dist/utils/command-security.js +122 -0
- package/dist/utils/command-security.js.map +1 -0
- package/dist/utils/error-sanitization.d.ts +77 -0
- package/dist/utils/error-sanitization.d.ts.map +1 -0
- package/dist/utils/error-sanitization.js +107 -0
- package/dist/utils/error-sanitization.js.map +1 -0
- package/dist/utils/errors.d.ts +30 -6
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +91 -12
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/help-handler.d.ts +23 -0
- package/dist/utils/help-handler.d.ts.map +1 -0
- package/dist/utils/help-handler.js +21 -0
- package/dist/utils/help-handler.js.map +1 -0
- package/dist/utils/help.d.ts +1 -1
- package/dist/utils/help.d.ts.map +1 -1
- package/dist/utils/help.js +57 -16
- package/dist/utils/help.js.map +1 -1
- package/dist/utils/host-utils.d.ts +31 -0
- package/dist/utils/host-utils.d.ts.map +1 -0
- package/dist/utils/host-utils.js +80 -0
- package/dist/utils/host-utils.js.map +1 -0
- package/dist/utils/index.d.ts +8 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +8 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/init-detection.d.ts +36 -0
- package/dist/utils/init-detection.d.ts.map +1 -0
- package/dist/utils/init-detection.js +79 -0
- package/dist/utils/init-detection.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +20 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +29 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/path-security.d.ts +132 -18
- package/dist/utils/path-security.d.ts.map +1 -1
- package/dist/utils/path-security.js +164 -35
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/sorting.d.ts +33 -0
- package/dist/utils/sorting.d.ts.map +1 -0
- package/dist/utils/sorting.js +57 -0
- package/dist/utils/sorting.js.map +1 -0
- package/dist/utils/text-filters.d.ts +13 -0
- package/dist/utils/text-filters.d.ts.map +1 -0
- package/dist/utils/text-filters.js +18 -0
- package/dist/utils/text-filters.js.map +1 -0
- package/dist/utils/time.d.ts +11 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +13 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/validation.d.ts +25 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +56 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +45 -19
- package/dist/schemas/discriminator.d.ts +0 -20
- package/dist/schemas/discriminator.d.ts.map +0 -1
- package/dist/schemas/discriminator.js +0 -25
- package/dist/schemas/discriminator.js.map +0 -1
- package/dist/schemas/unified.d.ts +0 -674
- package/dist/schemas/unified.d.ts.map +0 -1
- package/dist/schemas/unified.js +0 -453
- package/dist/schemas/unified.js.map +0 -1
- package/dist/tools/unified.d.ts +0 -7
- package/dist/tools/unified.d.ts.map +0 -1
- package/dist/tools/unified.js +0 -827
- 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
|
-
**
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
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
|
-
|
|
204
|
+
```
|
|
109
205
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
| `
|
|
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
|
|
125
|
-
|
|
|
126
|
-
| `pools`
|
|
127
|
-
| `datasets`
|
|
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`
|
|
236
|
+
| Subaction | Description |
|
|
237
|
+
| --------- | ----------------------------------------------- |
|
|
238
|
+
| `syslog` | Access system log files (/var/log) |
|
|
135
239
|
| `journal` | Access systemd journal logs with unit filtering |
|
|
136
|
-
| `dmesg`
|
|
137
|
-
| `auth`
|
|
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": "
|
|
222
|
-
"host": "
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"tags": ["
|
|
465
|
+
"name": "local",
|
|
466
|
+
"host": "localhost",
|
|
467
|
+
"protocol": "ssh",
|
|
468
|
+
"dockerSocketPath": "/var/run/docker.sock",
|
|
469
|
+
"tags": ["development"]
|
|
226
470
|
},
|
|
227
471
|
{
|
|
228
|
-
"name": "
|
|
472
|
+
"name": "production",
|
|
229
473
|
"host": "192.168.1.100",
|
|
230
|
-
"port":
|
|
231
|
-
"protocol": "
|
|
232
|
-
"
|
|
474
|
+
"port": 22,
|
|
475
|
+
"protocol": "ssh",
|
|
476
|
+
"sshUser": "admin",
|
|
477
|
+
"sshKeyPath": "~/.ssh/id_rsa",
|
|
478
|
+
"tags": ["production"]
|
|
233
479
|
},
|
|
234
480
|
{
|
|
235
|
-
"name": "
|
|
236
|
-
"host": "
|
|
481
|
+
"name": "unraid",
|
|
482
|
+
"host": "unraid.local",
|
|
483
|
+
"port": 2375,
|
|
237
484
|
"protocol": "http",
|
|
238
|
-
"
|
|
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
|
|
256
|
-
|
|
|
257
|
-
| `name`
|
|
258
|
-
| `host`
|
|
259
|
-
| `port`
|
|
260
|
-
| `protocol`
|
|
261
|
-
| `dockerSocketPath` | `string`
|
|
262
|
-
| `sshUser`
|
|
263
|
-
| `sshKeyPath`
|
|
264
|
-
| `tags`
|
|
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
|
|
269
|
-
|
|
|
270
|
-
| `CHARACTER_LIMIT`
|
|
271
|
-
| `DEFAULT_LIMIT`
|
|
272
|
-
| `MAX_LIMIT`
|
|
273
|
-
| `DEFAULT_LOG_LINES` | 50
|
|
274
|
-
| `MAX_LOG_LINES`
|
|
275
|
-
| `API_TIMEOUT`
|
|
276
|
-
| `STATS_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:
|
|
356
|
-
# Health check: http://127.0.0.1:
|
|
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
|
-
|
|
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
|
-
##
|
|
435
|
-
|
|
436
|
-
### Path Traversal Protection (CWE-22)
|
|
988
|
+
## Troubleshooting
|
|
437
989
|
|
|
438
|
-
|
|
990
|
+
Common issues and their solutions. For additional help, see the operational runbooks in `docs/runbooks/`.
|
|
439
991
|
|
|
440
|
-
|
|
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
|
-
|
|
446
|
-
```bash
|
|
447
|
-
# Rejected: Directory traversal
|
|
448
|
-
../../../etc/passwd
|
|
449
|
-
/app/../../../etc/passwd
|
|
994
|
+
#### Port Already in Use
|
|
450
995
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
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:
|
|
1891
|
+
- Total: 57 operations across both tools
|
|
537
1892
|
|
|
538
1893
|
**Discriminated Union for O(1) Validation**:
|
|
539
|
-
|
|
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
|
|
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
|
|
569
|
-
- **Flux optimization**:
|
|
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
|