Skip to main content

SessionState

Struct SessionState 

Source
pub struct SessionState { /* private fields */ }
Expand description

Shared session state that can be cloned across requests.

Uses atomic operations for thread-safe state transitions. Includes a type-safe extensions map for storing session-scoped data like authentication claims.

§Example

use tower_mcp::SessionState;

#[derive(Debug, Clone)]
struct UserClaims {
    user_id: String,
    role: String,
}

let session = SessionState::new();

// Store auth claims in the session
session.insert(UserClaims {
    user_id: "user123".to_string(),
    role: "admin".to_string(),
});

// Retrieve claims later
if let Some(claims) = session.get::<UserClaims>() {
    assert_eq!(claims.role, "admin");
}

Implementations§

Source§

impl SessionState

Source

pub fn new() -> Self

Create a new session in the Uninitialized phase

Source

pub fn insert<T: Send + Sync + Clone + 'static>(&self, val: T)

Insert a value into the session extensions.

This is typically used by auth middleware to store claims that can be checked by capability filters.

§Example
use tower_mcp::SessionState;

let session = SessionState::new();
session.insert(42u32);
assert_eq!(session.get::<u32>(), Some(42));
Source

pub fn get<T: Send + Sync + Clone + 'static>(&self) -> Option<T>

Get a cloned value from the session extensions.

Returns None if no value of the given type has been inserted or if the lock cannot be acquired.

§Example
use tower_mcp::SessionState;

let session = SessionState::new();
session.insert("hello".to_string());
assert_eq!(session.get::<String>(), Some("hello".to_string()));
assert_eq!(session.get::<u32>(), None);
Source

pub fn phase(&self) -> SessionPhase

Get the current session phase

Source

pub fn is_initialized(&self) -> bool

Check if the session is initialized (operation phase)

Source

pub fn mark_handshake_started(&self)

Record that an initialize request has been received for this session.

Transports that create a session in response to an initialize frame call this at the front door, before the request is dispatched. That is what lets mark_initialized tell the #458 race (the initialized notification overtook a dispatch that is still running) apart from a client that never sent initialize at all.

mark_initializing also sets this, so a transport that dispatches initialize in frame order does not need to call it. Idempotent, and never cleared.

Source

pub fn handshake_started(&self) -> bool

Whether an initialize request has been received for this session.

False for a fresh session, and for one a client is trying to open with an unsolicited initialized notification.

Source

pub fn mark_initializing(&self) -> bool

Transition from Uninitialized to Initializing. Called after responding to an initialize request. Returns true if the transition was successful.

Also records that the handshake has started, so the notification that follows can complete it.

Source

pub fn mark_initialized(&self) -> bool

Transition to Initialized phase. Called when receiving an initialized notification.

Accepts Initializing → Initialized, and Uninitialized → Initialized only once mark_handshake_started has run. The latter path handles a race in HTTP transports where the client sends the initialized notification before the server has finished processing the initialize request (#458); the handshake flag is what keeps it from also accepting a client that skipped initialize, which would leave the server serving a peer whose protocol version and capabilities it never learned.

Transports that serve without a handshake by design (restored sessions, optional_sessions, the stateless 2026-07-28 path) want mark_preinitialized instead.

Returns true if the transition was successful.

Source

pub fn mark_preinitialized(&self) -> bool

Move the session straight to Initialized, no handshake required.

For transports that serve requests without an initialize exchange because the protocol or the deployment says they should: a session restored from a store (it was initialized on another instance), the optional_sessions opt-in for clients that do not carry a session ID forward, and the stateless 2026-07-28 path, which has no handshake at all.

This is a server-side decision, unlike mark_initialized, which acts on a frame the client sent. Returns true if the phase changed.

Source

pub fn is_request_allowed(&self, method: &str) -> bool

Check if a request method is allowed in the current phase. Per spec:

  • Before initialization: only initialize and ping are valid
  • During all phases: ping is always valid

Trait Implementations§

Source§

impl Clone for SessionState

Source§

fn clone(&self) -> SessionState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for SessionState

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more