1use rmcp::{
4 handler::server::ServerHandler,
5 model::{
6 CallToolRequestParam, CallToolResult, CancelledNotificationParam, CompleteRequestParam,
7 CompleteResult, ErrorCode, ErrorData, GetPromptRequestParam, GetPromptResult,
8 InitializeRequestParam, InitializeResult, JsonObject, ListPromptsResult,
9 ListResourceTemplatesResult, ListResourcesResult, ListToolsResult, PaginatedRequestParam,
10 ProgressNotificationParam, PromptsCapability, ReadResourceRequestParam, ReadResourceResult,
11 ResourcesCapability, ServerCapabilities, ServerInfo, SetLevelRequestParam,
12 SubscribeRequestParam, ToolsCapability, UnsubscribeRequestParam,
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 mut info = self.info.get_info();
89 info.capabilities = self.combined_capabilities();
90 if self.instructions.is_some() {
91 info.instructions = self.instructions.clone();
92 }
93 info
94 }
95
96 async fn initialize(
97 &self,
98 _request: InitializeRequestParam,
99 _context: RequestContext<RoleServer>,
100 ) -> Result<InitializeResult, ErrorData> {
101 let base = self.info.get_info();
102 Ok(InitializeResult {
103 protocol_version: base.protocol_version,
104 capabilities: self.combined_capabilities(),
105 server_info: base.server_info,
106 instructions: self.instructions.clone().or(base.instructions),
107 })
108 }
109
110 async fn ping(&self, _context: RequestContext<RoleServer>) -> Result<(), ErrorData> {
111 Ok(())
112 }
113
114 async fn list_tools(
115 &self,
116 request: Option<PaginatedRequestParam>,
117 context: RequestContext<RoleServer>,
118 ) -> Result<ListToolsResult, ErrorData> {
119 match &self.tools {
120 Some(provider) => provider.list_tools(request, context).await,
121 None => Err(ErrorData::new(
122 ErrorCode::METHOD_NOT_FOUND,
123 "tools not supported",
124 None,
125 )),
126 }
127 }
128
129 async fn call_tool(
130 &self,
131 request: CallToolRequestParam,
132 context: RequestContext<RoleServer>,
133 ) -> Result<CallToolResult, ErrorData> {
134 match &self.tools {
135 Some(provider) => provider.call_tool(request, context).await,
136 None => Err(ErrorData::new(
137 ErrorCode::METHOD_NOT_FOUND,
138 "tools not supported",
139 None,
140 )),
141 }
142 }
143
144 async fn list_prompts(
145 &self,
146 request: Option<PaginatedRequestParam>,
147 context: RequestContext<RoleServer>,
148 ) -> Result<ListPromptsResult, ErrorData> {
149 match &self.prompts {
150 Some(provider) => provider.list_prompts(request, context).await,
151 None => Err(ErrorData::new(
152 ErrorCode::METHOD_NOT_FOUND,
153 "prompts not supported",
154 None,
155 )),
156 }
157 }
158
159 async fn get_prompt(
160 &self,
161 request: GetPromptRequestParam,
162 context: RequestContext<RoleServer>,
163 ) -> Result<GetPromptResult, ErrorData> {
164 match &self.prompts {
165 Some(provider) => provider.get_prompt(request, context).await,
166 None => Err(ErrorData::new(
167 ErrorCode::METHOD_NOT_FOUND,
168 "prompts not supported",
169 None,
170 )),
171 }
172 }
173
174 async fn list_resources(
175 &self,
176 request: Option<PaginatedRequestParam>,
177 context: RequestContext<RoleServer>,
178 ) -> Result<ListResourcesResult, ErrorData> {
179 match &self.resources {
180 Some(provider) => provider.list_resources(request, context).await,
181 None => Err(ErrorData::new(
182 ErrorCode::METHOD_NOT_FOUND,
183 "resources not supported",
184 None,
185 )),
186 }
187 }
188
189 async fn list_resource_templates(
190 &self,
191 request: Option<PaginatedRequestParam>,
192 context: RequestContext<RoleServer>,
193 ) -> Result<ListResourceTemplatesResult, ErrorData> {
194 match &self.resources {
195 Some(provider) => provider.list_resource_templates(request, context).await,
196 None => Err(ErrorData::new(
197 ErrorCode::METHOD_NOT_FOUND,
198 "resources not supported",
199 None,
200 )),
201 }
202 }
203
204 async fn read_resource(
205 &self,
206 request: ReadResourceRequestParam,
207 context: RequestContext<RoleServer>,
208 ) -> Result<ReadResourceResult, ErrorData> {
209 match &self.resources {
210 Some(provider) => provider.read_resource(request, context).await,
211 None => Err(ErrorData::new(
212 ErrorCode::METHOD_NOT_FOUND,
213 "resources not supported",
214 None,
215 )),
216 }
217 }
218
219 async fn subscribe(
220 &self,
221 request: SubscribeRequestParam,
222 context: RequestContext<RoleServer>,
223 ) -> Result<(), ErrorData> {
224 match &self.resources {
225 Some(provider) => provider.subscribe(request, context).await,
226 None => Err(ErrorData::new(
227 ErrorCode::METHOD_NOT_FOUND,
228 "resources not supported",
229 None,
230 )),
231 }
232 }
233
234 async fn unsubscribe(
235 &self,
236 request: UnsubscribeRequestParam,
237 context: RequestContext<RoleServer>,
238 ) -> Result<(), ErrorData> {
239 match &self.resources {
240 Some(provider) => provider.unsubscribe(request, context).await,
241 None => Err(ErrorData::new(
242 ErrorCode::METHOD_NOT_FOUND,
243 "resources not supported",
244 None,
245 )),
246 }
247 }
248
249 async fn complete(
250 &self,
251 request: CompleteRequestParam,
252 context: RequestContext<RoleServer>,
253 ) -> Result<CompleteResult, ErrorData> {
254 match &self.completion {
255 Some(provider) => provider.complete(request, context).await,
256 None => Err(ErrorData::new(
257 ErrorCode::METHOD_NOT_FOUND,
258 "completion not supported",
259 None,
260 )),
261 }
262 }
263
264 async fn set_level(
265 &self,
266 request: SetLevelRequestParam,
267 context: RequestContext<RoleServer>,
268 ) -> Result<(), ErrorData> {
269 match &self.logging {
270 Some(provider) => provider.set_level(request, context).await,
271 None => Err(ErrorData::new(
272 ErrorCode::METHOD_NOT_FOUND,
273 "logging not supported",
274 None,
275 )),
276 }
277 }
278
279 async fn on_cancelled(
280 &self,
281 _notification: CancelledNotificationParam,
282 _context: NotificationContext<RoleServer>,
283 ) {
284 }
285
286 async fn on_progress(
287 &self,
288 _notification: ProgressNotificationParam,
289 _context: NotificationContext<RoleServer>,
290 ) {
291 }
292
293 async fn on_initialized(&self, _context: NotificationContext<RoleServer>) {}
294
295 async fn on_roots_list_changed(&self, _context: NotificationContext<RoleServer>) {}
296}
297
298impl ToolsProvider for Unset {
303 async fn list_tools(
304 &self,
305 _request: Option<PaginatedRequestParam>,
306 _context: RequestContext<RoleServer>,
307 ) -> Result<ListToolsResult, ErrorData> {
308 Err(ErrorData::new(
309 ErrorCode::METHOD_NOT_FOUND,
310 "tools not supported",
311 None,
312 ))
313 }
314
315 async fn call_tool(
316 &self,
317 _request: CallToolRequestParam,
318 _context: RequestContext<RoleServer>,
319 ) -> Result<CallToolResult, ErrorData> {
320 Err(ErrorData::new(
321 ErrorCode::METHOD_NOT_FOUND,
322 "tools not supported",
323 None,
324 ))
325 }
326}
327
328impl PromptsProvider for Unset {
329 async fn list_prompts(
330 &self,
331 _request: Option<PaginatedRequestParam>,
332 _context: RequestContext<RoleServer>,
333 ) -> Result<ListPromptsResult, ErrorData> {
334 Err(ErrorData::new(
335 ErrorCode::METHOD_NOT_FOUND,
336 "prompts not supported",
337 None,
338 ))
339 }
340
341 async fn get_prompt(
342 &self,
343 _request: GetPromptRequestParam,
344 _context: RequestContext<RoleServer>,
345 ) -> Result<GetPromptResult, ErrorData> {
346 Err(ErrorData::new(
347 ErrorCode::METHOD_NOT_FOUND,
348 "prompts not supported",
349 None,
350 ))
351 }
352}
353
354impl ResourcesProvider for Unset {
355 async fn list_resources(
356 &self,
357 _request: Option<PaginatedRequestParam>,
358 _context: RequestContext<RoleServer>,
359 ) -> Result<ListResourcesResult, ErrorData> {
360 Err(ErrorData::new(
361 ErrorCode::METHOD_NOT_FOUND,
362 "resources not supported",
363 None,
364 ))
365 }
366
367 async fn list_resource_templates(
368 &self,
369 _request: Option<PaginatedRequestParam>,
370 _context: RequestContext<RoleServer>,
371 ) -> Result<ListResourceTemplatesResult, ErrorData> {
372 Err(ErrorData::new(
373 ErrorCode::METHOD_NOT_FOUND,
374 "resources not supported",
375 None,
376 ))
377 }
378
379 async fn read_resource(
380 &self,
381 _request: ReadResourceRequestParam,
382 _context: RequestContext<RoleServer>,
383 ) -> Result<ReadResourceResult, ErrorData> {
384 Err(ErrorData::new(
385 ErrorCode::METHOD_NOT_FOUND,
386 "resources not supported",
387 None,
388 ))
389 }
390
391 async fn subscribe(
392 &self,
393 _request: SubscribeRequestParam,
394 _context: RequestContext<RoleServer>,
395 ) -> Result<(), ErrorData> {
396 Err(ErrorData::new(
397 ErrorCode::METHOD_NOT_FOUND,
398 "resources not supported",
399 None,
400 ))
401 }
402
403 async fn unsubscribe(
404 &self,
405 _request: UnsubscribeRequestParam,
406 _context: RequestContext<RoleServer>,
407 ) -> Result<(), ErrorData> {
408 Err(ErrorData::new(
409 ErrorCode::METHOD_NOT_FOUND,
410 "resources not supported",
411 None,
412 ))
413 }
414}
415
416impl CompletionProvider for Unset {
417 async fn complete(
418 &self,
419 _request: CompleteRequestParam,
420 _context: RequestContext<RoleServer>,
421 ) -> Result<CompleteResult, ErrorData> {
422 Err(ErrorData::new(
423 ErrorCode::METHOD_NOT_FOUND,
424 "completion not supported",
425 None,
426 ))
427 }
428}
429
430impl LoggingProvider for Unset {
431 async fn set_level(
432 &self,
433 _request: SetLevelRequestParam,
434 _context: RequestContext<RoleServer>,
435 ) -> Result<(), ErrorData> {
436 Err(ErrorData::new(
437 ErrorCode::METHOD_NOT_FOUND,
438 "logging not supported",
439 None,
440 ))
441 }
442}