feat: stateless HTTP mode to eliminate session drops (#180)#232
Conversation
New AWARENESS_STATELESS_HTTP=true option creates a fresh MCP transport per request with no session tracking. Eliminates the entire class of session drop / 409 Conflict bugs since there are no sessions to go stale. Auth still flows per-request via JWT Bearer token. Session registry is automatically skipped in stateless mode. Stateful mode (default) remains available for clients that need persistent sessions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
7 tests total: - 3 unit: config wiring, session registry skip, FastMCP setting - 4 integration: tool call without session, no session ID in headers, stale session ID doesn't cause 409, concurrent requests succeed Fix env var leak between integration test classes by cleaning up AWARENESS_STATELESS_HTTP after stateless tests. README count: 754. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Adding QA Active — reviewing stateless HTTP mode. |
cmeans
left a comment
There was a problem hiding this comment.
QA Review — Round 1
Clean feature. The implementation is minimal — one env var, one stateless_http= kwarg to FastMCP, and a guard in _wrap_with_session_registry. The tests are thorough: 4 unit tests + 4 integration tests covering the no-session, no-409, concurrent, and backward-compat paths.
Code review
| Check | Result |
|---|---|
AWARENESS_STATELESS_HTTP parsed correctly (accepts "1", "true") |
✅ |
stateless_http=STATELESS_HTTP passed to FastMCP constructor |
✅ |
| Session registry skipped in stateless mode | ✅ |
| Log messages for mode identification | ✅ |
| README: env var documented with description | ✅ |
README: SESSION_DATABASE_URL doc updated ("Ignored when stateless") |
✅ |
CHANGELOG: entry under [Unreleased] ### Added |
✅ |
| README: 754 tests (verified locally) | ✅ |
| CI all green | ✅ |
Manual test results (Docker QA instance)
| # | Test | Result |
|---|---|---|
| 1 | Logs show stateless mode + session registry disabled | ✅ |
| 2 | get_briefing, remember, get_knowledge — all pass, no session ID in headers | ✅ |
| 3 | Restart + stale session ID → 200, not 409 | ✅ |
| 4 | Stateful mode — session ID returned, no stateless log messages | ✅ |
| 5 | Stateful + session registry | ⏭️ Already verified in PR #169 reviews |
QA infrastructure cleaned up.
Test sufficiency
The integration tests cover the key scenarios well. test_no_409_after_restart is the most important — it proves the core value proposition. test_concurrent_stateless_requests with 5 parallel threads validates that per-request transports don't interfere. The unit tests cover the configuration wiring. No gaps identified.
Zero findings. Verdict: Pass — ready for signoff.
|
Applying Ready for QA Signoff — stateless + stateful modes both verified on Docker QA instance, 754/754 tests pass, CI green, zero findings. |
6 bug-fix PRs since v0.16.1: - #226 LazyStore thread safety (#164) - #227 SQL template injection hardening (#165) - #232 Stateless HTTP mode (#180) - #233 GET /mcp intercept + request logger (#178) - #234 delete_entry IDOR fix (#193) - #236 RLS-safe opt-in cleanup (#179, #183) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 bug-fix PRs since v0.16.1: - #226 LazyStore thread safety (#164) - #227 SQL template injection hardening (#165) - #232 Stateless HTTP mode (#180) - #233 GET /mcp intercept + request logger (#178) - #234 delete_entry IDOR fix (#193) - #236 RLS-safe opt-in cleanup (#179, #183) Co-authored-by: cmeans-claude-dev[bot] <3223881+cmeans-claude-dev[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
AWARENESS_STATELESS_HTTP=trueenv var enables stateless HTTP transport — fresh MCP transport per request, no session trackingCloses #180
QA
Prerequisites
pip install -e ".[dev]"AWARENESS_PORT=8421)Manual tests (via MCP tools)
Stateless mode:
Expected: logs show "Transport mode: stateless HTTP" and "Session registry: disabled"
get_briefing, remember, get_knowledge — all return valid results, no session ID in response headers
Restarted instance, sent request with fake stale session ID — returned 200, not 409
Stateful mode (backward compat):
4. - [x] Start without AWARENESS_STATELESS_HTTP (or =false)
Stateful behavior unchanged, session ID returned in response headers, no stateless log messages
🤖 Generated with Claude Code