agenterra_rmcp/handler/
server.rs

1use crate::{
2    error::Error as McpError,
3    model::*,
4    service::{NotificationContext, RequestContext, RoleServer, Service, ServiceRole},
5};
6
7mod resource;
8pub mod router;
9pub mod tool;
10pub mod wrapper;
11impl<H: ServerHandler> Service<RoleServer> for H {
12    async fn handle_request(
13        &self,
14        request: <RoleServer as ServiceRole>::PeerReq,
15        context: RequestContext<RoleServer>,
16    ) -> Result<<RoleServer as ServiceRole>::Resp, McpError> {
17        match request {
18            ClientRequest::InitializeRequest(request) => self
19                .initialize(request.params, context)
20                .await
21                .map(ServerResult::InitializeResult),
22            ClientRequest::PingRequest(_request) => {
23                self.ping(context).await.map(ServerResult::empty)
24            }
25            ClientRequest::CompleteRequest(request) => self
26                .complete(request.params, context)
27                .await
28                .map(ServerResult::CompleteResult),
29            ClientRequest::SetLevelRequest(request) => self
30                .set_level(request.params, context)
31                .await
32                .map(ServerResult::empty),
33            ClientRequest::GetPromptRequest(request) => self
34                .get_prompt(request.params, context)
35                .await
36                .map(ServerResult::GetPromptResult),
37            ClientRequest::ListPromptsRequest(request) => self
38                .list_prompts(request.params, context)
39                .await
40                .map(ServerResult::ListPromptsResult),
41            ClientRequest::ListResourcesRequest(request) => self
42                .list_resources(request.params, context)
43                .await
44                .map(ServerResult::ListResourcesResult),
45            ClientRequest::ListResourceTemplatesRequest(request) => self
46                .list_resource_templates(request.params, context)
47                .await
48                .map(ServerResult::ListResourceTemplatesResult),
49            ClientRequest::ReadResourceRequest(request) => self
50                .read_resource(request.params, context)
51                .await
52                .map(ServerResult::ReadResourceResult),
53            ClientRequest::SubscribeRequest(request) => self
54                .subscribe(request.params, context)
55                .await
56                .map(ServerResult::empty),
57            ClientRequest::UnsubscribeRequest(request) => self
58                .unsubscribe(request.params, context)
59                .await
60                .map(ServerResult::empty),
61            ClientRequest::CallToolRequest(request) => self
62                .call_tool(request.params, context)
63                .await
64                .map(ServerResult::CallToolResult),
65            ClientRequest::ListToolsRequest(request) => self
66                .list_tools(request.params, context)
67                .await
68                .map(ServerResult::ListToolsResult),
69        }
70    }
71
72    async fn handle_notification(
73        &self,
74        notification: <RoleServer as ServiceRole>::PeerNot,
75        context: NotificationContext<RoleServer>,
76    ) -> Result<(), McpError> {
77        match notification {
78            ClientNotification::CancelledNotification(notification) => {
79                self.on_cancelled(notification.params, context).await
80            }
81            ClientNotification::ProgressNotification(notification) => {
82                self.on_progress(notification.params, context).await
83            }
84            ClientNotification::InitializedNotification(_notification) => {
85                self.on_initialized(context).await
86            }
87            ClientNotification::RootsListChangedNotification(_notification) => {
88                self.on_roots_list_changed(context).await
89            }
90        };
91        Ok(())
92    }
93
94    fn get_info(&self) -> <RoleServer as ServiceRole>::Info {
95        self.get_info()
96    }
97}
98
99#[allow(unused_variables)]
100pub trait ServerHandler: Sized + Send + Sync + 'static {
101    fn ping(
102        &self,
103        context: RequestContext<RoleServer>,
104    ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
105        std::future::ready(Ok(()))
106    }
107    // handle requests
108    fn initialize(
109        &self,
110        request: InitializeRequestParam,
111        context: RequestContext<RoleServer>,
112    ) -> impl Future<Output = Result<InitializeResult, McpError>> + Send + '_ {
113        if context.peer.peer_info().is_none() {
114            context.peer.set_peer_info(request);
115        }
116        std::future::ready(Ok(self.get_info()))
117    }
118    fn complete(
119        &self,
120        request: CompleteRequestParam,
121        context: RequestContext<RoleServer>,
122    ) -> impl Future<Output = Result<CompleteResult, McpError>> + Send + '_ {
123        std::future::ready(Err(McpError::method_not_found::<CompleteRequestMethod>()))
124    }
125    fn set_level(
126        &self,
127        request: SetLevelRequestParam,
128        context: RequestContext<RoleServer>,
129    ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
130        std::future::ready(Err(McpError::method_not_found::<SetLevelRequestMethod>()))
131    }
132    fn get_prompt(
133        &self,
134        request: GetPromptRequestParam,
135        context: RequestContext<RoleServer>,
136    ) -> impl Future<Output = Result<GetPromptResult, McpError>> + Send + '_ {
137        std::future::ready(Err(McpError::method_not_found::<GetPromptRequestMethod>()))
138    }
139    fn list_prompts(
140        &self,
141        request: Option<PaginatedRequestParam>,
142        context: RequestContext<RoleServer>,
143    ) -> impl Future<Output = Result<ListPromptsResult, McpError>> + Send + '_ {
144        std::future::ready(Ok(ListPromptsResult::default()))
145    }
146    fn list_resources(
147        &self,
148        request: Option<PaginatedRequestParam>,
149        context: RequestContext<RoleServer>,
150    ) -> impl Future<Output = Result<ListResourcesResult, McpError>> + Send + '_ {
151        std::future::ready(Ok(ListResourcesResult::default()))
152    }
153    fn list_resource_templates(
154        &self,
155        request: Option<PaginatedRequestParam>,
156        context: RequestContext<RoleServer>,
157    ) -> impl Future<Output = Result<ListResourceTemplatesResult, McpError>> + Send + '_ {
158        std::future::ready(Ok(ListResourceTemplatesResult::default()))
159    }
160    fn read_resource(
161        &self,
162        request: ReadResourceRequestParam,
163        context: RequestContext<RoleServer>,
164    ) -> impl Future<Output = Result<ReadResourceResult, McpError>> + Send + '_ {
165        std::future::ready(Err(
166            McpError::method_not_found::<ReadResourceRequestMethod>(),
167        ))
168    }
169    fn subscribe(
170        &self,
171        request: SubscribeRequestParam,
172        context: RequestContext<RoleServer>,
173    ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
174        std::future::ready(Err(McpError::method_not_found::<SubscribeRequestMethod>()))
175    }
176    fn unsubscribe(
177        &self,
178        request: UnsubscribeRequestParam,
179        context: RequestContext<RoleServer>,
180    ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
181        std::future::ready(Err(McpError::method_not_found::<UnsubscribeRequestMethod>()))
182    }
183    fn call_tool(
184        &self,
185        request: CallToolRequestParam,
186        context: RequestContext<RoleServer>,
187    ) -> impl Future<Output = Result<CallToolResult, McpError>> + Send + '_ {
188        std::future::ready(Err(McpError::method_not_found::<CallToolRequestMethod>()))
189    }
190    fn list_tools(
191        &self,
192        request: Option<PaginatedRequestParam>,
193        context: RequestContext<RoleServer>,
194    ) -> impl Future<Output = Result<ListToolsResult, McpError>> + Send + '_ {
195        std::future::ready(Ok(ListToolsResult::default()))
196    }
197
198    fn on_cancelled(
199        &self,
200        notification: CancelledNotificationParam,
201        context: NotificationContext<RoleServer>,
202    ) -> impl Future<Output = ()> + Send + '_ {
203        std::future::ready(())
204    }
205    fn on_progress(
206        &self,
207        notification: ProgressNotificationParam,
208        context: NotificationContext<RoleServer>,
209    ) -> impl Future<Output = ()> + Send + '_ {
210        std::future::ready(())
211    }
212    fn on_initialized(
213        &self,
214        context: NotificationContext<RoleServer>,
215    ) -> impl Future<Output = ()> + Send + '_ {
216        tracing::info!("client initialized");
217        std::future::ready(())
218    }
219    fn on_roots_list_changed(
220        &self,
221        context: NotificationContext<RoleServer>,
222    ) -> impl Future<Output = ()> + Send + '_ {
223        std::future::ready(())
224    }
225
226    fn get_info(&self) -> ServerInfo {
227        ServerInfo::default()
228    }
229}