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}