{
  "schema_version": "1.3.0",
  "slug": "which-invariants-prevent-mcp-http-native-transport-from-silently-resuming-a-session-across-a-channel-rebind",
  "title": "Which invariants prevent MCP HTTP-native transport from silently resuming a session across a channel rebind",
  "date_of_record": "2026 November 7",
  "scope": "Applies to MCP servers and clients using the HTTP-native (streamable) transport where a `Mcp-Session-Id` is issued at initialization and subsequent tool calls are dispatched over stateless HTTP requests that may land on different edge nodes or worker processes. Does not apply to stdio transports, nor to long-lived SSE-only connections where the channel is bound for the session's lifetime.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/which-invariants-prevent-mcp-http-native-transport-from-silently-resuming-a-session-across-a-channel-rebind.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-mcp-http-native-transport-from-silently-resuming-a-session-across-a-channel-rebind.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-mcp-http-native-transport-from-silently-resuming-a-session-across-a-channel-rebind.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1417,
    "python_slice_tokens": 167,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "The streamable HTTP transport decouples *session identity* from *channel identity*. A session is a logical conversation keyed by `Mcp-Session-Id`; a channel is the specific TCP/TLS connection, edge node, and request-scoped context that carries a single POST. Agents routinely conflate the two because, in stdio, they are identical. The invariant that matters i...",
    "what_was_observed": "A stateless streamable MCP deployment behind a load balancer issued `Mcp-Session-Id: s_7f3a...` on `initialize`. The client then dispatched `tools/call` requests with that header. Under normal load, requests were routed to the same worker and completed. Under a rolling deploy, requests for `s_7f3a...` began landing on a freshly started worker that had no in-memory record of the session. The worker's session store was...",
    "condition_of_validity": "The following invariants must all hold for stateless streamable resumption to be safe: 1. **Channel-bound cursor.** The resumption cursor (the `Last-Event-ID` or equivalent replay offset) is only valid on the channel that issued it. A cursor presented on a different channel is not a resumption request; it is a *new* request that happens to carry a stale curs...",
    "decision_boundary": "The boundary is between *continuation* and *resumption*: - **Continuation** — same channel, same generation, cursor ahead of last acknowledged. Safe to replay from cursor; no re-execution. - **Resumption** — new channel, same session, cursor from prior channel. Requires idempotency key check and generation increment; replay is *replay of results*, never *re-...",
    "operational_effect": "After the incident, the deployment added a channel token to the session record and a generation counter to the cursor. Resumption requests without a matching channel token are rejected with a structured error that the client must handle by re-issuing the call with an idempotency key. The practical effect for agents: a `409` on a streamable POST is not always..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "60f04c20c33d68b184320c095ceca9b8a3842fca5fbd00c70f64f42bf1f4ffd9",
    "verified_classes": [
      "ChannelRebindError",
      "StaleGenerationError"
    ],
    "verified_functions": [
      "resume_stream"
    ],
    "verified_functions_count": 1,
    "defensive_guards_count": 3,
    "raised_exceptions": [
      "ChannelRebindError",
      "StaleGenerationError"
    ],
    "sample_fail_closed_invariants": [
      "same-generation resumption without idempotency key; duplicate effect possible"
    ],
    "stdlib_dependencies": [],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
