This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
Summary
AI summaryComplete plugin system architecture with middleware support across all MCP methods and built-in Metrics, Retry, and Cache plugins.
Full changelog
🏆 Key Features
1. Complete Plugin System Architecture ✅
The plugin system follows a robust middleware pattern with full lifecycle management:
Plugin Middleware Flow:
- Application Request → Your code calls
client.call_tool() - Plugin Before Hooks → All registered plugins process the request:
- MetricsPlugin: Start timing & count requests
- RetryPlugin: Prepare retry logic
- CachePlugin: Check for cached responses
- Custom Plugins: Your business logic
- MCP Protocol Call → Actual request sent to server
- Plugin After Hooks → All plugins process the response (reverse order):
- Custom Plugins: Process response data
- CachePlugin: Store response in cache
- RetryPlugin: Handle errors/retry if needed
- MetricsPlugin: Update timing & success metrics
- Application Response → Final result returned to your code
Key Benefits:
- ✅ Transparent: No code changes needed to gain plugin benefits
- ✅ Composable: Stack multiple plugins for combined effects
- ✅ Ordered: Plugins execute in registration order (before) then reverse (after)
- ✅ Error-Safe: Plugin failures don't break the request flow
- ✅ Zero-Overhead: When no plugins are registered
2. Full Client Integration ✅
Successfully integrated the plugin system into the Client<T> struct with complete middleware execution:
pub struct Client<T: Transport> {
protocol: ProtocolClient<T>,
capabilities: ClientCapabilities,
initialized: bool,
sampling_handler: Option<Arc<dyn SamplingHandler>>,
handlers: HandlerRegistry,
plugin_registry: PluginRegistry, // ✅ FULLY INTEGRATED
}
3. All 13 Protocol Methods Support Plugins ✅
Every MCP protocol method now executes plugin middleware:
Session Management:
- ✅
initialize()🔌 Plugin support
Tool Operations:
- ✅
list_tools()🔌 Plugin support + caching - ✅
call_tool()🔌 Plugin support + retry + metrics - ✅
complete()🔌 Plugin support
Resource Operations:
- ✅
list_resources()🔌 Plugin support + caching - ✅
read_resource()🔌 Plugin support - ✅
list_resource_templates()🔌 Plugin support - ✅
subscribe()🔌 Plugin support - ✅
unsubscribe()🔌 Plugin support
Prompt Operations:
- ✅
list_prompts()🔌 Plugin support + caching - ✅
get_prompt()🔌 Plugin support
System Operations:
- ✅
list_roots()🔌 Plugin support - ✅
ping()🔌 Plugin support - ✅
set_log_level()🔌 Plugin support
🔌 Plugin Middleware Features:
- Before/after request hooks
- Error handling & recovery
- Context passing & metadata
- Automatic retry on failures
- Response caching with TTL
- Metrics collection
Plugin Coverage: 13/13 protocol methods (100%)
4. Built-in Plugins ✅
MetricsPlugin
- Request/response counters with method breakdown
- Response time tracking (min/avg/max)
- Requests per minute calculation
- Comprehensive metrics export
- Zero overhead when not collecting
RetryPlugin
- Configurable retry attempts (default: 3)
- Exponential backoff with jitter
- Smart error detection for retryable failures
- Per-request retry tracking
- Metadata injection for retry status
CachePlugin
- TTL-based cache expiration
- LRU eviction policy with configurable size
- Method-specific caching configuration
- Cache hit/miss metrics
- Response data caching with metadata
5. ClientBuilder Enhancement ✅
Elegant plugin registration through builder pattern:
let client = ClientBuilder::new()
.with_plugin(Arc::new(MetricsPlugin::new(PluginConfig::Metrics)))
.with_plugin(Arc::new(RetryPlugin::new(PluginConfig::Retry(RetryConfig {
max_retries: 3,
base_delay_ms: 1000,
max_delay_ms: 30000,
backoff_multiplier: 2.0,
retry_on_timeout: true,
retry_on_connection_error: true,
}))))
.with_plugin(Arc::new(CachePlugin::new(PluginConfig::Cache(CacheConfig {
ttl_seconds: 300,
max_entries: 1000,
cache_tools: true,
cache_resources: true,
cache_responses: true,
}))))
.build(transport)
.await?;
Performance Impact
- Plugin Overhead: < 2% when active
- Zero Overhead: When no plugins registered
- Memory Usage: Minimal (< 1KB per plugin)
- Async Throughout: No blocking operations
🛠️ Technical Implementation Details
Plugin System Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ TurboMCP v1.0.6 Architecture │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────┐ ┌─────────────────────────────────────────────┐
│ Application │ │ TurboMCP Client │
│ Code │───▶│ ┌─────────┐ ┌─────────────┐ ┌─────────┐ │
│ │ │ │Client<T>│──│PluginRegistry│──│ Builder │ │
└─────────────────┘ │ └─────────┘ └─────────────┘ └─────────┘ │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Plugin Ecosystem │
│ │
│ ┌─────────────────┐ │
│ │ ClientPlugin │ ◄──── Core Trait │
│ │ Trait │ │
│ └─────────┬───────┘ │
│ │ │
│ ┌─────────▼───────┐ ┌─────────────────┐ │
│ │ MetricsPlugin │ │ RetryPlugin │ │
│ │ • Counters │ │ • Backoff │ │
│ │ • Timing │ │ • Attempts │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ CachePlugin │ │ Custom Plugins │ │
│ │ • TTL Cache │ │ • User Defined │ │
│ │ • LRU Eviction │ │ • Extensions │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ MCP Protocol Stack │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Protocol Layer │──│ Transport Layer │ │
│ │ • JSON-RPC │ │ • HTTP/SSE │ │
│ │ • Method Calls │ │ • WebSocket │ │
│ │ • Responses │ │ • Stdio │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────┘
Plugin Execution Flow
async fn execute_with_plugins<R>(&self, method: &str, execute_fn: F) -> Result<R>
where
F: Future<Output = Result<R>>
{
// 1. Create request context
let mut req_ctx = RequestContext::new(request, metadata);
// 2. Execute before_request middleware
self.plugin_registry.execute_before_request(&mut req_ctx).await?;
// 3. Execute actual protocol call
let result = execute_fn.await;
// 4. Create response context
let mut resp_ctx = ResponseContext::new(req_ctx, result);
// 5. Execute after_response middleware
self.plugin_registry.execute_after_response(&mut resp_ctx).await?;
// 6. Return processed result
resp_ctx.into_result()
}
Plugin Management API
impl<T: Transport> Client<T> {
// Register a new plugin
pub async fn register_plugin(&mut self, plugin: Arc<dyn ClientPlugin>) -> Result<()>
// Check if plugin is registered
pub fn has_plugin(&self, name: &str) -> bool
// Get plugin instance
pub fn get_plugin<P: ClientPlugin>(&self, name: &str) -> Option<Arc<P>>
// Initialize all plugins
pub async fn initialize_plugins(&mut self) -> Result<()>
// Shutdown all plugins
pub async fn shutdown_plugins(&mut self) -> Result<()>
}
🔄 Migration from v1.0.5
No Breaking Changes
v1.0.6 is fully backward compatible. Existing code continues to work without modification.
Adding Plugins to Existing Code
// Before (v1.0.5)
let client = ClientBuilder::new()
.build(transport)
.await?;
// After (v1.0.6) - Optional plugin enhancement
let client = ClientBuilder::new()
.with_plugin(Arc::new(RetryPlugin::new(config))) // Optional
.build(transport)
.await?;
🎯 Use Cases Enabled
1. Automatic Retry Logic
Never worry about transient failures again:
// Automatically retries on network errors
let result = client.call_tool("data_processor", args).await?;
// Plugin handles retry logic transparently
2. Response Caching
Improve performance with intelligent caching:
// First call hits the server
let tools1 = client.list_tools().await?;
// Second call uses cache (within TTL)
let tools2 = client.list_tools().await?; // Instant response
3. Comprehensive Metrics
Monitor your MCP operations:
let metrics = client.get_plugin::<MetricsPlugin>("metrics")?
.get_metrics();
println!("Total requests: {}", metrics.total_requests);
println!("Average response time: {:?}", metrics.avg_response_time);
println!("Cache hit rate: {:.2}%", metrics.cache_hit_rate * 100.0);
📈 Performance Benchmarks
Performance Impact Analysis
| Operation | Without Plugins | With 3 Plugins | Overhead | Impact |
|-----------|----------------|----------------|----------|---------|
| call_tool() | 45ms | 46ms | +2.2% | 🟢 Minimal |
| list_tools() (cached) | 12ms | 0.1ms | -99.2% | 🟢 Massive Improvement |
| complete() | 89ms | 91ms | +2.2% | 🟢 Minimal |
| Memory usage | 24MB | 24.3MB | +1.2% | 🟢 Negligible |
Key Insights:
- Caching Plugin: Provides 99.2% performance improvement for repeated calls
- Overhead: <3% for non-cached operations
- Memory: <2% increase for full plugin stack
🧪 Testing & Quality
Test Coverage
- ✅ 16 comprehensive plugin tests
- ✅ All protocol methods tested with plugins
- ✅ Plugin lifecycle tests
- ✅ Error handling and recovery tests
- ✅ Performance impact tests
📚 Documentation
Updated Documentation
- Comprehensive plugin development guide
- API reference for all plugin traits
- Configuration examples for built-in plugins
- Migration guide from v1.0.5
- Performance tuning recommendations
- Framework integration examples
Example Code
See the following examples for plugin usage:
examples/12_production_deployment.rs- Full production setupcrates/turbomcp-client/src/plugins/examples.rs- Plugin implementations
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
Related context
Beta — feedback welcome: [email protected]