use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use llm_tool::{PromptRegistry, ResourceRegistry, ToolContext, ToolRegistry};
use super::{CallerView, McpServer, RegistryFactory, build_tools_list_value};
pub struct McpServerBuilder {
name: String,
version: String,
instructions: Option<String>,
registry: ToolRegistry,
context: ToolContext,
prompts: PromptRegistry,
resources: ResourceRegistry,
per_connection_identity: bool,
registry_factory: Option<Arc<dyn RegistryFactory>>,
}
impl McpServerBuilder {
#[must_use]
pub fn new(
name: impl Into<String>,
version: impl Into<String>,
registry: ToolRegistry,
) -> Self {
Self {
name: name.into(),
version: version.into(),
instructions: None,
registry,
context: ToolContext::new(),
prompts: PromptRegistry::new(),
resources: ResourceRegistry::new(),
per_connection_identity: false,
registry_factory: None,
}
}
#[must_use]
pub fn with_context(mut self, context: ToolContext) -> Self {
self.context = context;
self
}
#[must_use]
pub fn with_instructions(mut self, instructions: impl Into<String>) -> Self {
self.instructions = Some(instructions.into());
self
}
#[must_use]
pub const fn with_per_connection_identity(mut self, enabled: bool) -> Self {
self.per_connection_identity = enabled;
self
}
#[must_use]
pub fn with_registry_factory<F: RegistryFactory + 'static>(mut self, factory: F) -> Self {
self.registry_factory = Some(Arc::new(factory));
self
}
#[must_use]
pub fn with_prompt<P: llm_tool::RustPrompt + 'static>(mut self, prompt: P) -> Self {
self.prompts.register(prompt);
self
}
#[must_use]
pub fn with_resource<R: llm_tool::RustResource + 'static>(mut self, resource: R) -> Self {
self.resources.register(resource);
self
}
#[must_use]
pub fn build(self) -> McpServer {
let base_registry = match &self.registry_factory {
Some(factory) => factory.registry_for(None),
None => self.registry,
};
let registry = Arc::new(base_registry);
let cached_tools_list = Arc::new(build_tools_list_value(®istry));
let mut caller_views = HashMap::new();
if self.registry_factory.is_some() {
caller_views.insert(
String::new(),
CallerView {
registry: Arc::clone(®istry),
tools_list: Arc::clone(&cached_tools_list),
},
);
}
McpServer {
name: self.name,
version: self.version,
instructions: self.instructions,
registry,
context: Arc::new(self.context),
cached_tools_list,
prompts: Arc::new(self.prompts),
resources: Arc::new(self.resources),
per_connection_identity: self.per_connection_identity,
registry_factory: self.registry_factory,
caller_views: Arc::new(Mutex::new(caller_views)),
}
}
}