Skip to main content

StreamableHttpService

Struct StreamableHttpService 

Source
pub struct StreamableHttpService<S, M = LocalSessionManager> { /* private fields */ }
Expand description

Streamable HTTP transport service for actix-web integration.

Provides bidirectional MCP communication over HTTP with session management. This service can be integrated into existing actix-web applications. Uses a builder pattern for configuration.

§Type Parameters

  • S - The MCP service type that handles protocol messages
  • M - The session manager type (defaults to LocalSessionManager)

§Architecture

The service manages endpoints with multiple HTTP methods:

  • GET: For streaming event connections
  • POST: For sending messages and creating sessions
  • DELETE: For closing sessions

Each client is identified by a session ID that must be provided in request headers.

§Example

use rmcp_actix_web::transport::StreamableHttpService;
use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
use actix_web::{App, HttpServer, web};
use std::{sync::Arc, time::Duration};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // Create service OUTSIDE HttpServer::new() to share across workers
    let service = StreamableHttpService::builder()
        .service_factory(Arc::new(|| Ok(MyService::new())))
        .session_manager(Arc::new(LocalSessionManager::default()))
        .stateful_mode(true)
        .sse_keep_alive(Duration::from_secs(30))
        .build();

    HttpServer::new(move || {
        App::new()
            // Clone service for each worker (shares the same LocalSessionManager)
            .service(web::scope("/mcp").service(service.clone().scope()))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Implementations§

Source§

impl<S, M> StreamableHttpService<S, M>

Source

pub fn builder() -> StreamableHttpServiceBuilder<S, M>

Create an instance of StreamableHttpService using the builder syntax

Source§

impl<S, M> StreamableHttpService<S, M>
where S: Clone + ServerHandler + Send + 'static, M: SessionManager + 'static,

Source

pub fn scope( self, ) -> Scope<impl ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error, InitError = ()>>

Creates a new scope configured with this service for framework-level composition.

This method provides framework-level composition aligned with RMCP patterns, similar to how SseService::scope() works. This allows mounting the streamable HTTP service at custom paths using actix-web’s routing.

The method consumes self, so you can call it directly on the service instance. If you need to use the service multiple times, wrap it in an Arc and clone it.

This method is equivalent to scope_with_path("").

§Returns

Returns an actix-web Scope configured with the streamable HTTP routes

§Example
use rmcp_actix_web::transport::StreamableHttpService;
use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
use actix_web::{App, HttpServer, web};
use std::sync::Arc;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // Create service OUTSIDE HttpServer::new() to share across workers
    let service = StreamableHttpService::builder()
        .service_factory(Arc::new(|| Ok(MyService::new())))
        .session_manager(Arc::new(LocalSessionManager::default()))
        .build();

    HttpServer::new(move || {
        App::new()
            // Clone service for each worker (shares the same LocalSessionManager)
            .service(web::scope("/api/v1/mcp").service(service.clone().scope()))
    })
    .bind("127.0.0.1:8080")?
    .run();

    Ok(())
}
Source

pub fn scope_with_path( self, path: &str, ) -> Scope<impl ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error, InitError = ()>>

Creates a new scope configured with this service for framework-level composition.

This method provides framework-level composition aligned with RMCP patterns, similar to how SseService::scope() works. This allows mounting the streamable HTTP service at custom paths using actix-web’s routing.

The method consumes self, so you can call it directly on the service instance. If you need to use the service multiple times, wrap it in an Arc and clone it.

This method is similar to scope except that it allows specifying a custom path.

§Returns

Returns an actix-web Scope configured with the streamable HTTP routes

§Example
use rmcp_actix_web::transport::{StreamableHttpService, AuthorizationHeader};
use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
use actix_web::{App, HttpServer, web};
use std::sync::Arc;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // Create service OUTSIDE HttpServer::new() to share across workers
    let service = StreamableHttpService::builder()
        .service_factory(Arc::new(|| Ok(MyService::new())))
        .session_manager(Arc::new(LocalSessionManager::default()))
        .build();

    HttpServer::new(move || {
        App::new()
            // Clone service for each worker (shares the same LocalSessionManager)
            .service(service.clone().scope_with_path("/api/v1/mcp"))
    })
    .bind("127.0.0.1:8080")?
    .run();

    Ok(())
}

Trait Implementations§

Source§

impl<S, M> Clone for StreamableHttpService<S, M>

Source§

fn clone(&self) -> Self

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

Auto Trait Implementations§

§

impl<S, M = LocalSessionManager> !RefUnwindSafe for StreamableHttpService<S, M>

§

impl<S, M = LocalSessionManager> !UnwindSafe for StreamableHttpService<S, M>

§

impl<S, M> Freeze for StreamableHttpService<S, M>

§

impl<S, M> Send for StreamableHttpService<S, M>
where M: Sync + Send,

§

impl<S, M> Sync for StreamableHttpService<S, M>
where M: Sync + Send,

§

impl<S, M> Unpin for StreamableHttpService<S, M>

§

impl<S, M> UnsafeUnpin for StreamableHttpService<S, M>

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<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> 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> 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 = Infallible

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<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