1use rmcp::{
4 handler::server::ServerHandler,
5 model::{
6 CallToolRequestParams, CallToolResult, CancelledNotificationParam, CompleteRequestParams,
7 CompleteResult, ErrorCode, ErrorData, GetPromptRequestParams, GetPromptResult,
8 InitializeRequestParams, InitializeResult, JsonObject, ListPromptsResult,
9 ListResourceTemplatesResult, ListResourcesResult, ListToolsResult, PaginatedRequestParams,
10 ProgressNotificationParam, PromptsCapability, ReadResourceRequestParams,
11 ReadResourceResult, ResourcesCapability, ServerCapabilities, ServerInfo,
12 SetLevelRequestParams, SubscribeRequestParams, ToolsCapability, UnsubscribeRequestParams,
13 },
14 service::{NotificationContext, RequestContext, RoleServer},
15};
16
17use crate::providers::{
18 CompletionProvider, LoggingProvider, PromptsProvider, ResourcesProvider, ServerInfoProvider,
19 ToolsProvider,
20};
21
22#[derive(Clone, Copy, Debug, Default)]
24pub struct Unset;
25
26#[derive(Clone)]
39pub struct Server<T, P, R, C, L, I> {
40 pub(crate) tools: Option<T>,
41 pub(crate) prompts: Option<P>,
42 pub(crate) resources: Option<R>,
43 pub(crate) completion: Option<C>,
44 pub(crate) logging: Option<L>,
45 pub(crate) info: I,
46 pub(crate) instructions: Option<String>,
47}
48
49impl<T, P, R, C, L, I> Server<T, P, R, C, L, I>
50where
51 I: ServerInfoProvider,
52{
53 fn combined_capabilities(&self) -> ServerCapabilities {
55 let mut caps = self.info.capabilities();
56
57 if self.tools.is_some() {
58 caps.tools = Some(ToolsCapability::default());
59 }
60 if self.prompts.is_some() {
61 caps.prompts = Some(PromptsCapability::default());
62 }
63 if self.resources.is_some() {
64 caps.resources = Some(ResourcesCapability::default());
65 }
66 if self.logging.is_some() {
67 caps.logging = Some(JsonObject::default());
68 }
69
70 caps
71 }
72}
73
74impl<T, P, R, C, L, I> ServerHandler for Server<T, P, R, C, L, I>
79where
80 T: ToolsProvider,
81 P: PromptsProvider,
82 R: ResourcesProvider,
83 C: CompletionProvider,
84 L: LoggingProvider,
85 I: ServerInfoProvider,
86{
87 fn get_info(&self) -> ServerInfo {
88 let base = self.info.get_info();
89 let mut info = ServerInfo::new(self.combined_capabilities())
90 .with_protocol_version(base.protocol_version)
91 .with_server_info(base.server_info);
92 if let Some(instructions) = self.instructions.clone().or(base.instructions) {
93 info = info.with_instructions(instructions);
94 }
95 info
96 }
97
98 async fn initialize(
99 &self,
100 _request: InitializeRequestParams,
101 _context: RequestContext<RoleServer>,
102 ) -> Result<InitializeResult, ErrorData> {
103 let base = self.info.get_info();
104 let mut result = InitializeResult::new(self.combined_capabilities())
105 .with_protocol_version(base.protocol_version)
106 .with_server_info(base.server_info);
107 if let Some(instructions) = self.instructions.clone().or(base.instructions) {
108 result = result.with_instructions(instructions);
109 }
110 Ok(result)
111 }
112
113 async fn ping(&self, _context: RequestContext<RoleServer>) -> Result<(), ErrorData> {
114 Ok(())
115 }
116
117 async fn list_tools(
118 &self,
119 request: Option<PaginatedRequestParams>,
120 context: RequestContext<RoleServer>,
121 ) -> Result<ListToolsResult, ErrorData> {
122 match &self.tools {
123 Some(provider) => provider.list_tools(request, context).await,
124 None => Err(ErrorData::new(
125 ErrorCode::METHOD_NOT_FOUND,
126 "tools not supported",
127 None,
128 )),
129 }
130 }
131
132 async fn call_tool(
133 &self,
134 request: CallToolRequestParams,
135 context: RequestContext<RoleServer>,
136 ) -> Result<CallToolResult, ErrorData> {
137 match &self.tools {
138 Some(provider) => provider.call_tool(request, context).await,
139 None => Err(ErrorData::new(
140 ErrorCode::METHOD_NOT_FOUND,
141 "tools not supported",
142 None,
143 )),
144 }
145 }
146
147 async fn list_prompts(
148 &self,
149 request: Option<PaginatedRequestParams>,
150 context: RequestContext<RoleServer>,
151 ) -> Result<ListPromptsResult, ErrorData> {
152 match &self.prompts {
153 Some(provider) => provider.list_prompts(request, context).await,
154 None => Err(ErrorData::new(
155 ErrorCode::METHOD_NOT_FOUND,
156 "prompts not supported",
157 None,
158 )),
159 }
160 }
161
162 async fn get_prompt(
163 &self,
164 request: GetPromptRequestParams,
165 context: RequestContext<RoleServer>,
166 ) -> Result<GetPromptResult, ErrorData> {
167 match &self.prompts {
168 Some(provider) => provider.get_prompt(request, context).await,
169 None => Err(ErrorData::new(
170 ErrorCode::METHOD_NOT_FOUND,
171 "prompts not supported",
172 None,
173 )),
174 }
175 }
176
177 async fn list_resources(
178 &self,
179 request: Option<PaginatedRequestParams>,
180 context: RequestContext<RoleServer>,
181 ) -> Result<ListResourcesResult, ErrorData> {
182 match &self.resources {
183 Some(provider) => provider.list_resources(request, context).await,
184 None => Err(ErrorData::new(
185 ErrorCode::METHOD_NOT_FOUND,
186 "resources not supported",
187 None,
188 )),
189 }
190 }
191
192 async fn list_resource_templates(
193 &self,
194 request: Option<PaginatedRequestParams>,
195 context: RequestContext<RoleServer>,
196 ) -> Result<ListResourceTemplatesResult, ErrorData> {
197 match &self.resources {
198 Some(provider) => provider.list_resource_templates(request, context).await,
199 None => Err(ErrorData::new(
200 ErrorCode::METHOD_NOT_FOUND,
201 "resources not supported",
202 None,
203 )),
204 }
205 }
206
207 async fn read_resource(
208 &self,
209 request: ReadResourceRequestParams,
210 context: RequestContext<RoleServer>,
211 ) -> Result<ReadResourceResult, ErrorData> {
212 match &self.resources {
213 Some(provider) => provider.read_resource(request, context).await,
214 None => Err(ErrorData::new(
215 ErrorCode::METHOD_NOT_FOUND,
216 "resources not supported",
217 None,
218 )),
219 }
220 }
221
222 async fn subscribe(
223 &self,
224 request: SubscribeRequestParams,
225 context: RequestContext<RoleServer>,
226 ) -> Result<(), ErrorData> {
227 match &self.resources {
228 Some(provider) => provider.subscribe(request, context).await,
229 None => Err(ErrorData::new(
230 ErrorCode::METHOD_NOT_FOUND,
231 "resources not supported",
232 None,
233 )),
234 }
235 }
236
237 async fn unsubscribe(
238 &self,
239 request: UnsubscribeRequestParams,
240 context: RequestContext<RoleServer>,
241 ) -> Result<(), ErrorData> {
242 match &self.resources {
243 Some(provider) => provider.unsubscribe(request, context).await,
244 None => Err(ErrorData::new(
245 ErrorCode::METHOD_NOT_FOUND,
246 "resources not supported",
247 None,
248 )),
249 }
250 }
251
252 async fn complete(
253 &self,
254 request: CompleteRequestParams,
255 context: RequestContext<RoleServer>,
256 ) -> Result<CompleteResult, ErrorData> {
257 match &self.completion {
258 Some(provider) => provider.complete(request, context).await,
259 None => Err(ErrorData::new(
260 ErrorCode::METHOD_NOT_FOUND,
261 "completion not supported",
262 None,
263 )),
264 }
265 }
266
267 async fn set_level(
268 &self,
269 request: SetLevelRequestParams,
270 context: RequestContext<RoleServer>,
271 ) -> Result<(), ErrorData> {
272 match &self.logging {
273 Some(provider) => provider.set_level(request, context).await,
274 None => Err(ErrorData::new(
275 ErrorCode::METHOD_NOT_FOUND,
276 "logging not supported",
277 None,
278 )),
279 }
280 }
281
282 async fn on_cancelled(
283 &self,
284 _notification: CancelledNotificationParam,
285 _context: NotificationContext<RoleServer>,
286 ) {
287 }
288
289 async fn on_progress(
290 &self,
291 _notification: ProgressNotificationParam,
292 _context: NotificationContext<RoleServer>,
293 ) {
294 }
295
296 async fn on_initialized(&self, _context: NotificationContext<RoleServer>) {}
297
298 async fn on_roots_list_changed(&self, _context: NotificationContext<RoleServer>) {}
299}
300
301impl ToolsProvider for Unset {
306 async fn list_tools(
307 &self,
308 _request: Option<PaginatedRequestParams>,
309 _context: RequestContext<RoleServer>,
310 ) -> Result<ListToolsResult, ErrorData> {
311 Err(ErrorData::new(
312 ErrorCode::METHOD_NOT_FOUND,
313 "tools not supported",
314 None,
315 ))
316 }
317
318 async fn call_tool(
319 &self,
320 _request: CallToolRequestParams,
321 _context: RequestContext<RoleServer>,
322 ) -> Result<CallToolResult, ErrorData> {
323 Err(ErrorData::new(
324 ErrorCode::METHOD_NOT_FOUND,
325 "tools not supported",
326 None,
327 ))
328 }
329}
330
331impl PromptsProvider for Unset {
332 async fn list_prompts(
333 &self,
334 _request: Option<PaginatedRequestParams>,
335 _context: RequestContext<RoleServer>,
336 ) -> Result<ListPromptsResult, ErrorData> {
337 Err(ErrorData::new(
338 ErrorCode::METHOD_NOT_FOUND,
339 "prompts not supported",
340 None,
341 ))
342 }
343
344 async fn get_prompt(
345 &self,
346 _request: GetPromptRequestParams,
347 _context: RequestContext<RoleServer>,
348 ) -> Result<GetPromptResult, ErrorData> {
349 Err(ErrorData::new(
350 ErrorCode::METHOD_NOT_FOUND,
351 "prompts not supported",
352 None,
353 ))
354 }
355}
356
357impl ResourcesProvider for Unset {
358 async fn list_resources(
359 &self,
360 _request: Option<PaginatedRequestParams>,
361 _context: RequestContext<RoleServer>,
362 ) -> Result<ListResourcesResult, ErrorData> {
363 Err(ErrorData::new(
364 ErrorCode::METHOD_NOT_FOUND,
365 "resources not supported",
366 None,
367 ))
368 }
369
370 async fn list_resource_templates(
371 &self,
372 _request: Option<PaginatedRequestParams>,
373 _context: RequestContext<RoleServer>,
374 ) -> Result<ListResourceTemplatesResult, ErrorData> {
375 Err(ErrorData::new(
376 ErrorCode::METHOD_NOT_FOUND,
377 "resources not supported",
378 None,
379 ))
380 }
381
382 async fn read_resource(
383 &self,
384 _request: ReadResourceRequestParams,
385 _context: RequestContext<RoleServer>,
386 ) -> Result<ReadResourceResult, ErrorData> {
387 Err(ErrorData::new(
388 ErrorCode::METHOD_NOT_FOUND,
389 "resources not supported",
390 None,
391 ))
392 }
393
394 async fn subscribe(
395 &self,
396 _request: SubscribeRequestParams,
397 _context: RequestContext<RoleServer>,
398 ) -> Result<(), ErrorData> {
399 Err(ErrorData::new(
400 ErrorCode::METHOD_NOT_FOUND,
401 "resources not supported",
402 None,
403 ))
404 }
405
406 async fn unsubscribe(
407 &self,
408 _request: UnsubscribeRequestParams,
409 _context: RequestContext<RoleServer>,
410 ) -> Result<(), ErrorData> {
411 Err(ErrorData::new(
412 ErrorCode::METHOD_NOT_FOUND,
413 "resources not supported",
414 None,
415 ))
416 }
417}
418
419impl CompletionProvider for Unset {
420 async fn complete(
421 &self,
422 _request: CompleteRequestParams,
423 _context: RequestContext<RoleServer>,
424 ) -> Result<CompleteResult, ErrorData> {
425 Err(ErrorData::new(
426 ErrorCode::METHOD_NOT_FOUND,
427 "completion not supported",
428 None,
429 ))
430 }
431}
432
433impl LoggingProvider for Unset {
434 async fn set_level(
435 &self,
436 _request: SetLevelRequestParams,
437 _context: RequestContext<RoleServer>,
438 ) -> Result<(), ErrorData> {
439 Err(ErrorData::new(
440 ErrorCode::METHOD_NOT_FOUND,
441 "logging not supported",
442 None,
443 ))
444 }
445}