turbomcp 3.0.10

Rust SDK for Model Context Protocol (MCP) with zero-boilerplate macros and WASM support
Documentation
//! # Macro Server - Modern Minimal MCP
//!
//! **Learning Goals (5 minutes):**
//! - Understand the macro-based API for clean server definition
//! - See the minimal code needed for a functional server
//! - Introduction to the #[server] and #[tool] attributes
//!
//! **What this example demonstrates:**
//! - Cleanest possible server implementation
//! - Automatic schema generation from function signatures
//! - Zero boilerplate with maximum functionality
//!
//! **Run with:** `cargo run --example macro_server`

use turbomcp::prelude::*;

/// The simplest possible MCP server using macros
#[derive(Clone)]
struct CleanServer;

#[turbomcp::server(
    name = "clean-server",
    version = "1.0.0",
    description = "Minimal MCP server demonstrating clean architecture"
)]
impl CleanServer {
    /// Get current server time
    #[tool]
    async fn current_time(&self) -> McpResult<String> {
        Ok(chrono::Utc::now().to_rfc3339())
    }

    /// Echo back a message
    #[tool]
    async fn echo(&self, message: String) -> McpResult<String> {
        Ok(format!("Echo: {}", message))
    }

    /// Perform a calculation
    #[tool]
    async fn calculate(&self, operation: String, a: f64, b: f64) -> McpResult<f64> {
        match operation.as_str() {
            "add" => Ok(a + b),
            "subtract" => Ok(a - b),
            "multiply" => Ok(a * b),
            "divide" if b != 0.0 => Ok(a / b),
            "divide" => Err(McpError::invalid_params("Division by zero")),
            _ => Err(McpError::invalid_params(format!(
                "Unknown operation: {}",
                operation
            ))),
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize tracing to stderr (MUST NOT write to stdout as it pollutes the MCP protocol)
    tracing_subscriber::fmt()
        .with_writer(std::io::stderr)
        .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
        .init();

    tracing::info!("Starting Clean Server...");

    // That's it! The server is ready to run
    CleanServer.run_stdio().await?;
    Ok(())
}