feat: unified error type (#308)
* feat: unified error type * fix: use type id to compare transport type
This commit is contained in:
parent
c74b26b3e3
commit
e615300fea
5 changed files with 286 additions and 161 deletions
|
|
@ -1,6 +1,6 @@
|
|||
pub mod progress;
|
||||
use crate::{
|
||||
error::Error as McpError,
|
||||
error::ErrorData as McpError,
|
||||
model::*,
|
||||
service::{NotificationContext, RequestContext, RoleClient, Service, ServiceRole},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
error::Error as McpError,
|
||||
error::ErrorData as McpError,
|
||||
model::*,
|
||||
service::{NotificationContext, RequestContext, RoleServer, Service, ServiceRole},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ where
|
|||
&self,
|
||||
notification: <RoleServer as crate::service::ServiceRole>::PeerNot,
|
||||
context: NotificationContext<RoleServer>,
|
||||
) -> Result<(), crate::Error> {
|
||||
) -> Result<(), crate::ErrorData> {
|
||||
self.service
|
||||
.handle_notification(notification, context)
|
||||
.await
|
||||
|
|
@ -60,7 +60,7 @@ where
|
|||
&self,
|
||||
request: <RoleServer as crate::service::ServiceRole>::PeerReq,
|
||||
context: crate::service::RequestContext<RoleServer>,
|
||||
) -> Result<<RoleServer as crate::service::ServiceRole>::Resp, crate::Error> {
|
||||
) -> Result<<RoleServer as crate::service::ServiceRole>::Resp, crate::ErrorData> {
|
||||
match request {
|
||||
ClientRequest::CallToolRequest(request) => {
|
||||
if self.tool_router.has_route(request.params.name.as_ref())
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl<S: Send + Sync + 'static> ToolRoute<S> {
|
|||
where
|
||||
C: for<'a> Fn(
|
||||
ToolCallContext<'a, S>,
|
||||
) -> BoxFuture<'a, Result<CallToolResult, crate::Error>>
|
||||
) -> BoxFuture<'a, Result<CallToolResult, crate::ErrorData>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
|
|
@ -237,11 +237,11 @@ where
|
|||
pub async fn call(
|
||||
&self,
|
||||
context: ToolCallContext<'_, S>,
|
||||
) -> Result<CallToolResult, crate::Error> {
|
||||
) -> Result<CallToolResult, crate::ErrorData> {
|
||||
let item = self
|
||||
.map
|
||||
.get(context.name())
|
||||
.ok_or_else(|| crate::Error::invalid_params("tool not found", None))?;
|
||||
.ok_or_else(|| crate::ErrorData::invalid_params("tool not found", None))?;
|
||||
(item.call)(context).await
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ pub fn cached_schema_for_type<T: JsonSchema + std::any::Any>() -> Arc<JsonObject
|
|||
}
|
||||
|
||||
/// Deserialize a JSON object into a type
|
||||
pub fn parse_json_object<T: DeserializeOwned>(input: JsonObject) -> Result<T, crate::Error> {
|
||||
pub fn parse_json_object<T: DeserializeOwned>(input: JsonObject) -> Result<T, crate::ErrorData> {
|
||||
serde_json::from_value(serde_json::Value::Object(input)).map_err(|e| {
|
||||
crate::Error::invalid_params(
|
||||
crate::ErrorData::invalid_params(
|
||||
format!("failed to deserialize parameters: {error}", error = e),
|
||||
None,
|
||||
)
|
||||
|
|
@ -93,21 +93,23 @@ impl<'s, S> ToolCallContext<'s, S> {
|
|||
}
|
||||
|
||||
pub trait FromToolCallContextPart<S>: Sized {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error>;
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData>;
|
||||
}
|
||||
|
||||
pub trait IntoCallToolResult {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error>;
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::ErrorData>;
|
||||
}
|
||||
|
||||
impl<T: IntoContents> IntoCallToolResult for T {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::ErrorData> {
|
||||
Ok(CallToolResult::success(self.into_contents()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoContents, E: IntoContents> IntoCallToolResult for Result<T, E> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::ErrorData> {
|
||||
match self {
|
||||
Ok(value) => Ok(CallToolResult::success(value.into_contents())),
|
||||
Err(error) => Ok(CallToolResult::error(error.into_contents())),
|
||||
|
|
@ -115,8 +117,8 @@ impl<T: IntoContents, E: IntoContents> IntoCallToolResult for Result<T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: IntoCallToolResult> IntoCallToolResult for Result<T, crate::Error> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
|
||||
impl<T: IntoCallToolResult> IntoCallToolResult for Result<T, crate::ErrorData> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::ErrorData> {
|
||||
match self {
|
||||
Ok(value) => value.into_call_tool_result(),
|
||||
Err(error) => Err(error),
|
||||
|
|
@ -134,7 +136,7 @@ pin_project_lite::pin_project! {
|
|||
},
|
||||
Ready {
|
||||
#[pin]
|
||||
result: Ready<Result<CallToolResult, crate::Error>>,
|
||||
result: Ready<Result<CallToolResult, crate::ErrorData>>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -144,7 +146,7 @@ where
|
|||
F: Future<Output = R>,
|
||||
R: IntoCallToolResult,
|
||||
{
|
||||
type Output = Result<CallToolResult, crate::Error>;
|
||||
type Output = Result<CallToolResult, crate::ErrorData>;
|
||||
|
||||
fn poll(
|
||||
self: std::pin::Pin<&mut Self>,
|
||||
|
|
@ -159,8 +161,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoCallToolResult for Result<CallToolResult, crate::Error> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::Error> {
|
||||
impl IntoCallToolResult for Result<CallToolResult, crate::ErrorData> {
|
||||
fn into_call_tool_result(self) -> Result<CallToolResult, crate::ErrorData> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -169,10 +171,10 @@ pub trait CallToolHandler<S, A> {
|
|||
fn call(
|
||||
self,
|
||||
context: ToolCallContext<'_, S>,
|
||||
) -> BoxFuture<'_, Result<CallToolResult, crate::Error>>;
|
||||
) -> BoxFuture<'_, Result<CallToolResult, crate::ErrorData>>;
|
||||
}
|
||||
|
||||
pub type DynCallToolHandler<S> = dyn for<'s> Fn(ToolCallContext<'s, S>) -> BoxFuture<'s, Result<CallToolResult, crate::Error>>
|
||||
pub type DynCallToolHandler<S> = dyn for<'s> Fn(ToolCallContext<'s, S>) -> BoxFuture<'s, Result<CallToolResult, crate::ErrorData>>
|
||||
+ Send
|
||||
+ Sync;
|
||||
|
||||
|
|
@ -193,7 +195,9 @@ impl<P: JsonSchema> JsonSchema for Parameters<P> {
|
|||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for CancellationToken {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
Ok(context.request_context.ct.clone())
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +205,9 @@ impl<S> FromToolCallContextPart<S> for CancellationToken {
|
|||
pub struct ToolName(pub Cow<'static, str>);
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for ToolName {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
Ok(Self(context.name.clone()))
|
||||
}
|
||||
}
|
||||
|
|
@ -210,11 +216,13 @@ impl<S, P> FromToolCallContextPart<S> for Parameters<P>
|
|||
where
|
||||
P: DeserializeOwned,
|
||||
{
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let arguments = context.arguments.take().unwrap_or_default();
|
||||
let value: P =
|
||||
serde_json::from_value(serde_json::Value::Object(arguments)).map_err(|e| {
|
||||
crate::Error::invalid_params(
|
||||
crate::ErrorData::invalid_params(
|
||||
format!("failed to deserialize parameters: {error}", error = e),
|
||||
None,
|
||||
)
|
||||
|
|
@ -224,14 +232,18 @@ where
|
|||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for JsonObject {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let object = context.arguments.take().unwrap_or_default();
|
||||
Ok(object)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for crate::model::Extensions {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let extensions = context.request_context.extensions.clone();
|
||||
Ok(extensions)
|
||||
}
|
||||
|
|
@ -243,14 +255,16 @@ impl<S, T> FromToolCallContextPart<S> for Extension<T>
|
|||
where
|
||||
T: Send + Sync + 'static + Clone,
|
||||
{
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let extension = context
|
||||
.request_context
|
||||
.extensions
|
||||
.get::<T>()
|
||||
.cloned()
|
||||
.ok_or_else(|| {
|
||||
crate::Error::invalid_params(
|
||||
crate::ErrorData::invalid_params(
|
||||
format!("missing extension {}", std::any::type_name::<T>()),
|
||||
None,
|
||||
)
|
||||
|
|
@ -260,14 +274,18 @@ where
|
|||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for crate::Peer<RoleServer> {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let peer = context.request_context.peer.clone();
|
||||
Ok(peer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for crate::model::Meta {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
let mut meta = crate::model::Meta::default();
|
||||
std::mem::swap(&mut meta, &mut context.request_context.meta);
|
||||
Ok(meta)
|
||||
|
|
@ -276,19 +294,23 @@ impl<S> FromToolCallContextPart<S> for crate::model::Meta {
|
|||
|
||||
pub struct RequestId(pub crate::model::RequestId);
|
||||
impl<S> FromToolCallContextPart<S> for RequestId {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
Ok(RequestId(context.request_context.id.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromToolCallContextPart<S> for RequestContext<RoleServer> {
|
||||
fn from_tool_call_context_part(context: &mut ToolCallContext<S>) -> Result<Self, crate::Error> {
|
||||
fn from_tool_call_context_part(
|
||||
context: &mut ToolCallContext<S>,
|
||||
) -> Result<Self, crate::ErrorData> {
|
||||
Ok(context.request_context.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, S> ToolCallContext<'s, S> {
|
||||
pub fn invoke<H, A>(self, h: H) -> BoxFuture<'s, Result<CallToolResult, crate::Error>>
|
||||
pub fn invoke<H, A>(self, h: H) -> BoxFuture<'s, Result<CallToolResult, crate::ErrorData>>
|
||||
where
|
||||
H: CallToolHandler<S, A>,
|
||||
{
|
||||
|
|
@ -331,7 +353,7 @@ macro_rules! impl_for {
|
|||
fn call(
|
||||
self,
|
||||
mut context: ToolCallContext<'_, S>,
|
||||
) -> BoxFuture<'_, Result<CallToolResult, crate::Error>>{
|
||||
) -> BoxFuture<'_, Result<CallToolResult, crate::ErrorData>>{
|
||||
$(
|
||||
let result = $Tn::from_tool_call_context_part(&mut context);
|
||||
let $Tn = match result {
|
||||
|
|
@ -362,7 +384,7 @@ macro_rules! impl_for {
|
|||
fn call(
|
||||
self,
|
||||
mut context: ToolCallContext<S>,
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::Error>>{
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::ErrorData>>{
|
||||
$(
|
||||
let result = $Tn::from_tool_call_context_part(&mut context);
|
||||
let $Tn = match result {
|
||||
|
|
@ -391,7 +413,7 @@ macro_rules! impl_for {
|
|||
fn call(
|
||||
self,
|
||||
mut context: ToolCallContext<S>,
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::Error>> {
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::ErrorData>> {
|
||||
$(
|
||||
let result = $Tn::from_tool_call_context_part(&mut context);
|
||||
let $Tn = match result {
|
||||
|
|
@ -416,7 +438,7 @@ macro_rules! impl_for {
|
|||
fn call(
|
||||
self,
|
||||
mut context: ToolCallContext<S>,
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::Error>> {
|
||||
) -> BoxFuture<'static, Result<CallToolResult, crate::ErrorData>> {
|
||||
$(
|
||||
let result = $Tn::from_tool_call_context_part(&mut context);
|
||||
let $Tn = match result {
|
||||
|
|
|
|||
Loading…
Reference in a new issue