Crate rmcp_actix_web

Source
Expand description

§rmcp-actix-web

actix-web transport implementations for RMCP (Rust Model Context Protocol).

This crate provides HTTP-based transport layers for the Model Context Protocol (MCP), offering a complete alternative to the default Axum-based transports in the main RMCP crate. If you’re already using actix-web in your application or prefer its API, this crate allows you to integrate MCP services seamlessly without introducing additional web frameworks.

§Features

  • SSE (Server-Sent Events) Transport: Real-time, unidirectional communication from server to client
  • Streamable HTTP Transport: Bidirectional communication with session management
  • Full MCP Compatibility: Implements the complete MCP specification
  • Drop-in Replacement: Same service implementations work with either Axum or actix-web transports
  • Production Ready: Built on battle-tested actix-web framework

§Quick Start

§SSE Server Example

use rmcp_actix_web::SseServer;
use rmcp::{ServerHandler, model::ServerInfo};

#[actix_web::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create SSE server with default configuration
    let server = SseServer::serve("127.0.0.1:8080".parse()?).await?;
     
    // Attach your MCP service implementation
    let ct = server.with_service(|| MyMcpService::new());
     
    // Server runs until cancellation token is triggered
    ct.cancelled().await;
    Ok(())
}

§Streamable HTTP Server Example

use rmcp_actix_web::StreamableHttpService;
use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
use rmcp::{ServerHandler, model::ServerInfo};
use actix_web::{App, HttpServer};
use std::sync::Arc;

#[actix_web::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let service = Arc::new(StreamableHttpService::new(
        || Ok(MyMcpService::new()),
        LocalSessionManager::default().into(),
        Default::default(),
    ));

    HttpServer::new(move || {
        App::new()
            .configure(StreamableHttpService::configure(service.clone()))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await?;
     
    Ok(())
}

§Transport Selection

Choose between the two transport types based on your needs:

  • SSE Transport: Best for server-to-client streaming, simpler protocol, works through proxies
  • Streamable HTTP: Full bidirectional communication, session management, more complex protocol

§Examples

See the examples/ directory for complete working examples:

  • counter_sse.rs - SSE server with a simple counter service
  • counter_streamable_http.rs - Streamable HTTP server example
  • composition_sse_example.rs - SSE server with framework-level composition
  • composition_streamable_http_example.rs - StreamableHttp with custom mounting
  • multi_service_example.rs - Multiple MCP services with different transports

§Framework-Level Composition

Both transports support framework-level composition aligned with RMCP patterns, allowing you to mount MCP services at custom paths within existing actix-web applications.

§SSE Server Composition

The SseServer::new() method returns a tuple of (SseServer, Scope) where the Scope can be mounted at custom paths:

use rmcp_actix_web::{SseServer, SseServerConfig};
use actix_web::{App, web};
use tokio_util::sync::CancellationToken;

let config = SseServerConfig {
    bind: "127.0.0.1:8080".parse().unwrap(),
    sse_path: "/sse".to_string(),
    post_path: "/message".to_string(),
    ct: CancellationToken::new(),
    sse_keep_alive: None,
};

let (sse_server, mcp_scope) = SseServer::new(config);
let _ct = sse_server.with_service(|| MyService::new());

// Mount at custom path
let app = App::new()
    .service(web::scope("/api/v1/mcp").service(mcp_scope));

§StreamableHttp Service Composition

The StreamableHttpService::scope() method returns a configured Scope for framework-level composition:

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

let service = Arc::new(StreamableHttpService::new(
    || Ok(MyService::new()),
    LocalSessionManager::default().into(),
    Default::default(),
));

let scope = StreamableHttpService::scope(service);

// Mount at custom path
let app = App::new()
    .service(web::scope("/api/v1/calculator").service(scope));

§Multi-Service Composition

You can compose multiple MCP services with different transports in a single application:

use rmcp_actix_web::{SseServer, SseServerConfig, StreamableHttpService};
use actix_web::{App, web};

// SSE service
let sse_config = SseServerConfig {
    bind: "127.0.0.1:0".parse().unwrap(),
    sse_path: "/sse".to_string(),
    post_path: "/message".to_string(),
    ct: CancellationToken::new(),
    sse_keep_alive: None,
};
let (sse_server, sse_scope) = SseServer::new(sse_config);
let _ct = sse_server.with_service(|| MyService::new());

// StreamableHttp service
let http_service = Arc::new(StreamableHttpService::new(
    || Ok(MyService::new()),
    LocalSessionManager::default().into(),
    Default::default(),
));
let http_scope = StreamableHttpService::scope(http_service);

// Compose both in one app
let app = App::new()
    .service(web::scope("/api/v1/sse").service(sse_scope))
    .service(web::scope("/api/v1/http").service(http_scope));

See the examples/ directory for complete working examples of composition patterns.

§Performance Considerations

  • SSE transport has lower overhead for unidirectional communication
  • Streamable HTTP maintains persistent sessions which may use more memory
  • Both transports use efficient async I/O through actix-web’s actor system
  • Framework-level composition adds minimal overhead

§Feature Flags

This crate supports selective compilation of transport types:

  • transport-sse-server (default): Enables SSE transport
  • transport-streamable-http-server (default): Enables StreamableHttp transport

To use only specific transports, disable default features:

[dependencies]
rmcp-actix-web = { version = "0.1", default-features = false, features = ["transport-sse-server"] }

Re-exports§

pub use transport::sse_server::SseServer;
pub use transport::streamable_http_server::StreamableHttpService;

Modules§

transport
Transport implementations for the Model Context Protocol using actix-web.

Structs§

SseServerConfig
Configuration for the SSE server transport.
StreamableHttpServerConfig
Configuration for the streamable HTTP server transport.

Type Aliases§

SessionId
Unique identifier for client sessions in server-side HTTP transports.