Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion crates/rmcp-macros/src/tool.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use darling::{FromMeta, ast::NestedMeta};
use proc_macro2::TokenStream;
use quote::{ToTokens, format_ident, quote};
use syn::{Expr, Ident, ImplItemFn, ReturnType};
use syn::{Expr, Ident, ImplItemFn, ReturnType, parse_quote};

use crate::common::{extract_doc_line, none_expr};

Expand Down Expand Up @@ -120,7 +120,10 @@ impl ResolvedToolAttribute {
} else {
quote! { None }
};
let doc_comment = format!("Generated tool metadata function for {name}");
let doc_attr: syn::Attribute = parse_quote!(#[doc = #doc_comment]);
let tokens = quote! {
#doc_attr
pub fn #fn_ident() -> rmcp::model::Tool {
rmcp::model::Tool {
name: #name.into(),
Expand Down
28 changes: 22 additions & 6 deletions crates/rmcp/tests/test_tool_macros.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//! Test tool macros, including documentation for generated fns.

//cargo test --test test_tool_macros --features "client server"
// Enforce that all generated code has sufficient docs to pass missing_docs lint
#![deny(missing_docs)]
#![allow(dead_code)]
use std::sync::Arc;

Expand All @@ -11,22 +15,27 @@ use rmcp::{
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

/// Parameters for weather tool.
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct GetWeatherRequest {
/// City of interest.
pub city: String,
/// Date of interest.
pub date: String,
}

#[tool_handler(router = self.tool_router)]
impl ServerHandler for Server {}

/// Trivial stateless server.
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct Server {
tool_router: ToolRouter<Self>,
}

impl Server {
/// Create weather server.
pub fn new() -> Self {
Self {
tool_router: Self::tool_router(),
Expand All @@ -53,8 +62,9 @@ impl Server {
async fn empty_param(&self) {}
}

// define generic service trait
/// Generic service trait.
pub trait DataService: Send + Sync + 'static {
/// Get data from service.
fn get_data(&self) -> String;
}

Expand All @@ -67,7 +77,7 @@ impl DataService for MockDataService {
}
}

// define generic server
/// Generic server.
#[derive(Debug, Clone)]
pub struct GenericServer<DS: DataService> {
data_service: Arc<DS>,
Expand All @@ -76,6 +86,7 @@ pub struct GenericServer<DS: DataService> {

#[tool_router]
impl<DS: DataService> GenericServer<DS> {
/// Create data server instance.
pub fn new(data_service: DS) -> Self {
Self {
data_service: Arc::new(data_service),
Expand Down Expand Up @@ -142,22 +153,26 @@ async fn test_tool_macros_with_optional_param() {

impl GetWeatherRequest {}

// Struct defined for testing optional field schema generation
/// Struct defined for testing optional field schema generation.
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct OptionalFieldTestSchema {
/// Field description.
#[schemars(description = "An optional description field")]
pub description: Option<String>,
}

// Struct defined for testing optional i64 field schema generation and null handling
/// Struct defined for testing optional i64 field schema generation and null handling.
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct OptionalI64TestSchema {
/// Optional count field.
#[schemars(description = "An optional i64 field")]
pub count: Option<i64>,
pub mandatory_field: String, // Added to ensure non-empty object schema

/// Added to ensure non-empty object schema.
pub mandatory_field: String,
}

// Dummy struct to host the test tool method
/// Dummy struct to host the test tool method.
#[derive(Debug, Clone)]
pub struct OptionalSchemaTester {
tool_router: ToolRouter<Self>,
Expand All @@ -170,6 +185,7 @@ impl Default for OptionalSchemaTester {
}

impl OptionalSchemaTester {
/// Create instance of optional schema tester service.
pub fn new() -> Self {
Self {
tool_router: Self::tool_router(),
Expand Down