Command-line tools for managing and testing MCP servers


Keywords
testing, cli, tools, management, mcp
License
MIT

Documentation

TurboMCP

Crates.io Documentation License: MIT Tests

High-performance Rust SDK for the Model Context Protocol (MCP) with SIMD acceleration, enterprise security, and ergonomic APIs.

Overview

TurboMCP is a production-ready Rust implementation of the Model Context Protocol (MCP) featuring:

  • 🚀 High Performance - SIMD-accelerated JSON processing with simd-json and sonic-rs
  • 🛡️ Enterprise Security - OAuth 2.0, CORS, rate limiting, security headers, TLS support
  • ⚡ Zero-Overhead Macros - Ergonomic #[server], #[tool], #[resource] attributes
  • 🔗 Multi-Transport - STDIO, HTTP/SSE, WebSocket, TCP, Unix sockets
  • 🎯 Type Safety - Compile-time validation with automatic schema generation
  • 📁 Roots Support - MCP-compliant filesystem boundaries with OS-aware defaults
  • 🔄 Production Ready - Circuit breakers, graceful shutdown, session management
  • 🎭 Elicitation Support - Server-initiated interactive user input (New in 1.0.3)
  • 🤖 Sampling Protocol - Bidirectional LLM sampling capabilities

Quick Start

Add TurboMCP to your Cargo.toml:

[dependencies]
turbomcp = "1.0.4"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"

Create a simple calculator server:

use turbomcp::prelude::*;

#[derive(Clone)]
struct Calculator;

#[server(
    name = "calculator-server",
    version = "1.0.0",
    description = "A simple calculator"
)]
impl Calculator {
    #[tool("Add two numbers")]
    async fn add(&self, a: i32, b: i32) -> McpResult<i32> {
        Ok(a + b)
    }

    #[tool("Get server status")]
    async fn status(&self, ctx: Context) -> McpResult<String> {
        ctx.info("Status requested").await?;
        Ok("Server running".to_string())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    Calculator.run_stdio().await?;
    Ok(())
}

Client Setup

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "my-turbomcp-server": {
      "command": "/path/to/your/server/binary",
      "args": []
    }
  }
}

Testing Your Server

# Test with CLI tool
cargo install turbomcp-cli

# For HTTP/WebSocket servers
turbomcp-cli tools-list --url http://localhost:8080/mcp

# For STDIO servers (like Claude Desktop)
turbomcp-cli tools-list --command "./your-server"

# Test directly
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | ./your-server

Key Features

Enterprise Security

Production-ready security features with environment-aware configurations:

use turbomcp_transport::{AxumMcpExt, McpServerConfig};

// Production security configuration  
let config = McpServerConfig::production()
    .with_cors_origins(vec!["https://app.example.com".to_string()])
    .with_custom_csp("default-src 'self'; connect-src 'self' wss:")
    .with_rate_limit(120, 20)  // 120 requests/minute, 20 burst
    .with_jwt_auth("your-secret-key".to_string());

let app = Router::new()
    .route("/api/status", get(status_handler))
    .merge(Router::<()>::turbo_mcp_routes_for_merge(mcp_service, config));

Security Features:

  • 🔒 CORS Protection - Environment-aware cross-origin policies
  • 📋 Security Headers - CSP, HSTS, X-Frame-Options, and more
  • Rate Limiting - Token bucket algorithm with flexible strategies
  • 🔑 Multi-Auth - JWT validation and API key authentication
  • 🔐 TLS Support - Automatic certificate loading with TLS 1.3

OAuth 2.0 Authentication

Built-in OAuth 2.0 support with Google, GitHub, Microsoft providers:

use turbomcp::prelude::*;
use turbomcp::auth::*;

#[derive(Clone)]
pub struct AuthenticatedServer {
    oauth_providers: Arc<RwLock<HashMap<String, OAuth2Provider>>>,
}

#[server]
impl AuthenticatedServer {
    #[tool("Get authenticated user profile")]
    async fn get_user_profile(&self, ctx: Context) -> McpResult<String> {
        if let Some(user_id) = ctx.user_id() {
            Ok(format!("Authenticated user: {}", user_id))
        } else {
            Err(mcp_error!("Authentication required"))
        }
    }

    #[tool("Start OAuth flow")]
    async fn start_oauth_flow(&self, provider: String) -> McpResult<String> {
        let providers = self.oauth_providers.read().await;
        if let Some(oauth_provider) = providers.get(&provider) {
            let auth_result = oauth_provider.start_authorization().await?;
            Ok(format!("Visit: {}", auth_result.auth_url))
        } else {
            Err(mcp_error!("Unknown provider: {}", provider))
        }
    }
}

OAuth Features:

  • 🔐 Multiple Providers - Google, GitHub, Microsoft, custom OAuth 2.0
  • 🛡️ Always-On PKCE - Security enabled by default
  • 🔄 All OAuth Flows - Authorization Code, Client Credentials, Device Code
  • 👥 Session Management - User session tracking with cleanup

Context Injection

Robust dependency injection with request correlation:

#[server]
impl ProductionServer {
    #[tool("Process with full observability")]
    async fn process_data(&self, ctx: Context, data: String) -> McpResult<String> {
        // Context provides:
        // - Request correlation and distributed tracing  
        // - Structured logging with metadata
        // - Performance monitoring and metrics
        // - Dependency injection container access
        
        ctx.info(&format!("Processing: {}", data)).await?;
        
        let start = std::time::Instant::now();
        let result = self.database.process(&data).await?;
        
        ctx.info(&format!("Completed in {:?}", start.elapsed())).await?;
        Ok(result)
    }
}

Multi-Transport Support

Flexible transport protocols for different deployment scenarios:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let server = Calculator::new();
    
    match std::env::var("TRANSPORT").as_deref() {
        Ok("tcp") => server.run_tcp("127.0.0.1:8080").await?,
        Ok("unix") => server.run_unix("/tmp/mcp.sock").await?,
        _ => server.run_stdio().await?, // Default
    }
    Ok(())
}

Graceful Shutdown

Production-ready shutdown handling:

use tokio::signal;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let server = MyServer::new();
    let (server, shutdown_handle) = server.into_server_with_shutdown()?;
    
    let server_task = tokio::spawn(async move {
        server.run_stdio().await
    });
    
    signal::ctrl_c().await?;
    tracing::info!("Shutdown signal received");
    
    shutdown_handle.shutdown().await;
    server_task.await??;
    
    Ok(())
}

Architecture

TurboMCP's modular, compile-time optimized architecture separates concerns while maximizing performance:

🎯 Design Philosophy: "Compile-Time Complexity, Runtime Simplicity"

Our architecture prioritizes compile-time computation over runtime flexibility. While this creates a more sophisticated build process, it delivers unmatched runtime performance and predictability. Each crate is optimized for its specific role, with aggressive feature gating to ensure minimal production footprints.

📦 Focused Crate Organization

Crate Purpose Key Features
turbomcp Main SDK Procedural macros, prelude, integration
turbomcp-core Core types SIMD message handling, sessions, errors
turbomcp-protocol MCP protocol JSON-RPC, schema validation, versioning
turbomcp-transport Transport layer HTTP, WebSocket, circuit breakers
turbomcp-server Server framework Routing, authentication, middleware
turbomcp-client Client library Connection management, error recovery
turbomcp-macros Proc macros #[server], #[tool], #[resource]
turbomcp-cli CLI tools Testing, schema export, debugging

Advanced Usage

Roots & Filesystem Boundaries (New in 1.0.3)

Configure filesystem roots for secure server operations:

use turbomcp::prelude::*;

// Method 1: Using macro attributes (recommended)
#[server(
    name = "filesystem-server",
    version = "1.0.0",
    root = "file:///workspace:Project Workspace",
    root = "file:///tmp:Temporary Files",
    root = "file:///Users/shared:Shared Documents"
)]
impl FileSystemServer {
    #[tool("List files in directory")]
    async fn list_files(&self, ctx: Context, path: String) -> McpResult<Vec<String>> {
        ctx.info(&format!("Listing files in: {}", path)).await?;
        // File operations are bounded by configured roots
        Ok(vec!["file1.txt".to_string(), "file2.txt".to_string()])
    }
}

// Method 2: Using ServerBuilder API
use turbomcp_server::ServerBuilder;
use turbomcp_protocol::types::Root;

let server = ServerBuilder::new()
    .name("filesystem-server")
    .version("1.0.0")
    .root("file:///workspace", Some("Workspace".to_string()))
    .roots(vec![
        Root { uri: "file:///tmp".to_string(), name: Some("Temp".to_string()) }
    ])
    .build();

Roots Features:

  • 📁 Multiple Configuration Methods - Macro attributes, builder API, and runtime
  • 🖥️ OS-Aware Defaults - Automatic platform-specific roots (Linux: /, macOS: /, /Volumes, Windows: drive letters)
  • 🔒 Security Foundation - Establish filesystem operation boundaries
  • 🔗 MCP Compliance - Full support for roots/list protocol method

Elicitation (Enhanced in 1.0.4)

Server-initiated requests for interactive user input with world-class ergonomics:

use turbomcp::prelude::*;
use turbomcp::elicitation_api::{ElicitationResult, text, checkbox, integer_field};
use turbomcp_macros::elicit;

#[tool("Configure deployment")]
async fn deploy(&self, ctx: Context, project: String) -> McpResult<String> {
    // Simple elicit macro for quick prompts
    let confirmation = elicit!(ctx, "Deploy to production?")?;
    if matches!(confirmation, ElicitationResult::Decline(_)) {
        return Ok("Deployment cancelled".to_string());
    }

    // Advanced form with beautiful ergonomic builders
    let config = elicit("Configure deployment")
        .field("environment", text("Environment").options(&["dev", "staging", "production"]))
        .field("auto_scale", checkbox("Enable Auto-scaling").default(true))
        .field("replicas", integer_field("Replica Count").range(1.0, 10.0))
        .require(vec!["environment"])
        .send(&ctx.request)
        .await?;
    
    match config {
        ElicitationResult::Accept(data) => {
            let env = data.get::<String>("environment")?;
            let replicas = data.get::<i64>("replicas").unwrap_or(1);
            Ok(format!("Deployed {} to {} with {} replicas", project, env, replicas))
        }
        _ => Err(mcp_error!("Deployment cancelled"))
    }
}

Schema Generation

Automatic JSON schema generation with validation:

#[tool("Process user data")]
async fn process_user(
    &self,
    #[description("User's email address")]
    email: String,
    #[description("User's age in years")] 
    age: u8,
) -> McpResult<UserProfile> {
    // Schema automatically generated and validated
    Ok(UserProfile { email, age })
}

Resource Handlers

URI template-based resource handling:

#[resource("file://{path}")]
async fn read_file(&self, path: String) -> McpResult<String> {
    tokio::fs::read_to_string(&path).await
        .map_err(|e| mcp_error!("Resource error: {}", e))
}

Feature-Gated Transports

Optimize binary size by selecting only needed transports:

# Minimal STDIO-only server
turbomcp = { version = "1.0.3", default-features = false, features = ["minimal"] }

# Network deployment with TCP + Unix
turbomcp = { version = "1.0.3", default-features = false, features = ["network"] }

# All transports for maximum flexibility  
turbomcp = { version = "1.0.3", default-features = false, features = ["all-transports"] }

CLI Tools

Install the CLI for development and testing:

cargo install turbomcp-cli

Usage:

# List available tools (HTTP)
turbomcp-cli tools-list --url http://localhost:8080/mcp

# List available tools (STDIO)
turbomcp-cli tools-list --command "./my-server"

# Call a tool with arguments
turbomcp-cli tools-call --url http://localhost:8080/mcp --name add --arguments '{"a": 5, "b": 3}'

# Export JSON schemas to file
turbomcp-cli schema-export --url http://localhost:8080/mcp --output schemas.json

Performance & Architecture Advantages

TurboMCP's leapfrog architecture delivers superior performance through fundamental design choices:

🏗️ Compile-Time Optimization Philosophy

  • Zero-overhead abstractions - All tool registration and schema generation happens at compile time
  • Macro-powered efficiency - #[server] and #[tool] macros eliminate runtime reflection overhead
  • Type-driven performance - Rust's type system enables aggressive optimizations impossible in dynamic languages
  • Smart feature gating - While our codebase is comprehensive, compile-time feature selection ensures lean production binaries

Runtime Performance

  • JSON Processing - 2-3x faster than serde_json with SIMD acceleration
  • Memory Efficiency - Zero-copy message handling with Bytes eliminates unnecessary allocations
  • Concurrency - Tokio-based async runtime with efficient task scheduling
  • Cold Start Speed - Pre-computed schemas and handlers enable faster initialization
  • Reliability - Circuit breakers and connection pooling with intelligent failover

🎯 Architectural Superiority

Our compile-time first approach means:

  • No runtime schema generation - Schemas computed at compile time, not during requests
  • Direct handler dispatch - O(1) tool lookup without HashMap traversals or string matching
  • Zero reflection - All type information resolved statically
  • Predictable performance - No garbage collection pauses or dynamic allocation surprises

The TurboMCP advantage: While some frameworks trade complexity for simplicity, we've engineered complexity away through compile-time optimization. Users get maximum performance with minimal cognitive overhead.

Examples

TurboMCP includes 12 carefully crafted examples that guide you from basics to production deployment. See the Examples Guide for a complete learning path.

Foundation (Start Here)

Core MCP Features

Advanced Features

Production Ready

Run any example:

# Basic examples
cargo run --example 01_hello_world
cargo run --example 02_clean_server

# Architecture comparison (run in separate terminals)
cargo run --example 06_architecture_patterns builder  # Terminal 1
cargo run --example 06_architecture_patterns macro    # Terminal 2
cargo run --example 06b_architecture_client          # Terminal 3 - test client

Development

Setup:

git clone https://github.com/Epistates/turbomcp.git
cd turbomcp
cargo build --workspace

Testing:

make test                    # Run comprehensive test suite
cargo test --workspace      # Run all tests
cargo test --all-features   # Test with all features

Quality:

cargo fmt --all                              # Format code
cargo clippy --workspace --all-targets       # Lint code  
cargo bench --workspace                      # Run benchmarks

Documentation

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature-name
  3. Make your changes and add tests
  4. Run the full test suite: make test
  5. Submit a pull request

Please ensure all tests pass and follow the existing code style.

License

Licensed under the MIT License.


Related Projects