Skip to content

Commit 26f7ca2

Browse files
committed
feat: add sse transport support
1 parent c2854e1 commit 26f7ca2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+6336
-305
lines changed

Cargo.lock

Lines changed: 2411 additions & 228 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ members = [
88
"examples/simple-mcp-client-core",
99
"examples/hello-world-mcp-server",
1010
"examples/hello-world-mcp-server-core",
11+
"examples/hello-world-server-sse",
12+
"examples/hello-world-server-core-sse",
13+
"examples/simple-mcp-client-sse",
14+
"examples/simple-mcp-client-core-sse",
1115
]
1216

1317
[workspace.dependencies]
@@ -26,13 +30,20 @@ async-trait = { version = "0.1" }
2630
strum = { version = "0.27", features = ["derive"] }
2731
thiserror = { version = "2.0" }
2832
tokio-stream = { version = "0.1" }
33+
uuid = { version = "1" }
2934
tracing = "0.1"
3035
tracing-subscriber = { version = "0.3", features = [
3136
"env-filter",
3237
"std",
3338
"fmt",
3439
] }
3540

41+
axum = "0.8"
42+
rustls = "0.23"
43+
tokio-rustls = "0.26"
44+
axum-server = { version = "0.7" }
45+
reqwest = "0.12"
46+
bytes = "1.10.1"
3647

3748
# [workspace.dependencies.windows]
3849

Makefile.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ args = ["fmt", "--all", "--", "--check"]
88

99
[tasks.clippy]
1010
command = "cargo"
11-
args = ["clippy"]
11+
args = ["clippy", "--workspace", "--all-targets", "--all-features"]
1212

1313
[tasks.test]
1414
install_crate = "nextest"

README.md

Lines changed: 132 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,41 @@
1111
[<img alt="Hello World MCP Server" src="https://img.shields.io/badge/Example-Hello%20World%20MCP-0286ba?style=for-the-badge&logo=rust" height="22">
1212
](examples/hello-world-mcp-server)
1313

14-
A high-performance, asynchronous toolkit for building MCP servers and clients.
14+
A high-performance, asynchronous toolkit for building MCP servers and clients.
1515
Focus on your app's logic while **rust-mcp-sdk** takes care of the rest!
1616

17-
**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
17+
**rust-mcp-sdk** provides the necessary components for developing both servers and clients in the MCP ecosystem.
1818
Leveraging the [rust-mcp-schema](https://github.com/rust-mcp-stack/rust-mcp-schema) crate simplifies the process of building robust and reliable MCP servers and clients, ensuring consistency and minimizing errors in data handling and message processing.
1919

20-
**⚠️WARNING**: This project only supports Standard Input/Output (stdio) transport at this time, with support for SSE (Server-Sent Events) transport still in progress and not yet available. Project is currently under development and should be used at your own risk.
20+
This project currently supports **stdio** (Standard Input/Output) and **sse** (Server-Sent Events) transports.
2121

22-
## Projects using `rust-mcp-sdk`
2322

24-
Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
23+
🚀 SSE transport works over HTTP/HTTPS. The `rust-mcp-sdk` includes a lightweight Axum-based server that handles all core functionality seamlessly. Switching between `stdio` and `sse` is straightforward, requiring minimal code changes. The server is designed to efficiently handle multiple concurrent client connections and offers built-in support for SSL and custom middleware.
2524

26-
| Icon | Name | Description | Link |
27-
|------|------|-------------|------|
28-
| <a href="https://rust-mcp-stack.github.io/rust-mcp-filesystem"><img src="https://raw.githubusercontent.com/rust-mcp-stack/rust-mcp-filesystem/refs/heads/main/docs/_media/rust-mcp-filesystem.png" width="64"/></a> | [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
29-
| <a href="https://rust-mcp-stack.github.io/mcp-discovery"><img src="https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/refs/heads/main/docs/_media/mcp-discovery-logo.png" width="64"/></a> | [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
25+
**⚠️** **Streamable HTTP** transport and authentication still in progress and not yet available. Project is currently under development and should be used at your own risk.
26+
27+
## Table of Contents
28+
- [Usage Examples](#usage-examples)
29+
- [MCP Server (stdio)](#mcp-server-stdio)
30+
- [MCP Server (sse)](#mcp-server-sse)
31+
- [MCP Client (stdio)](#mcp-client-stdio)
32+
- [MCP Client (sse)](#mcp-client-sse)
33+
- [Cargo features](#cargo-features)
34+
- [Available Features](#available-features)
35+
- [Default Features](#default-features)
36+
- [Using Only the server Features](#using-only-the-server-features)
37+
- [Using Only the client Features](#using-only-the-client-features)
38+
- [Choosing Between Standard and Core Handlers traits](#choosing-between-standard-and-core-handlers-traits)
39+
- [Choosing Between **ServerHandler** and **ServerHandlerCore**](#choosing-between-serverhandler-and-serverhandlercore)
40+
- [Choosing Between **ClientHandler** and **ClientHandlerCore**](#choosing-between-clienthandler-and-clienthandlercore)
41+
- [Projects using Rust MCP SDK](#projects-using-rust-mcp-sdk)
42+
- [Contributing](#contributing)
43+
- [Development](#development)
44+
- [License](#license)
3045

3146
## Usage Examples
3247

33-
### MCP Server
48+
### MCP Server (stdio)
3449

3550
Create a MCP server with a `tool` that will print a `Hello World!` message:
3651

@@ -70,7 +85,51 @@ async fn main() -> SdkResult<()> {
7085
}
7186
```
7287

73-
The implementation of `MyServerHandler` could be as simple as the following:
88+
### MCP Server (sse)
89+
90+
Creating an MCP server in `rust-mcp-sdk` with the `sse` transport allows multiple clients to connect simultaneously with no additional setup.
91+
Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and transform options.
92+
93+
```rust
94+
95+
// STEP 1: Define server details and capabilities
96+
let server_details = InitializeResult {
97+
// server name and version
98+
server_info: Implementation {
99+
name: "Hello World MCP Server".to_string(),
100+
version: "0.1.0".to_string(),
101+
},
102+
capabilities: ServerCapabilities {
103+
// indicates that server support mcp tools
104+
tools: Some(ServerCapabilitiesTools { list_changed: None }),
105+
..Default::default() // Using default values for other fields
106+
},
107+
meta: None,
108+
instructions: Some("server instructions...".to_string()),
109+
protocol_version: LATEST_PROTOCOL_VERSION.to_string(),
110+
};
111+
112+
// STEP 2: instantiate our custom handler for handling MCP messages
113+
let handler = MyServerHandler {};
114+
115+
// STEP 3: instantiate HyperServer, providing `server_details` , `handler` and HyperServerOptions
116+
let server = hyper_server::create_server(
117+
server_details,
118+
handler,
119+
HyperServerOptions {
120+
host: "127.0.0.1".to_string(),
121+
..Default::default()
122+
},
123+
);
124+
125+
// STEP 4: Start the server
126+
server.start().await?;
127+
128+
Ok(())
129+
```
130+
131+
132+
The implementation of `MyServerHandler` is the same regardless of the transport used and could be as simple as the following:
74133

75134
```rust
76135

@@ -122,7 +181,7 @@ See hello-world-mcp-server example running in [MCP Inspector](https://modelconte
122181

123182
---
124183

125-
### MCP Client
184+
### MCP Client (stdio)
126185

127186
Create an MCP client that starts the [@modelcontextprotocol/server-everything](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) server, displays the server's name, version, and list of tools, then uses the add tool provided by the server to sum 120 and 28, printing the result.
128187

@@ -203,23 +262,38 @@ Here is the output :
203262

204263
> your results may vary slightly depending on the version of the MCP Server in use when you run it.
205264
265+
### MCP Client (sse)
266+
Creating an MCP client using the `rust-mcp-sdk` with the SSE transport is almost identical, with one exception at `step 3`. Instead of creating a `StdioTransport`, you simply create a `ClientSseTransport`. The rest of the code remains the same:
267+
268+
```diff
269+
- let transport = StdioTransport::create_with_server_launch(
270+
- "npx",
271+
- vec![ "-y".to_string(), "@modelcontextprotocol/server-everything".to_string()],
272+
- None, TransportOptions::default()
273+
-)?;
274+
+ let transport = ClientSseTransport::new(MCP_SERVER_URL, ClientSseTransportOptions::default())?;
275+
```
276+
277+
206278
## Getting Started
207279

208280
If you are looking for a step-by-step tutorial on how to get started with `rust-mcp-sdk` , please see : [Getting Started MCP Server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/doc/getting-started-mcp-server.md)
209281

210-
## Features
282+
## Cargo Features
211283

212-
The `rust-mcp-sdk` crate provides three optional features: `server` , `client` and `macros`. By default, all features are enabled for maximum functionality. You can customize which features to include based on your project's needs.
284+
The `rust-mcp-sdk` crate provides several features that can be enabled or disabled. By default, all features are enabled to ensure maximum functionality, but you can customize which ones to include based on your project's requirements.
213285

214286
### Available Features
215287

216-
- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP services.
288+
- `server`: Activates MCP server capabilities in `rust-mcp-sdk`, providing modules and APIs for building and managing MCP servers.
217289
- `client`: Activates MCP client capabilities, offering modules and APIs for client development and communicating with MCP servers.
290+
- `hyper-server`: This feature enables the **sse** transport for MCP servers, supporting multiple simultaneous client connections out of the box.
291+
- `ssl`: This feature enables TLS/SSL support for the **sse** transport when used with the `hyper-server`.
218292
- `macros`: Provides procedural macros for simplifying the creation and manipulation of MCP Tool structures.
219293

220-
### Default Behavior
294+
### Default Features
221295

222-
All features (server, client, and macros) are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
296+
All features are enabled by default. When you include rust-mcp-sdk as a dependency without specifying features, all will be included:
223297

224298
<!-- x-release-please-start-version -->
225299

@@ -230,7 +304,7 @@ rust-mcp-sdk = "0.2.0"
230304

231305
<!-- x-release-please-end -->
232306

233-
### Using Only the server Feature
307+
### Using Only the server Features
234308

235309
If you only need the MCP Server functionality, you can disable the default features and explicitly enable the server feature. Add the following to your Cargo.toml:
236310

@@ -240,10 +314,11 @@ If you only need the MCP Server functionality, you can disable the default featu
240314
[dependencies]
241315
rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["server","macros"] }
242316
```
317+
Optionally add `hyper-server` for **sse** transport, and `ssl` feature for tls/ssl support of the `hyper-server`
243318

244319
<!-- x-release-please-end -->
245320

246-
### Using Only the client Feature
321+
### Using Only the client Features
247322

248323
If you only need the MCP Client functionality, you can disable the default features and explicitly enable the client feature. Add the following to your Cargo.toml:
249324

@@ -256,28 +331,59 @@ rust-mcp-sdk = { version = "0.2.0", default-features = false, features = ["clien
256331

257332
<!-- x-release-please-end -->
258333

259-
### Choosing Between `mcp_server_handler` and `mcp_server_handler_core`
334+
## Choosing Between Standard and Core Handlers traits
335+
Learn when to use the `mcp_*_handler` traits versus the lower-level `mcp_*_handler_core` traits for both server and client implementations. This section helps you decide based on your project's need for simplicity versus fine-grained control.
336+
337+
### Choosing Between `ServerHandler` and `ServerHandlerCore`
260338

261339
[rust-mcp-sdk](https://github.com/rust-mcp-stack/rust-mcp-sdk) provides two type of handler traits that you can chose from:
262340

263-
- **mcp_server_handler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
341+
- **ServerHandler**: This is the recommended trait for your MCP project, offering a default implementation for all types of MCP messages. It includes predefined implementations within the trait, such as handling initialization or responding to ping requests, so you only need to override and customize the handler functions relevant to your specific needs.
264342
Refer to [examples/hello-world-mcp-server/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server/src/handler.rs) for an example.
265343

266-
- **mcp_server_handler_core**: If you need more control over MCP messages, consider using `mcp_server_handler_core`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
344+
- **ServerHandlerCore**: If you need more control over MCP messages, consider using `ServerHandlerCore`. It offers three primary methods to manage the three MCP message types: `request`, `notification`, and `error`. While still providing type-safe objects in these methods, it allows you to determine how to handle each message based on its type and parameters.
267345
Refer to [examples/hello-world-mcp-server-core/src/handler.rs](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server-core/src/handler.rs) for an example.
268346

269347
---
270348

271-
**👉 Note:** Depending on your choice between `mcp_server_handler` and `mcp_server_handler_core`, you must use either `server_runtime::create_server()` or `server_runtime_core::create_server()` , respectively.
349+
**👉 Note:** Depending on whether you choose `ServerHandler` or `ServerHandlerCore`, you must use the `create_server()` function from the appropriate module:
350+
351+
- For `ServerHandler`:
352+
- Use `server_runtime::create_server()` for servers with stdio transport
353+
- Use `hyper_server::create_server()` for servers with sse transport
354+
355+
- For `ServerHandlerCore`:
356+
- Use `server_runtime_core::create_server()` for servers with stdio transport
357+
- Use `hyper_server_core::create_server()` for servers with sse transport
272358

273359
---
274360

275-
### Choosing Between `mcp_client_handler` and `mcp_client_handler_core`
276361

277-
The same principles outlined above apply to the client-side handlers, `mcp_client_handler` and `mcp_client_handler_core`.
278-
Use `client_runtime::create_client()` or `client_runtime_core::create_client()` , respectively.
362+
### Choosing Between `ClientHandler` and `ClientHandlerCore`
363+
364+
The same principles outlined above apply to the client-side handlers, `ClientHandler` and `ClientHandlerCore`.
365+
366+
- Use `client_runtime::create_client()` when working with `ClientHandler`
367+
368+
- Use `client_runtime_core::create_client()` when working with `ClientHandlerCore`
369+
370+
Both functions create an MCP client instance.
371+
372+
373+
279374
Check out the corresponding examples at: [examples/simple-mcp-client](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client) and [examples/simple-mcp-client-core](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client-core).
280375

376+
377+
## Projects using Rust MCP SDK
378+
379+
Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their name, description, and links to their repositories or project pages.
380+
381+
| Icon | Name | Description | Link |
382+
|------|------|-------------|------|
383+
| <a href="https://rust-mcp-stack.github.io/rust-mcp-filesystem"><img src="https://raw.githubusercontent.com/rust-mcp-stack/rust-mcp-filesystem/refs/heads/main/docs/_media/rust-mcp-filesystem.png" width="64"/></a> | [Rust MCP Filesystem](https://rust-mcp-stack.github.io/rust-mcp-filesystem) | Fast, asynchronous MCP server for seamless filesystem operations offering enhanced capabilities, improved performance, and a robust feature set tailored for modern filesystem interactions. | [GitHub](https://github.com/rust-mcp-stack/rust-mcp-filesystem) |
384+
| <a href="https://rust-mcp-stack.github.io/mcp-discovery"><img src="https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/refs/heads/main/docs/_media/mcp-discovery-logo.png" width="64"/></a> | [MCP Discovery](https://rust-mcp-stack.github.io/mcp-discovery) | A lightweight command-line tool for discovering and documenting MCP Server capabilities. | [GitHub](https://github.com/rust-mcp-stack/mcp-discovery) |
385+
386+
281387
## Contributing
282388

283389
We welcome everyone who wishes to contribute! Please refer to the [contributing](CONTRIBUTING.md) guidelines for more details.
504 KB
Loading
283 KB
Loading

crates/rust-mcp-sdk/Cargo.toml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,35 @@ async-trait = { workspace = true }
2222
futures = { workspace = true }
2323
thiserror = { workspace = true }
2424

25+
axum = { workspace = true, optional = true }
26+
uuid = { workspace = true, features = ["v4"], optional = true }
27+
tokio-stream = { workspace = true, optional = true }
28+
axum-server = { version = "0.7", features = [], optional = true }
29+
tracing.workspace = true
30+
31+
# rustls = { workspace = true, optional = true }
32+
hyper = { version = "1.6.0" }
33+
34+
[dev-dependencies]
35+
tracing-subscriber = { workspace = true, features = [
36+
"env-filter",
37+
"std",
38+
"fmt",
39+
] }
40+
2541
[features]
26-
default = ["client", "server", "macros"] # All features enabled by default
27-
server = [] # Server feature
28-
client = [] # Client feature
42+
default = [
43+
"client",
44+
"server",
45+
"macros",
46+
"hyper-server",
47+
"ssl",
48+
] # All features enabled by default
49+
server = [] # Server feature
50+
client = [] # Client feature
51+
hyper-server = ["axum", "axum-server", "uuid", "tokio-stream"]
52+
ssl = ["axum-server/tls-rustls"]
2953
macros = ["rust-mcp-macros"]
3054

31-
3255
[lints]
3356
workspace = true

crates/rust-mcp-sdk/src/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use rust_mcp_schema::RpcError;
22
use rust_mcp_transport::error::TransportError;
33
use thiserror::Error;
44

5+
#[cfg(feature = "hyper-server")]
6+
use crate::hyper_servers::error::TransportServerError;
7+
58
pub type SdkResult<T> = core::result::Result<T, McpSdkError>;
69

710
#[derive(Debug, Error)]
@@ -18,6 +21,9 @@ pub enum McpSdkError {
1821
AnyError(Box<(dyn std::error::Error + Send + Sync)>),
1922
#[error("{0}")]
2023
SdkError(#[from] rust_mcp_schema::schema_utils::SdkError),
24+
#[cfg(feature = "hyper-server")]
25+
#[error("{0}")]
26+
TransportServerError(#[from] TransportServerError),
2127
}
2228

2329
#[deprecated(since = "0.2.0", note = "Use `McpSdkError` instead.")]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
mod app_state;
2+
pub mod error;
3+
pub mod hyper_server;
4+
pub mod hyper_server_core;
5+
mod routes;
6+
mod server;
7+
mod session_store;
8+
9+
pub use server::*;
10+
pub use session_store::*;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use std::{sync::Arc, time::Duration};
2+
3+
use rust_mcp_schema::InitializeResult;
4+
use rust_mcp_transport::TransportOptions;
5+
6+
use crate::mcp_traits::mcp_handler::McpServerHandler;
7+
8+
use super::{session_store::SessionStore, IdGenerator};
9+
10+
/// Application state struct for the Hyper server
11+
///
12+
/// Holds shared, thread-safe references to session storage, ID generator,
13+
/// server details, handler, ping interval, and transport options.
14+
#[derive(Clone)]
15+
pub struct AppState {
16+
pub session_store: Arc<dyn SessionStore>,
17+
pub id_generator: Arc<dyn IdGenerator>,
18+
pub server_details: Arc<InitializeResult>,
19+
pub handler: Arc<dyn McpServerHandler>,
20+
pub ping_interval: Duration,
21+
pub transport_options: Arc<TransportOptions>,
22+
}

0 commit comments

Comments
 (0)