model_context_protocol_macros/lib.rs
1//! Procedural macros for MCP server and tool definitions.
2//!
3//! This crate provides macros to reduce boilerplate when defining MCP servers:
4//!
5//! - `#[mcp_server]` - Define server metadata and collect tools from impl blocks
6//! - `#[mcp_tool]` - Mark a method as an MCP tool (used within `#[mcp_server]` impl blocks)
7//! - `#[param(...)]` - Mark a parameter with description for the tool schema
8//!
9//! # Example
10//!
11//! ```rust,ignore
12//! use mcp::macros::mcp_server;
13//!
14//! #[mcp_server(name = "calculator", version = "1.0.0")]
15//! pub struct Calculator;
16//!
17//! #[mcp_server]
18//! impl Calculator {
19//! #[mcp_tool("Add two numbers together")]
20//! pub fn add(
21//! &self,
22//! #[param("The first number")] a: f64,
23//! #[param("The second number")] b: f64,
24//! ) -> f64 {
25//! a + b
26//! }
27//! }
28//! ```
29//!
30//! Note: `#[mcp_tool]` and `#[param]` are inert marker attributes processed by `#[mcp_server]`.
31//! They should only be used within impl blocks marked with `#[mcp_server]`.
32
33use proc_macro::TokenStream;
34
35mod schema;
36mod server;
37mod tool;
38
39/// Marks a struct as an MCP server or an impl block as containing MCP tools.
40///
41/// When applied to a struct, it adds server name and version metadata.
42/// When applied to an impl block, it processes methods marked with `#[mcp_tool]`
43/// and generates the `MacroServer` trait implementation.
44///
45/// # On Structs
46///
47/// ```rust,ignore
48/// #[mcp_server(name = "my-server", version = "1.0.0")]
49/// pub struct MyServer { ... }
50/// ```
51///
52/// # On Impl Blocks
53///
54/// ```rust,ignore
55/// #[mcp_server]
56/// impl MyServer {
57/// #[mcp_tool(description = "Tool description")]
58/// pub fn my_tool(
59/// &self,
60/// #[param("Parameter description")] param: String,
61/// ) -> Result<String, String> { ... }
62/// }
63/// ```
64///
65/// # Parameter Attributes
66///
67/// Within `#[mcp_tool]` methods, use `#[param(...)]` on parameters:
68///
69/// **Shorthand (recommended):**
70/// - `#[param("description")]` - Just the description
71///
72/// **Full form:**
73/// - `#[param(description = "...", name = "...", required = true)]`
74///
75/// Options:
76/// - `description` - Description shown to the LLM
77/// - `name` - Custom parameter name override (optional)
78/// - `required` - Override required/optional inference (optional)
79///
80/// All non-self parameters must have `#[param(...)]` - unmarked parameters cause compile errors.
81#[proc_macro_attribute]
82pub fn mcp_server(attr: TokenStream, item: TokenStream) -> TokenStream {
83 server::mcp_server_impl(attr.into(), item.into()).into()
84}
85
86/// Marks a method as an MCP tool.
87///
88/// **Note**: This is an inert marker attribute that should only be used within
89/// impl blocks marked with `#[mcp_server]`. When used outside of `#[mcp_server]`,
90/// it will generate tool metadata but won't be collected into a server.
91///
92/// # Example
93///
94/// ```rust,ignore
95/// #[mcp_server]
96/// impl MyServer {
97/// #[mcp_tool(description = "Store a value in memory")]
98/// pub fn memory_write(
99/// &self,
100/// #[mcp(description = "The scope/namespace")]
101/// scope: String,
102/// #[mcp(description = "The key to store under")]
103/// key: String,
104/// ) -> Result<String, String> {
105/// // implementation
106/// }
107/// }
108/// ```
109#[proc_macro_attribute]
110pub fn mcp_tool(attr: TokenStream, item: TokenStream) -> TokenStream {
111 tool::mcp_tool_impl(attr.into(), item.into()).into()
112}