pulseengine_mcp_macros/lib.rs
1//! # PulseEngine MCP Macros
2//!
3//! Procedural macros for the PulseEngine MCP Framework that dramatically simplify
4//! server and tool development while maintaining enterprise-grade capabilities.
5//!
6//! ## Quick Start
7//!
8//! Create a simple MCP server with tools:
9//!
10//! ```rust,ignore
11//! use pulseengine_mcp_macros::{mcp_server, mcp_tool};
12//!
13//! #[mcp_server(name = "Hello World")]
14//! struct HelloWorld;
15//!
16//! #[mcp_tool]
17//! impl HelloWorld {
18//! /// Say hello to someone
19//! async fn say_hello(&self, name: String) -> String {
20//! format!("Hello, {}!", name)
21//! }
22//! }
23//! ```
24//!
25//! ## Features
26//!
27//! - **Zero Boilerplate**: Focus on business logic, not protocol details
28//! - **Type Safety**: Compile-time validation of tool definitions
29//! - **Auto Schema Generation**: JSON schemas derived from Rust types
30//! - **Doc Comments**: Function documentation becomes tool descriptions
31//! - **Progressive Complexity**: Start simple, add enterprise features as needed
32
33use proc_macro::TokenStream;
34
35mod mcp_backend;
36mod mcp_prompt;
37mod mcp_resource;
38mod mcp_server;
39mod mcp_tool;
40mod utils;
41
42/// Automatically generates MCP tool definitions from Rust functions.
43///
44/// This macro transforms regular Rust functions into MCP tools with automatic
45/// JSON schema generation, parameter validation, and error handling.
46///
47/// # Basic Usage
48///
49/// ```rust,ignore
50/// use pulseengine_mcp_macros::mcp_tool;
51///
52/// #[mcp_tool]
53/// async fn say_hello(name: String) -> String {
54/// format!("Hello, {}!", name)
55/// }
56/// ```
57///
58/// # With Custom Description
59///
60/// ```rust,ignore
61/// #[mcp_tool(description = "Say hello to someone or something")]
62/// async fn say_hello(name: String, greeting: Option<String>) -> String {
63/// format!("{}, {}!", greeting.unwrap_or("Hello"), name)
64/// }
65/// ```
66///
67/// # Parameters
68///
69/// - `description`: Optional custom description (defaults to doc comments)
70/// - `name`: Optional custom tool name (defaults to function name)
71///
72/// # Features
73///
74/// - **Automatic Schema**: JSON schemas generated from Rust parameter types
75/// - **Doc Comments**: Function documentation becomes tool description
76/// - **Type Safety**: Compile-time validation of parameters
77/// - **Error Handling**: Automatic conversion of Result types
78/// - **Async Support**: Both sync and async functions supported
79#[proc_macro_attribute]
80pub fn mcp_tool(attr: TokenStream, item: TokenStream) -> TokenStream {
81 mcp_tool::mcp_tool_impl(attr.into(), item.into())
82 .unwrap_or_else(|err| err.to_compile_error())
83 .into()
84}
85
86/// Auto-implements the McpBackend trait with smart defaults.
87///
88/// This macro generates a complete McpBackend implementation with minimal
89/// configuration required. It inspects the struct and automatically generates
90/// appropriate server info, capabilities, and default implementations.
91///
92/// # Basic Usage
93///
94/// ```rust,ignore
95/// use pulseengine_mcp_macros::mcp_backend;
96///
97/// #[mcp_backend(name = "My Server")]
98/// struct MyBackend {
99/// data: String,
100/// }
101/// ```
102///
103/// # Parameters
104///
105/// - `name`: Server name (required)
106/// - `version`: Server version (defaults to Cargo package version)
107/// - `description`: Server description (defaults to doc comments)
108/// - `capabilities`: Custom capabilities (auto-detected by default)
109///
110/// # Features
111///
112/// - **Smart Capabilities**: Auto-detects capabilities from available tools
113/// - **Default Implementations**: Provides sensible defaults for all methods
114/// - **Error Handling**: Automatic error type conversion
115/// - **Version Integration**: Uses Cargo.toml version by default
116#[proc_macro_attribute]
117pub fn mcp_backend(attr: TokenStream, item: TokenStream) -> TokenStream {
118 mcp_backend::mcp_backend_impl(attr.into(), item.into())
119 .unwrap_or_else(|err| err.to_compile_error())
120 .into()
121}
122
123/// Complete server generation from a simple struct.
124///
125/// This macro combines `#[mcp_backend]` with additional server lifecycle
126/// management, providing a complete MCP server implementation.
127///
128/// # Basic Usage
129///
130/// ```rust,ignore
131/// use pulseengine_mcp_macros::mcp_server;
132///
133/// #[mcp_server(name = "Hello World")]
134/// struct HelloWorld;
135/// ```
136///
137/// # With Configuration
138///
139/// ```rust,ignore
140/// #[mcp_server(
141/// name = "Advanced Server",
142/// version = "1.0.0",
143/// description = "A more advanced MCP server"
144/// )]
145/// struct AdvancedServer {
146/// config: MyConfig,
147/// }
148/// ```
149///
150/// # Parameters
151///
152/// - `name`: Server name (required)
153/// - `version`: Server version (defaults to Cargo package version)
154/// - `description`: Server description (defaults to doc comments)
155/// - `transport`: Default transport type (defaults to auto-detect)
156///
157/// # Features
158///
159/// - **Complete Implementation**: Backend + server management
160/// - **Fluent Builder**: Provides `.serve_*()` methods
161/// - **Transport Auto-Detection**: Smart defaults based on environment
162/// - **Configuration Integration**: Works with PulseEngine config system
163#[proc_macro_attribute]
164pub fn mcp_server(attr: TokenStream, item: TokenStream) -> TokenStream {
165 mcp_server::mcp_server_impl(attr.into(), item.into())
166 .unwrap_or_else(|err| err.to_compile_error())
167 .into()
168}
169
170/// Automatically generates MCP resource definitions from Rust functions.
171///
172/// This macro transforms regular Rust functions into MCP resources with automatic
173/// URI template parsing, parameter extraction, and content type handling.
174///
175/// # Basic Usage
176///
177/// ```rust,ignore
178/// use pulseengine_mcp_macros::mcp_resource;
179///
180/// #[mcp_resource(uri_template = "file://{path}")]
181/// async fn read_file(&self, path: String) -> Result<String, std::io::Error> {
182/// tokio::fs::read_to_string(&path).await
183/// }
184/// ```
185///
186/// # With Custom Configuration
187///
188/// ```rust,ignore
189/// #[mcp_resource(
190/// uri_template = "db://{database}/{table}",
191/// name = "database_table",
192/// description = "Read data from a database table",
193/// mime_type = "application/json"
194/// )]
195/// async fn read_table(&self, database: String, table: String) -> Result<serde_json::Value, Error> {
196/// // Implementation
197/// }
198/// ```
199///
200/// # Parameters
201///
202/// - `uri_template`: Required URI template with parameters in `{param}` format
203/// - `name`: Optional custom resource name (defaults to function name)
204/// - `description`: Optional custom description (defaults to doc comments)
205/// - `mime_type`: Optional MIME type (defaults to "text/plain")
206///
207/// # Features
208///
209/// - **URI Template Parsing**: Automatic extraction of parameters from URI templates
210/// - **Type Safety**: Compile-time validation of parameter types
211/// - **Auto-Documentation**: Uses function doc comments as resource descriptions
212/// - **Content Type Detection**: Automatic MIME type handling
213/// - **Error Handling**: Converts function errors to MCP protocol errors
214///
215/// # References
216///
217/// - [MCP Resources Specification](https://modelcontextprotocol.io/specification/)
218/// - [Building with LLMs Tutorial](https://modelcontextprotocol.io/tutorials/building-mcp-with-llms)
219#[allow(clippy::empty_line_after_doc_comments, clippy::doc_lazy_continuation)]
220/// Automatically generates MCP prompt definitions from Rust functions.
221///
222/// This macro transforms regular Rust functions into MCP prompts with automatic
223/// argument validation and prompt message generation.
224///
225/// # Basic Usage
226///
227/// ```rust,ignore
228/// use pulseengine_mcp_macros::mcp_prompt;
229///
230/// #[mcp_prompt(name = "code_review")]
231/// async fn generate_code_review(&self, code: String, language: String) -> Result<PromptMessage, Error> {
232/// // Generate prompt for code review
233/// }
234/// ```
235///
236/// # With Custom Configuration
237///
238/// ```rust,ignore
239/// #[mcp_prompt(
240/// name = "sql_query_helper",
241/// description = "Generate SQL queries based on natural language",
242/// arguments = ["description", "table_schema", "output_format"]
243/// )]
244/// async fn sql_helper(&self, description: String, table_schema: String, output_format: String) -> Result<PromptMessage, Error> {
245/// // Implementation
246/// }
247/// ```
248///
249/// # Parameters
250///
251/// - `name`: Optional custom prompt name (defaults to function name)
252/// - `description`: Optional custom description (defaults to doc comments)
253/// - `arguments`: Optional array of argument names for documentation
254///
255/// # Features
256///
257/// - **Argument Validation**: Automatic validation of prompt arguments
258/// - **Type Safety**: Compile-time validation of parameter types
259/// - **Auto-Documentation**: Uses function doc comments as prompt descriptions
260/// - **Error Handling**: Converts function errors to MCP protocol errors
261/// - **Schema Generation**: Automatic argument schema generation
262///
263/// # References
264///
265/// - [MCP Prompts Specification](https://modelcontextprotocol.io/specification/)
266/// - [Building with LLMs Tutorial](https://modelcontextprotocol.io/tutorials/building-mcp-with-llms)
267#[proc_macro_attribute]
268pub fn mcp_prompt(attr: TokenStream, item: TokenStream) -> TokenStream {
269 mcp_prompt::mcp_prompt_impl(attr.into(), item.into())
270 .unwrap_or_else(|err| err.to_compile_error())
271 .into()
272}
273
274/// Derives MCP tool implementations for all methods in an impl block.
275///
276/// This is a convenience macro that applies `#[mcp_tool]` to all public
277/// methods in an impl block.
278///
279/// # Usage
280///
281/// ```rust,ignore
282/// use pulseengine_mcp_macros::mcp_tools;
283///
284/// #[mcp_tools]
285/// impl MyServer {
286/// /// This becomes an MCP tool
287/// async fn tool_one(&self, param: String) -> String {
288/// param.to_uppercase()
289/// }
290///
291/// /// This also becomes an MCP tool
292/// fn tool_two(&self, x: i32, y: i32) -> i32 {
293/// x + y
294/// }
295///
296/// // Private methods are ignored
297/// fn helper_method(&self) -> bool {
298/// true
299/// }
300/// }
301/// ```
302#[proc_macro_attribute]
303pub fn mcp_tools(attr: TokenStream, item: TokenStream) -> TokenStream {
304 mcp_tool::mcp_tools_impl(attr.into(), item.into())
305 .unwrap_or_else(|err| err.to_compile_error())
306 .into()
307}
308
309/// Creates a complete MCP application with minimal boilerplate.
310///
311/// This macro combines `#[mcp_server]`, `#[mcp_tools]`, and generates a
312/// complete main function, reducing a full MCP server to just 5 lines of code.
313///
314/// # Ultra-Simple Usage (5 lines total!)
315///
316/// ```rust,ignore
317/// use pulseengine_mcp_macros::mcp_app;
318///
319/// #[mcp_app(name = "My App")]
320/// impl MyApp {
321/// /// Say hello to someone
322/// pub async fn say_hello(&self, name: String) -> String {
323/// format!("Hello, {}!", name)
324/// }
325/// }
326/// ```
327///
328/// This generates:
329/// - A struct with the impl block name
330/// - Complete MCP server implementation
331/// - All public methods as MCP tools with auto-generated schemas
332/// - A main function that runs the server on STDIO
333/// - Proper error handling and logging setup
334///
335/// # Parameters
336///
337/// - `name`: Server name (required)
338/// - `version`: Server version (defaults to Cargo package version)
339/// - `description`: Server description (defaults to doc comments)
340/// - `transport`: Transport type - "stdio" (default), "websocket", or "http"
341///
342/// # Advanced Usage
343///
344/// ```rust,ignore
345/// #[mcp_app(
346/// name = "Advanced App",
347/// version = "2.0.0",
348/// description = "An advanced MCP application",
349/// transport = "websocket"
350/// )]
351/// impl AdvancedApp {
352/// /// Calculate the answer to everything
353/// pub fn answer(&self) -> i32 { 42 }
354/// }
355/// ```
356///
357/// # Features
358///
359/// - **Ultra-Minimal**: Complete server in ~5 lines of code
360/// - **Zero Boilerplate**: No main function, no setup code needed
361/// - **Auto Schema**: JSON schemas generated from Rust function signatures
362/// - **Transport Flexibility**: Support for STDIO, WebSocket, and HTTP
363/// - **Production Ready**: Includes proper logging and error handling
364/// - **Type Safe**: Full compile-time validation
365///
366/// # Comparison with Official SDKs
367///
368/// This macro makes PulseEngine competitive with the simplest official SDKs:
369/// - **TypeScript SDK**: ~8-10 lines for basic server
370/// - **PulseEngine**: ~5 lines with `#[mcp_app]`
371/// - **Rust Official**: ~15-20 lines minimum
372///
373/// Perfect for rapid prototyping while maintaining enterprise capabilities!
374#[proc_macro_attribute]
375pub fn mcp_app(attr: TokenStream, item: TokenStream) -> TokenStream {
376 mcp_server::mcp_app_impl(attr.into(), item.into())
377 .unwrap_or_else(|err| err.to_compile_error())
378 .into()
379}
380
381/// Generates MCP resource implementations from Rust functions.
382///
383/// Resources in MCP represent data that clients can read, such as files,
384/// database records, or computed values. This macro transforms regular Rust
385/// functions into MCP resources with automatic URI parsing and content handling.
386///
387/// # Basic Usage
388///
389/// ```rust,ignore
390/// use pulseengine_mcp_macros::mcp_resource;
391///
392/// impl MyServer {
393/// #[mcp_resource(
394/// uri_template = "file://{path}",
395/// name = "file_reader",
396/// description = "Read file contents",
397/// mime_type = "text/plain"
398/// )]
399/// async fn read_file(&self, path: String) -> Result<String, std::io::Error> {
400/// std::fs::read_to_string(&path)
401/// }
402/// }
403/// ```
404///
405/// # Parameters
406///
407/// - `uri_template`: URI template with parameters (e.g., "db://{table}/{id}")
408/// - `name`: Resource name (defaults to function name)
409/// - `description`: Resource description (defaults to doc comments)
410/// - `mime_type`: MIME type of resource content (defaults to "text/plain")
411///
412/// # Features
413///
414/// - **URI Templates**: Extract parameters from URIs automatically
415/// - **Type Safety**: Parameters parsed and validated at runtime
416/// - **Async Support**: Both sync and async functions supported
417/// - **Content Negotiation**: Automatic JSON serialization when possible
418#[proc_macro_attribute]
419pub fn mcp_resource(attr: TokenStream, item: TokenStream) -> TokenStream {
420 mcp_resource::mcp_resource_impl(attr.into(), item.into())
421 .unwrap_or_else(|err| err.to_compile_error())
422 .into()
423}