Skip to main content

fastmcp_rs/
server.rs

1use std::sync::Arc;
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use uuid::Uuid;
7
8use crate::error::Result;
9use crate::prompt::{PromptDefinitionMetadata, PromptManager, PromptTemplate};
10use crate::resource::{
11    ResourceContent, ResourceDefinition, ResourceDefinitionMetadata, ResourceManager,
12};
13use crate::tool::{
14    DuplicateBehavior, ToolDefinition, ToolDefinitionMetadata, ToolManager, ToolResponse,
15};
16
17/// Metadata describing server identity and capabilities.
18#[derive(Clone, Debug, Serialize, Deserialize)]
19pub struct ServerMetadata {
20    pub id: Uuid,
21    pub name: String,
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub instructions: Option<String>,
24    pub version: String,
25    pub created_at: DateTime<Utc>,
26}
27
28impl ServerMetadata {
29    pub fn new(
30        name: impl Into<String>,
31        instructions: Option<String>,
32        version: impl Into<String>,
33    ) -> Self {
34        Self {
35            id: Uuid::new_v4(),
36            name: name.into(),
37            instructions,
38            version: version.into(),
39            created_at: Utc::now(),
40        }
41    }
42}
43
44pub struct FastMcpServer {
45    metadata: ServerMetadata,
46    tool_manager: ToolManager,
47    resource_manager: ResourceManager,
48    prompt_manager: PromptManager,
49}
50
51impl FastMcpServer {
52    pub fn builder() -> FastMcpServerBuilder {
53        FastMcpServerBuilder::default()
54    }
55
56    pub fn metadata(&self) -> ServerMetadata {
57        self.metadata.clone()
58    }
59
60    pub fn register_tool(&self, tool: ToolDefinition) -> Result<()> {
61        self.tool_manager.register(tool)
62    }
63
64    pub fn list_tools(&self) -> Vec<ToolDefinitionMetadata> {
65        self.tool_manager.list()
66    }
67
68    pub async fn call_tool(&self, name: &str, arguments: Value) -> Result<ToolResponse> {
69        self.tool_manager.call(name, arguments).await
70    }
71
72    pub fn register_resource(&self, resource: ResourceDefinition) -> Result<()> {
73        self.resource_manager.register(resource)
74    }
75
76    pub fn list_resources(&self) -> Vec<ResourceDefinitionMetadata> {
77        self.resource_manager.list()
78    }
79
80    pub async fn read_resource(&self, uri: &str) -> Result<ResourceContent> {
81        self.resource_manager.read(uri).await
82    }
83
84    pub fn register_prompt(&self, prompt: PromptTemplate) -> Result<()> {
85        self.prompt_manager.register(prompt)
86    }
87
88    pub fn list_prompts(&self) -> Vec<PromptDefinitionMetadata> {
89        self.prompt_manager.list()
90    }
91
92    pub fn instantiate_prompt(
93        &self,
94        name: &str,
95        arguments: Option<&Value>,
96    ) -> Result<Vec<crate::prompt::PromptMessage>> {
97        let prompt = self.prompt_manager.get(name)?;
98        prompt.instantiate(arguments)
99    }
100
101    pub fn into_shared(self) -> Arc<Self> {
102        Arc::new(self)
103    }
104}
105
106#[derive(Default)]
107pub struct FastMcpServerBuilder {
108    name: Option<String>,
109    instructions: Option<String>,
110    version: Option<String>,
111    tool_duplicates: DuplicateBehavior,
112    resource_duplicates: DuplicateBehavior,
113    prompt_duplicates: DuplicateBehavior,
114}
115
116impl FastMcpServerBuilder {
117    pub fn name(mut self, name: impl Into<String>) -> Self {
118        self.name = Some(name.into());
119        self
120    }
121
122    pub fn instructions(mut self, instructions: impl Into<String>) -> Self {
123        self.instructions = Some(instructions.into());
124        self
125    }
126
127    pub fn version(mut self, version: impl Into<String>) -> Self {
128        self.version = Some(version.into());
129        self
130    }
131
132    pub fn tool_duplicates(mut self, behavior: DuplicateBehavior) -> Self {
133        self.tool_duplicates = behavior;
134        self
135    }
136
137    pub fn resource_duplicates(mut self, behavior: DuplicateBehavior) -> Self {
138        self.resource_duplicates = behavior;
139        self
140    }
141
142    pub fn prompt_duplicates(mut self, behavior: DuplicateBehavior) -> Self {
143        self.prompt_duplicates = behavior;
144        self
145    }
146
147    pub fn build(self) -> FastMcpServer {
148        let name = self
149            .name
150            .unwrap_or_else(|| format!("fastmcp-{}", Uuid::new_v4()));
151        let version = self.version.unwrap_or_else(|| "0.1.0-preview".into());
152        let server = FastMcpServer {
153            metadata: ServerMetadata::new(name, self.instructions, version),
154            tool_manager: ToolManager::new(self.tool_duplicates),
155            resource_manager: ResourceManager::new(self.resource_duplicates),
156            prompt_manager: PromptManager::new(self.prompt_duplicates),
157        };
158
159        #[cfg(feature = "auto-register")]
160        {
161            crate::tool::register_discovered_tools(&server);
162        }
163
164        server
165    }
166}