pub struct StreamableHttpService<S, M> {
pub config: StreamableHttpServerConfig,
/* private fields */
}Expand description
§Streamable HTTP server
An HTTP service that implements the Streamable HTTP transport for MCP servers.
§Session management
When StreamableHttpServerConfig::stateful_mode is true (the default),
the server creates a session for each client that sends an initialize
request. The session ID is returned in the Mcp-Session-Id response header
and the client must include it on all subsequent requests.
Two tool calls carrying the same Mcp-Session-Id come from the same logical
session (typically one conversation in an LLM client). Different session IDs
mean different sessions.
The SessionManager trait controls how sessions are stored and routed:
LocalSessionManager— in-memory session store (default).NeverSessionManager— disables sessions entirely (stateless mode).
§Accessing HTTP request data from tool handlers
The service consumes the request body but injects the remaining
http::request::Parts into crate::model::Extensions, which is
accessible through crate::service::RequestContext.
§Reading the raw HTTP parts
use rmcp::handler::server::tool::Extension;
use http::request::Parts;
async fn my_tool(Extension(parts): Extension<Parts>) {
tracing::info!("http parts:{parts:?}")
}§Reading the session ID inside a tool handler
use rmcp::handler::server::tool::Extension;
use rmcp::service::RequestContext;
use rmcp::model::RoleServer;
#[tool(description = "session-aware tool")]
async fn my_tool(
&self,
Extension(parts): Extension<http::request::Parts>,
) -> Result<CallToolResult, rmcp::ErrorData> {
if let Some(session_id) = parts.headers.get("mcp-session-id") {
tracing::info!(?session_id, "called from session");
}
// ...
}§Accessing custom axum/tower extension state
State added via axum’s Extension layer is available inside
Parts.extensions:
use rmcp::service::RequestContext;
use rmcp::model::RoleServer;
#[derive(Clone)]
struct AppState { /* ... */ }
#[tool(description = "example")]
async fn my_tool(
&self,
ctx: RequestContext<RoleServer>,
) -> Result<CallToolResult, rmcp::ErrorData> {
let parts = ctx.extensions.get::<http::request::Parts>().unwrap();
let state = parts.extensions.get::<AppState>().unwrap();
// use state...
}Fields§
§config: StreamableHttpServerConfigImplementations§
Source§impl<S, M> StreamableHttpService<S, M>
impl<S, M> StreamableHttpService<S, M>
Trait Implementations§
Source§impl<S, M> Clone for StreamableHttpService<S, M>
impl<S, M> Clone for StreamableHttpService<S, M>
Source§fn clone(&self) -> StreamableHttpService<S, M>
fn clone(&self) -> StreamableHttpService<S, M>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<RequestBody, S, M> Service<Request<RequestBody>> for StreamableHttpService<S, M>
impl<RequestBody, S, M> Service<Request<RequestBody>> for StreamableHttpService<S, M>
Source§type Error = Infallible
type Error = Infallible
Source§type Future = Pin<Box<dyn Future<Output = Result<<StreamableHttpService<S, M> as Service<Request<RequestBody>>>::Response, <StreamableHttpService<S, M> as Service<Request<RequestBody>>>::Error>> + Send>>
type Future = Pin<Box<dyn Future<Output = Result<<StreamableHttpService<S, M> as Service<Request<RequestBody>>>::Response, <StreamableHttpService<S, M> as Service<Request<RequestBody>>>::Error>> + Send>>
Auto Trait Implementations§
impl<S, M> !RefUnwindSafe for StreamableHttpService<S, M>
impl<S, M> !UnwindSafe for StreamableHttpService<S, M>
impl<S, M> Freeze for StreamableHttpService<S, M>
impl<S, M> Send for StreamableHttpService<S, M>
impl<S, M> Sync for StreamableHttpService<S, M>
impl<S, M> Unpin for StreamableHttpService<S, M>
impl<S, M> UnsafeUnpin for StreamableHttpService<S, M>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T, Request> ServiceExt<Request> for T
impl<T, Request> ServiceExt<Request> for T
Source§fn ready(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
fn ready(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
Source§fn ready_and(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
fn ready_and(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
please use the ServiceExt::ready method instead
Source§fn ready_oneshot(self) -> ReadyOneshot<Self, Request>where
Self: Sized,
fn ready_oneshot(self) -> ReadyOneshot<Self, Request>where
Self: Sized,
Source§fn oneshot(self, req: Request) -> Oneshot<Self, Request>where
Self: Sized,
fn oneshot(self, req: Request) -> Oneshot<Self, Request>where
Self: Sized,
Service, calling with the providing request once it is ready.Source§fn and_then<F>(self, f: F) -> AndThen<Self, F>
fn and_then<F>(self, f: F) -> AndThen<Self, F>
poll_ready method. Read moreSource§fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
poll_ready method. Read moreSource§fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
poll_ready method. Read moreSource§fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
Result<Self::Response, Self::Error>)
to a different value, regardless of whether the future succeeds or
fails. Read more