Patterns¶
Implementation patterns and usage techniques
Buffer Pooling and Performance Optimization¶
HTTP Buffer Pool Implementation¶
AIRS MCP provides a production-ready HTTP buffer pool that reduces allocation overhead:
use airsprotocols_mcp::transport::http::{BufferPool, BufferPoolConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure HTTP buffer pool
let config = BufferPoolConfig::new()
.max_buffers(100) // Pool up to 100 buffers
.buffer_size(8 * 1024) // 8KB buffers
.adaptive_sizing(true); // Enable adaptive sizing
let pool = BufferPool::new(config);
// Get buffers with automatic pooling
let mut buffer = pool.get_buffer();
buffer.extend_from_slice(b"Hello, World!");
// Buffer automatically returns to pool when dropped
Ok(())
}
Buffer Pool Metrics and Monitoring¶
use airsprotocols_mcp::transport::http::BufferPool;
async fn monitor_buffer_performance(pool: &BufferPool) {
let stats = pool.stats();
println!("HTTP Buffer Pool Performance:");
println!(" Available Buffers: {}", stats.available_buffers);
println!(" Total Buffers: {}", stats.total_buffers);
println!(" Max Buffers: {}", stats.max_buffers);
}
JSON-RPC Message Patterns¶
Working with Different Message Types¶
use airsprotocols_mcp::{JsonRpcRequest, JsonRpcResponse, JsonRpcNotification, RequestId, JsonRpcMessageTrait};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create different message types
let request = JsonRpcRequest::new(
"ping",
Some(json!({"message": "hello"})),
RequestId::new_string("req-001")
);
let response = JsonRpcResponse::success(
json!({"message": "pong"}),
RequestId::new_string("req-001")
);
let notification = JsonRpcNotification::new(
"heartbeat",
Some(json!({"timestamp": "2025-09-20T19:00:00Z"}))
);
// All message types implement the same serialization trait
println!("Request: {}", request.to_json()?);
println!("Response: {}", response.to_json()?);
println!("Notification: {}", notification.to_json()?);
Ok(())
}
Request ID Patterns¶
use airsprotocols_mcp::{JsonRpcRequest, RequestId};
use serde_json::json;
fn request_id_examples() -> Result<(), Box<dyn std::error::Error>> {
// Numeric IDs for simple counting
let numeric_request = JsonRpcRequest::new(
"calculate",
Some(json!({"operation": "add", "values": [1, 2, 3]})),
RequestId::new_number(42)
);
// String IDs for UUIDs or correlation tracking
let string_request = JsonRpcRequest::new(
"fetch_data",
Some(json!({"table": "users", "limit": 10})),
RequestId::new_string("fetch-users-001")
);
// Access ID values
match numeric_request.id {
Some(RequestId::Number(n)) => println!("Numeric ID: {}", n),
Some(RequestId::String(s)) => println!("String ID: {}", s),
None => println!("No ID (notification)"),
}
Ok(())
}
MCP Client Patterns¶
Basic Client Usage¶
use airsprotocols_mcp::integration::{McpClientBuilder, McpResult};
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClientBuilder;
use std::time::Duration;
async fn basic_client_example() -> McpResult<()> {
// Create transport
let transport = StdioTransportClientBuilder::new()
.command("python")
.args(vec!["-m".to_string(), "my_mcp_server".to_string()])
.timeout(Duration::from_secs(30))
.build()
.await?;
// Create client
let mut client = McpClientBuilder::new()
.client_info("my-client", "1.0.0")
.timeout(Duration::from_secs(60))
.build(transport);
// Initialize connection
let capabilities = client.initialize().await?;
println!("Server capabilities: {:?}", capabilities);
// List available tools
let tools = client.list_tools().await?;
println!("Available tools: {}", tools.tools.len());
// List available resources
let resources = client.list_resources().await?;
println!("Available resources: {}", resources.resources.len());
client.close().await?;
Ok(())
}
HTTP Client with Authentication¶
use airsprotocols_mcp::integration::{McpClientBuilder, McpResult};
use airsprotocols_mcp::transport::adapters::http::{HttpTransportClientBuilder, AuthMethod};
use std::time::Duration;
async fn http_client_example() -> McpResult<()> {
// Create HTTP transport with Bearer token
let transport = HttpTransportClientBuilder::new()
.endpoint("https://api.example.com/mcp")?
.auth(AuthMethod::Bearer {
token: "your-access-token".to_string(),
})
.timeout(Duration::from_secs(30))
.build()
.await?;
// Create MCP client
let mut client = McpClientBuilder::new()
.client_info("my-http-client", "1.0.0")
.build(transport);
// Use the client
client.initialize().await?;
let tools = client.list_tools().await?;
// Call a specific tool
if let Some(tool) = tools.tools.first() {
let result = client.call_tool(&tool.name, None).await?;
println!("Tool result: {:?}", result);
}
client.close().await?;
Ok(())
}
Error Handling Patterns¶
Comprehensive Error Handling¶
use airsprotocols_mcp::integration::{McpClient, McpError, McpResult};
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClient;
async fn error_handling_example(
client: &mut McpClient<StdioTransportClient>
) -> McpResult<()> {
match client.call_tool("calculator", Some(serde_json::json!({"operation": "divide", "a": 10, "b": 0}))).await {
Ok(result) => {
println!("Success: {:?}", result);
}
Err(McpError::Protocol(protocol_error)) => {
eprintln!("Protocol error: {}", protocol_error);
}
Err(McpError::Transport(transport_error)) => {
eprintln!("Transport error: {}", transport_error);
}
Err(McpError::Timeout) => {
eprintln!("Request timed out");
}
Err(McpError::InvalidState(msg)) => {
eprintln!("Invalid state: {}", msg);
}
Err(other) => {
eprintln!("Other error: {}", other);
}
}
Ok(())
}
Real-World Integration Patterns¶
Multi-Tool Workflow¶
use airsprotocols_mcp::integration::{McpClient, McpResult};
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClient;
use serde_json::json;
async fn multi_tool_workflow(
client: &mut McpClient<StdioTransportClient>
) -> McpResult<()> {
// Step 1: Get available tools
let tools = client.list_tools().await?;
println!("Found {} tools", tools.tools.len());
// Step 2: Find specific tools
let calculator = tools.tools.iter().find(|t| t.name == "calculator");
let text_processor = tools.tools.iter().find(|t| t.name == "text_processor");
if let Some(calc) = calculator {
// Step 3: Perform calculation
let calc_result = client.call_tool(
&calc.name,
Some(json!({"operation": "multiply", "a": 25, "b": 4}))
).await?;
println!("Calculation result: {:?}", calc_result);
// Step 4: Process the result with text tool
if let Some(processor) = text_processor {
let text_result = client.call_tool(
&processor.name,
Some(json!({
"action": "format",
"text": format!("The result is: {:?}", calc_result.content)
}))
).await?;
println!("Formatted result: {:?}", text_result);
}
}
Ok(())
}
Resource Management¶
use airsprotocols_mcp::integration::{McpClient, McpResult};
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClient;
async fn resource_management_example(
client: &mut McpClient<StdioTransportClient>
) -> McpResult<()> {
// List all available resources
let resources = client.list_resources().await?;
for resource in &resources.resources {
println!("Resource: {} ({})", resource.name, resource.uri);
// Read each resource
match client.read_resource(&resource.uri).await {
Ok(content) => {
println!(" Content type: {:?}", content.mimeType);
if let Some(text) = content.text {
println!(" Preview: {}...",
text.chars().take(100).collect::<String>());
}
}
Err(e) => {
eprintln!(" Failed to read: {}", e);
}
}
}
Ok(())
}
Transport Layer Patterns¶
Custom Configuration¶
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClientBuilder;
use std::time::Duration;
async fn custom_transport_config() -> Result<(), Box<dyn std::error::Error>> {
// Custom STDIO configuration
let transport = StdioTransportClientBuilder::new()
.command("python")
.args(vec!["-m".to_string(), "my_server".to_string()])
.timeout(Duration::from_secs(45))
.build()
.await?;
// Use the transport...
Ok(())
}
Testing Patterns¶
Mock Responses for Testing¶
use airsprotocols_mcp::{JsonRpcResponse, RequestId, JsonRpcMessageTrait};
use serde_json::json;
fn create_test_responses() -> Result<(), Box<dyn std::error::Error>> {
// Create success response
let success = JsonRpcResponse::success(
json!({"result": "operation completed", "data": [1, 2, 3]}),
RequestId::new_number(1)
);
// Create error response
let error = JsonRpcResponse::error(
json!({"code": -32602, "message": "Invalid params", "data": "Expected number"}),
Some(RequestId::new_number(2))
);
// Serialize for testing
let success_json = success.to_json()?;
let error_json = error.to_json()?;
println!("Success response: {}", success_json);
println!("Error response: {}", error_json);
Ok(())
}
Best Practices¶
Session Management¶
use airsprotocols_mcp::integration::{McpClientBuilder, McpSessionState, McpResult, McpError};
use airsprotocols_mcp::transport::adapters::stdio::StdioTransportClientBuilder;
use std::time::Duration;
async fn session_management_example() -> McpResult<()> {
let transport = StdioTransportClientBuilder::new()
.command("python")
.args(vec!["-m".to_string(), "my_server".to_string()])
.timeout(Duration::from_secs(30))
.build()
.await?;
let mut client = McpClientBuilder::new()
.client_info("session-client", "1.0.0")
.build(transport);
// Check session state before operations
match client.session_state() {
McpSessionState::NotInitialized => {
println!("Initializing session...");
client.initialize().await?;
}
McpSessionState::Ready => {
println!("Session already initialized");
}
McpSessionState::Initializing => {
println!("Session is initializing...");
// Wait or handle appropriately
}
McpSessionState::Failed => {
return Err(McpError::InvalidState("Session failed".to_string()));
}
}
// Perform operations...
let tools = client.list_tools().await?;
// Always clean up
client.close().await?;
Ok(())
}