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>>, pub input: String, }
impl MyTool {
async fn run(&self, ctx: ExecutionContext<'_>) -> Result<Vec<Box<dyn Content>>, ToolError> {
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, }
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))],
})
}
}