diff --git a/Cargo.lock b/Cargo.lock
index d51b2d6..9d4b91d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.88"
+version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
@@ -118,7 +118,7 @@ dependencies = [
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"hyper-util",
"itoa",
"matchit",
@@ -170,7 +170,7 @@ dependencies = [
"fs-err",
"http 1.3.1",
"http-body 1.0.1",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"rustls",
@@ -239,9 +239,9 @@ dependencies = [
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
[[package]]
name = "bumpalo"
@@ -257,9 +257,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
-version = "1.2.32"
+version = "1.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
+checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
dependencies = [
"jobserver",
"libc",
@@ -277,9 +277,9 @@ dependencies = [
[[package]]
name = "cfg-if"
-version = "1.0.1"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cfg_aliases"
@@ -870,13 +870,14 @@ dependencies = [
[[package]]
name = "hyper"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [
+ "atomic-waker",
"bytes",
"futures-channel",
- "futures-util",
+ "futures-core",
"h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
@@ -884,6 +885,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
+ "pin-utils",
"smallvec",
"tokio",
"want",
@@ -896,7 +898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
dependencies = [
"http 1.3.1",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"hyper-util",
"rustls",
"rustls-pki-types",
@@ -919,7 +921,7 @@ dependencies = [
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"ipnet",
"libc",
"percent-encoding",
@@ -1385,9 +1387,9 @@ dependencies = [
[[package]]
name = "prettyplease"
-version = "0.2.36"
+version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
@@ -1395,9 +1397,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.97"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
@@ -1432,7 +1434,7 @@ dependencies = [
"rustc-hash 2.1.1",
"rustls",
"socket2 0.5.10",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
"tracing",
"web-time",
@@ -1453,7 +1455,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tinyvec",
"tracing",
"web-time",
@@ -1626,7 +1628,7 @@ dependencies = [
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"hyper-rustls",
"hyper-util",
"js-sys",
@@ -1705,14 +1707,14 @@ dependencies = [
"axum",
"axum-server",
"futures",
- "hyper 1.6.0",
+ "hyper 1.7.0",
"reqwest",
"rust-mcp-macros",
"rust-mcp-schema",
"rust-mcp-transport",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
"tokio-stream",
"tracing",
@@ -1731,7 +1733,7 @@ dependencies = [
"rust-mcp-schema",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
"tokio-stream",
"tracing",
@@ -1855,9 +1857,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.142"
+version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
+checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
dependencies = [
"itoa",
"memchr",
@@ -1932,7 +1934,7 @@ dependencies = [
"rust-mcp-sdk",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
]
@@ -1946,7 +1948,7 @@ dependencies = [
"rust-mcp-sdk",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
]
@@ -1960,7 +1962,7 @@ dependencies = [
"rust-mcp-sdk",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
"tracing",
"tracing-subscriber",
@@ -1976,7 +1978,7 @@ dependencies = [
"rust-mcp-sdk",
"serde",
"serde_json",
- "thiserror 2.0.14",
+ "thiserror 2.0.15",
"tokio",
"tracing",
"tracing-subscriber",
@@ -2028,9 +2030,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.104"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -2068,11 +2070,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.14"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
+checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
dependencies = [
- "thiserror-impl 2.0.14",
+ "thiserror-impl 2.0.15",
]
[[package]]
@@ -2088,9 +2090,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
-version = "2.0.14"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
+checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
dependencies = [
"proc-macro2",
"quote",
@@ -2149,9 +2151,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
diff --git a/README.md b/README.md
index ef5b4ed..1581d1d 100644
--- a/README.md
+++ b/README.md
@@ -526,6 +526,7 @@ Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their na
|
| [text-to-cypher](https://github.com/FalkorDB/text-to-cypher) | A high-performance Rust-based API service that translates natural language text to Cypher queries for graph databases. | [GitHub](https://github.com/FalkorDB/text-to-cypher) |
|
| [notify-mcp](https://github.com/Tuurlijk/notify-mcp) | A Model Context Protocol (MCP) server that provides desktop notification functionality. | [GitHub](https://github.com/Tuurlijk/notify-mcp) |
|
| [lst](https://github.com/WismutHansen/lst) | `lst` is a personal lists, notes, and blog posts management application with a focus on plain-text storage, offline-first functionality, and multi-device synchronization. | [GitHub](https://github.com/WismutHansen/lst) |
+|
| [rust-mcp-server](https://github.com/Vaiz/rust-mcp-server) | `rust-mcp-server` allows the model to perform actions on your behalf, such as building, testing, and analyzing your Rust code. | [GitHub](https://github.com/Vaiz/rust-mcp-server) |
diff --git a/crates/rust-mcp-sdk/README.md b/crates/rust-mcp-sdk/README.md
index ef5b4ed..1581d1d 100644
--- a/crates/rust-mcp-sdk/README.md
+++ b/crates/rust-mcp-sdk/README.md
@@ -526,6 +526,7 @@ Below is a list of projects that utilize the `rust-mcp-sdk`, showcasing their na
|
| [text-to-cypher](https://github.com/FalkorDB/text-to-cypher) | A high-performance Rust-based API service that translates natural language text to Cypher queries for graph databases. | [GitHub](https://github.com/FalkorDB/text-to-cypher) |
|
| [notify-mcp](https://github.com/Tuurlijk/notify-mcp) | A Model Context Protocol (MCP) server that provides desktop notification functionality. | [GitHub](https://github.com/Tuurlijk/notify-mcp) |
|
| [lst](https://github.com/WismutHansen/lst) | `lst` is a personal lists, notes, and blog posts management application with a focus on plain-text storage, offline-first functionality, and multi-device synchronization. | [GitHub](https://github.com/WismutHansen/lst) |
+|
| [rust-mcp-server](https://github.com/Vaiz/rust-mcp-server) | `rust-mcp-server` allows the model to perform actions on your behalf, such as building, testing, and analyzing your Rust code. | [GitHub](https://github.com/Vaiz/rust-mcp-server) |
diff --git a/crates/rust-mcp-sdk/src/error.rs b/crates/rust-mcp-sdk/src/error.rs
index 2feab67..3de8d98 100644
--- a/crates/rust-mcp-sdk/src/error.rs
+++ b/crates/rust-mcp-sdk/src/error.rs
@@ -41,6 +41,3 @@ impl McpSdkError {
None
}
}
-
-#[deprecated(since = "0.2.0", note = "Use `McpSdkError` instead.")]
-pub type MCPSdkError = McpSdkError;
diff --git a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler.rs b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler.rs
index f8ee1a0..c6fb208 100644
--- a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler.rs
+++ b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler.rs
@@ -148,7 +148,7 @@ pub trait ClientHandler: Send + Sync + 'static {
//********************//
async fn handle_error(
&self,
- error: RpcError,
+ error: &RpcError,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError> {
Ok(())
diff --git a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler_core.rs b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler_core.rs
index 3bbe5c9..a0afdf1 100644
--- a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler_core.rs
+++ b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_client_handler_core.rs
@@ -38,7 +38,7 @@ pub trait ClientHandlerCore: Send + Sync + 'static {
/// - `error` – The error data received from the MCP server.
async fn handle_error(
&self,
- error: RpcError,
+ error: &RpcError,
runtime: &dyn McpClient,
) -> std::result::Result<(), RpcError>;
diff --git a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler.rs b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler.rs
index bf3fe17..89aebf5 100644
--- a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler.rs
+++ b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler.rs
@@ -319,7 +319,7 @@ pub trait ServerHandler: Send + Sync + 'static {
/// Customize this function in your specific handler to implement behavior tailored to your MCP server's capabilities and requirements.
async fn handle_error(
&self,
- error: RpcError,
+ error: &RpcError,
runtime: &dyn McpServer,
) -> std::result::Result<(), RpcError> {
Ok(())
diff --git a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler_core.rs b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler_core.rs
index fffe2fc..e7b0e6d 100644
--- a/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler_core.rs
+++ b/crates/rust-mcp-sdk/src/mcp_handlers/mcp_server_handler_core.rs
@@ -45,7 +45,7 @@ pub trait ServerHandlerCore: Send + Sync + 'static {
/// - `error` – The error data received from the MCP client.
async fn handle_error(
&self,
- error: RpcError,
+ error: &RpcError,
runtime: &dyn McpServer,
) -> std::result::Result<(), RpcError>;
async fn on_server_started(&self, runtime: &dyn McpServer) {
diff --git a/crates/rust-mcp-sdk/src/mcp_macros/tool_box.rs b/crates/rust-mcp-sdk/src/mcp_macros/tool_box.rs
index 3bd2735..a5b75d5 100644
--- a/crates/rust-mcp-sdk/src/mcp_macros/tool_box.rs
+++ b/crates/rust-mcp-sdk/src/mcp_macros/tool_box.rs
@@ -57,15 +57,6 @@ macro_rules! tool_box {
)*
]
}
-
- #[deprecated(since = "0.2.0", note = "Use `tools()` instead.")]
- pub fn get_tools() -> Vec {
- vec![
- $(
- $tool::tool(),
- )*
- ]
- }
}
diff --git a/crates/rust-mcp-sdk/src/mcp_runtimes/client_runtime.rs b/crates/rust-mcp-sdk/src/mcp_runtimes/client_runtime.rs
index 8d113c3..7ee0815 100644
--- a/crates/rust-mcp-sdk/src/mcp_runtimes/client_runtime.rs
+++ b/crates/rust-mcp-sdk/src/mcp_runtimes/client_runtime.rs
@@ -1,20 +1,26 @@
pub mod mcp_client_runtime;
pub mod mcp_client_runtime_core;
-use crate::schema::{
- schema_utils::{
- self, ClientMessage, ClientMessages, FromMessage, MessageFromClient, ServerMessage,
- ServerMessages,
+use crate::{
+ mcp_traits::{RequestIdGen, RequestIdGenNumeric},
+ schema::{
+ schema_utils::{
+ self, ClientMessage, ClientMessages, FromMessage, MessageFromClient, ServerMessage,
+ ServerMessages,
+ },
+ InitializeRequest, InitializeRequestParams, InitializeResult, InitializedNotification,
+ RequestId, RpcError, ServerResult,
},
- InitializeRequest, InitializeRequestParams, InitializeResult, InitializedNotification,
- RpcError, ServerResult,
};
use async_trait::async_trait;
use futures::future::{join_all, try_join_all};
use futures::StreamExt;
use rust_mcp_transport::{IoStream, McpDispatch, MessageDispatcher, Transport};
-use std::sync::{Arc, RwLock};
+use std::{
+ sync::{Arc, RwLock},
+ time::Duration,
+};
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::sync::Mutex;
@@ -41,6 +47,7 @@ pub struct ClientRuntime {
// Details about the connected server
server_details: Arc>>,
handlers: Mutex>>>,
+ request_id_gen: Box,
}
impl ClientRuntime {
@@ -61,6 +68,7 @@ impl ClientRuntime {
client_details,
server_details: Arc::new(RwLock::new(None)),
handlers: Mutex::new(vec![]),
+ request_id_gen: Box::new(RequestIdGenNumeric::new(None)),
}
}
@@ -123,7 +131,19 @@ impl ClientRuntime {
None
}
ServerMessage::Error(jsonrpc_error) => {
- self.handler.handle_error(jsonrpc_error.error, self).await?;
+ self.handler
+ .handle_error(&jsonrpc_error.error, self)
+ .await?;
+ if let Some(tx_response) = transport.pending_request_tx(&jsonrpc_error.id).await {
+ tx_response
+ .send(ServerMessage::Error(jsonrpc_error))
+ .map_err(|e| RpcError::internal_error().with_message(e.to_string()))?;
+ } else {
+ tracing::warn!(
+ "Received an error response with no corresponding request: {:?}",
+ &jsonrpc_error.id
+ );
+ }
None
}
ServerMessage::Response(response) => {
@@ -133,7 +153,7 @@ impl ClientRuntime {
.map_err(|e| RpcError::internal_error().with_message(e.to_string()))?;
} else {
tracing::warn!(
- "Received response or error without a matching request: {:?}",
+ "Received a response with no corresponding request: {:?}",
&response.id
);
}
@@ -284,6 +304,33 @@ impl McpClient for ClientRuntime {
}
}
+ async fn send(
+ &self,
+ message: MessageFromClient,
+ request_id: Option,
+ timeout: Option,
+ ) -> SdkResult