Skip to content

mcp-data-platform-v0.35.6

Choose a tag to compare

@github-actions github-actions released this 07 Mar 06:46
· 83 commits to main since this release
11483fe

Session Stability Fix

This release fixes a critical session management bug that caused provenance tracking and enrichment deduplication to silently fail after session expiry.

The Problem

When a client reconnects after its session expires (30-min TTL or pod restart), the server previously generated a new random session ID. However, MCP clients like Claude Desktop cache their session ID from the initial handshake and never update it from response headers. This created an infinite replacement cycle:

Client sends Mcp-Session-Id: ABC123
  → store.Get("ABC123") returns nil (expired)
  → server generates new ID: XYZ789
  → client ignores new header, keeps sending ABC123
  → next request: store.Get("ABC123") returns nil again
  → cycle repeats indefinitely

Impact: Every tool call after session expiry was recorded under a different session ID, so provenance.harvest always returned 0 calls. Enrichment dedup (WasSentRecently) also broke since each request appeared to be a fresh session, causing redundant metadata injection on every response.

The Fix

A new reviveSession method recreates the expired session using the client's original ID instead of generating a new one. After revival, the session is stable and all subsequent requests resolve normally.

Client sends Mcp-Session-Id: ABC123
  → store.Get("ABC123") returns nil (expired)
  → reviveSession recreates session with ID ABC123
  → next request: store.Get("ABC123") succeeds
  → provenance and dedup work correctly from here on

Additional Hardening

  • Postgres upsert on session createINSERT ... ON CONFLICT (id) DO UPDATE eliminates unique constraint violations if two concurrent requests try to revive the same expired session simultaneously
  • Dead code removal — Removed the now-unused ReplacedSessionID / WithReplacedSessionID context propagation and the harvestProvenance replaced-session fallback, which became unreachable after switching to same-ID revival

Changed Files

File Change
pkg/session/handler.go New reviveSession method; handleExisting uses same-ID revival; removed ReplacedSessionID infrastructure
pkg/session/handler_test.go 6 new/updated tests covering revive stability, timestamps, error paths, and concurrent access
pkg/session/postgres/store.go Create uses upsert to handle race conditions on expired rows
pkg/middleware/mcp_provenance.go Simplified harvestProvenance — no longer checks for replaced session IDs
pkg/middleware/mcp_provenance_test.go Removed session-replacement merge tests (dead code paths)

Test Coverage

  • handleExisting: 96.3%
  • reviveSession: 100%
  • harvestProvenance: 100%
  • All checks pass via make verify

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v0.35.6

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_0.35.6_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_0.35.6_linux_amd64.tar.gz