turbomcp_protocol/lib.rs
1//! # TurboMCP Protocol
2//!
3//! Complete Model Context Protocol (MCP) implementation in Rust, providing all protocol types,
4//! traits, context management, and message handling for building MCP applications.
5//!
6//! ## What's Inside
7//!
8//! This crate provides everything needed for MCP:
9//!
10//! - **Types**: All MCP request/response types from the MCP 2025-06-18 specification
11//! - **Traits**: `ServerToClientRequests` for bidirectional communication
12//! - **Context**: Request and response context management with full observability
13//! - **JSON-RPC**: JSON-RPC 2.0 implementation with batching and notifications
14//! - **Validation**: JSON Schema validation with comprehensive constraints
15//! - **Error Handling**: Rich error types with context and tracing
16//! - **Message Handling**: Optimized message processing with zero-copy support
17//! - **Session Management**: Configurable LRU eviction and lifecycle management
18//! - **Zero-Copy**: Optional zero-copy optimizations for high performance
19//!
20//! ## Features
21//!
22//! ### Core Protocol Support
23//! - Complete MCP 2025-06-18 protocol implementation
24//! - JSON-RPC 2.0 support with batching and notifications
25//! - Type-safe capability negotiation and compatibility checking
26//! - Protocol versioning with backward compatibility
27//! - Fast serialization with SIMD acceleration
28//!
29//! ### Advanced Protocol Features
30//! - **Elicitation Protocol** - Server-initiated user input requests with rich schema validation
31//! - **Sampling Support** - Bidirectional LLM sampling with fully-typed interfaces
32//! - **Roots Protocol** - Filesystem boundaries with `roots/list` support
33//! - **Server-to-Client Requests** - Fully typed trait for sampling, elicitation, and roots
34//! - **Comprehensive Schema Builders** - Type-safe builders for all schema types
35//!
36//! ### Performance & Observability
37//! - **SIMD-Accelerated JSON** - Fast processing with `simd-json` and `sonic-rs`
38//! - **Zero-Copy Processing** - Memory-efficient message handling with `Bytes`
39//! - **Request Context** - Full request/response context tracking for observability
40//! - **Session Management** - Memory-bounded state management with cleanup tasks
41//! - **Observability Ready** - Built-in support for tracing and metrics collection
42//!
43//! ## Migration from v1.x
44//!
45//! In v2.0.0, `turbomcp-core` was merged into `turbomcp-protocol` to eliminate circular
46//! dependencies and enable fully-typed bidirectional communication.
47//!
48//! ```rust,ignore
49//! // v1.x
50//! use turbomcp_protocol::{RequestContext, Error};
51//! use turbomcp_protocol::types::CreateMessageRequest;
52//!
53//! // v2.0.0
54//! use turbomcp_protocol::{RequestContext, Error, types::CreateMessageRequest};
55//! ```
56//!
57//! All functionality is preserved, just the import path changed!
58//!
59//! ## Architecture
60//!
61//! ```text
62//! turbomcp-protocol/
63//! ├── error/ # Error types and handling
64//! ├── message/ # Message types and serialization
65//! ├── context/ # Request/response context with server capabilities
66//! ├── types/ # MCP protocol types
67//! ├── jsonrpc/ # JSON-RPC 2.0 implementation
68//! ├── validation/ # Schema validation
69//! ├── session/ # Session management
70//! ├── registry/ # Component registry
71//! └── utils/ # Utility functions
72//! ```
73//!
74//! ## Server-to-Client Communication
75//!
76//! The protocol provides a `ServerToClientRequests` trait that enables server-initiated requests
77//! to clients, supporting bidirectional communication patterns like sampling and elicitation:
78//!
79//! ```rust,no_run
80//! use turbomcp_protocol::{RequestContext, types::CreateMessageRequest, ServerToClientRequests};
81//!
82//! // Tools can access server capabilities through the context
83//! async fn my_tool(ctx: RequestContext) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
84//! if let Some(capabilities) = ctx.clone().server_to_client() {
85//! // Make a fully-typed sampling request to the client
86//! let request = CreateMessageRequest {
87//! messages: vec![/* ... */],
88//! max_tokens: 100,
89//! model_preferences: None,
90//! system_prompt: None,
91//! include_context: None,
92//! temperature: None,
93//! stop_sequences: None,
94//! _meta: None,
95//! };
96//! let response = capabilities.create_message(request, ctx).await?;
97//! }
98//! Ok(())
99//! }
100//! ```
101
102#![warn(
103 missing_docs,
104 missing_debug_implementations,
105 rust_2018_idioms,
106 unreachable_pub,
107 clippy::all
108)]
109#![cfg_attr(
110 all(not(feature = "mmap"), not(feature = "lock-free")),
111 deny(unsafe_code)
112)]
113#![cfg_attr(docsrs, feature(doc_cfg))]
114#![allow(
115 clippy::module_name_repetitions,
116 clippy::missing_errors_doc, // Error documentation in progress
117 clippy::cast_possible_truncation, // Intentional in metrics/performance code
118 clippy::cast_possible_wrap, // Intentional in metrics/performance code
119 clippy::cast_precision_loss, // Intentional for f64 metrics
120 clippy::cast_sign_loss, // Intentional for metrics
121 clippy::must_use_candidate, // Too pedantic for library APIs
122 clippy::return_self_not_must_use, // Constructor methods don't need must_use
123 clippy::struct_excessive_bools, // Sometimes bools are the right design
124 clippy::missing_panics_doc, // Panic docs added where genuinely needed
125 clippy::default_trait_access, // Default::default() is sometimes clearer
126 clippy::significant_drop_tightening, // Overly pedantic about drop timing
127 clippy::used_underscore_binding, // Sometimes underscore bindings are needed
128 clippy::wildcard_imports // Used in test modules
129)]
130
131// Core abstractions (merged from turbomcp-core in v2.0.0)
132/// Configuration for protocol components.
133pub mod config;
134/// Request/response context, including server-to-client capabilities.
135pub mod context;
136/// An advanced handler registry with metrics and enhanced features.
137pub mod enhanced_registry;
138/// Error types and handling for the protocol.
139pub mod error;
140/// Utilities for creating and working with protocol errors.
141pub mod error_utils;
142/// Traits and types for handling different MCP requests (tools, prompts, etc.).
143pub mod handlers;
144/// Lock-free data structures for high-performance concurrent scenarios.
145#[cfg(feature = "lock-free")]
146pub mod lock_free;
147/// Core message types and serialization logic.
148pub mod message;
149/// Basic handler registration and lookup.
150pub mod registry;
151/// Security-related utilities, such as path validation.
152pub mod security;
153/// Session management for client connections.
154pub mod session;
155/// Utilities for shared, concurrent state management.
156pub mod shared;
157/// State management for the protocol.
158pub mod state;
159/// General utility functions.
160pub mod utils;
161/// Zero-copy data handling utilities for performance-critical operations.
162pub mod zero_copy;
163
164// Protocol-specific modules
165/// Capability negotiation and management.
166pub mod capabilities;
167// Old elicitation module removed - use types::elicitation instead (MCP 2025-06-18 compliant)
168/// JSON-RPC 2.0 protocol implementation.
169pub mod jsonrpc;
170/// All MCP protocol types (requests, responses, and data structures).
171pub mod types;
172/// Schema validation for protocol messages.
173pub mod validation;
174/// Protocol version management and compatibility checking.
175pub mod versioning;
176
177// Test utilities (public to allow downstream crates to use them in tests)
178// Following the pattern from axum and tokio
179/// Public test utilities for use in downstream crates.
180pub mod test_helpers;
181
182// Re-export core types
183pub use context::{
184 BidirectionalContext, ClientCapabilities as ContextClientCapabilities, ClientId,
185 ClientIdExtractor, ClientSession, CommunicationDirection, CommunicationInitiator,
186 CompletionCapabilities, CompletionContext, CompletionOption,
187 CompletionReference as ContextCompletionReference, ConnectionMetrics, ElicitationContext,
188 ElicitationState, PingContext, PingOrigin, RequestContext, RequestContextExt, RequestInfo,
189 ResourceTemplateContext, ResponseContext, ServerInitiatedContext, ServerInitiatedType,
190 ServerToClientRequests, TemplateParameter,
191};
192// Timestamp and ContentType are now in types module
193pub use enhanced_registry::{EnhancedRegistry, HandlerStats};
194pub use error::{Error, ErrorContext, ErrorKind, Result, RetryInfo};
195pub use handlers::{
196 CompletionItem, CompletionProvider, ElicitationHandler, ElicitationResponse,
197 HandlerCapabilities, JsonRpcHandler, PingHandler, PingResponse, ResolvedResource,
198 ResourceTemplate as HandlerResourceTemplate, ResourceTemplateHandler, ServerInfo,
199 ServerInitiatedCapabilities, TemplateParam,
200};
201pub use message::{Message, MessageId, MessageMetadata};
202pub use registry::RegistryError;
203pub use security::{validate_file_extension, validate_path, validate_path_within};
204pub use session::{SessionAnalytics, SessionConfig, SessionManager};
205pub use shared::{ConsumableShared, Shareable, Shared, SharedError};
206pub use state::StateManager;
207
208// Re-export ONLY essential types at root (v2.0 - world-class DX)
209// Everything else requires module qualification: turbomcp_protocol::types::*
210pub use types::{
211 // Most common tool operations
212 CallToolRequest,
213 CallToolResult,
214
215 ClientCapabilities,
216 // Macro API types (used by generated code - not typically imported by users)
217 GetPromptRequest,
218 GetPromptResult,
219 // Most common request/response pairs (initialization flow)
220 InitializeRequest,
221 InitializeResult,
222
223 ReadResourceRequest,
224 ReadResourceResult,
225
226 // Capability negotiation (used in every initialize)
227 ServerCapabilities,
228};
229
230// Note: types module is already declared as `pub mod types;` above
231// Users access other types via turbomcp_protocol::types::Tool, etc.
232
233pub use jsonrpc::{
234 JsonRpcBatch, JsonRpcError, JsonRpcErrorCode, JsonRpcNotification, JsonRpcRequest,
235 JsonRpcResponse, JsonRpcVersion,
236};
237
238pub use capabilities::{
239 CapabilityMatcher, CapabilityNegotiator, CapabilitySet,
240 builders::{
241 ClientCapabilitiesBuilder, ClientCapabilitiesBuilderState, ServerCapabilitiesBuilder,
242 ServerCapabilitiesBuilderState,
243 },
244};
245
246pub use versioning::{VersionCompatibility, VersionManager, VersionRequirement};
247
248/// Alias for RequestContext for backward compatibility
249pub type Context = RequestContext;
250
251/// Current MCP protocol version supported by this SDK
252pub const PROTOCOL_VERSION: &str = "2025-06-18";
253
254/// Supported protocol versions for compatibility
255pub const SUPPORTED_VERSIONS: &[&str] = &["2025-06-18", "2025-03-26", "2024-11-05"];
256
257/// Maximum message size in bytes (1MB) - Reduced for security (DoS protection)
258pub const MAX_MESSAGE_SIZE: usize = 1024 * 1024;
259
260/// Default timeout for operations in milliseconds
261pub const DEFAULT_TIMEOUT_MS: u64 = 30_000;
262
263/// SDK version information
264pub const SDK_VERSION: &str = env!("CARGO_PKG_VERSION");
265
266/// SDK name identifier
267pub const SDK_NAME: &str = "turbomcp";
268
269/// Protocol feature flags
270pub mod features {
271 /// Tool calling capability
272 pub const TOOLS: &str = "tools";
273
274 /// Prompt capability
275 pub const PROMPTS: &str = "prompts";
276
277 /// Resource capability
278 pub const RESOURCES: &str = "resources";
279
280 /// Logging capability
281 pub const LOGGING: &str = "logging";
282
283 /// Progress notifications
284 pub const PROGRESS: &str = "progress";
285
286 /// Sampling capability
287 pub const SAMPLING: &str = "sampling";
288
289 /// Roots capability
290 pub const ROOTS: &str = "roots";
291}
292
293/// Protocol method names
294pub mod methods {
295 // Initialization
296 /// Initialize handshake method
297 pub const INITIALIZE: &str = "initialize";
298 /// Initialized notification method
299 pub const INITIALIZED: &str = "notifications/initialized";
300
301 // Tools
302 /// List available tools method
303 pub const LIST_TOOLS: &str = "tools/list";
304 /// Call a specific tool method
305 pub const CALL_TOOL: &str = "tools/call";
306
307 // Prompts
308 /// List available prompts method
309 pub const LIST_PROMPTS: &str = "prompts/list";
310 /// Get a specific prompt method
311 pub const GET_PROMPT: &str = "prompts/get";
312
313 // Resources
314 /// List available resources method
315 pub const LIST_RESOURCES: &str = "resources/list";
316 /// Read a specific resource method
317 pub const READ_RESOURCE: &str = "resources/read";
318 /// Subscribe to resource updates method
319 pub const SUBSCRIBE: &str = "resources/subscribe";
320 /// Unsubscribe from resource updates method
321 pub const UNSUBSCRIBE: &str = "resources/unsubscribe";
322 /// Resource updated notification
323 pub const RESOURCE_UPDATED: &str = "notifications/resources/updated";
324 /// Resource list changed notification
325 pub const RESOURCE_LIST_CHANGED: &str = "notifications/resources/list_changed";
326
327 // Logging
328 /// Set logging level method
329 pub const SET_LEVEL: &str = "logging/setLevel";
330 /// Log message notification
331 pub const LOG_MESSAGE: &str = "notifications/message";
332
333 // Progress
334 /// Progress update notification
335 pub const PROGRESS: &str = "notifications/progress";
336
337 // Sampling
338 /// Create sampling message method
339 pub const CREATE_MESSAGE: &str = "sampling/createMessage";
340
341 // Roots
342 /// List directory roots method
343 pub const LIST_ROOTS: &str = "roots/list";
344 /// Roots list changed notification
345 pub const ROOTS_LIST_CHANGED: &str = "notifications/roots/list_changed";
346}
347
348/// Protocol error codes (JSON-RPC standard + MCP extensions)
349pub mod error_codes {
350 // JSON-RPC standard errors
351 /// Parse error - Invalid JSON was received by the server
352 pub const PARSE_ERROR: i32 = -32700;
353 /// Invalid request - The JSON sent is not a valid Request object
354 pub const INVALID_REQUEST: i32 = -32600;
355 /// Method not found - The method does not exist / is not available
356 pub const METHOD_NOT_FOUND: i32 = -32601;
357 /// Invalid params - Invalid method parameter(s)
358 pub const INVALID_PARAMS: i32 = -32602;
359 /// Internal error - Internal JSON-RPC error
360 pub const INTERNAL_ERROR: i32 = -32603;
361
362 // MCP-specific errors (application-defined range)
363 /// Tool not found error
364 pub const TOOL_NOT_FOUND: i32 = -32001;
365 /// Tool execution error
366 pub const TOOL_EXECUTION_ERROR: i32 = -32002;
367 /// Prompt not found error
368 pub const PROMPT_NOT_FOUND: i32 = -32003;
369 /// Resource not found error
370 pub const RESOURCE_NOT_FOUND: i32 = -32004;
371 /// Resource access denied error
372 pub const RESOURCE_ACCESS_DENIED: i32 = -32005;
373 /// Capability not supported error
374 pub const CAPABILITY_NOT_SUPPORTED: i32 = -32006;
375 /// Protocol version mismatch error
376 pub const PROTOCOL_VERSION_MISMATCH: i32 = -32007;
377 /// Authentication required error
378 pub const AUTHENTICATION_REQUIRED: i32 = -32008;
379 /// Rate limited error
380 pub const RATE_LIMITED: i32 = -32009;
381 /// Server overloaded error
382 pub const SERVER_OVERLOADED: i32 = -32010;
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388
389 #[test]
390 fn test_version_constants() {
391 assert_eq!(PROTOCOL_VERSION, "2025-06-18");
392 assert!(SUPPORTED_VERSIONS.contains(&PROTOCOL_VERSION));
393 }
394
395 #[test]
396 fn test_size_constants() {
397 // Constants are statically verified at compile-time
398 const _: () = assert!(
399 MAX_MESSAGE_SIZE > 1024,
400 "MAX_MESSAGE_SIZE must be larger than 1KB"
401 );
402 const _: () = assert!(
403 MAX_MESSAGE_SIZE == 1024 * 1024,
404 "MAX_MESSAGE_SIZE must be 1MB for security"
405 );
406
407 const _: () = assert!(
408 DEFAULT_TIMEOUT_MS > 1000,
409 "DEFAULT_TIMEOUT_MS must be larger than 1 second"
410 );
411 const _: () = assert!(
412 DEFAULT_TIMEOUT_MS == 30_000,
413 "DEFAULT_TIMEOUT_MS must be 30 seconds"
414 );
415 }
416
417 #[test]
418 fn test_method_names() {
419 assert_eq!(methods::INITIALIZE, "initialize");
420 assert_eq!(methods::LIST_TOOLS, "tools/list");
421 assert_eq!(methods::CALL_TOOL, "tools/call");
422 }
423
424 #[test]
425 fn test_error_codes() {
426 assert_eq!(error_codes::PARSE_ERROR, -32700);
427 assert_eq!(error_codes::TOOL_NOT_FOUND, -32001);
428 }
429}