Skip to content

Commit e714482

Browse files
authored
feat: update examples and docs for streamable http (#77)
* feat: add streamable http support to mcp server * chore: update readme * docs: update readme * fix: typo * chore: update sse support flag * fix: test on windows * chore: update examples and readme * feat: strengthen protocol compliance * chore: update readme * chore: update recording gift * chore: add tracing for client disconnect * chore: update captures * fix: typo * fix: stream lifecycle and improve shutdown * fix: build issue * fix: build issue
1 parent 1864ce8 commit e714482

File tree

25 files changed

+413
-126
lines changed

25 files changed

+413
-126
lines changed

.release-manifest.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
2-
"crates/rust-mcp-sdk": "0.5.0",
3-
"crates/rust-mcp-macros": "0.5.0",
4-
"crates/rust-mcp-transport": "0.4.0",
5-
"examples/hello-world-mcp-server": "0.1.24",
6-
"examples/hello-world-mcp-server-core": "0.1.15",
7-
"examples/simple-mcp-client": "0.1.24",
8-
"examples/simple-mcp-client-core": "0.1.24",
9-
"examples/hello-world-server-core-sse": "0.1.15",
10-
"examples/hello-world-server-sse": "0.1.24",
11-
"examples/simple-mcp-client-core-sse": "0.1.15",
12-
"examples/simple-mcp-client-sse": "0.1.15"
13-
}
2+
"crates/rust-mcp-sdk": "0.5.0",
3+
"crates/rust-mcp-macros": "0.5.0",
4+
"crates/rust-mcp-transport": "0.4.0",
5+
"examples/hello-world-mcp-server": "0.1.24",
6+
"examples/hello-world-mcp-server-core": "0.1.15",
7+
"examples/simple-mcp-client": "0.1.24",
8+
"examples/simple-mcp-client-core": "0.1.24",
9+
"examples/hello-world-server-core-streamable-http": "0.1.15",
10+
"examples/hello-world-server-streamable-http": "0.1.24",
11+
"examples/simple-mcp-client-core-sse": "0.1.15",
12+
"examples/simple-mcp-client-sse": "0.1.15"
13+
}

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ 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",
11+
"examples/hello-world-server-streamable-http",
12+
"examples/hello-world-server-core-streamable-http",
1313
"examples/simple-mcp-client-sse",
1414
"examples/simple-mcp-client-core-sse",
1515
]

README.md

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ This project supports following transports:
3737
- [x] Streamable HTTP Support for MCP Servers
3838
- [x] DNS Rebinding Protection
3939
- [x] Batch Messages
40-
- [x] Streaming & non-streaming JSON responses
40+
- [x] Streaming & non-streaming JSON response
4141
- [ ] Streamable HTTP Support for MCP Clients
4242
- [ ] Resumability
43-
- [ ] Authentication / OAuth
43+
- [ ] Authentication / Oauth
4444

4545
**⚠️** Project is currently under development and should be used at your own risk.
4646

@@ -50,6 +50,9 @@ This project supports following transports:
5050
- [MCP Server (sse)](#mcp-server-sse)
5151
- [MCP Client (stdio)](#mcp-client-stdio)
5252
- [MCP Client (sse)](#mcp-client-sse)
53+
- [Getting Started](#getting-started)
54+
- [HyperServerOptions](#hyperserveroptions)
55+
- [Security Considerations](#security-considerations)
5356
- [Cargo features](#cargo-features)
5457
- [Available Features](#available-features)
5558
- [MCP protocol versions with corresponding features](#mcp-protocol-versions-with-corresponding-features)
@@ -111,10 +114,14 @@ See hello-world-mcp-server example running in [MCP Inspector](https://modelconte
111114

112115
![mcp-server in rust](assets/examples/hello-world-mcp-server.gif)
113116

114-
### MCP Server (sse)
117+
### MCP Server (Streamable HTTP)
115118

116119
Creating an MCP server in `rust-mcp-sdk` with the `sse` transport allows multiple clients to connect simultaneously with no additional setup.
117-
Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and transform options.
120+
Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and HyperServerOptions.
121+
122+
123+
💡 By default, both **Streamable HTTP** and **SSE** transports are enabled for backward compatibility. To disable the SSE transport , set the `sse_support` to false in the `HyperServerOptions`.
124+
118125

119126
```rust
120127

@@ -145,6 +152,7 @@ let server = hyper_server::create_server(
145152
handler,
146153
HyperServerOptions {
147154
host: "127.0.0.1".to_string(),
155+
sse_support: false,
148156
..Default::default()
149157
},
150158
);
@@ -199,9 +207,9 @@ impl ServerHandler for MyServerHandler {
199207

200208
👉 For a more detailed example of a [Hello World MCP](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server) Server that supports multiple tools and provides more type-safe handling of `CallToolRequest`, check out: **[examples/hello-world-mcp-server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server)**
201209

202-
See hello-world-server-sse example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
210+
See hello-world-server-streamable-http example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
203211

204-
![mcp-server in rust](assets/examples/hello-world-server-sse.gif)
212+
![mcp-server in rust](assets/examples/hello-world-server-streamable-http.gif)
205213

206214
---
207215

@@ -303,6 +311,103 @@ Creating an MCP client using the `rust-mcp-sdk` with the SSE transport is almost
303311

304312
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)
305313

314+
## HyperServerOptions
315+
316+
HyperServer is a lightweight Axum-based server that streamlines MCP servers by supporting **Streamable HTTP** and **SSE** transports. It supports simultaneous client connections, internal session management, and includes built-in security features like DNS rebinding protection and more.
317+
318+
HyperServer is highly customizable through HyperServerOptions provided during initialization.
319+
320+
A typical example of creating a HyperServer that exposes the MCP server via Streamable HTTP and SSE transports at:
321+
322+
```rs
323+
324+
let server = hyper_server::create_server(
325+
server_details,
326+
handler,
327+
HyperServerOptions {
328+
host: "127.0.0.1".to_string(),
329+
enable_ssl: true,
330+
..Default::default()
331+
},
332+
);
333+
334+
server.start().await?;
335+
336+
```
337+
338+
Here is a list of available options with descriptions for configuring the HyperServer:
339+
```rs
340+
pub struct HyperServerOptions {
341+
/// Hostname or IP address the server will bind to (default: "127.0.0.1")
342+
pub host: String,
343+
344+
/// Hostname or IP address the server will bind to (default: "8080")
345+
pub port: u16,
346+
347+
/// Optional custom path for the Streamable HTTP endpoint (default: `/mcp`)
348+
pub custom_streamable_http_endpoint: Option<String>,
349+
350+
/// This setting only applies to streamable HTTP.
351+
/// If true, the server will return JSON responses instead of starting an SSE stream.
352+
/// This can be useful for simple request/response scenarios without streaming.
353+
/// Default is false (SSE streams are preferred).
354+
pub enable_json_response: Option<bool>,
355+
356+
/// Interval between automatic ping messages sent to clients to detect disconnects
357+
pub ping_interval: Duration,
358+
359+
/// Shared transport configuration used by the server
360+
pub transport_options: Arc<TransportOptions>,
361+
362+
/// Optional thread-safe session id generator to generate unique session IDs.
363+
pub session_id_generator: Option<Arc<dyn IdGenerator>>,
364+
365+
/// Enables SSL/TLS if set to `true`
366+
pub enable_ssl: bool,
367+
368+
/// Path to the SSL/TLS certificate file (e.g., "cert.pem").
369+
/// Required if `enable_ssl` is `true`.
370+
pub ssl_cert_path: Option<String>,
371+
372+
/// Path to the SSL/TLS private key file (e.g., "key.pem").
373+
/// Required if `enable_ssl` is `true`.
374+
pub ssl_key_path: Option<String>,
375+
376+
/// If set to true, the SSE transport will also be supported for backward compatibility (default: true)
377+
pub sse_support: bool,
378+
379+
/// Optional custom path for the Server-Sent Events (SSE) endpoint (default: `/sse`)
380+
/// Applicable only if sse_support is true
381+
pub custom_sse_endpoint: Option<String>,
382+
383+
/// Optional custom path for the MCP messages endpoint for sse (default: `/messages`)
384+
/// Applicable only if sse_support is true
385+
pub custom_messages_endpoint: Option<String>,
386+
387+
/// List of allowed host header values for DNS rebinding protection.
388+
/// If not specified, host validation is disabled.
389+
pub allowed_hosts: Option<Vec<String>>,
390+
391+
/// List of allowed origin header values for DNS rebinding protection.
392+
/// If not specified, origin validation is disabled.
393+
pub allowed_origins: Option<Vec<String>>,
394+
395+
/// Enable DNS rebinding protection (requires allowedHosts and/or allowedOrigins to be configured).
396+
/// Default is false for backwards compatibility.
397+
pub dns_rebinding_protection: bool,
398+
}
399+
400+
```
401+
402+
### Security Considerations
403+
404+
When using Streamable HTTP transport, following security best practices are recommended:
405+
406+
- Enable DNS rebinding protection and provide proper `allowed_hosts` and `allowed_origins` to prevent DNS rebinding attacks.
407+
- When running locally, bind only to localhost (127.0.0.1 / localhost) rather than all network interfaces (0.0.0.0)
408+
- Use TLS/HTTPS for production deployments
409+
410+
306411
## Cargo Features
307412

308413
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.
-7.75 KB
Loading
266 KB
Loading
360 KB
Loading

crates/rust-mcp-sdk/README.md

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ This project supports following transports:
3737
- [x] Streamable HTTP Support for MCP Servers
3838
- [x] DNS Rebinding Protection
3939
- [x] Batch Messages
40-
- [x] Streaming & non-streaming JSON responses
40+
- [x] Streaming & non-streaming JSON response
4141
- [ ] Streamable HTTP Support for MCP Clients
4242
- [ ] Resumability
43-
- [ ] Authentication / OAuth
43+
- [ ] Authentication / Oauth
4444

4545
**⚠️** Project is currently under development and should be used at your own risk.
4646

@@ -50,6 +50,9 @@ This project supports following transports:
5050
- [MCP Server (sse)](#mcp-server-sse)
5151
- [MCP Client (stdio)](#mcp-client-stdio)
5252
- [MCP Client (sse)](#mcp-client-sse)
53+
- [Getting Started](#getting-started)
54+
- [HyperServerOptions](#hyperserveroptions)
55+
- [Security Considerations](#security-considerations)
5356
- [Cargo features](#cargo-features)
5457
- [Available Features](#available-features)
5558
- [MCP protocol versions with corresponding features](#mcp-protocol-versions-with-corresponding-features)
@@ -111,10 +114,14 @@ See hello-world-mcp-server example running in [MCP Inspector](https://modelconte
111114

112115
![mcp-server in rust](assets/examples/hello-world-mcp-server.gif)
113116

114-
### MCP Server (sse)
117+
### MCP Server (Streamable HTTP)
115118

116119
Creating an MCP server in `rust-mcp-sdk` with the `sse` transport allows multiple clients to connect simultaneously with no additional setup.
117-
Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and transform options.
120+
Simply create a Hyper Server using `hyper_server::create_server()` and pass in the same handler and HyperServerOptions.
121+
122+
123+
💡 By default, both **Streamable HTTP** and **SSE** transports are enabled for backward compatibility. To disable the SSE transport , set the `sse_support` to false in the `HyperServerOptions`.
124+
118125

119126
```rust
120127

@@ -145,6 +152,7 @@ let server = hyper_server::create_server(
145152
handler,
146153
HyperServerOptions {
147154
host: "127.0.0.1".to_string(),
155+
sse_support: false,
148156
..Default::default()
149157
},
150158
);
@@ -199,9 +207,9 @@ impl ServerHandler for MyServerHandler {
199207

200208
👉 For a more detailed example of a [Hello World MCP](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server) Server that supports multiple tools and provides more type-safe handling of `CallToolRequest`, check out: **[examples/hello-world-mcp-server](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server)**
201209

202-
See hello-world-server-sse example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
210+
See hello-world-server-streamable-http example running in [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) :
203211

204-
![mcp-server in rust](assets/examples/hello-world-server-sse.gif)
212+
![mcp-server in rust](assets/examples/hello-world-server-streamable-http.gif)
205213

206214
---
207215

@@ -303,6 +311,103 @@ Creating an MCP client using the `rust-mcp-sdk` with the SSE transport is almost
303311

304312
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)
305313

314+
## HyperServerOptions
315+
316+
HyperServer is a lightweight Axum-based server that streamlines MCP servers by supporting **Streamable HTTP** and **SSE** transports. It supports simultaneous client connections, internal session management, and includes built-in security features like DNS rebinding protection and more.
317+
318+
HyperServer is highly customizable through HyperServerOptions provided during initialization.
319+
320+
A typical example of creating a HyperServer that exposes the MCP server via Streamable HTTP and SSE transports at:
321+
322+
```rs
323+
324+
let server = hyper_server::create_server(
325+
server_details,
326+
handler,
327+
HyperServerOptions {
328+
host: "127.0.0.1".to_string(),
329+
enable_ssl: true,
330+
..Default::default()
331+
},
332+
);
333+
334+
server.start().await?;
335+
336+
```
337+
338+
Here is a list of available options with descriptions for configuring the HyperServer:
339+
```rs
340+
pub struct HyperServerOptions {
341+
/// Hostname or IP address the server will bind to (default: "127.0.0.1")
342+
pub host: String,
343+
344+
/// Hostname or IP address the server will bind to (default: "8080")
345+
pub port: u16,
346+
347+
/// Optional custom path for the Streamable HTTP endpoint (default: `/mcp`)
348+
pub custom_streamable_http_endpoint: Option<String>,
349+
350+
/// This setting only applies to streamable HTTP.
351+
/// If true, the server will return JSON responses instead of starting an SSE stream.
352+
/// This can be useful for simple request/response scenarios without streaming.
353+
/// Default is false (SSE streams are preferred).
354+
pub enable_json_response: Option<bool>,
355+
356+
/// Interval between automatic ping messages sent to clients to detect disconnects
357+
pub ping_interval: Duration,
358+
359+
/// Shared transport configuration used by the server
360+
pub transport_options: Arc<TransportOptions>,
361+
362+
/// Optional thread-safe session id generator to generate unique session IDs.
363+
pub session_id_generator: Option<Arc<dyn IdGenerator>>,
364+
365+
/// Enables SSL/TLS if set to `true`
366+
pub enable_ssl: bool,
367+
368+
/// Path to the SSL/TLS certificate file (e.g., "cert.pem").
369+
/// Required if `enable_ssl` is `true`.
370+
pub ssl_cert_path: Option<String>,
371+
372+
/// Path to the SSL/TLS private key file (e.g., "key.pem").
373+
/// Required if `enable_ssl` is `true`.
374+
pub ssl_key_path: Option<String>,
375+
376+
/// If set to true, the SSE transport will also be supported for backward compatibility (default: true)
377+
pub sse_support: bool,
378+
379+
/// Optional custom path for the Server-Sent Events (SSE) endpoint (default: `/sse`)
380+
/// Applicable only if sse_support is true
381+
pub custom_sse_endpoint: Option<String>,
382+
383+
/// Optional custom path for the MCP messages endpoint for sse (default: `/messages`)
384+
/// Applicable only if sse_support is true
385+
pub custom_messages_endpoint: Option<String>,
386+
387+
/// List of allowed host header values for DNS rebinding protection.
388+
/// If not specified, host validation is disabled.
389+
pub allowed_hosts: Option<Vec<String>>,
390+
391+
/// List of allowed origin header values for DNS rebinding protection.
392+
/// If not specified, origin validation is disabled.
393+
pub allowed_origins: Option<Vec<String>>,
394+
395+
/// Enable DNS rebinding protection (requires allowedHosts and/or allowedOrigins to be configured).
396+
/// Default is false for backwards compatibility.
397+
pub dns_rebinding_protection: bool,
398+
}
399+
400+
```
401+
402+
### Security Considerations
403+
404+
When using Streamable HTTP transport, following security best practices are recommended:
405+
406+
- Enable DNS rebinding protection and provide proper `allowed_hosts` and `allowed_origins` to prevent DNS rebinding attacks.
407+
- When running locally, bind only to localhost (127.0.0.1 / localhost) rather than all network interfaces (0.0.0.0)
408+
- Use TLS/HTTPS for production deployments
409+
410+
306411
## Cargo Features
307412

308413
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.
-7.75 KB
Loading
266 KB
Loading

0 commit comments

Comments
 (0)