1use serde_json::Value;
18use std::collections::HashMap;
19use std::sync::Arc;
20use tokio::sync::{Mutex, RwLock};
21use tracing::Instrument;
22
23use crate::core::{
24 completion::{CompletionContext, CompletionHandler},
25 error::{McpError, McpResult},
26 prompt::{Prompt, PromptHandler},
27 resource::{Resource, ResourceHandler},
28 tool::{MultiRoundToolCall, MultiRoundToolHandler, Tool, ToolHandler},
29 PromptInfo, ResourceInfo, ToolInfo,
30};
31use crate::protocol::tasks::{
32 has_tasks_extension, CancelTaskParams, CreateTaskResult, GetTaskParams, GetTaskResult,
33 TaskAcknowledgement, UpdateTaskParams, TASKS_EXTENSION_ID,
34};
35use crate::protocol::{messages::*, methods, types::*, validation::*, version::*};
36use crate::security::{RequestContext, RequestPolicy, RequestTarget};
37use crate::server::tasks::{ComposedTaskToolHandler, TaskRegistry, TaskToolHandler};
38use crate::transport::traits::ServerTransport;
39
40#[cfg(feature = "plugin")]
41use crate::plugin::PluginManager;
42#[cfg(feature = "plugin")]
43use async_trait::async_trait;
44
45use crate::core::tool::ClosureWrapper;
47
48#[cfg(feature = "plugin")]
50struct PluginToolHandler {
51 manager: Arc<RwLock<PluginManager>>,
52 tool_name: String,
53}
54
55#[cfg(feature = "plugin")]
56impl PluginToolHandler {
57 fn new(manager: Arc<RwLock<PluginManager>>, tool_name: String) -> Self {
58 Self { manager, tool_name }
59 }
60}
61
62#[cfg(feature = "plugin")]
63#[async_trait]
64impl ToolHandler for PluginToolHandler {
65 async fn call(
66 &self,
67 arguments: HashMap<String, Value>,
68 ) -> McpResult<crate::protocol::types::ToolResult> {
69 self.manager
70 .read()
71 .await
72 .execute_tool(&self.tool_name, serde_json::to_value(arguments)?)
73 .await
74 }
75}
76
77#[derive(Debug, Clone)]
79pub struct ServerConfig {
80 pub max_concurrent_requests: usize,
82 pub request_timeout_ms: u64,
84 pub validate_requests: bool,
86 pub enable_logging: bool,
88}
89
90impl Default for ServerConfig {
91 fn default() -> Self {
92 Self {
93 max_concurrent_requests: 100,
94 request_timeout_ms: 30000,
95 validate_requests: true,
96 enable_logging: true,
97 }
98 }
99}
100
101pub struct McpServer {
167 info: ServerInfo,
169 capabilities: ServerCapabilities,
171 config: ServerConfig,
173 resources: Arc<RwLock<HashMap<String, Resource>>>,
175 tools: Arc<RwLock<HashMap<String, Tool>>>,
177 multi_round_tools: Arc<RwLock<HashMap<String, RegisteredMultiRoundTool>>>,
179 task_tools: Arc<RwLock<HashMap<String, RegisteredTaskTool>>>,
181 task_registry: TaskRegistry,
183 prompts: Arc<RwLock<HashMap<String, Prompt>>>,
185 resource_templates: Arc<RwLock<HashMap<String, ResourceTemplate>>>,
187 completion_handlers: Arc<RwLock<HashMap<String, Box<dyn CompletionHandler>>>>,
189 transport: Arc<Mutex<Option<Box<dyn ServerTransport>>>>,
191 state: Arc<RwLock<ServerState>>,
193 #[allow(dead_code)]
195 request_counter: Arc<Mutex<u64>>,
196 request_policy: RequestPolicy,
198 protocol_mode: ProtocolMode,
200 #[cfg(feature = "plugin")]
202 plugin_manager: Option<Arc<RwLock<PluginManager>>>,
203}
204
205struct RegisteredMultiRoundTool {
206 info: ToolInfo,
207 handler: Box<dyn MultiRoundToolHandler>,
208}
209
210#[derive(Clone)]
211struct RegisteredTaskTool {
212 info: ToolInfo,
213 execution: TaskExecution,
214 fallback: Option<Arc<dyn ToolHandler>>,
215}
216
217#[derive(Clone)]
218enum TaskExecution {
219 Direct(Arc<dyn TaskToolHandler>),
220 Composed {
221 preflight: Arc<dyn MultiRoundToolHandler>,
222 handler: Arc<dyn ComposedTaskToolHandler>,
223 },
224}
225
226#[derive(Debug, Clone, PartialEq)]
228pub enum ServerState {
229 Uninitialized,
231 Initializing,
233 Running,
235 Stopping,
237 Stopped,
239}
240
241fn request_target(request: &JsonRpcRequest) -> RequestTarget {
242 let resource = request.params.as_ref().and_then(|params| {
243 params
244 .get("name")
245 .or_else(|| params.get("uri"))
246 .and_then(Value::as_str)
247 .map(str::to_owned)
248 });
249 RequestTarget::new(request.method.clone(), resource)
250}
251
252fn validate_input_required_result(
253 result: &InputRequiredResult,
254 capabilities: &ClientCapabilities,
255) -> McpResult<()> {
256 if result.result_type != ResultType::InputRequired {
257 return Err(McpError::Validation(
258 "multi-round handler must return resultType input_required".to_string(),
259 ));
260 }
261 if result.input_requests.is_empty() && result.request_state.is_none() {
262 return Err(McpError::Validation(
263 "input_required needs inputRequests or requestState".to_string(),
264 ));
265 }
266 for input_request in result.input_requests.values() {
267 let method = input_request
268 .get("method")
269 .and_then(Value::as_str)
270 .ok_or_else(|| McpError::Validation("input request is missing method".to_string()))?;
271 let required = match method {
272 methods::SAMPLING_CREATE_MESSAGE if capabilities.sampling.is_none() => {
273 Some(serde_json::json!({"sampling": {}}))
274 }
275 methods::ROOTS_LIST if capabilities.roots.is_none() => {
276 Some(serde_json::json!({"roots": {}}))
277 }
278 methods::ELICITATION_CREATE if capabilities.elicitation.is_none() => {
279 Some(serde_json::json!({"elicitation": {}}))
280 }
281 methods::SAMPLING_CREATE_MESSAGE
282 | methods::ROOTS_LIST
283 | methods::ELICITATION_CREATE => None,
284 _ => {
285 return Err(McpError::Validation(format!(
286 "unsupported input request method: {method}"
287 )))
288 }
289 };
290 if let Some(required) = required {
291 return Err(McpError::MissingRequiredClientCapability(required));
292 }
293 }
294 Ok(())
295}
296
297fn tasks_capability_error() -> McpError {
298 McpError::MissingRequiredClientCapability(serde_json::json!({
299 "extensions": { (TASKS_EXTENSION_ID): {} }
300 }))
301}
302
303fn parse_multi_round_tool_call(
304 raw_params: &Value,
305 arguments: HashMap<String, Value>,
306 modern_context: Option<&ModernRequestContext>,
307) -> McpResult<MultiRoundToolCall> {
308 let raw_object = raw_params.as_object().ok_or_else(|| {
309 McpError::Validation("tool call parameters must be an object".to_string())
310 })?;
311 let input_responses = raw_object
312 .get("inputResponses")
313 .map(|value| {
314 value
315 .as_object()
316 .cloned()
317 .map(|values| values.into_iter().collect())
318 .ok_or_else(|| McpError::Validation("inputResponses must be an object".to_string()))
319 })
320 .transpose()?
321 .unwrap_or_default();
322 let request_state = raw_object
323 .get("requestState")
324 .map(|value| {
325 value
326 .as_str()
327 .map(str::to_string)
328 .ok_or_else(|| McpError::Validation("requestState must be a string".to_string()))
329 })
330 .transpose()?;
331 let (client_info, client_capabilities) = modern_context
332 .map(|context| {
333 (
334 context.client_info.clone(),
335 context.client_capabilities.clone(),
336 )
337 })
338 .unwrap_or_else(|| (None, ClientCapabilities::default()));
339 Ok(MultiRoundToolCall {
340 arguments,
341 input_responses,
342 request_state,
343 client_info,
344 client_capabilities,
345 })
346}
347
348impl McpServer {
349 pub fn new(name: String, version: String) -> Self {
351 Self {
352 info: ServerInfo::new(name, version),
353 capabilities: ServerCapabilities {
354 extensions: None,
355 prompts: Some(PromptsCapability {
356 list_changed: Some(true),
357 }),
358 resources: Some(ResourcesCapability {
359 subscribe: Some(true),
360 list_changed: Some(true),
361 }),
362 tools: Some(ToolsCapability {
363 list_changed: Some(true),
364 }),
365 sampling: None,
366 logging: None,
367 completions: Some(CompletionsCapability::default()),
368 experimental: None,
369 },
370 config: ServerConfig::default(),
371 resources: Arc::new(RwLock::new(HashMap::new())),
372 tools: Arc::new(RwLock::new(HashMap::new())),
373 multi_round_tools: Arc::new(RwLock::new(HashMap::new())),
374 task_tools: Arc::new(RwLock::new(HashMap::new())),
375 task_registry: TaskRegistry::default(),
376 prompts: Arc::new(RwLock::new(HashMap::new())),
377 resource_templates: Arc::new(RwLock::new(HashMap::new())),
378 completion_handlers: Arc::new(RwLock::new(HashMap::new())),
379 transport: Arc::new(Mutex::new(None)),
380 state: Arc::new(RwLock::new(ServerState::Uninitialized)),
381 request_counter: Arc::new(Mutex::new(0)),
382 request_policy: RequestPolicy::default(),
383 protocol_mode: ProtocolMode::Auto,
384 #[cfg(feature = "plugin")]
385 plugin_manager: None,
386 }
387 }
388
389 pub fn create(name: impl Into<String>, version: impl Into<String>) -> Self {
391 Self::new(name.into(), version.into())
392 }
393
394 pub fn with_config(name: String, version: String, config: ServerConfig) -> Self {
396 let mut server = Self::new(name, version);
397 server.config = config;
398 server
399 }
400
401 #[cfg(feature = "plugin")]
403 pub fn with_plugin_manager(mut self, manager: PluginManager) -> Self {
404 self.plugin_manager = Some(Arc::new(RwLock::new(manager)));
405 self
406 }
407
408 #[cfg(feature = "plugin")]
410 pub async fn sync_plugin_tools(&self) -> McpResult<()> {
411 if let Some(ref manager) = self.plugin_manager {
412 let plugin_tools = manager.read().await.list_tools().await;
413
414 for tool in plugin_tools {
415 let handler = PluginToolHandler::new(manager.clone(), tool.name.clone());
417
418 let schema = serde_json::json!({
420 "type": tool.input_schema.schema_type,
421 "properties": tool.input_schema.properties,
422 "required": tool.input_schema.required,
423 });
424
425 self.add_tool(tool.name.clone(), tool.description.clone(), schema, handler)
427 .await?;
428 }
429 }
430 Ok(())
431 }
432
433 pub fn set_capabilities(&mut self, capabilities: ServerCapabilities) {
435 self.capabilities = capabilities;
436 }
437
438 pub fn set_protocol_mode(&mut self, mode: ProtocolMode) {
440 self.protocol_mode = mode;
441 }
442
443 pub fn protocol_mode(&self) -> ProtocolMode {
445 self.protocol_mode
446 }
447
448 pub fn set_config(&mut self, config: ServerConfig) {
450 self.config = config;
451 }
452
453 pub fn set_request_policy(&mut self, policy: RequestPolicy) {
455 self.request_policy = policy;
456 }
457
458 pub fn with_request_policy(mut self, policy: RequestPolicy) -> Self {
460 self.request_policy = policy;
461 self
462 }
463
464 pub fn set_initial_resources(&mut self, resources: HashMap<String, Resource>) {
466 let resources_arc = Arc::clone(&self.resources);
469 std::thread::spawn(move || {
470 let rt = tokio::runtime::Runtime::new().unwrap();
471 rt.block_on(async {
472 let mut resources_lock = resources_arc.write().await;
473 *resources_lock = resources;
474 });
475 })
476 .join()
477 .unwrap();
478 }
479
480 pub fn set_initial_tools(&mut self, tools: HashMap<String, Tool>) {
482 let tools_arc = Arc::clone(&self.tools);
483 std::thread::spawn(move || {
484 let rt = tokio::runtime::Runtime::new().unwrap();
485 rt.block_on(async {
486 let mut tools_lock = tools_arc.write().await;
487 *tools_lock = tools;
488 });
489 })
490 .join()
491 .unwrap();
492 }
493
494 pub fn set_initial_prompts(&mut self, prompts: HashMap<String, Prompt>) {
496 let prompts_arc = Arc::clone(&self.prompts);
497 std::thread::spawn(move || {
498 let rt = tokio::runtime::Runtime::new().unwrap();
499 rt.block_on(async {
500 let mut prompts_lock = prompts_arc.write().await;
501 *prompts_lock = prompts;
502 });
503 })
504 .join()
505 .unwrap();
506 }
507
508 pub fn set_initial_resource_templates(&mut self, templates: HashMap<String, ResourceTemplate>) {
510 let templates_arc = Arc::clone(&self.resource_templates);
511 std::thread::spawn(move || {
512 let rt = tokio::runtime::Runtime::new().unwrap();
513 rt.block_on(async {
514 let mut templates_lock = templates_arc.write().await;
515 *templates_lock = templates;
516 });
517 })
518 .join()
519 .unwrap();
520 }
521
522 pub fn builder() -> crate::server::builder::ServerBuilder {
524 crate::server::builder::ServerBuilder::new()
525 }
526
527 pub fn with_capabilities(mut self, capabilities: ServerCapabilities) -> Self {
529 self.capabilities = capabilities;
530 self
531 }
532
533 pub fn with_server_config(mut self, config: ServerConfig) -> Self {
535 self.config = config;
536 self
537 }
538
539 pub async fn add_tool<H>(
548 &self,
549 name: impl Into<String>,
550 description: Option<impl Into<String>>,
551 input_schema: Value,
552 handler: H,
553 ) -> McpResult<()>
554 where
555 H: ToolHandler + 'static,
556 {
557 let name = name.into();
558 let description = description.map(|d| d.into());
559 let tool = Tool::new(name.clone(), description, input_schema, handler);
560 self.multi_round_tools.write().await.remove(&name);
561 self.task_tools.write().await.remove(&name);
562 self.tools.write().await.insert(name, tool);
563 Ok(())
564 }
565
566 pub async fn add_multi_round_tool<H>(
568 &self,
569 name: impl Into<String>,
570 description: Option<impl Into<String>>,
571 input_schema: Value,
572 handler: H,
573 ) -> McpResult<()>
574 where
575 H: MultiRoundToolHandler + 'static,
576 {
577 let name = name.into();
578 let description = description.map(Into::into);
579 let schema_object = input_schema.as_object().ok_or_else(|| {
580 McpError::Validation("tool input schema must be an object".to_string())
581 })?;
582 let info = ToolInfo {
583 name: name.clone(),
584 description,
585 input_schema: ToolInputSchema {
586 schema_type: schema_object
587 .get("type")
588 .and_then(Value::as_str)
589 .unwrap_or("object")
590 .to_string(),
591 properties: schema_object
592 .get("properties")
593 .and_then(Value::as_object)
594 .map(|properties| {
595 properties
596 .iter()
597 .map(|(key, value)| (key.clone(), value.clone()))
598 .collect()
599 }),
600 required: schema_object
601 .get("required")
602 .and_then(Value::as_array)
603 .map(|required| {
604 required
605 .iter()
606 .filter_map(Value::as_str)
607 .map(str::to_string)
608 .collect()
609 }),
610 additional_properties: schema_object
611 .iter()
612 .filter(|(key, _)| !matches!(key.as_str(), "type" | "properties" | "required"))
613 .map(|(key, value)| (key.clone(), value.clone()))
614 .collect(),
615 },
616 output_schema: None,
617 annotations: None,
618 title: None,
619 icons: None,
620 meta: None,
621 };
622 validate_tool_info(&info)?;
623
624 self.tools.write().await.remove(&name);
625 self.task_tools.write().await.remove(&name);
626 self.multi_round_tools.write().await.insert(
627 name,
628 RegisteredMultiRoundTool {
629 info,
630 handler: Box::new(handler),
631 },
632 );
633 self.emit_tools_list_changed().await
634 }
635
636 pub async fn add_multi_round_tool_detailed<H>(
638 &self,
639 info: ToolInfo,
640 handler: H,
641 ) -> McpResult<()>
642 where
643 H: MultiRoundToolHandler + 'static,
644 {
645 validate_tool_info(&info)?;
646 let name = info.name.clone();
647 self.tools.write().await.remove(&name);
648 self.task_tools.write().await.remove(&name);
649 self.multi_round_tools.write().await.insert(
650 name,
651 RegisteredMultiRoundTool {
652 info,
653 handler: Box::new(handler),
654 },
655 );
656 self.emit_tools_list_changed().await
657 }
658
659 pub async fn add_tool_with_closure<F>(
669 &self,
670 name: impl Into<String>,
671 description: Option<impl Into<String>>,
672 input_schema: Value,
673 handler: F,
674 ) -> McpResult<()>
675 where
676 F: Fn(&HashMap<String, Value>) -> McpResult<Vec<ContentBlock>> + Send + Sync + 'static,
677 {
678 let name = name.into();
679 let description = description.map(|d| d.into());
680 self.add_tool(name, description, input_schema, ClosureWrapper(handler))
681 .await
682 }
683
684 pub async fn add_tool_built(&self, tool: Tool) -> McpResult<()> {
686 let name = tool.info.name.clone();
687 self.multi_round_tools.write().await.remove(&name);
688 self.task_tools.write().await.remove(&name);
689 self.tools.write().await.insert(name, tool);
690 Ok(())
691 }
692
693 pub async fn add_task_tool<H>(&self, info: ToolInfo, handler: H) -> McpResult<()>
695 where
696 H: TaskToolHandler + 'static,
697 {
698 validate_tool_info(&info)?;
699 let name = info.name.clone();
700 self.tools.write().await.remove(&name);
701 self.multi_round_tools.write().await.remove(&name);
702 self.task_tools.write().await.insert(
703 name,
704 RegisteredTaskTool {
705 info,
706 execution: TaskExecution::Direct(Arc::new(handler)),
707 fallback: None,
708 },
709 );
710 self.emit_tools_list_changed().await
711 }
712
713 pub async fn add_task_tool_with_fallback<H, F>(
716 &self,
717 info: ToolInfo,
718 handler: H,
719 fallback: F,
720 ) -> McpResult<()>
721 where
722 H: TaskToolHandler + 'static,
723 F: ToolHandler + 'static,
724 {
725 validate_tool_info(&info)?;
726 let name = info.name.clone();
727 self.tools.write().await.remove(&name);
728 self.multi_round_tools.write().await.remove(&name);
729 self.task_tools.write().await.insert(
730 name,
731 RegisteredTaskTool {
732 info,
733 execution: TaskExecution::Direct(Arc::new(handler)),
734 fallback: Some(Arc::new(fallback)),
735 },
736 );
737 self.emit_tools_list_changed().await
738 }
739
740 pub async fn add_composed_task_tool<P, H>(
748 &self,
749 info: ToolInfo,
750 preflight: P,
751 handler: H,
752 ) -> McpResult<()>
753 where
754 P: MultiRoundToolHandler + 'static,
755 H: ComposedTaskToolHandler + 'static,
756 {
757 validate_tool_info(&info)?;
758 let name = info.name.clone();
759 self.tools.write().await.remove(&name);
760 self.multi_round_tools.write().await.remove(&name);
761 self.task_tools.write().await.insert(
762 name,
763 RegisteredTaskTool {
764 info,
765 execution: TaskExecution::Composed {
766 preflight: Arc::new(preflight),
767 handler: Arc::new(handler),
768 },
769 fallback: None,
770 },
771 );
772 self.emit_tools_list_changed().await
773 }
774 pub fn info(&self) -> &ServerInfo {
776 &self.info
777 }
778
779 pub fn name(&self) -> &str {
781 &self.info.name
782 }
783
784 pub fn version(&self) -> &str {
786 &self.info.version
787 }
788
789 pub fn capabilities(&self) -> &ServerCapabilities {
791 &self.capabilities
792 }
793
794 pub fn config(&self) -> &ServerConfig {
796 &self.config
797 }
798
799 pub async fn add_resource<H>(&self, name: String, uri: String, handler: H) -> McpResult<()>
805 where
806 H: ResourceHandler + 'static,
807 {
808 let resource_info = ResourceInfo {
809 uri: uri.clone(),
810 name: name.clone(),
811 description: None,
812 mime_type: None,
813 annotations: None,
814 size: None,
815 icons: None,
816 title: None,
817 meta: None,
818 };
819
820 validate_resource_info(&resource_info)?;
821
822 let resource = Resource::new(resource_info, handler);
823
824 {
825 let mut resources = self.resources.write().await;
826 resources.insert(uri, resource);
827 }
828
829 self.emit_resources_list_changed().await?;
831
832 Ok(())
833 }
834
835 pub async fn add_resource_detailed<H>(&self, info: ResourceInfo, handler: H) -> McpResult<()>
837 where
838 H: ResourceHandler + 'static,
839 {
840 validate_resource_info(&info)?;
841
842 let uri = info.uri.clone();
843 let resource = Resource::new(info, handler);
844
845 {
846 let mut resources = self.resources.write().await;
847 resources.insert(uri, resource);
848 }
849
850 self.emit_resources_list_changed().await?;
851
852 Ok(())
853 }
854
855 pub async fn remove_resource(&self, uri: &str) -> McpResult<bool> {
857 let removed = {
858 let mut resources = self.resources.write().await;
859 resources.remove(uri).is_some()
860 };
861
862 if removed {
863 self.emit_resources_list_changed().await?;
864 }
865
866 Ok(removed)
867 }
868
869 pub async fn list_resources(&self) -> McpResult<Vec<ResourceInfo>> {
871 let resources = self.resources.read().await;
872 let mut values: Vec<_> = resources
873 .values()
874 .map(|resource| resource.info.clone())
875 .collect();
876 values.sort_by(|left, right| left.uri.cmp(&right.uri));
877 Ok(values)
878 }
879
880 pub async fn read_resource(&self, uri: &str) -> McpResult<Vec<ResourceContents>> {
882 let resources = self.resources.read().await;
883
884 match resources.get(uri) {
885 Some(resource) => {
886 let params = HashMap::new(); resource.handler.read(uri, ¶ms).await
888 }
889 None => Err(McpError::ResourceNotFound(uri.to_string())),
890 }
891 }
892
893 pub async fn add_tool_detailed<H>(&self, info: ToolInfo, handler: H) -> McpResult<()>
899 where
900 H: ToolHandler + 'static,
901 {
902 validate_tool_info(&info)?;
903
904 let name = info.name.clone();
905 let tool = Tool::new(
906 name.clone(),
907 info.description.clone(),
908 serde_json::to_value(&info.input_schema)?,
909 handler,
910 );
911
912 {
913 let mut tools = self.tools.write().await;
914 self.multi_round_tools.write().await.remove(&name);
915 self.task_tools.write().await.remove(&name);
916 tools.insert(name, tool);
917 }
918
919 self.emit_tools_list_changed().await?;
920
921 Ok(())
922 }
923
924 pub async fn remove_tool(&self, name: &str) -> McpResult<bool> {
926 let removed_regular = {
927 let mut tools = self.tools.write().await;
928 tools.remove(name).is_some()
929 };
930 let removed_multi_round = self.multi_round_tools.write().await.remove(name).is_some();
931 let removed_task = self.task_tools.write().await.remove(name).is_some();
932 let removed = removed_regular || removed_multi_round || removed_task;
933
934 if removed {
935 self.emit_tools_list_changed().await?;
936 }
937
938 Ok(removed)
939 }
940
941 pub async fn list_tools(&self) -> McpResult<Vec<ToolInfo>> {
943 let tools = self.tools.read().await;
944 let mut values: Vec<_> = tools.values().map(|tool| tool.info.clone()).collect();
945 drop(tools);
946 values.extend(
947 self.multi_round_tools
948 .read()
949 .await
950 .values()
951 .map(|tool| tool.info.clone()),
952 );
953 values.extend(
954 self.task_tools
955 .read()
956 .await
957 .values()
958 .map(|tool| tool.info.clone()),
959 );
960 values.sort_by(|left, right| left.name.cmp(&right.name));
961 Ok(values)
962 }
963
964 pub async fn call_tool(
966 &self,
967 name: &str,
968 arguments: Option<HashMap<String, Value>>,
969 ) -> McpResult<ToolResult> {
970 let tools = self.tools.read().await;
971
972 match tools.get(name) {
973 Some(tool) => {
974 if !tool.enabled {
975 return Err(McpError::ToolNotFound(format!("Tool '{name}' is disabled")));
976 }
977
978 let args = arguments.unwrap_or_default();
979 tool.handler.call(args).await
980 }
981 None => Err(McpError::ToolNotFound(name.to_string())),
982 }
983 }
984
985 pub async fn add_prompt<H>(&self, info: PromptInfo, handler: H) -> McpResult<()>
991 where
992 H: PromptHandler + 'static,
993 {
994 validate_prompt_info(&info)?;
995
996 let name = info.name.clone();
997 let prompt = Prompt::new(info, handler);
998
999 {
1000 let mut prompts = self.prompts.write().await;
1001 prompts.insert(name, prompt);
1002 }
1003
1004 self.emit_prompts_list_changed().await?;
1005
1006 Ok(())
1007 }
1008
1009 pub async fn remove_prompt(&self, name: &str) -> McpResult<bool> {
1011 let removed = {
1012 let mut prompts = self.prompts.write().await;
1013 prompts.remove(name).is_some()
1014 };
1015
1016 if removed {
1017 self.emit_prompts_list_changed().await?;
1018 }
1019
1020 Ok(removed)
1021 }
1022
1023 pub async fn list_prompts(&self) -> McpResult<Vec<PromptInfo>> {
1025 let prompts = self.prompts.read().await;
1026 let mut values: Vec<_> = prompts.values().map(|prompt| prompt.info.clone()).collect();
1027 values.sort_by(|left, right| left.name.cmp(&right.name));
1028 Ok(values)
1029 }
1030
1031 pub async fn get_prompt(
1033 &self,
1034 name: &str,
1035 arguments: Option<HashMap<String, Value>>,
1036 ) -> McpResult<PromptResult> {
1037 let prompts = self.prompts.read().await;
1038
1039 match prompts.get(name) {
1040 Some(prompt) => {
1041 let args = arguments.unwrap_or_default();
1042 prompt.handler.get(args).await
1043 }
1044 None => Err(McpError::PromptNotFound(name.to_string())),
1045 }
1046 }
1047
1048 pub async fn add_resource_template(&self, template: ResourceTemplate) -> McpResult<()> {
1054 let name = template.name.clone();
1055 {
1056 let mut templates = self.resource_templates.write().await;
1057 templates.insert(name, template);
1058 }
1059
1060 self.emit_resource_templates_list_changed().await?;
1062 Ok(())
1063 }
1064
1065 pub async fn list_resource_templates(&self) -> McpResult<Vec<ResourceTemplate>> {
1067 let templates = self.resource_templates.read().await;
1068 let mut values: Vec<_> = templates.values().cloned().collect();
1069 values.sort_by(|left, right| left.uri_template.cmp(&right.uri_template));
1070 Ok(values)
1071 }
1072
1073 pub async fn remove_resource_template(&self, name: &str) -> McpResult<bool> {
1075 let removed = {
1076 let mut templates = self.resource_templates.write().await;
1077 templates.remove(name).is_some()
1078 };
1079
1080 if removed {
1081 self.emit_resource_templates_list_changed().await?;
1082 }
1083
1084 Ok(removed)
1085 }
1086
1087 async fn emit_resource_templates_list_changed(&self) -> McpResult<()> {
1089 Ok(())
1092 }
1093
1094 pub async fn add_completion_handler<H>(&self, ref_type: String, handler: H) -> McpResult<()>
1100 where
1101 H: CompletionHandler + 'static,
1102 {
1103 let mut handlers = self.completion_handlers.write().await;
1104 handlers.insert(ref_type, Box::new(handler));
1105 Ok(())
1106 }
1107
1108 pub async fn remove_completion_handler(&self, ref_type: &str) -> McpResult<bool> {
1110 let mut handlers = self.completion_handlers.write().await;
1111 Ok(handlers.remove(ref_type).is_some())
1112 }
1113
1114 pub async fn handle_completion(
1116 &self,
1117 reference: &CompletionReference,
1118 argument: &CompletionArgument,
1119 context: Option<&CompletionContext>,
1120 ) -> McpResult<Vec<String>> {
1121 let ref_type = match reference {
1122 CompletionReference::Prompt { .. } => "ref/prompt",
1123 CompletionReference::Resource { .. } => "ref/resource",
1124 CompletionReference::Tool { .. } => "ref/tool",
1125 };
1126
1127 let handlers = self.completion_handlers.read().await;
1128 if let Some(handler) = handlers.get(ref_type) {
1129 handler.complete(reference, argument, context).await
1130 } else {
1131 Ok(vec![])
1133 }
1134 }
1135
1136 pub async fn send_client_request(
1142 &self,
1143 _request: JsonRpcRequest,
1144 ) -> McpResult<JsonRpcResponse> {
1145 let mut transport_guard = self.transport.lock().await;
1146 if let Some(_transport) = transport_guard.as_mut() {
1147 Err(McpError::MethodNotFound(
1149 "Bidirectional communication not yet fully implemented".to_string(),
1150 ))
1151 } else {
1152 Err(McpError::Transport("Not connected".to_string()))
1153 }
1154 }
1155
1156 pub async fn request_sampling(
1158 &self,
1159 params: CreateMessageParams,
1160 ) -> McpResult<CreateMessageResult> {
1161 let request = JsonRpcRequest::new(
1162 Value::from(self.next_request_id().await),
1163 methods::SAMPLING_CREATE_MESSAGE.to_string(),
1164 Some(params),
1165 )?;
1166
1167 let response = self.send_client_request(request).await?;
1168
1169 if let Some(result) = response.result {
1170 Ok(serde_json::from_value(result)?)
1171 } else {
1172 Err(McpError::Protocol("No result in response".to_string()))
1173 }
1174 }
1175
1176 pub async fn request_roots(&self) -> McpResult<ListRootsResult> {
1178 let request = JsonRpcRequest::new(
1179 Value::from(self.next_request_id().await),
1180 methods::ROOTS_LIST.to_string(),
1181 Some(ListRootsParams { meta: None }),
1182 )?;
1183
1184 let response = self.send_client_request(request).await?;
1185
1186 if let Some(result) = response.result {
1187 Ok(serde_json::from_value(result)?)
1188 } else {
1189 Err(McpError::Protocol("No result in response".to_string()))
1190 }
1191 }
1192
1193 pub async fn request_elicitation(&self, params: ElicitParams) -> McpResult<ElicitResult> {
1195 let request = JsonRpcRequest::new(
1196 Value::from(self.next_request_id().await),
1197 methods::ELICITATION_CREATE.to_string(),
1198 Some(params),
1199 )?;
1200
1201 let response = self.send_client_request(request).await?;
1202
1203 if let Some(result) = response.result {
1204 Ok(serde_json::from_value(result)?)
1205 } else {
1206 Err(McpError::Protocol("No result in response".to_string()))
1207 }
1208 }
1209
1210 pub async fn request_list_roots(&self) -> McpResult<ListRootsResult> {
1215 let request = JsonRpcRequest::new(
1216 Value::from(self.next_request_id().await),
1217 methods::ROOTS_LIST.to_string(),
1218 None::<serde_json::Value>,
1219 )?;
1220
1221 let response = self.send_client_request(request).await?;
1222
1223 if let Some(result) = response.result {
1224 Ok(serde_json::from_value(result)?)
1225 } else {
1226 Err(McpError::Protocol("No result in response".to_string()))
1227 }
1228 }
1229
1230 pub async fn notify_roots_list_changed(&self) -> McpResult<()> {
1235 let notification = JsonRpcNotification {
1236 jsonrpc: "2.0".to_string(),
1237 method: methods::ROOTS_LIST_CHANGED.to_string(),
1238 params: None,
1239 };
1240
1241 if let Some(ref mut transport) = *self.transport.lock().await {
1242 transport.send_notification(notification).await
1243 } else {
1244 Err(McpError::Connection("No transport available".to_string()))
1245 }
1246 }
1247
1248 pub async fn notify_tools_list_changed(&self) -> McpResult<()> {
1250 self.emit_tools_list_changed().await
1251 }
1252
1253 pub async fn notify_prompts_list_changed(&self) -> McpResult<()> {
1255 self.emit_prompts_list_changed().await
1256 }
1257
1258 pub async fn notify_resources_list_changed(&self) -> McpResult<()> {
1260 self.emit_resources_list_changed().await
1261 }
1262
1263 pub async fn start<T>(&mut self, mut transport: T) -> McpResult<()>
1269 where
1270 T: ServerTransport + 'static,
1271 {
1272 let mut state = self.state.write().await;
1273
1274 match *state {
1275 ServerState::Uninitialized => {
1276 *state = ServerState::Initializing;
1277 }
1278 _ => return Err(McpError::Protocol("Server is already started".to_string())),
1279 }
1280
1281 drop(state);
1282
1283 transport.set_server_capabilities(self.modern_capabilities().await)?;
1284 transport.set_task_notifications(self.task_registry.subscribe())?;
1285
1286 let tool_schemas = {
1287 let tools = self.tools.read().await;
1288 let mut schemas = tools
1289 .iter()
1290 .map(|(name, tool)| {
1291 serde_json::to_value(&tool.info.input_schema)
1292 .map(|schema| (name.clone(), schema))
1293 .map_err(McpError::from)
1294 })
1295 .collect::<McpResult<HashMap<_, _>>>()?;
1296 drop(tools);
1297 for (name, tool) in self.multi_round_tools.read().await.iter() {
1298 schemas.insert(name.clone(), serde_json::to_value(&tool.info.input_schema)?);
1299 }
1300 for (name, tool) in self.task_tools.read().await.iter() {
1301 schemas.insert(name.clone(), serde_json::to_value(&tool.info.input_schema)?);
1302 }
1303 schemas
1304 };
1305 transport.set_tool_schemas(tool_schemas)?;
1306
1307 let resources = self.resources.clone();
1309 let tools = self.tools.clone();
1310 let multi_round_tools = self.multi_round_tools.clone();
1311 let task_tools = self.task_tools.clone();
1312 let task_registry = self.task_registry.clone();
1313 let prompts = self.prompts.clone();
1314 let resource_templates = self.resource_templates.clone();
1315 let completion_handlers = self.completion_handlers.clone();
1316 let info = self.info.clone();
1317 let capabilities = self.capabilities.clone();
1318 let config = self.config.clone();
1319 let request_policy = self.request_policy.clone();
1320 let protocol_mode = self.protocol_mode;
1321
1322 let request_handler: crate::transport::traits::ServerRequestHandler =
1323 Arc::new(move |request| {
1324 let resources = resources.clone();
1325 let tools = tools.clone();
1326 let multi_round_tools = multi_round_tools.clone();
1327 let task_tools = task_tools.clone();
1328 let task_registry = task_registry.clone();
1329 let prompts = prompts.clone();
1330 let resource_templates = resource_templates.clone();
1331 let completion_handlers = completion_handlers.clone();
1332 let info = info.clone();
1333 let capabilities = capabilities.clone();
1334 let config = config.clone();
1335 let request_policy = request_policy.clone();
1336 Box::pin(async move {
1337 let temp_server = McpServer {
1339 info,
1340 capabilities,
1341 config,
1342 resources,
1343 tools,
1344 multi_round_tools,
1345 task_tools,
1346 task_registry,
1347 prompts,
1348 resource_templates,
1349 completion_handlers,
1350 transport: Arc::new(Mutex::new(None)),
1351 state: Arc::new(RwLock::new(ServerState::Running)),
1352 request_counter: Arc::new(Mutex::new(0)),
1353 request_policy,
1354 protocol_mode,
1355 #[cfg(feature = "plugin")]
1356 plugin_manager: None,
1357 };
1358 temp_server.handle_request(request).await
1359 })
1360 });
1361
1362 transport.set_request_handler(request_handler);
1364
1365 {
1367 let mut transport_guard = self.transport.lock().await;
1368 *transport_guard = Some(Box::new(transport));
1369 }
1370
1371 {
1373 let mut transport_guard = self.transport.lock().await;
1374 if let Some(transport) = transport_guard.as_mut() {
1375 transport.start().await?;
1376 }
1377 }
1378
1379 {
1381 let mut state = self.state.write().await;
1382 *state = ServerState::Running;
1383 }
1384
1385 Ok(())
1386 }
1387
1388 pub async fn stop(&self) -> McpResult<()> {
1390 let mut state = self.state.write().await;
1391
1392 match *state {
1393 ServerState::Running => {
1394 *state = ServerState::Stopping;
1395 }
1396 ServerState::Stopped => return Ok(()),
1397 _ => return Err(McpError::Protocol("Server is not running".to_string())),
1398 }
1399
1400 drop(state);
1401
1402 {
1404 let mut transport_guard = self.transport.lock().await;
1405 if let Some(transport) = transport_guard.as_mut() {
1406 transport.stop().await?;
1407 }
1408 }
1409
1410 {
1412 let mut state = self.state.write().await;
1413 *state = ServerState::Stopped;
1414 }
1415
1416 Ok(())
1417 }
1418
1419 pub async fn is_running(&self) -> bool {
1421 let state = self.state.read().await;
1422 matches!(*state, ServerState::Running)
1423 }
1424
1425 pub async fn state(&self) -> ServerState {
1427 let state = self.state.read().await;
1428 state.clone()
1429 }
1430
1431 pub async fn run_with_transport<T>(mut self, transport: T) -> McpResult<()>
1463 where
1464 T: ServerTransport + 'static,
1465 {
1466 self.start(transport).await?;
1467
1468 tracing::info!("Server started. Press Ctrl+C to stop.");
1469
1470 tokio::signal::ctrl_c()
1472 .await
1473 .map_err(|e| McpError::internal(format!("Signal handling error: {e}")))?;
1474
1475 tracing::info!("Shutdown signal received, stopping server...");
1476 self.stop().await
1477 }
1478
1479 pub async fn handle_request(&self, request: JsonRpcRequest) -> McpResult<JsonRpcResponse> {
1484 self.handle_request_with_context(request, RequestContext::anonymous())
1485 .await
1486 }
1487
1488 pub async fn handle_request_with_context(
1493 &self,
1494 request: JsonRpcRequest,
1495 context: RequestContext,
1496 ) -> McpResult<JsonRpcResponse> {
1497 let target = request_target(&request);
1498 let method = request.method.clone();
1499 let principal = context.principal.id.clone();
1500 let request_id = context.request_id.clone();
1501 let transport = context.transport.clone();
1502 let span = tracing::info_span!(
1503 "mcp.request",
1504 request.id = %request_id,
1505 rpc.method = %method,
1506 principal.id = %principal,
1507 transport = %transport,
1508 otel.kind = "server"
1509 );
1510
1511 async move {
1512 let started_at = std::time::Instant::now();
1513 if let Err(error) = self.request_policy.enforce(&context, &target).await {
1514 tracing::warn!(
1515 event = "security.policy_denied",
1516 error.category = error.category(),
1517 error = %error,
1518 "request rejected by production policy"
1519 );
1520 return Err(error);
1521 }
1522
1523 let modern_context = match modern_request_context(&request) {
1525 Err(McpError::UnsupportedProtocolVersion { requested, .. }) => {
1526 let supported = match self.protocol_mode {
1527 ProtocolMode::Auto => SUPPORTED_PROTOCOL_VERSIONS
1528 .iter()
1529 .map(|version| (*version).to_string())
1530 .collect(),
1531 ProtocolMode::ModernOnly => vec![MODERN_PROTOCOL_VERSION.to_string()],
1532 ProtocolMode::LegacyOnly => vec![LEGACY_PROTOCOL_VERSION.to_string()],
1533 };
1534 return Err(McpError::UnsupportedProtocolVersion {
1535 requested,
1536 supported,
1537 });
1538 }
1539 result => result?,
1540 };
1541 let is_modern = modern_context.is_some();
1542 if request.method == methods::SERVER_DISCOVER && !is_modern {
1543 return Err(McpError::Validation(
1544 "server/discover requires MCP 2026 request metadata".to_string(),
1545 ));
1546 }
1547 match self.protocol_mode {
1548 ProtocolMode::ModernOnly if !is_modern => {
1549 return Err(McpError::UnsupportedProtocolVersion {
1550 requested: LEGACY_PROTOCOL_VERSION.to_string(),
1551 supported: vec![MODERN_PROTOCOL_VERSION.to_string()],
1552 });
1553 }
1554 ProtocolMode::LegacyOnly if is_modern => {
1555 return Err(McpError::UnsupportedProtocolVersion {
1556 requested: MODERN_PROTOCOL_VERSION.to_string(),
1557 supported: vec![LEGACY_PROTOCOL_VERSION.to_string()],
1558 });
1559 }
1560 _ => {}
1561 }
1562 if is_modern && is_legacy_only_method(&request.method) {
1563 return Err(McpError::MethodNotFound(format!(
1564 "{} is unavailable in MCP {MODERN_PROTOCOL_VERSION}",
1565 request.method
1566 )));
1567 }
1568
1569 if self.config.validate_requests {
1570 validate_jsonrpc_request(&request)?;
1571 validate_mcp_request(&request.method, request.params.as_ref())?;
1572 }
1573
1574 let result = match request.method.as_str() {
1576 methods::INITIALIZE => self.handle_initialize(request.params).await,
1577 methods::SERVER_DISCOVER => self.handle_server_discover().await,
1578 methods::PING => self.handle_ping().await,
1579 methods::TOOLS_LIST => self.handle_tools_list(request.params).await,
1580 methods::TOOLS_CALL => {
1581 self.handle_tools_call(request.params, modern_context.as_ref(), &context)
1582 .await
1583 }
1584 methods::TASKS_GET => {
1585 self.handle_tasks_get(request.params, modern_context.as_ref(), &context)
1586 .await
1587 }
1588 methods::TASKS_UPDATE => {
1589 self.handle_tasks_update(request.params, modern_context.as_ref(), &context)
1590 .await
1591 }
1592 methods::TASKS_CANCEL => {
1593 self.handle_tasks_cancel(request.params, modern_context.as_ref(), &context)
1594 .await
1595 }
1596 methods::RESOURCES_LIST => self.handle_resources_list(request.params).await,
1597 methods::RESOURCES_READ => self.handle_resources_read(request.params).await,
1598 methods::RESOURCES_SUBSCRIBE => {
1599 self.handle_resources_subscribe(request.params).await
1600 }
1601 methods::RESOURCES_UNSUBSCRIBE => {
1602 self.handle_resources_unsubscribe(request.params).await
1603 }
1604 methods::PROMPTS_LIST => self.handle_prompts_list(request.params).await,
1605 methods::PROMPTS_GET => self.handle_prompts_get(request.params).await,
1606 methods::RESOURCES_TEMPLATES_LIST => {
1607 self.handle_resource_templates_list(request.params).await
1608 }
1609 methods::COMPLETION_COMPLETE => {
1610 self.handle_completion_complete(request.params).await
1611 }
1612 methods::LOGGING_SET_LEVEL => self.handle_logging_set_level(request.params).await,
1613 methods::RPC_DISCOVER => self.handle_rpc_discover(request.params).await,
1614 _ => {
1615 let method = &request.method;
1616 Err(McpError::MethodNotFound(format!(
1617 "Unknown method: {method}"
1618 )))
1619 }
1620 };
1621
1622 let response = match result {
1624 Ok(result_value) => {
1625 let result_value = if is_modern {
1626 decorate_modern_result(&request.method, result_value, &self.info)?
1627 } else {
1628 result_value
1629 };
1630 Ok(JsonRpcResponse::success(request.id, result_value)?)
1631 }
1632 Err(error @ McpError::Forbidden(_)) => Err(error),
1633 Err(error @ McpError::RateLimited { .. }) => Err(error),
1634 Err(error) => Err(error),
1635 };
1636
1637 tracing::info!(
1638 event = "security.request_audit",
1639 outcome = if response.is_ok() { "allowed" } else { "error" },
1640 duration_ms = started_at.elapsed().as_millis() as u64,
1641 "request completed"
1642 );
1643 response
1644 }
1645 .instrument(span)
1646 .await
1647 }
1648
1649 async fn handle_initialize(&self, params: Option<Value>) -> McpResult<Value> {
1654 let params: InitializeParams = match params {
1655 Some(p) => serde_json::from_value(p)?,
1656 None => {
1657 return Err(McpError::Validation(
1658 "Missing initialize parameters".to_string(),
1659 ));
1660 }
1661 };
1662
1663 validate_initialize_params(¶ms)?;
1664 if params.protocol_version != LEGACY_PROTOCOL_VERSION {
1665 return Err(McpError::UnsupportedProtocolVersion {
1666 requested: params.protocol_version,
1667 supported: vec![LEGACY_PROTOCOL_VERSION.to_string()],
1668 });
1669 }
1670
1671 let result = InitializeResult::new(
1672 LEGACY_PROTOCOL_VERSION.to_string(),
1673 self.capabilities.clone(),
1674 self.info.clone(),
1675 );
1676
1677 Ok(serde_json::to_value(result)?)
1678 }
1679
1680 async fn handle_server_discover(&self) -> McpResult<Value> {
1681 let supported_versions: Vec<&str> = match self.protocol_mode {
1682 ProtocolMode::Auto => SUPPORTED_PROTOCOL_VERSIONS.to_vec(),
1683 ProtocolMode::ModernOnly => vec![MODERN_PROTOCOL_VERSION],
1684 ProtocolMode::LegacyOnly => vec![LEGACY_PROTOCOL_VERSION],
1685 };
1686 Ok(serde_json::json!({
1687 "supportedVersions": supported_versions,
1688 "capabilities": self.modern_capabilities().await,
1689 "instructions": self.config.enable_logging.then_some(
1690 "Prism MCP server with stateless 2026 and legacy 2025 interoperability"
1691 )
1692 }))
1693 }
1694
1695 async fn modern_capabilities(&self) -> ServerCapabilities {
1696 let mut capabilities = self.capabilities.clone();
1697 if let Some(tools) = capabilities.tools.as_mut() {
1698 tools.list_changed = Some(true);
1699 }
1700 if let Some(prompts) = capabilities.prompts.as_mut() {
1701 prompts.list_changed = Some(true);
1702 }
1703 if let Some(resources) = capabilities.resources.as_mut() {
1704 resources.list_changed = Some(true);
1705 }
1706 if !self.task_tools.read().await.is_empty() {
1707 capabilities
1708 .extensions
1709 .get_or_insert_with(HashMap::new)
1710 .insert(TASKS_EXTENSION_ID.to_string(), serde_json::json!({}));
1711 }
1712 capabilities
1713 }
1714
1715 async fn handle_ping(&self) -> McpResult<Value> {
1716 Ok(serde_json::to_value(PingResult { meta: None })?)
1717 }
1718
1719 async fn handle_tools_list(&self, params: Option<Value>) -> McpResult<Value> {
1720 let _params: ListToolsParams = match params {
1721 Some(p) => serde_json::from_value(p)?,
1722 None => ListToolsParams::default(),
1723 };
1724
1725 let tools = self.list_tools().await?;
1726 let result = ListToolsResult {
1727 tools,
1728 next_cursor: None, meta: None,
1730 };
1731
1732 Ok(serde_json::to_value(result)?)
1733 }
1734
1735 async fn handle_tools_call(
1736 &self,
1737 params: Option<Value>,
1738 modern_context: Option<&ModernRequestContext>,
1739 request_context: &RequestContext,
1740 ) -> McpResult<Value> {
1741 let raw_params = match params {
1742 Some(params) => params,
1743 None => {
1744 return Err(McpError::Validation(
1745 "Missing tool call parameters".to_string(),
1746 ));
1747 }
1748 };
1749 let params: CallToolParams = serde_json::from_value(raw_params.clone())?;
1750
1751 validate_call_tool_params(¶ms)?;
1752
1753 let task_tool = self.task_tools.read().await.get(¶ms.name).cloned();
1754 if let Some(tool) = task_tool {
1755 let tasks_negotiated = modern_context
1756 .map(|context| has_tasks_extension(&context.client_capabilities))
1757 .unwrap_or(false);
1758 if !tasks_negotiated {
1759 if let Some(fallback) = &tool.fallback {
1760 return Ok(serde_json::to_value(
1761 fallback.call(params.arguments.unwrap_or_default()).await?,
1762 )?);
1763 }
1764 return Err(tasks_capability_error());
1765 }
1766 let task = match tool.execution {
1767 TaskExecution::Direct(handler) => {
1768 self.task_registry
1769 .create(
1770 request_context.principal.id.clone(),
1771 params.arguments.unwrap_or_default(),
1772 handler,
1773 )
1774 .await?
1775 }
1776 TaskExecution::Composed { preflight, handler } => {
1777 let call = parse_multi_round_tool_call(
1778 &raw_params,
1779 params.arguments.unwrap_or_default(),
1780 modern_context,
1781 )?;
1782 match preflight.call(call.clone()).await? {
1783 OperationResult::Complete(_) => {
1784 self.task_registry
1785 .create_composed(
1786 request_context.principal.id.clone(),
1787 call,
1788 handler,
1789 )
1790 .await?
1791 }
1792 OperationResult::InputRequired(result) => {
1793 validate_input_required_result(&result, &call.client_capabilities)?;
1794 return Ok(serde_json::to_value(result)?);
1795 }
1796 }
1797 }
1798 };
1799 return Ok(serde_json::to_value(CreateTaskResult {
1800 result_type: "task".to_string(),
1801 task,
1802 meta: HashMap::new(),
1803 })?);
1804 }
1805
1806 if let Some(tool) = self.multi_round_tools.read().await.get(¶ms.name) {
1807 let call = parse_multi_round_tool_call(
1808 &raw_params,
1809 params.arguments.unwrap_or_default(),
1810 modern_context,
1811 )?;
1812 let client_capabilities = call.client_capabilities.clone();
1813 return match tool.handler.call(call).await? {
1814 OperationResult::Complete(result) => Ok(serde_json::to_value(result)?),
1815 OperationResult::InputRequired(result) if modern_context.is_some() => {
1816 validate_input_required_result(&result, &client_capabilities)?;
1817 Ok(serde_json::to_value(result)?)
1818 }
1819 OperationResult::InputRequired(_) => Err(McpError::Protocol(
1820 "input_required is unavailable in MCP 2025-11-25".to_string(),
1821 )),
1822 };
1823 }
1824
1825 let result = self.call_tool(¶ms.name, params.arguments).await?;
1826 Ok(serde_json::to_value(result)?)
1827 }
1828
1829 fn require_tasks_context<'a>(
1830 &self,
1831 modern_context: Option<&'a ModernRequestContext>,
1832 ) -> McpResult<&'a ClientCapabilities> {
1833 let capabilities = modern_context
1834 .map(|context| &context.client_capabilities)
1835 .ok_or_else(tasks_capability_error)?;
1836 if !has_tasks_extension(capabilities) {
1837 return Err(tasks_capability_error());
1838 }
1839 Ok(capabilities)
1840 }
1841
1842 async fn handle_tasks_get(
1843 &self,
1844 params: Option<Value>,
1845 modern_context: Option<&ModernRequestContext>,
1846 context: &RequestContext,
1847 ) -> McpResult<Value> {
1848 self.require_tasks_context(modern_context)?;
1849 let params: GetTaskParams = serde_json::from_value(
1850 params.ok_or_else(|| McpError::InvalidParams("Missing taskId".to_string()))?,
1851 )?;
1852 let task = self
1853 .task_registry
1854 .get(¶ms.task_id, &context.principal.id)
1855 .await?;
1856 Ok(serde_json::to_value(GetTaskResult {
1857 result_type: "complete".to_string(),
1858 task,
1859 meta: HashMap::new(),
1860 })?)
1861 }
1862
1863 async fn handle_tasks_update(
1864 &self,
1865 params: Option<Value>,
1866 modern_context: Option<&ModernRequestContext>,
1867 context: &RequestContext,
1868 ) -> McpResult<Value> {
1869 self.require_tasks_context(modern_context)?;
1870 let params: UpdateTaskParams = serde_json::from_value(
1871 params.ok_or_else(|| McpError::InvalidParams("Missing task update".to_string()))?,
1872 )?;
1873 self.task_registry
1874 .update(
1875 ¶ms.task_id,
1876 &context.principal.id,
1877 params.input_responses,
1878 )
1879 .await?;
1880 Ok(serde_json::to_value(TaskAcknowledgement {
1881 result_type: "complete".to_string(),
1882 meta: HashMap::new(),
1883 })?)
1884 }
1885
1886 async fn handle_tasks_cancel(
1887 &self,
1888 params: Option<Value>,
1889 modern_context: Option<&ModernRequestContext>,
1890 context: &RequestContext,
1891 ) -> McpResult<Value> {
1892 self.require_tasks_context(modern_context)?;
1893 let params: CancelTaskParams = serde_json::from_value(
1894 params.ok_or_else(|| McpError::InvalidParams("Missing taskId".to_string()))?,
1895 )?;
1896 self.task_registry
1897 .cancel(¶ms.task_id, &context.principal.id)
1898 .await?;
1899 Ok(serde_json::to_value(TaskAcknowledgement {
1900 result_type: "complete".to_string(),
1901 meta: HashMap::new(),
1902 })?)
1903 }
1904
1905 async fn handle_resources_list(&self, params: Option<Value>) -> McpResult<Value> {
1906 let _params: ListResourcesParams = match params {
1907 Some(p) => serde_json::from_value(p)?,
1908 None => ListResourcesParams::default(),
1909 };
1910
1911 let resources = self.list_resources().await?;
1912 let result = ListResourcesResult {
1913 resources,
1914 next_cursor: None, meta: None,
1916 };
1917
1918 Ok(serde_json::to_value(result)?)
1919 }
1920
1921 async fn handle_resources_read(&self, params: Option<Value>) -> McpResult<Value> {
1922 let params: ReadResourceParams = match params {
1923 Some(p) => serde_json::from_value(p)?,
1924 None => {
1925 return Err(McpError::Validation(
1926 "Missing resource read parameters".to_string(),
1927 ));
1928 }
1929 };
1930
1931 validate_read_resource_params(¶ms)?;
1932
1933 let contents = self.read_resource(¶ms.uri).await?;
1934 let result = ReadResourceResult {
1935 contents,
1936 meta: None,
1937 };
1938
1939 Ok(serde_json::to_value(result)?)
1940 }
1941
1942 async fn handle_resources_subscribe(&self, params: Option<Value>) -> McpResult<Value> {
1943 let resources = self.resources.read().await;
1944 let result =
1945 crate::server::handlers::ResourceHandler::handle_subscribe(&resources, params).await?;
1946 Ok(serde_json::to_value(result)?)
1947 }
1948
1949 async fn handle_resources_unsubscribe(&self, params: Option<Value>) -> McpResult<Value> {
1950 let resources = self.resources.read().await;
1951 let result =
1952 crate::server::handlers::ResourceHandler::handle_unsubscribe(&resources, params)
1953 .await?;
1954 Ok(serde_json::to_value(result)?)
1955 }
1956
1957 async fn handle_prompts_list(&self, params: Option<Value>) -> McpResult<Value> {
1958 let _params: ListPromptsParams = match params {
1959 Some(p) => serde_json::from_value(p)?,
1960 None => ListPromptsParams::default(),
1961 };
1962
1963 let prompts = self.list_prompts().await?;
1964 let result = ListPromptsResult {
1965 prompts,
1966 next_cursor: None, meta: None,
1968 };
1969
1970 Ok(serde_json::to_value(result)?)
1971 }
1972
1973 async fn handle_prompts_get(&self, params: Option<Value>) -> McpResult<Value> {
1974 let params: GetPromptParams = match params {
1975 Some(p) => serde_json::from_value(p)?,
1976 None => {
1977 return Err(McpError::Validation(
1978 "Missing prompt get parameters".to_string(),
1979 ));
1980 }
1981 };
1982
1983 validate_get_prompt_params(¶ms)?;
1984
1985 let arguments = params.arguments.map(|args| {
1986 args.into_iter()
1987 .map(|(k, v)| (k, serde_json::Value::String(v)))
1988 .collect()
1989 });
1990 let result = self.get_prompt(¶ms.name, arguments).await?;
1991 Ok(serde_json::to_value(result)?)
1992 }
1993
1994 async fn handle_logging_set_level(&self, params: Option<Value>) -> McpResult<Value> {
1995 let _params: SetLoggingLevelParams = match params {
1996 Some(p) => serde_json::from_value(p)?,
1997 None => {
1998 return Err(McpError::Validation(
1999 "Missing logging level parameters".to_string(),
2000 ));
2001 }
2002 };
2003
2004 let result = SetLoggingLevelResult { meta: None };
2006 Ok(serde_json::to_value(result)?)
2007 }
2008
2009 async fn handle_resource_templates_list(&self, params: Option<Value>) -> McpResult<Value> {
2011 let _params: ListResourceTemplatesParams = match params {
2012 Some(p) => serde_json::from_value(p)?,
2013 None => ListResourceTemplatesParams::default(),
2014 };
2015
2016 let templates = self.list_resource_templates().await?;
2017 let result = ListResourceTemplatesResult {
2018 resource_templates: templates,
2019 next_cursor: None, meta: None,
2021 };
2022
2023 Ok(serde_json::to_value(result)?)
2024 }
2025
2026 async fn handle_completion_complete(&self, params: Option<Value>) -> McpResult<Value> {
2028 let params: CompleteParams = match params {
2029 Some(p) => serde_json::from_value(p)?,
2030 None => {
2031 return Err(McpError::Validation(
2032 "Missing completion parameters".to_string(),
2033 ));
2034 }
2035 };
2036
2037 let completions = self
2038 .handle_completion(
2039 ¶ms.reference,
2040 ¶ms.argument,
2041 None, )
2043 .await?;
2044
2045 let result = CompleteResult {
2046 completion: CompletionData {
2047 values: completions,
2048 total: None,
2049 has_more: None,
2050 },
2051 meta: None,
2052 };
2053
2054 Ok(serde_json::to_value(result)?)
2055 }
2056
2057 async fn handle_rpc_discover(&self, params: Option<Value>) -> McpResult<Value> {
2059 use crate::server::discovery_handler::DiscoveryHandler;
2060
2061 let handler = DiscoveryHandler::new();
2062 let result = handler
2063 .handle(&self.info, &self.capabilities, params)
2064 .await?;
2065 Ok(serde_json::to_value(result)?)
2066 }
2067
2068 async fn emit_resources_list_changed(&self) -> McpResult<()> {
2073 let notification = JsonRpcNotification::new(
2074 methods::RESOURCES_LIST_CHANGED.to_string(),
2075 Some(ResourceListChangedParams { meta: None }),
2076 )?;
2077
2078 self.send_notification(notification).await
2079 }
2080
2081 async fn emit_tools_list_changed(&self) -> McpResult<()> {
2082 let notification = JsonRpcNotification::new(
2083 methods::TOOLS_LIST_CHANGED.to_string(),
2084 Some(ToolListChangedParams { meta: None }),
2085 )?;
2086
2087 self.send_notification(notification).await
2088 }
2089
2090 async fn emit_prompts_list_changed(&self) -> McpResult<()> {
2091 let notification = JsonRpcNotification::new(
2092 methods::PROMPTS_LIST_CHANGED.to_string(),
2093 Some(PromptListChangedParams { meta: None }),
2094 )?;
2095
2096 self.send_notification(notification).await
2097 }
2098
2099 async fn send_notification(&self, notification: JsonRpcNotification) -> McpResult<()> {
2101 let mut transport_guard = self.transport.lock().await;
2102 if let Some(transport) = transport_guard.as_mut() {
2103 transport.send_notification(notification).await?;
2104 }
2105 Ok(())
2106 }
2107
2108 async fn next_request_id(&self) -> u64 {
2113 let mut counter = self.request_counter.lock().await;
2114 *counter += 1;
2115 *counter
2116 }
2117
2118 pub async fn is_initialized(&self) -> bool {
2124 let state = self.state.read().await;
2125 matches!(*state, ServerState::Running)
2126 }
2127
2128 pub async fn is_stopped(&self) -> bool {
2130 let state = self.state.read().await;
2131 matches!(*state, ServerState::Stopping | ServerState::Stopped)
2132 }
2133
2134 pub async fn get_state(&self) -> ServerState {
2136 self.state().await
2137 }
2138
2139 pub async fn has_tools(&self) -> bool {
2141 let tools = self.tools.read().await;
2142 !tools.is_empty()
2143 }
2144
2145 pub async fn has_resources(&self) -> bool {
2147 let resources = self.resources.read().await;
2148 !resources.is_empty()
2149 }
2150
2151 pub async fn has_prompts(&self) -> bool {
2153 let prompts = self.prompts.read().await;
2154 !prompts.is_empty()
2155 }
2156
2157 pub async fn tool_count(&self) -> usize {
2159 let tools = self.tools.read().await;
2160 tools.len()
2161 }
2162
2163 pub async fn resource_count(&self) -> usize {
2165 let resources = self.resources.read().await;
2166 resources.len()
2167 }
2168
2169 pub async fn prompt_count(&self) -> usize {
2171 let prompts = self.prompts.read().await;
2172 prompts.len()
2173 }
2174
2175 pub async fn has_tool(&self, name: &str) -> bool {
2177 let tools = self.tools.read().await;
2178 tools.contains_key(name)
2179 }
2180
2181 pub async fn has_resource(&self, uri: &str) -> bool {
2183 let resources = self.resources.read().await;
2184 resources.contains_key(uri)
2185 }
2186
2187 pub async fn has_prompt(&self, name: &str) -> bool {
2189 let prompts = self.prompts.read().await;
2190 prompts.contains_key(name)
2191 }
2192
2193 async fn set_state(&self, new_state: ServerState) {
2195 let mut state = self.state.write().await;
2196 *state = new_state;
2197 }
2198
2199 pub async fn initialize(&self) -> McpResult<()> {
2201 self.set_state(ServerState::Running).await;
2202 Ok(())
2203 }
2204}
2205
2206#[cfg(test)]
2207mod tests {
2208 use super::*;
2209 use serde_json::json;
2210
2211 #[tokio::test]
2212 async fn test_server_creation() {
2213 let server = McpServer::new("test-server".to_string(), "1.0.0".to_string());
2214 assert_eq!(server.info().name, "test-server");
2215 assert_eq!(server.info().version, "1.0.0");
2216 assert!(!server.is_running().await);
2217 }
2218
2219 #[tokio::test]
2220 async fn test_tool_management() {
2221 let server = McpServer::new("test-server".to_string(), "1.0.0".to_string());
2222
2223 let schema = json!({
2225 "type": "object",
2226 "properties": {
2227 "name": {"type": "string"}
2228 }
2229 });
2230
2231 struct TestToolHandler;
2232
2233 #[async_trait::async_trait]
2234 impl ToolHandler for TestToolHandler {
2235 async fn call(&self, _arguments: HashMap<String, Value>) -> McpResult<ToolResult> {
2236 Ok(ToolResult {
2237 content: vec![Content::text("Hello from tool")],
2238 is_error: None,
2239 structured_content: None,
2240 meta: None,
2241 })
2242 }
2243 }
2244
2245 server
2246 .add_tool(
2247 "test_tool".to_string(),
2248 Some("A test tool".to_string()),
2249 schema,
2250 TestToolHandler,
2251 )
2252 .await
2253 .unwrap();
2254
2255 let tools = server.list_tools().await.unwrap();
2257 assert_eq!(tools.len(), 1);
2258 assert_eq!(tools[0].name, "test_tool");
2259
2260 let result = server.call_tool("test_tool", None).await.unwrap();
2262 assert_eq!(result.content.len(), 1);
2263 }
2264
2265 #[tokio::test]
2266 async fn test_initialize_request() {
2267 let server = McpServer::new("test-server".to_string(), "1.0.0".to_string());
2268
2269 let init_params = InitializeParams::new(
2270 crate::protocol::LEGACY_PROTOCOL_VERSION.to_string(),
2271 ClientCapabilities::default(),
2272 ClientInfo {
2273 name: "test-client".to_string(),
2274 version: "1.0.0".to_string(),
2275 description: None,
2276 title: Some("Test Client".to_string()),
2277 website_url: None,
2278 icons: None,
2279 },
2280 );
2281
2282 let request =
2283 JsonRpcRequest::new(json!(1), methods::INITIALIZE.to_string(), Some(init_params))
2284 .unwrap();
2285
2286 let response = server.handle_request(request).await.unwrap();
2287 assert!(response.result.is_some());
2288 }
2289}