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//! ## MCP Version Support
7//!
8//! TurboMCP supports multiple MCP specification versions:
9//!
10//! | Specification | Status | Feature Flag | Use Case |
11//! |---------------|--------|--------------|----------|
12//! | **MCP 2025-06-18** | โœ… Stable | (default) | Production systems |
13//! | **MCP 2025-11-25** | ๐Ÿšง Draft | `mcp-draft` | Experimental features |
14//!
15//! **Quick Start:**
16//! ```toml
17//! # Stable (recommended for production)
18//! turbomcp-protocol = "2.2"
19//!
20//! # Draft (experimental features)
21//! turbomcp-protocol = { version = "2.2", features = ["mcp-draft"] }
22//! ```
23//!
24//! See [Version Selection Guide](#version-selection) below for detailed guidance.
25//!
26//! ## What's Inside
27//!
28//! This crate provides everything needed for MCP:
29//!
30//! - **Types**: All MCP request/response types (2025-06-18 stable + 2025-11-25 draft)
31//! - **Traits**: `ServerToClientRequests` for bidirectional communication
32//! - **Context**: Request and response context management with full observability
33//! - **JSON-RPC**: JSON-RPC 2.0 implementation with batching and notifications
34//! - **Validation**: JSON Schema validation with comprehensive constraints
35//! - **Error Handling**: Rich error types with context and tracing
36//! - **Message Handling**: Optimized message processing with zero-copy support
37//! - **Session Management**: Configurable LRU eviction and lifecycle management
38//! - **Zero-Copy**: Optional zero-copy optimizations for high performance
39//!
40//! ## Features
41//!
42//! ### Core Protocol Support (MCP 2025-06-18 Stable)
43//! - Complete MCP 2025-06-18 protocol implementation
44//! - JSON-RPC 2.0 support with batching and notifications
45//! - Type-safe capability negotiation and compatibility checking
46//! - Protocol versioning with backward compatibility
47//! - Fast serialization with SIMD acceleration
48//!
49//! ### Advanced Protocol Features (MCP 2025-06-18 Stable)
50//! - **Elicitation Protocol** - Server-initiated user input requests with rich schema validation
51//! - **Sampling Support** - Bidirectional LLM sampling with fully-typed interfaces
52//! - **Roots Protocol** - Filesystem boundaries with `roots/list` support
53//! - **Server-to-Client Requests** - Fully typed trait for sampling, elicitation, and roots
54//! - **Comprehensive Schema Builders** - Type-safe builders for all schema types
55//!
56//! ### Draft Specification Features (MCP 2025-11-25)
57//!
58//! Enable with `features = ["mcp-draft"]` or individual feature flags:
59//!
60//! | Feature Flag | SEP | Description |
61//! |-------------|-----|-------------|
62//! | `mcp-url-elicitation` | SEP-1036 | URL mode for OAuth/sensitive data |
63//! | `mcp-sampling-tools` | SEP-1577 | Tool calling in LLM sampling |
64//! | `mcp-icons` | SEP-973 | Icon metadata for UI |
65//! | `mcp-enum-improvements` | SEP-1330 | Standards-based enum schemas |
66//! | `mcp-tasks` | SEP-1686 | Experimental tasks API |
67//!
68//! **Authentication & Security** (always enabled):
69//! - SSRF protection for URL validation
70//! - Client ID Metadata Documents (CIMD) for OAuth 2.1
71//! - OpenID Connect Discovery (RFC 8414 + OIDC 1.0)
72//! - Incremental consent with WWW-Authenticate (SEP-835)
73//!
74//! ### Performance & Observability
75//! - **SIMD-Accelerated JSON** - Fast processing with `simd-json` and `sonic-rs`
76//! - **Zero-Copy Processing** - Memory-efficient message handling with `Bytes`
77//! - **Request Context** - Full request/response context tracking for observability
78//! - **Session Management** - Memory-bounded state management with cleanup tasks
79//! - **Observability Ready** - Built-in support for tracing and metrics collection
80//!
81//! ## Version Selection
82//!
83//! ### When to Use Each Version
84//!
85//! **MCP 2025-06-18 (Stable - Recommended for Production):**
86//! - โœ… Production systems requiring stability
87//! - โœ… Maximum interoperability with existing MCP implementations
88//! - โœ… Long-term API stability guarantees
89//! - โœ… Well-tested, battle-hardened features
90//!
91//! **MCP 2025-11-25 (Draft - Experimental):**
92//! - ๐Ÿงช Experimenting with cutting-edge features
93//! - ๐Ÿงช Advanced capabilities (multi-select forms, tasks API, etc.)
94//! - ๐Ÿงช Contributing to MCP specification development
95//! - โš ๏ธ Accept potential breaking changes in future releases
96//!
97//! ### Feature Flag Selection
98//!
99//! **All draft features:**
100//! ```toml
101//! [dependencies]
102//! turbomcp-protocol = { version = "2.2", features = ["mcp-draft"] }
103//! ```
104//!
105//! **Selective draft features (recommended):**
106//! ```toml
107//! [dependencies]
108//! turbomcp-protocol = { version = "2.2", features = [
109//!     "mcp-url-elicitation",    # Need OAuth/sensitive data support
110//!     "mcp-sampling-tools",     # Need tool calling in sampling
111//!     "mcp-icons",              # Want icon metadata
112//! ] }
113//! ```
114//!
115//! ### Runtime Version Negotiation
116//!
117//! Clients and servers negotiate protocol versions during initialization:
118//!
119//! ```rust,no_run
120//! use turbomcp_protocol::{InitializeRequest, InitializeResult, ClientCapabilities};
121//! use turbomcp_protocol::types::{Implementation, ServerCapabilities}; // Corrected import path
122//!
123//! // Client requests draft features
124//! let request = InitializeRequest {
125//!     protocol_version: "2025-11-25".into(),  // Request draft
126//!     capabilities: ClientCapabilities::default(),
127//!     client_info: Implementation {
128//!         name: "my-client".to_string(),
129//!         title: None,
130//!         version: "1.0.0".to_string(),
131//!         ..Default::default()
132//!     },
133//!     _meta: None,
134//! };
135//!
136//! // Server responds with actual supported version
137//! // (may downgrade to 2025-06-18 if draft features unavailable)
138//! let response = InitializeResult {
139//!     protocol_version: "2025-11-25".into(),
140//!     capabilities: ServerCapabilities::default(),
141//!     server_info: Implementation {
142//!         name: "my-server".to_string(),
143//!         title: None,
144//!         version: "1.0.0".to_string(),
145//!         ..Default::default()
146//!     },
147//!     instructions: None,
148//!     _meta: None,
149//! };
150//! ```
151//!
152//! **Key Principle:** Clients request, servers decide. The negotiated version is the server's response.
153//!
154//! ## Migration from v1.x
155//!
156//! In v2.0.0, `turbomcp-core` was merged into `turbomcp-protocol` to eliminate circular
157//! dependencies and enable fully-typed bidirectional communication.
158//!
159//! ```rust,ignore
160//! // v1.x
161//! use turbomcp_protocol::{RequestContext, Error};
162//! use turbomcp_protocol::types::CreateMessageRequest;
163//!
164//! // v2.0.0
165//! use turbomcp_protocol::{RequestContext, Error, types::CreateMessageRequest};
166//! ```
167//!
168//! All functionality is preserved, just the import path changed!
169//!
170//! ## Architecture
171//!
172//! ```text
173//! turbomcp-protocol/
174//! โ”œโ”€โ”€ error/              # Error types and handling
175//! โ”œโ”€โ”€ message/            # Message types and serialization
176//! โ”œโ”€โ”€ context/            # Request/response context with server capabilities
177//! โ”œโ”€โ”€ types/              # MCP protocol types
178//! โ”œโ”€โ”€ jsonrpc/            # JSON-RPC 2.0 implementation
179//! โ”œโ”€โ”€ validation/         # Schema validation
180//! โ”œโ”€โ”€ session/            # Session management
181//! โ”œโ”€โ”€ registry/           # Component registry
182//! โ””โ”€โ”€ utils/              # Utility functions
183//! ```
184//!
185//! ## Server-to-Client Communication
186//!
187//! The protocol provides a `ServerToClientRequests` trait that enables server-initiated requests
188//! to clients, supporting bidirectional communication patterns like sampling and elicitation:
189//!
190//! ```rust,no_run
191//! use turbomcp_protocol::{RequestContext, types::CreateMessageRequest, ServerToClientRequests};
192//!
193//! // Tools can access server capabilities through the context
194//! async fn my_tool(ctx: RequestContext) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
195//!     if let Some(capabilities) = ctx.clone().server_to_client() {
196//!         // Make a fully-typed sampling request to the client
197//!         let request = CreateMessageRequest {
198//!             messages: vec![/* ... */],
199//!             max_tokens: 100,
200//!             model_preferences: None,
201//!             system_prompt: None,
202//!             include_context: None,
203//!             temperature: None,
204//!             stop_sequences: None,
205//!             task: None,
206//!             _meta: None,
207//!         };
208//!         let response = capabilities.create_message(request, ctx).await?;
209//!     }
210//!     Ok(())
211//! }
212//! ```
213
214#![warn(
215    missing_docs,
216    missing_debug_implementations,
217    rust_2018_idioms,
218    unreachable_pub,
219    clippy::all
220)]
221#![cfg_attr(
222    all(not(feature = "mmap"), not(feature = "lock-free")),
223    deny(unsafe_code)
224)]
225#![cfg_attr(docsrs, feature(doc_cfg))]
226#![allow(
227    clippy::module_name_repetitions,
228    clippy::cast_possible_truncation,  // Intentional in metrics/performance code
229    clippy::cast_possible_wrap,  // Intentional in metrics/performance code
230    clippy::cast_precision_loss,  // Intentional for f64 metrics
231    clippy::cast_sign_loss,  // Intentional for metrics
232    clippy::must_use_candidate,  // Too pedantic for library APIs
233    clippy::return_self_not_must_use,  // Constructor methods don't need must_use
234    clippy::struct_excessive_bools,  // Sometimes bools are the right design
235    clippy::missing_panics_doc,  // Panic docs added where genuinely needed
236    clippy::default_trait_access,  // Default::default() is sometimes clearer
237    clippy::significant_drop_tightening,  // Overly pedantic about drop timing
238    clippy::used_underscore_binding,  // Sometimes underscore bindings are needed
239    clippy::wildcard_imports  // Used in test modules
240)]
241
242// Core abstractions (merged from turbomcp-core in v2.0.0)
243/// Configuration for protocol components.
244pub mod config;
245/// Request/response context, including server-to-client capabilities.
246pub mod context;
247/// An advanced handler registry with metrics and enhanced features.
248pub mod enhanced_registry;
249/// Error types and handling for the protocol.
250pub mod error;
251/// Utilities for creating and working with protocol errors.
252pub mod error_utils;
253/// Traits and types for handling different MCP requests (tools, prompts, etc.).
254pub mod handlers;
255/// Lock-free data structures for high-performance concurrent scenarios.
256#[cfg(feature = "lock-free")]
257pub mod lock_free;
258/// Core message types and serialization logic.
259pub mod message;
260/// Basic handler registration and lookup.
261pub mod registry;
262/// Security-related utilities, such as path validation.
263pub mod security;
264/// Session management for client connections.
265pub mod session;
266/// Utilities for shared, concurrent state management.
267pub mod shared;
268/// State management for the protocol.
269pub mod state;
270/// General utility functions.
271pub mod utils;
272/// Zero-copy data handling utilities for performance-critical operations.
273pub mod zero_copy;
274
275// Protocol-specific modules
276/// Capability negotiation and management.
277pub mod capabilities;
278// Old elicitation module removed - use types::elicitation instead (MCP 2025-06-18 compliant)
279/// JSON-RPC 2.0 protocol implementation.
280pub mod jsonrpc;
281/// All MCP protocol types (requests, responses, and data structures).
282pub mod types;
283/// Schema validation for protocol messages.
284pub mod validation;
285/// Protocol version management and compatibility checking.
286pub mod versioning;
287
288// Test utilities (public to allow downstream crates to use them in tests)
289// Following the pattern from axum and tokio
290/// Public test utilities for use in downstream crates.
291pub mod test_helpers;
292
293// Re-export core types
294pub use context::{
295    BidirectionalContext, ClientCapabilities as ContextClientCapabilities, ClientId,
296    ClientIdExtractor, ClientSession, CommunicationDirection, CommunicationInitiator,
297    CompletionCapabilities, CompletionContext, CompletionOption,
298    CompletionReference as ContextCompletionReference, ConnectionMetrics, ElicitationContext,
299    ElicitationState, PingContext, PingOrigin, RequestContext, RequestContextExt, RequestInfo,
300    ResourceTemplateContext, ResponseContext, ServerInitiatedContext, ServerInitiatedType,
301    ServerToClientRequests, TemplateParameter,
302};
303// Timestamp and ContentType are now in types module
304pub use enhanced_registry::{EnhancedRegistry, HandlerStats};
305pub use error::{Error, ErrorContext, ErrorKind, Result, RetryInfo};
306pub use handlers::{
307    CompletionItem, CompletionProvider, ElicitationHandler, ElicitationResponse,
308    HandlerCapabilities, JsonRpcHandler, PingHandler, PingResponse, ResolvedResource,
309    ResourceTemplate as HandlerResourceTemplate, ResourceTemplateHandler, ServerInfo,
310    ServerInitiatedCapabilities, TemplateParam,
311};
312pub use message::{Message, MessageId, MessageMetadata};
313pub use registry::RegistryError;
314pub use security::{validate_file_extension, validate_path, validate_path_within};
315pub use session::{SessionAnalytics, SessionConfig, SessionManager};
316pub use shared::{ConsumableShared, Shareable, Shared, SharedError};
317pub use state::StateManager;
318
319// Re-export ONLY essential types at root (v2.0 - improved ergonomics)
320// Everything else requires module qualification: turbomcp_protocol::types::*
321pub use types::{
322    // Most common tool operations
323    CallToolRequest,
324    CallToolResult,
325
326    ClientCapabilities,
327    // Macro API types (used by generated code - not typically imported by users)
328    GetPromptRequest,
329    GetPromptResult,
330    // Most common request/response pairs (initialization flow)
331    InitializeRequest,
332    InitializeResult,
333
334    ReadResourceRequest,
335    ReadResourceResult,
336
337    // Capability negotiation (used in every initialize)
338    ServerCapabilities,
339};
340
341// Note: types module is already declared as `pub mod types;` above
342// Users access other types via turbomcp_protocol::types::Tool, etc.
343
344// Allow deprecated on re-export - users importing JsonRpcBatch will still get deprecation warnings
345#[allow(deprecated)]
346pub use jsonrpc::{
347    JsonRpcBatch, JsonRpcError, JsonRpcErrorCode, JsonRpcNotification, JsonRpcRequest,
348    JsonRpcResponse, JsonRpcVersion,
349};
350
351pub use capabilities::{
352    CapabilityMatcher, CapabilityNegotiator, CapabilitySet,
353    builders::{
354        ClientCapabilitiesBuilder, ClientCapabilitiesBuilderState, ServerCapabilitiesBuilder,
355        ServerCapabilitiesBuilderState,
356    },
357};
358
359pub use versioning::{VersionCompatibility, VersionManager, VersionRequirement};
360
361/// Alias for RequestContext for backward compatibility
362pub type Context = RequestContext;
363
364/// Current MCP protocol version supported by this SDK (latest official spec)
365pub const PROTOCOL_VERSION: &str = "2025-11-25";
366
367/// Supported protocol versions in preference order (latest first)
368/// Server will negotiate down this list if client doesn't support preferred version
369pub const SUPPORTED_VERSIONS: &[&str] = &["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
370
371/// Maximum message size in bytes (1MB) - Reduced for security (DoS protection)
372pub const MAX_MESSAGE_SIZE: usize = 1024 * 1024;
373
374/// Default timeout for operations in milliseconds
375pub const DEFAULT_TIMEOUT_MS: u64 = 30_000;
376
377/// SDK version information
378pub const SDK_VERSION: &str = env!("CARGO_PKG_VERSION");
379
380/// SDK name identifier
381pub const SDK_NAME: &str = "turbomcp";
382
383/// Protocol feature flags
384pub mod features {
385    /// Tool calling capability
386    pub const TOOLS: &str = "tools";
387
388    /// Prompt capability
389    pub const PROMPTS: &str = "prompts";
390
391    /// Resource capability
392    pub const RESOURCES: &str = "resources";
393
394    /// Logging capability
395    pub const LOGGING: &str = "logging";
396
397    /// Progress notifications
398    pub const PROGRESS: &str = "progress";
399
400    /// Sampling capability
401    pub const SAMPLING: &str = "sampling";
402
403    /// Roots capability
404    pub const ROOTS: &str = "roots";
405}
406
407/// Protocol method names
408pub mod methods {
409    // Initialization
410    /// Initialize handshake method
411    pub const INITIALIZE: &str = "initialize";
412    /// Initialized notification method
413    pub const INITIALIZED: &str = "notifications/initialized";
414
415    // Tools
416    /// List available tools method
417    pub const LIST_TOOLS: &str = "tools/list";
418    /// Call a specific tool method
419    pub const CALL_TOOL: &str = "tools/call";
420
421    // Prompts
422    /// List available prompts method
423    pub const LIST_PROMPTS: &str = "prompts/list";
424    /// Get a specific prompt method
425    pub const GET_PROMPT: &str = "prompts/get";
426
427    // Resources
428    /// List available resources method
429    pub const LIST_RESOURCES: &str = "resources/list";
430    /// Read a specific resource method
431    pub const READ_RESOURCE: &str = "resources/read";
432    /// Subscribe to resource updates method
433    pub const SUBSCRIBE: &str = "resources/subscribe";
434    /// Unsubscribe from resource updates method
435    pub const UNSUBSCRIBE: &str = "resources/unsubscribe";
436    /// Resource updated notification
437    pub const RESOURCE_UPDATED: &str = "notifications/resources/updated";
438    /// Resource list changed notification
439    pub const RESOURCE_LIST_CHANGED: &str = "notifications/resources/list_changed";
440
441    // Logging
442    /// Set logging level method
443    pub const SET_LEVEL: &str = "logging/setLevel";
444    /// Log message notification
445    pub const LOG_MESSAGE: &str = "notifications/message";
446
447    // Progress
448    /// Progress update notification
449    pub const PROGRESS: &str = "notifications/progress";
450
451    // Sampling
452    /// Create sampling message method
453    pub const CREATE_MESSAGE: &str = "sampling/createMessage";
454
455    // Roots
456    /// List directory roots method
457    pub const LIST_ROOTS: &str = "roots/list";
458    /// Roots list changed notification
459    pub const ROOTS_LIST_CHANGED: &str = "notifications/roots/list_changed";
460}
461
462/// Protocol error codes (JSON-RPC standard + MCP extensions)
463pub mod error_codes {
464    // JSON-RPC standard errors
465    /// Parse error - Invalid JSON was received by the server
466    pub const PARSE_ERROR: i32 = -32700;
467    /// Invalid request - The JSON sent is not a valid Request object
468    pub const INVALID_REQUEST: i32 = -32600;
469    /// Method not found - The method does not exist / is not available
470    pub const METHOD_NOT_FOUND: i32 = -32601;
471    /// Invalid params - Invalid method parameter(s)
472    pub const INVALID_PARAMS: i32 = -32602;
473    /// Internal error - Internal JSON-RPC error
474    pub const INTERNAL_ERROR: i32 = -32603;
475
476    // Implementation-specific JSON-RPC errors (reserved range -32000 to -32099)
477    /// URL elicitation required - Server requires client to provide info via URL elicitation
478    pub const URL_ELICITATION_REQUIRED: i32 = -32042;
479
480    // MCP-specific errors (application-defined range)
481    /// Tool not found error
482    pub const TOOL_NOT_FOUND: i32 = -32001;
483    /// Tool execution error
484    pub const TOOL_EXECUTION_ERROR: i32 = -32002;
485    /// Prompt not found error
486    pub const PROMPT_NOT_FOUND: i32 = -32003;
487    /// Resource not found error
488    pub const RESOURCE_NOT_FOUND: i32 = -32004;
489    /// Resource access denied error
490    pub const RESOURCE_ACCESS_DENIED: i32 = -32005;
491    /// Capability not supported error
492    pub const CAPABILITY_NOT_SUPPORTED: i32 = -32006;
493    /// Protocol version mismatch error
494    pub const PROTOCOL_VERSION_MISMATCH: i32 = -32007;
495    /// Authentication required error
496    pub const AUTHENTICATION_REQUIRED: i32 = -32008;
497    /// Rate limited error
498    pub const RATE_LIMITED: i32 = -32009;
499    /// Server overloaded error
500    pub const SERVER_OVERLOADED: i32 = -32010;
501}
502
503#[cfg(test)]
504mod tests {
505    use super::*;
506
507    #[test]
508    fn test_version_constants() {
509        assert_eq!(PROTOCOL_VERSION, "2025-11-25");
510        assert!(SUPPORTED_VERSIONS.contains(&PROTOCOL_VERSION));
511        // Latest should be first in supported versions
512        assert_eq!(SUPPORTED_VERSIONS[0], PROTOCOL_VERSION);
513    }
514
515    #[test]
516    fn test_size_constants() {
517        // Constants are statically verified at compile-time
518        const _: () = assert!(
519            MAX_MESSAGE_SIZE > 1024,
520            "MAX_MESSAGE_SIZE must be larger than 1KB"
521        );
522        const _: () = assert!(
523            MAX_MESSAGE_SIZE == 1024 * 1024,
524            "MAX_MESSAGE_SIZE must be 1MB for security"
525        );
526
527        const _: () = assert!(
528            DEFAULT_TIMEOUT_MS > 1000,
529            "DEFAULT_TIMEOUT_MS must be larger than 1 second"
530        );
531        const _: () = assert!(
532            DEFAULT_TIMEOUT_MS == 30_000,
533            "DEFAULT_TIMEOUT_MS must be 30 seconds"
534        );
535    }
536
537    #[test]
538    fn test_method_names() {
539        assert_eq!(methods::INITIALIZE, "initialize");
540        assert_eq!(methods::LIST_TOOLS, "tools/list");
541        assert_eq!(methods::CALL_TOOL, "tools/call");
542    }
543
544    #[test]
545    fn test_error_codes() {
546        assert_eq!(error_codes::PARSE_ERROR, -32700);
547        assert_eq!(error_codes::TOOL_NOT_FOUND, -32001);
548    }
549}