MCP session reuse and host identity¶
Read this when…
You integrate an MCP client or host wrapper and need stable sessions across reconnects, tabs, or subagents.
What to know first: Concepts, Incremental DOMAIN prompts (symbol stability).
Practical takeaway: intent (host-supplied) defines the logical session—not MCP-Session-Id. Keep intent stable for the life of a task; rotate it only when you intentionally want a new logical session.
This document is the canonical description of how plasm_context, plasm, and execute session reuse interact. The MCP transport (MCP-Session-Id) does not identify a host agent, window, or subagent. That boundary is always defined by the host via the intent string on plasm_context and the resulting logical session.
See also: MCP logical sessions, incremental DOMAIN prompts, MCP trace correlation.
1. Flow¶
plasm_contextwithintentand non-emptyseeds- The server is idempotent on
(tenant_scope, intent): the same string yields the same canonicallogical_session_idand the same per-transportlogical_session_ref(e.g.s0). - If a live execute session is already bound for that logical id, the server expands or federates into that session (no fresh-open path).
- Duplicate seeds (already exposed): if the request does not add new entity picks, the expand path returns a short notice only—the full DOMAIN / TSV teaching table is not replayed (token-saving). Steady state remains
plasm/plasm_runwith the existinglogical_session_ref. - If there is no binding, or the stored binding points at an expired or missing execute row, the server may open a new
(prompt_hash, session). - The primary
entry_idfor the first open is chosen in lexicographic order among distinct catalog ids in the seed set, so two calls with the same set of catalog seeds in different order still agree on the same primary for SessionReuseKey matching. - The tool response JSON includes
logical_session_id,logical_session_ref, andexecute_binding: { prompt_hash, session_id }. plasmwithlogical_session_refandprogram- Steady state for most user turns: use
plasmonly; do not repeatplasm_contextunless you need a newintentor new seeds.
2. intent (host contract)¶
- Role: Opaque string selected by the host to mean “this agent / window / subagent / task isolation boundary / whatever the host needs to separate.”
- Stability: Must stay stable for the duration of that context. Rotating
intentper message or per unrelated micro-step breaks idempotent logical session recovery and will fragment reuse. - Not inferable: The Plasm server does not infer a stable “ongoing user task” from the transport, workspace path, or prompt text. The host must supply
intentwhen it wants continuity.
3. SessionReuseKey (when execute open can reuse a row)¶
Defined in execute_session.rs as the key for in-memory try_reuse_session on new open:
| Field | Role |
|---|---|
tenant_scope |
Incoming-auth tenant / anonymous scope. |
entry_id |
Primary catalog id for the open (lexicographically first among seed catalogs). |
catalog_cgs_hash |
Pinned CGS digest. |
entities |
Sorted, deduplicated primary-catalog entity seeds. |
principal |
Present when PLASM_AUTH_RESOLUTION=delegated. |
plugin_generation_id |
Compile-plugin pin when a compile plugin is loaded. |
logical_session_id |
Logical UUID string; scopes reuse per logical session. Absent when a host opens execution without binding a logical id. |
If any of these differ from a prior open, a new execute row may be created. Changing catalog hash or plugin generation is intentional: the old session is not a safe match.
4. Stale execute binding (continuity break)¶
MCP can retain a logical handle (logical_session_ref) and a binding (prompt_hash, session_id) in memory or in the host-wide map after the in-memory ExecuteSessionStore row was dropped (e.g. idle TTL). The next plasm_context will treat the binding as missing and may open a new execute session.
When that happens, the plasm_context result includes:
- Markdown: a prominent notice that the prior in-memory session was missing or expired, that all earlier
e#/m#/p#from this chat are void, and that the model must re-read the new DOMAIN/TSV from this response only. _meta.plasm.continuity: on everyplasm_contextresponse,stale_binding_recovered(boolean) andnew_symbol_space(boolean —truewhen a new execute row with a new symbol table was bound, e.g. first open or a non-reused open after an expiry). Whenstale_binding_recoveredis true,previous_executemay name the old(prompt_hash, session_id). Whennew_symbol_spaceis true,discard_cached_plasm_symbolsis alsotrue(same meaning asnew_symbol_spacefor tool clients that key off a dedicated key).
5. Execute-time projection and result summaries¶
- Projection (path expressions, batch steps): selects which fields and rows the executor materializes. This is the authoritative narrowing for what the engine computes.
- Table / TSV / Markdown on the wire: may still cap, summarize lossy fields, or point at
resources/readfor full JSON snapshots, even when the execution already used projection. That is transport shaping, not a second projection system.
Large-result guidance: prefer projection in expressions first; when the surface must still be shortened for the tool channel, use snapshot links and _meta.plasm as today.
6. Related code¶
plasm_context/plasm: mcp_server.rsapply_capability_seeds,execute_session_create_response_inner, primary entry: http_execute.rsSessionReuseKey,ExecuteSessionStore::try_reuse_session: execute_session.rs- MCP Markdown previews and threshold: mcp_run_markdown.rs