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::cast_possible_truncation,  // Intentional in metrics/performance code
117    clippy::cast_possible_wrap,  // Intentional in metrics/performance code
118    clippy::cast_precision_loss,  // Intentional for f64 metrics
119    clippy::cast_sign_loss,  // Intentional for metrics
120    clippy::must_use_candidate,  // Too pedantic for library APIs
121    clippy::return_self_not_must_use,  // Constructor methods don't need must_use
122    clippy::struct_excessive_bools,  // Sometimes bools are the right design
123    clippy::missing_panics_doc,  // Panic docs added where genuinely needed
124    clippy::default_trait_access,  // Default::default() is sometimes clearer
125    clippy::significant_drop_tightening,  // Overly pedantic about drop timing
126    clippy::used_underscore_binding,  // Sometimes underscore bindings are needed
127    clippy::wildcard_imports  // Used in test modules
128)]
129
130// Core abstractions (merged from turbomcp-core in v2.0.0)
131/// Configuration for protocol components.
132pub mod config;
133/// Request/response context, including server-to-client capabilities.
134pub mod context;
135/// An advanced handler registry with metrics and enhanced features.
136pub mod enhanced_registry;
137/// Error types and handling for the protocol.
138pub mod error;
139/// Utilities for creating and working with protocol errors.
140pub mod error_utils;
141/// Traits and types for handling different MCP requests (tools, prompts, etc.).
142pub mod handlers;
143/// Lock-free data structures for high-performance concurrent scenarios.
144#[cfg(feature = "lock-free")]
145pub mod lock_free;
146/// Core message types and serialization logic.
147pub mod message;
148/// Basic handler registration and lookup.
149pub mod registry;
150/// Security-related utilities, such as path validation.
151pub mod security;
152/// Session management for client connections.
153pub mod session;
154/// Utilities for shared, concurrent state management.
155pub mod shared;
156/// State management for the protocol.
157pub mod state;
158/// General utility functions.
159pub mod utils;
160/// Zero-copy data handling utilities for performance-critical operations.
161pub mod zero_copy;
162
163// Protocol-specific modules
164/// Capability negotiation and management.
165pub mod capabilities;
166// Old elicitation module removed - use types::elicitation instead (MCP 2025-06-18 compliant)
167/// JSON-RPC 2.0 protocol implementation.
168pub mod jsonrpc;
169/// All MCP protocol types (requests, responses, and data structures).
170pub mod types;
171/// Schema validation for protocol messages.
172pub mod validation;
173/// Protocol version management and compatibility checking.
174pub mod versioning;
175
176// Test utilities (public to allow downstream crates to use them in tests)
177// Following the pattern from axum and tokio
178/// Public test utilities for use in downstream crates.
179pub mod test_helpers;
180
181// Re-export core types
182pub use context::{
183    BidirectionalContext, ClientCapabilities as ContextClientCapabilities, ClientId,
184    ClientIdExtractor, ClientSession, CommunicationDirection, CommunicationInitiator,
185    CompletionCapabilities, CompletionContext, CompletionOption,
186    CompletionReference as ContextCompletionReference, ConnectionMetrics, ElicitationContext,
187    ElicitationState, PingContext, PingOrigin, RequestContext, RequestContextExt, RequestInfo,
188    ResourceTemplateContext, ResponseContext, ServerInitiatedContext, ServerInitiatedType,
189    ServerToClientRequests, TemplateParameter,
190};
191// Timestamp and ContentType are now in types module
192pub use enhanced_registry::{EnhancedRegistry, HandlerStats};
193pub use error::{Error, ErrorContext, ErrorKind, Result, RetryInfo};
194pub use handlers::{
195    CompletionItem, CompletionProvider, ElicitationHandler, ElicitationResponse,
196    HandlerCapabilities, JsonRpcHandler, PingHandler, PingResponse, ResolvedResource,
197    ResourceTemplate as HandlerResourceTemplate, ResourceTemplateHandler, ServerInfo,
198    ServerInitiatedCapabilities, TemplateParam,
199};
200pub use message::{Message, MessageId, MessageMetadata};
201pub use registry::RegistryError;
202pub use security::{validate_file_extension, validate_path, validate_path_within};
203pub use session::{SessionAnalytics, SessionConfig, SessionManager};
204pub use shared::{ConsumableShared, Shareable, Shared, SharedError};
205pub use state::StateManager;
206
207// Re-export ONLY essential types at root (v2.0 - improved ergonomics)
208// Everything else requires module qualification: turbomcp_protocol::types::*
209pub use types::{
210    // Most common tool operations
211    CallToolRequest,
212    CallToolResult,
213
214    ClientCapabilities,
215    // Macro API types (used by generated code - not typically imported by users)
216    GetPromptRequest,
217    GetPromptResult,
218    // Most common request/response pairs (initialization flow)
219    InitializeRequest,
220    InitializeResult,
221
222    ReadResourceRequest,
223    ReadResourceResult,
224
225    // Capability negotiation (used in every initialize)
226    ServerCapabilities,
227};
228
229// Note: types module is already declared as `pub mod types;` above
230// Users access other types via turbomcp_protocol::types::Tool, etc.
231
232// Allow deprecated on re-export - users importing JsonRpcBatch will still get deprecation warnings
233#[allow(deprecated)]
234pub use jsonrpc::{
235    JsonRpcBatch, JsonRpcError, JsonRpcErrorCode, JsonRpcNotification, JsonRpcRequest,
236    JsonRpcResponse, JsonRpcVersion,
237};
238
239pub use capabilities::{
240    CapabilityMatcher, CapabilityNegotiator, CapabilitySet,
241    builders::{
242        ClientCapabilitiesBuilder, ClientCapabilitiesBuilderState, ServerCapabilitiesBuilder,
243        ServerCapabilitiesBuilderState,
244    },
245};
246
247pub use versioning::{VersionCompatibility, VersionManager, VersionRequirement};
248
249/// Alias for RequestContext for backward compatibility
250pub type Context = RequestContext;
251
252/// Current MCP protocol version supported by this SDK
253pub const PROTOCOL_VERSION: &str = "2025-06-18";
254
255/// Supported protocol versions for compatibility
256pub const SUPPORTED_VERSIONS: &[&str] = &["2025-06-18", "2025-03-26", "2024-11-05"];
257
258/// Maximum message size in bytes (1MB) - Reduced for security (DoS protection)
259pub const MAX_MESSAGE_SIZE: usize = 1024 * 1024;
260
261/// Default timeout for operations in milliseconds
262pub const DEFAULT_TIMEOUT_MS: u64 = 30_000;
263
264/// SDK version information
265pub const SDK_VERSION: &str = env!("CARGO_PKG_VERSION");
266
267/// SDK name identifier
268pub const SDK_NAME: &str = "turbomcp";
269
270/// Protocol feature flags
271pub mod features {
272    /// Tool calling capability
273    pub const TOOLS: &str = "tools";
274
275    /// Prompt capability
276    pub const PROMPTS: &str = "prompts";
277
278    /// Resource capability
279    pub const RESOURCES: &str = "resources";
280
281    /// Logging capability
282    pub const LOGGING: &str = "logging";
283
284    /// Progress notifications
285    pub const PROGRESS: &str = "progress";
286
287    /// Sampling capability
288    pub const SAMPLING: &str = "sampling";
289
290    /// Roots capability
291    pub const ROOTS: &str = "roots";
292}
293
294/// Protocol method names
295pub mod methods {
296    // Initialization
297    /// Initialize handshake method
298    pub const INITIALIZE: &str = "initialize";
299    /// Initialized notification method
300    pub const INITIALIZED: &str = "notifications/initialized";
301
302    // Tools
303    /// List available tools method
304    pub const LIST_TOOLS: &str = "tools/list";
305    /// Call a specific tool method
306    pub const CALL_TOOL: &str = "tools/call";
307
308    // Prompts
309    /// List available prompts method
310    pub const LIST_PROMPTS: &str = "prompts/list";
311    /// Get a specific prompt method
312    pub const GET_PROMPT: &str = "prompts/get";
313
314    // Resources
315    /// List available resources method
316    pub const LIST_RESOURCES: &str = "resources/list";
317    /// Read a specific resource method
318    pub const READ_RESOURCE: &str = "resources/read";
319    /// Subscribe to resource updates method
320    pub const SUBSCRIBE: &str = "resources/subscribe";
321    /// Unsubscribe from resource updates method
322    pub const UNSUBSCRIBE: &str = "resources/unsubscribe";
323    /// Resource updated notification
324    pub const RESOURCE_UPDATED: &str = "notifications/resources/updated";
325    /// Resource list changed notification
326    pub const RESOURCE_LIST_CHANGED: &str = "notifications/resources/list_changed";
327
328    // Logging
329    /// Set logging level method
330    pub const SET_LEVEL: &str = "logging/setLevel";
331    /// Log message notification
332    pub const LOG_MESSAGE: &str = "notifications/message";
333
334    // Progress
335    /// Progress update notification
336    pub const PROGRESS: &str = "notifications/progress";
337
338    // Sampling
339    /// Create sampling message method
340    pub const CREATE_MESSAGE: &str = "sampling/createMessage";
341
342    // Roots
343    /// List directory roots method
344    pub const LIST_ROOTS: &str = "roots/list";
345    /// Roots list changed notification
346    pub const ROOTS_LIST_CHANGED: &str = "notifications/roots/list_changed";
347}
348
349/// Protocol error codes (JSON-RPC standard + MCP extensions)
350pub mod error_codes {
351    // JSON-RPC standard errors
352    /// Parse error - Invalid JSON was received by the server
353    pub const PARSE_ERROR: i32 = -32700;
354    /// Invalid request - The JSON sent is not a valid Request object
355    pub const INVALID_REQUEST: i32 = -32600;
356    /// Method not found - The method does not exist / is not available
357    pub const METHOD_NOT_FOUND: i32 = -32601;
358    /// Invalid params - Invalid method parameter(s)
359    pub const INVALID_PARAMS: i32 = -32602;
360    /// Internal error - Internal JSON-RPC error
361    pub const INTERNAL_ERROR: i32 = -32603;
362
363    // MCP-specific errors (application-defined range)
364    /// Tool not found error
365    pub const TOOL_NOT_FOUND: i32 = -32001;
366    /// Tool execution error
367    pub const TOOL_EXECUTION_ERROR: i32 = -32002;
368    /// Prompt not found error
369    pub const PROMPT_NOT_FOUND: i32 = -32003;
370    /// Resource not found error
371    pub const RESOURCE_NOT_FOUND: i32 = -32004;
372    /// Resource access denied error
373    pub const RESOURCE_ACCESS_DENIED: i32 = -32005;
374    /// Capability not supported error
375    pub const CAPABILITY_NOT_SUPPORTED: i32 = -32006;
376    /// Protocol version mismatch error
377    pub const PROTOCOL_VERSION_MISMATCH: i32 = -32007;
378    /// Authentication required error
379    pub const AUTHENTICATION_REQUIRED: i32 = -32008;
380    /// Rate limited error
381    pub const RATE_LIMITED: i32 = -32009;
382    /// Server overloaded error
383    pub const SERVER_OVERLOADED: i32 = -32010;
384}
385
386#[cfg(test)]
387mod tests {
388    use super::*;
389
390    #[test]
391    fn test_version_constants() {
392        assert_eq!(PROTOCOL_VERSION, "2025-06-18");
393        assert!(SUPPORTED_VERSIONS.contains(&PROTOCOL_VERSION));
394    }
395
396    #[test]
397    fn test_size_constants() {
398        // Constants are statically verified at compile-time
399        const _: () = assert!(
400            MAX_MESSAGE_SIZE > 1024,
401            "MAX_MESSAGE_SIZE must be larger than 1KB"
402        );
403        const _: () = assert!(
404            MAX_MESSAGE_SIZE == 1024 * 1024,
405            "MAX_MESSAGE_SIZE must be 1MB for security"
406        );
407
408        const _: () = assert!(
409            DEFAULT_TIMEOUT_MS > 1000,
410            "DEFAULT_TIMEOUT_MS must be larger than 1 second"
411        );
412        const _: () = assert!(
413            DEFAULT_TIMEOUT_MS == 30_000,
414            "DEFAULT_TIMEOUT_MS must be 30 seconds"
415        );
416    }
417
418    #[test]
419    fn test_method_names() {
420        assert_eq!(methods::INITIALIZE, "initialize");
421        assert_eq!(methods::LIST_TOOLS, "tools/list");
422        assert_eq!(methods::CALL_TOOL, "tools/call");
423    }
424
425    #[test]
426    fn test_error_codes() {
427        assert_eq!(error_codes::PARSE_ERROR, -32700);
428        assert_eq!(error_codes::TOOL_NOT_FOUND, -32001);
429    }
430}