Skip to content

v0.2.2 — per-connection HTTP session isolation

Choose a tag to compare

@zach-source zach-source released this 25 Jul 07:38
· 22 commits to main since this release
v0.2.2
dbeea31

Fixes the identity-collision gap that v0.2.1 (commit 8534c19) documented but
deliberately left unfixed: concurrent HTTP-mode connections used to share one
process-global session (sid, git context, bead_id, objective, captured
channel-push session) — whichever connection registered most recently became
who the server thought every caller was.

What changed

  • server.py: the module-global _State singleton is now a per-connection
    _SessionState registry, keyed by FastMCP's Context.session_id — verified
    present and stable for every transport (including stdio) in the installed
    fastmcp 3.4.4, not just HTTP as the prior investigation assumed.
  • channel.py: the captured channel-push session is per-connection too, so
    proactive <channel> push now delivers to every connected client, not just
    the first one to register.
  • Idle HTTP-mode connections (no tool call for 15 minutes) are reaped instead
    of heartbeating forever, reusing the existing stale/reap conventions.
  • stdio mode is unaffected — a stdio process still gets exactly one tracked
    connection for its whole life, and the full pre-existing stdio test suite
    passes unchanged.
  • New tests cover concurrent-connection isolation (two live in-process MCP
    clients never leak sid/bead_id/objective/status into each other) and the
    idle-reap cleanup path.

Residual limitation

Idle-connection cleanup is time-based (no client tool call for 15 minutes),
not a true transport-liveness check — a connection that stays open but is
genuinely idle that long is indistinguishable from an abandoned one and gets
reaped too. Documented in README.md and docs/DESIGN.md. This only applies
under MAILBOX_TRANSPORT=http; stdio is never affected.

Full diff: v0.2.1...v0.2.2