Skip to content

idle_shutdown_seconds default of 30s is a footgun for MCP clients with frozen session-start tool sets #4

Description

@kpachhai

Summary

DaemonConfig.idle_shutdown_seconds defaults to 30. The intent is "let idle daemons clean themselves up." But for MCP clients whose tool set is frozen at session-start (Claude Code is the example I hit; suspect Codex CLI and others), the default causes a perpetual disconnect loop:

  1. Claude Code session starts, probes engram MCP, finds daemon not running -> registers engram as "Failed to connect" for the session lifetime.
  2. A SessionStart hook or user action spawns the daemon AFTER session-start.
  3. Daemon comes up. No proxy connects, because Claude Code's MCP set is already frozen for this session.
  4. Daemon's _connected_proxies == 0 condition holds, idle timer fires at 30s, daemon exits.
  5. Next session-start probe again sees "Failed to connect". Loop.

The loop is invisible to the user: each session correctly reports engram: ... Failed to connect and degrades silently to alternative persistent-memory MCPs. Detection only happens if the user explicitly checks claude mcp list or notices missing engram tool availability.

Reproduction

  1. Default config (no daemon: block in vault config -> idle_shutdown_seconds=30).
  2. Engram registered in ~/.claude.json mcpServers.
  3. Start Claude Code session. Notice claude mcp list shows engram: ... Failed to connect.
  4. Run engram daemon start --vault <name> --detach from any shell.
  5. Verify daemon ready.
  6. Wait 35s, re-run engram daemon status --vault <name>.
  7. Observe: daemon stopped (the idle timer fired before any proxy connected, because the MCP set was already frozen at step 3).

In my logs the pattern was textbook: every daemon process for 9+ consecutive invocations died with engram daemon stopped at exactly 30.0 +/- 0.1 seconds after engram daemon ready.

Proposed change

Two options, not mutually exclusive:

  • (a) Change the default to 0 (always-on). Rationale: the 30s default optimizes for a "casual one-off CLI invocation" scenario that isn't actually engram's primary deployment shape. Local-first MCP servers are persistent by design; the daemon SHOULD stay up until explicitly stopped.
  • (b) Document the gotcha prominently in docs/DAEMON_MODE.md. Specifically: a section titled "Frozen-tool-set MCP clients (Claude Code, etc.)" explaining the loop and recommending idle_shutdown_seconds: 0 for these deployments.

(a) + (b) together would also work: change the default, document why, leave the knob configurable for the casual-CLI case (where the user might want auto-cleanup).

Workaround (current)

Set idle_shutdown_seconds: 0 in the per-vault engram.config.yaml:

daemon:
  idle_shutdown_seconds: 0

Plus a SessionStart hook that calls engram daemon start --vault <name> --detach if the MCP shows Failed to connect. Both together close the loop. The hook is in my dotfiles; the config knob is in the vault repo.

Context

Surfaced 2026-05-16 during the same session that produced the three filed bug issues above. The 30s exact periodicity in the daemon log was the give-away — voluntary shutdowns, not crashes. Took longer than it should have to spot because "idle shutdown" intuitively reads as "the daemon was actually idle" (correct, by the daemon's definition) rather than "the daemon was waiting for a proxy that will never connect in this session" (the actual operational situation).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions