Skip to main content

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", description = "A simple calculator server")]
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", description = "My server description")]
49/// pub struct MyServer { ... }
50/// ```
51///
52/// Available attributes:
53/// - `name` - Server name (defaults to lowercase struct name)
54/// - `version` - Server version (optional)
55/// - `description` - Server description (optional)
56///
57/// # On Impl Blocks
58///
59/// ```rust,ignore
60/// #[mcp_server]
61/// impl MyServer {
62///     #[mcp_tool(description = "Tool description")]
63///     pub fn my_tool(
64///         &self,
65///         #[param("Parameter description")] param: String,
66///     ) -> Result<String, String> { ... }
67/// }
68/// ```
69///
70/// # Parameter Attributes
71///
72/// Within `#[mcp_tool]` methods, use `#[param(...)]` on parameters:
73///
74/// **Shorthand (recommended):**
75/// - `#[param("description")]` - Just the description
76///
77/// **Full form:**
78/// - `#[param(description = "...", name = "...", required = true)]`
79///
80/// Options:
81/// - `description` - Description shown to the LLM
82/// - `name` - Custom parameter name override (optional)
83/// - `required` - Override required/optional inference (optional)
84///
85/// All non-self parameters must have `#[param(...)]` - unmarked parameters cause compile errors.
86#[proc_macro_attribute]
87pub fn mcp_server(attr: TokenStream, item: TokenStream) -> TokenStream {
88    server::mcp_server_impl(attr.into(), item.into()).into()
89}
90
91/// Marks a method as an MCP tool.
92///
93/// **Note**: This is an inert marker attribute that should only be used within
94/// impl blocks marked with `#[mcp_server]`. When used outside of `#[mcp_server]`,
95/// it will generate tool metadata but won't be collected into a server.
96///
97/// # Example
98///
99/// ```rust,ignore
100/// #[mcp_server]
101/// impl MyServer {
102///     #[mcp_tool(description = "Store a value in memory")]
103///     pub fn memory_write(
104///         &self,
105///         #[mcp(description = "The scope/namespace")]
106///         scope: String,
107///         #[mcp(description = "The key to store under")]
108///         key: String,
109///     ) -> Result<String, String> {
110///         // implementation
111///     }
112/// }
113/// ```
114#[proc_macro_attribute]
115pub fn mcp_tool(attr: TokenStream, item: TokenStream) -> TokenStream {
116    tool::mcp_tool_impl(attr.into(), item.into()).into()
117}