v3.6.0 — Live config hot reload + stdio lifecycle fix
Live config hot reload + stdio lifecycle fix
Two community contributions, verified end-to-end and shipped together.
♻️ Added — Live configuration hot reload (#40, thanks @EnjoySR)
Add or edit a server in your .env/TOML and the running MCP server picks it up on the next call — ssh_list_servers sees it without a restart.
- A new
ServerConfigManagerreloads lazily when a config file's signature (path +mtime+ size) changes — no file watcher, no polling thread, no background timer. - Fail-safe: if a reload throws (malformed file caught mid-edit), the last known-good config is kept in memory and the error is logged. The server never ends up empty or broken.
.envparsing no longer permanently mutatesprocess.env; real environment variables keep the highest priority over file values.
🔌 Fixed — Orphaned stdio process per session (#41, thanks @LegendaryGatz)
A stdio MCP server is torn down by its host closing stdin (EOF) and/or sending SIGTERM — not SIGINT (interactive Ctrl-C only). The only handler was SIGINT, so on normal teardown the process was never signalled, got reparented to init, and leaked ~83 MB + live timers per session.
- Shutdown is now an idempotent
shutdown(reason)onSIGINT/SIGTERM/SIGHUPand stdin'end'/'close'. - Keepalive and 10-minute cleanup intervals are
unref()'d so process lifetime tracks the transport, not a timer.ssh.dispose()is try/catch-guarded and a shortunref'd timer forces exit so teardown can't hang. - Measured: exits cleanly ~10 ms after stdin EOF, versus staying alive indefinitely before.
✅ Tests
- New
tests/test-lifecycle.js(npm run test:lifecycle) — black-box teardown coverage on stdin EOF, SIGTERM, SIGINT and overlapping signals. tests/test-server-config-manager.jsextended to 9 checks — laziness, reload-failure-keeps-last-valid-config + recovery, deleted-file robustness.
♻️ Backward compatibility
Zero impact on existing setups. Hot reload is transparent (no config change → identical behavior); the lifecycle fix is pure teardown hygiene. No new field, prompt or file. All pre-existing suites pass unmodified.
Full changelog: https://github.com/bvisible/mcp-ssh-manager/blob/main/CHANGELOG.md#360---2026-06-09