mcp_kit/server/
handler.rs1use std::{future::Future, pin::Pin, sync::Arc};
2
3use crate::{
4 error::{McpError, McpResult},
5 types::{
6 messages::{CallToolRequest, GetPromptRequest, ReadResourceRequest},
7 prompt::GetPromptResult,
8 resource::ReadResourceResult,
9 tool::CallToolResult,
10 },
11};
12use serde::de::DeserializeOwned;
13
14pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
16
17pub type HandlerFn<Req, Res> =
19 Arc<dyn Fn(Req) -> BoxFuture<'static, McpResult<Res>> + Send + Sync + 'static>;
20
21pub type ToolHandlerFn = HandlerFn<CallToolRequest, CallToolResult>;
22pub type ResourceHandlerFn = HandlerFn<ReadResourceRequest, ReadResourceResult>;
23pub type PromptHandlerFn = HandlerFn<GetPromptRequest, GetPromptResult>;
24
25pub trait IntoToolResult {
29 fn into_tool_result(self) -> CallToolResult;
30}
31
32impl IntoToolResult for CallToolResult {
33 fn into_tool_result(self) -> CallToolResult {
34 self
35 }
36}
37
38impl IntoToolResult for String {
39 fn into_tool_result(self) -> CallToolResult {
40 CallToolResult::text(self)
41 }
42}
43
44impl IntoToolResult for &str {
45 fn into_tool_result(self) -> CallToolResult {
46 CallToolResult::text(self)
47 }
48}
49
50impl IntoToolResult for serde_json::Value {
51 fn into_tool_result(self) -> CallToolResult {
52 CallToolResult::text(self.to_string())
53 }
54}
55
56impl<T: IntoToolResult, E: std::fmt::Display> IntoToolResult for Result<T, E> {
57 fn into_tool_result(self) -> CallToolResult {
58 match self {
59 Ok(v) => v.into_tool_result(),
60 Err(e) => CallToolResult::error(e.to_string()),
61 }
62 }
63}
64
65pub trait ToolHandler<Marker>: Clone + Send + Sync + 'static {
73 fn into_handler_fn(self) -> ToolHandlerFn;
74}
75
76pub struct TypedMarker<T>(std::marker::PhantomData<T>);
80
81impl<F, Fut, R, T> ToolHandler<TypedMarker<T>> for F
82where
83 F: Fn(T) -> Fut + Clone + Send + Sync + 'static,
84 Fut: Future<Output = R> + Send + 'static,
85 R: IntoToolResult + Send + 'static,
86 T: DeserializeOwned + Send + 'static,
87{
88 fn into_handler_fn(self) -> ToolHandlerFn {
89 Arc::new(move |req: CallToolRequest| {
90 let f = self.clone();
91 let args = req.arguments.clone();
92 Box::pin(async move {
93 let params: T = serde_json::from_value(args)
94 .map_err(|e| McpError::InvalidParams(e.to_string()))?;
95 Ok(f(params).await.into_tool_result())
96 })
97 })
98 }
99}
100
101pub trait PromptHandler<Marker>: Clone + Send + Sync + 'static {
104 fn into_handler_fn(self) -> PromptHandlerFn;
105}
106
107pub struct PromptRawMarker;
108
109impl<F, Fut> PromptHandler<PromptRawMarker> for F
110where
111 F: Fn(GetPromptRequest) -> Fut + Clone + Send + Sync + 'static,
112 Fut: Future<Output = McpResult<GetPromptResult>> + Send + 'static,
113{
114 fn into_handler_fn(self) -> PromptHandlerFn {
115 Arc::new(move |req| {
116 let f = self.clone();
117 Box::pin(async move { f(req).await })
118 })
119 }
120}
121
122pub trait ResourceHandler<Marker>: Clone + Send + Sync + 'static {
125 fn into_handler_fn(self) -> ResourceHandlerFn;
126}
127
128pub struct ResourceRawMarker;
129
130impl<F, Fut> ResourceHandler<ResourceRawMarker> for F
131where
132 F: Fn(ReadResourceRequest) -> Fut + Clone + Send + Sync + 'static,
133 Fut: Future<Output = McpResult<ReadResourceResult>> + Send + 'static,
134{
135 fn into_handler_fn(self) -> ResourceHandlerFn {
136 Arc::new(move |req| {
137 let f = self.clone();
138 Box::pin(async move { f(req).await })
139 })
140 }
141}