Skip to content

feat(mcp): DB-backed session store for cross-instance/LB deployments (v4.6.0)#93

Merged
kennethphough merged 1 commit into
masterfrom
feature/mcp-db-session-store
May 29, 2026
Merged

feat(mcp): DB-backed session store for cross-instance/LB deployments (v4.6.0)#93
kennethphough merged 1 commit into
masterfrom
feature/mcp-db-session-store

Conversation

@kennethphough

Copy link
Copy Markdown
Member

Summary

Adds a DB-backed MCP protocol-session store so deployments behind a load balancer share session state across instances. Fixes the per-host FileSessionStore breakage where initialize and follow-up requests land on different boxes (the blocker for the kyte-etometry MCP connection on ETOM's 2 nodes). Refs KYTE-183.

What changed

  • src/Mvc/Model/KyteMCPSession.php — new model, auto-registered by the Mvc/Model loader.
  • src/Mcp/Session/DbSessionStore.phpSessionStoreInterface impl against KyteMCPSession.
  • src/Mcp/Endpoint.phpbuildSessionStore() selects backend.
  • migrations/4.6.0_mcp_session_store.sqlCREATE TABLE IF NOT EXISTS, indexed (UNIQUE session_id, composite kyte_account,session_id, last_activity).
  • tests/DbSessionStoreTest.php — 7 tests; full unit suite green (194 tests) on MariaDB 10.5.
  • CHANGELOG.md — v4.6.0.

Behavior / decisions

  • DB store is the default. define('KYTE_MCP_SESSION_STORE', 'file') opts back to the SDK file store (kept as a break-glass option). KYTE_MCP_SESSION_TTL overrides idle TTL (default 3600s).
  • TTL semantics mirror FileSessionStore exactlylast_activity slides on each request (Protocol calls save() per request); exists() reports expiry without deleting, read() purges on expiry.
  • Per-account scoped reads/writes/destroys; global gc() sweep capped at 1000/call. Rows are hard-deleted (purge), not soft-deleted, to keep the session_id UNIQUE index clean.

Rollout note

With DB as default, the migration must run on every install before it serves MCP on v4.6.0 (additive, IF NOT EXISTS). Single-instance installs (dev, ORB/ORT) are functionally unaffected — they just move to the DB store. ETOM is the one that actually needs it.

Validation so far

  • ✅ 7 store tests + full 194-test unit suite green against MariaDB 10.5 (dockerized).
  • ✅ Migration applied + verified on dev DB (table + indexes).
  • ⏳ This PR is for review ahead of a smoke test on dev via a temporary dev- branch pin (no tag yet).

Adds KyteMCPSession + DbSessionStore so MCP protocol sessions are shared
across instances behind a load balancer, fixing the per-host FileSessionStore
breakage on multi-instance installs (e.g. ETOM). The DB store is the default;
KYTE_MCP_SESSION_STORE='file' opts back to the SDK file store. TTL semantics
mirror the file store (idle timeout via last-write); lookups are per-account
scoped, gc() is a global capped sweep.

- src/Mvc/Model/KyteMCPSession.php   new model (auto-registered by loader)
- src/Mcp/Session/DbSessionStore.php SessionStoreInterface implementation
- src/Mcp/Endpoint.php               buildSessionStore() backend selector
- migrations/4.6.0_mcp_session_store.sql  CREATE TABLE IF NOT EXISTS
- tests/DbSessionStoreTest.php        7 tests (round-trip, miss, upsert,
  destroy, account isolation, TTL expiry, gc) -- green on MariaDB 10.5
- CHANGELOG.md                        v4.6.0 entry

Refs KYTE-183.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kennethphough
kennethphough merged commit b12a3da into master May 29, 2026
7 checks passed
@kennethphough
kennethphough deleted the feature/mcp-db-session-store branch May 29, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant