Skip to content

Commit 3cefc7a

Browse files
committed
refactor(rmcpk-core): migrates model and errors into rmcp-core
1 parent 6a42304 commit 3cefc7a

32 files changed

+142
-75
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11

22

33
[workspace]
4-
members = ["crates/rmcp", "crates/rmcp-macros", "examples/*"]
4+
members = ["crates/rmcp","crates/rmcp-core", "crates/rmcp-macros", "examples/*"]
55
resolver = "2"
66

77
[workspace.dependencies]
8+
rmcp-core = { version = "0.1.5", path = "./crates/rmcp-core" }
89
rmcp = { version = "0.1.5", path = "./crates/rmcp" }
910
rmcp-macros = { version = "0.1.5", path = "./crates/rmcp-macros" }
1011

crates/rmcp-core/Cargo.toml

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[package]
2+
name = "rmcp-core"
3+
license = { workspace = true }
4+
version = { workspace = true }
5+
edition = { workspace = true }
6+
repository = { workspace = true }
7+
homepage = { workspace = true }
8+
readme = { workspace = true }
9+
description = "Rust SDK for Model Context Protocol"
10+
documentation = "https://docs.rs/rmcp"
11+
12+
[package.metadata.docs.rs]
13+
all-features = true
14+
15+
[dependencies]
16+
serde = { version = "1.0", features = ["derive", "rc"] }
17+
serde_json = "1.0"
18+
thiserror = "2"
19+
chrono = { version = "0.4.38", features = ["serde"] }
20+
tokio = { version = "1", features = ["sync", "macros", "rt", "time"] }
21+
futures = "0.3"
22+
tracing = { version = "0.1" }
23+
tokio-util = { version = "0.7" }
24+
pin-project-lite = "0.2"
25+
paste = { version = "1", optional = true }
26+
# for auto generate schema
27+
schemars = { version = "0.8", optional = true }
28+
29+
# for image encoding
30+
base64 = { version = "0.22", optional = true }
31+
32+
# macro
33+
rmcp-macros = { version = "0.1", workspace = true, optional = true }
34+
35+
[features]
36+
default = ["base64", "macros"]
37+
macros = ["dep:rmcp-macros", "dep:paste"]
38+
schemars = ["dep:schemars"]
39+
40+
[dev-dependencies]
41+
tokio = { version = "1", features = ["full"] }
42+
43+
anyhow = "1.0"
44+
tracing-subscriber = { version = "0.3", features = [
45+
"env-filter",
46+
"std",
47+
"fmt",
48+
] }
49+
async-trait = "0.1"
File renamed without changes.

crates/rmcp-core/src/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod error;
2+
pub use error::Error;
3+
4+
pub mod model;
5+
pub use model::*;
6+
#[cfg(feature = "macros")]
7+
pub use paste;
8+
#[cfg(feature = "macros")]
9+
pub use rmcp_macros::tool;

crates/rmcp/src/model.rs renamed to crates/rmcp-core/src/model.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ macro_rules! object {
4545
};
4646
}
4747
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
48-
#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
48+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4949
pub struct EmptyObject {}
5050

5151
pub trait ConstString: Default {
@@ -1040,6 +1040,36 @@ impl From<CancelledNotification> for ClientNotification {
10401040
}
10411041
}
10421042

1043+
pub trait IntoCallToolResult {
1044+
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error>;
1045+
}
1046+
impl IntoCallToolResult for () {
1047+
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
1048+
Ok(CallToolResult::success(vec![]))
1049+
}
1050+
}
1051+
1052+
impl<T: IntoContents> IntoCallToolResult for T {
1053+
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
1054+
Ok(CallToolResult::success(self.into_contents()))
1055+
}
1056+
}
1057+
1058+
impl IntoCallToolResult for Result<CallToolResult, crate::Error> {
1059+
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
1060+
self
1061+
}
1062+
}
1063+
1064+
impl<T: IntoContents, E: IntoContents> IntoCallToolResult for Result<T, E> {
1065+
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
1066+
match self {
1067+
Ok(value) => Ok(CallToolResult::success(value.into_contents())),
1068+
Err(error) => Ok(CallToolResult::error(error.into_contents())),
1069+
}
1070+
}
1071+
}
1072+
10431073
#[cfg(test)]
10441074
mod tests {
10451075
use serde_json::json;

crates/rmcp/src/model/capabilities.rs renamed to crates/rmcp-core/src/model/capabilities.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub struct RootsCapabilities {
3838
///
3939
/// # Builder
4040
/// ```rust
41-
/// # use rmcp::model::ClientCapabilities;
41+
/// # use rmcp_core::model::ClientCapabilities;
4242
/// let cap = ClientCapabilities::builder()
4343
/// .enable_experimental()
4444
/// .enable_roots()
@@ -58,7 +58,7 @@ pub struct ClientCapabilities {
5858
///
5959
/// ## Builder
6060
/// ```rust
61-
/// # use rmcp::model::ServerCapabilities;
61+
/// # use rmcp_core::model::ServerCapabilities;
6262
/// let cap = ServerCapabilities::builder()
6363
/// .enable_logging()
6464
/// .enable_experimental()

crates/rmcp/src/model/extension.rs renamed to crates/rmcp-core/src/model/extension.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl Extensions {
6161
/// # Example
6262
///
6363
/// ```
64-
/// # use rmcp::model::Extensions;
64+
/// # use rmcp_core::model::Extensions;
6565
/// let mut ext = Extensions::new();
6666
/// assert!(ext.insert(5i32).is_none());
6767
/// assert!(ext.insert(4u8).is_none());
@@ -79,7 +79,7 @@ impl Extensions {
7979
/// # Example
8080
///
8181
/// ```
82-
/// # use rmcp::model::Extensions;
82+
/// # use rmcp_core::model::Extensions;
8383
/// let mut ext = Extensions::new();
8484
/// assert!(ext.get::<i32>().is_none());
8585
/// ext.insert(5i32);
@@ -98,7 +98,7 @@ impl Extensions {
9898
/// # Example
9999
///
100100
/// ```
101-
/// # use rmcp::model::Extensions;
101+
/// # use rmcp_core::model::Extensions;
102102
/// let mut ext = Extensions::new();
103103
/// ext.insert(String::from("Hello"));
104104
/// ext.get_mut::<String>().unwrap().push_str(" World");
@@ -118,7 +118,7 @@ impl Extensions {
118118
/// # Example
119119
///
120120
/// ```
121-
/// # use rmcp::model::Extensions;
121+
/// # use rmcp_core::model::Extensions;
122122
/// let mut ext = Extensions::new();
123123
/// *ext.get_or_insert(1i32) += 2;
124124
///
@@ -134,7 +134,7 @@ impl Extensions {
134134
/// # Example
135135
///
136136
/// ```
137-
/// # use rmcp::model::Extensions;
137+
/// # use rmcp_core::model::Extensions;
138138
/// let mut ext = Extensions::new();
139139
/// *ext.get_or_insert_with(|| 1i32) += 2;
140140
///
@@ -158,7 +158,7 @@ impl Extensions {
158158
/// # Example
159159
///
160160
/// ```
161-
/// # use rmcp::model::Extensions;
161+
/// # use rmcp_core::model::Extensions;
162162
/// let mut ext = Extensions::new();
163163
/// *ext.get_or_insert_default::<i32>() += 2;
164164
///
@@ -175,7 +175,7 @@ impl Extensions {
175175
/// # Example
176176
///
177177
/// ```
178-
/// # use rmcp::model::Extensions;
178+
/// # use rmcp_core::model::Extensions;
179179
/// let mut ext = Extensions::new();
180180
/// ext.insert(5i32);
181181
/// assert_eq!(ext.remove::<i32>(), Some(5i32));
@@ -193,7 +193,7 @@ impl Extensions {
193193
/// # Example
194194
///
195195
/// ```
196-
/// # use rmcp::model::Extensions;
196+
/// # use rmcp_core::model::Extensions;
197197
/// let mut ext = Extensions::new();
198198
/// ext.insert(5i32);
199199
/// ext.clear();
@@ -212,7 +212,7 @@ impl Extensions {
212212
/// # Example
213213
///
214214
/// ```
215-
/// # use rmcp::model::Extensions;
215+
/// # use rmcp_core::model::Extensions;
216216
/// let mut ext = Extensions::new();
217217
/// assert!(ext.is_empty());
218218
/// ext.insert(5i32);
@@ -228,7 +228,7 @@ impl Extensions {
228228
/// # Example
229229
///
230230
/// ```
231-
/// # use rmcp::model::Extensions;
231+
/// # use rmcp_core::model::Extensions;
232232
/// let mut ext = Extensions::new();
233233
/// assert_eq!(ext.len(), 0);
234234
/// ext.insert(5i32);
@@ -247,7 +247,7 @@ impl Extensions {
247247
/// # Example
248248
///
249249
/// ```
250-
/// # use rmcp::model::Extensions;
250+
/// # use rmcp_core::model::Extensions;
251251
/// let mut ext_a = Extensions::new();
252252
/// ext_a.insert(8u8);
253253
/// ext_a.insert(16u16);
File renamed without changes.
File renamed without changes.

crates/rmcp/Cargo.toml

+5-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ paste = { version = "1", optional = true }
2727
schemars = { version = "0.8", optional = true }
2828

2929
# for image encoding
30-
base64 = { version = "0.21", optional = true }
30+
base64 = { version = "0.22", optional = true }
3131

3232
# for SSE client
3333
reqwest = { version = "0.12", default-features = false, features = [
@@ -52,11 +52,12 @@ tokio-stream = { version = "0.1", optional = true }
5252

5353
# macro
5454
rmcp-macros = { version = "0.1", workspace = true, optional = true }
55+
rmcp-core = { version = "0.1", workspace = true, optional = true, features = ["schemars"] }
5556

5657
[features]
57-
default = ["base64", "macros", "server"]
58-
client = []
59-
server = ["transport-async-rw", "dep:schemars"]
58+
default = ["base64", "macros", "server", "dep:rmcp-core"]
59+
client = ["dep:rmcp-core"]
60+
server = ["transport-async-rw", "dep:schemars", "dep:rmcp-core"]
6061
macros = ["dep:rmcp-macros", "dep:paste"]
6162
transport-sse = ["dep:reqwest", "dep:sse-stream", "dep:url"]
6263
transport-async-rw = ["tokio/io-util", "tokio-util/codec"]

crates/rmcp/src/handler/client.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
error::Error as McpError,
2+
Error as McpError,
33
model::*,
44
service::{Peer, RequestContext, RoleClient, Service, ServiceRole},
55
};

crates/rmcp/src/handler/server.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
error::Error as McpError,
2+
Error as McpError,
33
model::*,
44
service::{Peer, RequestContext, RoleServer, Service, ServiceRole},
55
};

crates/rmcp/src/handler/server/tool.rs

+1-31
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use tokio_util::sync::CancellationToken;
99

1010
use crate::{
1111
RoleServer,
12-
model::{CallToolRequestParam, CallToolResult, ConstString, IntoContents, JsonObject},
12+
model::{CallToolRequestParam, CallToolResult, ConstString, IntoCallToolResult, JsonObject},
1313
service::RequestContext,
1414
};
1515
/// A shortcut for generating a JSON schema for a type.
@@ -86,30 +86,6 @@ pub trait FromToolCallContextPart<'a, S>: Sized {
8686
) -> Result<(Self, ToolCallContext<'a, S>), crate::Error>;
8787
}
8888

89-
pub trait IntoCallToolResult {
90-
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error>;
91-
}
92-
impl IntoCallToolResult for () {
93-
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
94-
Ok(CallToolResult::success(vec![]))
95-
}
96-
}
97-
98-
impl<T: IntoContents> IntoCallToolResult for T {
99-
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
100-
Ok(CallToolResult::success(self.into_contents()))
101-
}
102-
}
103-
104-
impl<T: IntoContents, E: IntoContents> IntoCallToolResult for Result<T, E> {
105-
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
106-
match self {
107-
Ok(value) => Ok(CallToolResult::success(value.into_contents())),
108-
Err(error) => Ok(CallToolResult::error(error.into_contents())),
109-
}
110-
}
111-
}
112-
11389
pin_project_lite::pin_project! {
11490
#[project = IntoCallToolResultFutProj]
11591
pub enum IntoCallToolResultFut<F, R> {
@@ -145,12 +121,6 @@ where
145121
}
146122
}
147123

148-
impl IntoCallToolResult for Result<CallToolResult, crate::Error> {
149-
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
150-
self
151-
}
152-
}
153-
154124
pub trait CallToolHandler<'a, S, A> {
155125
type Fut: Future<Output = Result<CallToolResult, crate::Error>> + Send + 'a;
156126
fn call(self, context: ToolCallContext<'a, S>) -> Self::Fut;

crates/rmcp/src/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
mod error;
2-
pub use error::Error;
1+
pub use rmcp_core::{Error, model};
32

43
/// Basic data types in MCP specification
5-
pub mod model;
64
#[cfg(any(feature = "client", feature = "server"))]
75
pub mod service;
86
#[cfg(feature = "client")]

crates/rmcp/src/service.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use futures::future::BoxFuture;
22
use thiserror::Error;
33

44
use crate::{
5-
error::Error as McpError,
5+
Error as McpError,
66
model::{
77
CancelledNotification, CancelledNotificationParam, Extensions, GetExtensions, GetMeta,
88
JsonRpcBatchRequestItem, JsonRpcBatchResponseItem, JsonRpcError, JsonRpcMessage,

crates/rmcp/tests/common/calculator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rmcp::{
22
ServerHandler,
3-
model::{ServerCapabilities, ServerInfo},
3+
model::{IntoCallToolResult, ServerCapabilities, ServerInfo},
44
schemars, tool,
55
};
66
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]

crates/rmcp/tests/test_tool_macros.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use std::sync::Arc;
22

3-
use rmcp::{ServerHandler, handler::server::tool::ToolCallContext, tool};
3+
use rmcp::{
4+
ServerHandler,
5+
handler::server::tool::ToolCallContext,
6+
model::{IntoCallToolResult},
7+
tool,
8+
};
49
use schemars::JsonSchema;
510
use serde::{Deserialize, Serialize};
611

examples/clients/Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
[package]
42
name = "mcp-client-examples"
53
version = "0.1.5"
@@ -13,12 +11,13 @@ rmcp = { path = "../../crates/rmcp", features = [
1311
"transport-child-process",
1412
"tower"
1513
] }
14+
rmcp-core = { path = "../../crates/rmcp-core", features = ["macros"] }
1615
tokio = { version = "1", features = ["full"] }
1716
serde = { version = "1.0", features = ["derive"] }
1817
serde_json = "1.0"
1918
tracing = "0.1"
2019
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
21-
rand = "0.8"
20+
rand = "0.9"
2221
futures = "0.3"
2322
anyhow = "1.0"
2423

examples/clients/src/everything_stdio.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use anyhow::Result;
22
use rmcp::{
33
ServiceExt,
44
model::{CallToolRequestParam, GetPromptRequestParam, ReadResourceRequestParam},
5-
object,
65
transport::TokioChildProcess,
76
};
7+
use rmcp_core::object;
88
use tokio::process::Command;
99
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
1010

0 commit comments

Comments
 (0)