mcp-host-macros 0.1.2

Procedural macros for mcp-host crate
Documentation

Procedural macros for mcp-host

Provides derive macros for MCP tools, resources, and prompts.

Attributes

Struct-level attributes

  • #[mcp(name = "...")] - Override the tool/resource name (default: struct name)
  • #[mcp(description = "...")] - Set the description

Field-level attributes

  • #[mcp(skip)] - Exclude field from input schema (for internal state fields)

Example

use mcp_host::prelude::*;

#[derive(McpTool)]
#[mcp(name = "my_tool", description = "Does something useful")]
pub struct MyTool {
    #[mcp(skip)]
    pub state: Arc<Mutex<State>>,  // Internal, not in schema
    pub input: String,              // Included in schema
}

// User MUST implement this method - the macro delegates execute() to it
impl MyTool {
    async fn run(&self, ctx: ExecutionContext<'_>) -> Result<Vec<Box<dyn Content>>, ToolError> {
        // Your custom logic here
        Ok(vec![Box::new(TextContent::new("Hello!"))])
    }
}

For resources, implement read_resource():

#[derive(McpResource)]
#[mcp(description = "My resource")]
pub struct MyResource {
    pub uri: String,
    pub mime_type: Option<String>,
}

impl MyResource {
    async fn read_resource(&self, _ctx: ExecutionContext<'_>) -> Result<Vec<ResourceContent>, ResourceError> {
        Ok(vec![ResourceContent::text("content", None)])
    }
}

For prompts, implement get_prompt():

#[derive(McpPrompt)]
#[mcp(name = "greeting", description = "Generates a greeting")]
pub struct GreetingPrompt {
    pub name: String,  // becomes a required argument
}

impl GreetingPrompt {
    async fn get_prompt(&self, ctx: ExecutionContext<'_>) -> Result<GetPromptResult, PromptError> {
        let name = ctx.params.get("name").and_then(|v| v.as_str()).unwrap_or("World");
        Ok(GetPromptResult {
            description: Some(format!("Greeting for {}", name)),
            messages: vec![self.user(&format!("Hello, {}!", name))],
        })
    }
}