33//! This template provides a starting point for building MCP servers using the
44//! PulseEngine MCP framework. It demonstrates:
55//! - Using the #[mcp_server] macro for automatic server setup
6- //! - Using the #[mcp_tools] macro for automatic tool discovery
6+ //! - Using the #[mcp_tools] macro for automatic tool and resource discovery
77//! - Basic tool implementations with different parameter types
8+ //! - Resource implementations for read-only data access
9+ //! - URI templates for parameterized resources
810//! - Proper error handling and async support
911
10- use pulseengine_mcp_macros:: { mcp_server, mcp_tools} ;
12+ use pulseengine_mcp_macros:: { mcp_server, mcp_tools, mcp_resource } ;
1113use serde:: { Deserialize , Serialize } ;
1214
1315/// Example data structure that your tools might work with
@@ -19,6 +21,25 @@ pub struct ExampleData {
1921 pub tags : Vec < String > ,
2022}
2123
24+ /// Server status information (exposed as a resource)
25+ #[ derive( Debug , Serialize , Deserialize , Clone ) ]
26+ pub struct ServerStatus {
27+ pub name : String ,
28+ pub version : String ,
29+ pub uptime_seconds : u64 ,
30+ pub tools_count : usize ,
31+ pub resources_count : usize ,
32+ }
33+
34+ /// Server configuration (exposed as a resource)
35+ #[ derive( Debug , Serialize , Deserialize , Clone ) ]
36+ pub struct ServerConfig {
37+ pub max_concurrent_requests : usize ,
38+ pub timeout_seconds : u64 ,
39+ pub debug_mode : bool ,
40+ pub supported_formats : Vec < String > ,
41+ }
42+
2243/// Template MCP Server
2344///
2445/// Replace this with your own server implementation. The #[mcp_server] macro
@@ -29,14 +50,24 @@ pub struct ExampleData {
2950 description = "A template MCP server demonstrating basic functionality" ,
3051 auth = "disabled" // Change to "memory", "file", or remove for production
3152) ]
32- #[ derive( Default , Clone ) ]
53+ #[ derive( Clone ) ]
3354pub struct TemplateMcpServer {
55+ start_time : std:: time:: Instant ,
3456 // Add your server state here
3557 // Example:
3658 // data_store: Arc<RwLock<HashMap<u64, ExampleData>>>,
3759}
3860
39- /// All public methods in this impl block become MCP tools automatically
61+ impl Default for TemplateMcpServer {
62+ fn default ( ) -> Self {
63+ Self {
64+ start_time : std:: time:: Instant :: now ( ) ,
65+ }
66+ }
67+ }
68+
69+ /// All public methods in this impl block become MCP tools or resources automatically
70+ /// Methods with #[mcp_resource] become resources, others become tools
4071#[ mcp_tools]
4172impl TemplateMcpServer {
4273 /// Get server status and basic information
@@ -133,6 +164,80 @@ impl TemplateMcpServer {
133164 Ok ( "Tool executed successfully" . to_string ( ) )
134165 }
135166 }
167+
168+ // Resources - Read-only data accessible via MCP resource URIs
169+
170+ /// Get server status information
171+ ///
172+ /// This resource provides read-only access to the server's current status.
173+ /// Resources are for data that clients need to read but not modify.
174+ #[ mcp_resource(
175+ uri_template = "template://server-status" ,
176+ name = "server_status" ,
177+ description = "Current server status and statistics" ,
178+ mime_type = "application/json"
179+ ) ]
180+ pub async fn server_status_resource ( & self ) -> anyhow:: Result < ServerStatus > {
181+ let uptime = self . start_time . elapsed ( ) ;
182+
183+ Ok ( ServerStatus {
184+ name : "Template MCP Server" . to_string ( ) ,
185+ version : "0.1.0" . to_string ( ) ,
186+ uptime_seconds : uptime. as_secs ( ) ,
187+ tools_count : 6 , // Update this if you add/remove tools
188+ resources_count : 3 , // Update this if you add/remove resources
189+ } )
190+ }
191+
192+ /// Get server configuration
193+ ///
194+ /// This resource exposes the server's configuration settings.
195+ /// Resources are perfect for configuration data that clients need to read.
196+ #[ mcp_resource(
197+ uri_template = "template://server-config" ,
198+ name = "server_config" ,
199+ description = "Server configuration settings" ,
200+ mime_type = "application/json"
201+ ) ]
202+ pub async fn server_config_resource ( & self ) -> anyhow:: Result < ServerConfig > {
203+ Ok ( ServerConfig {
204+ max_concurrent_requests : 100 ,
205+ timeout_seconds : 30 ,
206+ debug_mode : cfg ! ( debug_assertions) ,
207+ supported_formats : vec ! [
208+ "json" . to_string( ) ,
209+ "text" . to_string( ) ,
210+ "binary" . to_string( ) ,
211+ ] ,
212+ } )
213+ }
214+
215+ /// Get example data by ID
216+ ///
217+ /// This resource demonstrates parameterized resources using URI templates.
218+ /// The {id} parameter is extracted from the URI when the resource is accessed.
219+ #[ mcp_resource(
220+ uri_template = "template://example-data/{id}" ,
221+ name = "example_data" ,
222+ description = "Example data entry by ID" ,
223+ mime_type = "application/json"
224+ ) ]
225+ pub async fn example_data_resource ( & self , id : String ) -> anyhow:: Result < ExampleData > {
226+ // In a real implementation, you'd look up the data by ID
227+ // For this template, we'll generate example data
228+ let id_num = id. parse :: < u64 > ( ) . unwrap_or ( 1 ) ;
229+
230+ Ok ( ExampleData {
231+ id : id_num,
232+ name : format ! ( "Example Item {}" , id_num) ,
233+ value : ( id_num as f64 ) * 1.5 ,
234+ tags : vec ! [
235+ "example" . to_string( ) ,
236+ "template" . to_string( ) ,
237+ format!( "id-{}" , id_num) ,
238+ ] ,
239+ } )
240+ }
136241}
137242
138243// Add any additional implementation methods here that are NOT tools
0 commit comments