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//!     },
132//!     _meta: None,
133//! };
134//!
135//! // Server responds with actual supported version
136//! // (may downgrade to 2025-06-18 if draft features unavailable)
137//! let response = InitializeResult {
138//!     protocol_version: "2025-11-25".into(),
139//!     capabilities: ServerCapabilities::default(),
140//!     server_info: Implementation {
141//!         name: "my-server".to_string(),
142//!         title: None,
143//!         version: "1.0.0".to_string(),
144//!     },
145//!     instructions: None,
146//!     _meta: None,
147//! };
148//! ```
149//!
150//! **Key Principle:** Clients request, servers decide. The negotiated version is the server's response.
151//!
152//! ## Migration from v1.x
153//!
154//! In v2.0.0, `turbomcp-core` was merged into `turbomcp-protocol` to eliminate circular
155//! dependencies and enable fully-typed bidirectional communication.
156//!
157//! ```rust,ignore
158//! // v1.x
159//! use turbomcp_protocol::{RequestContext, Error};
160//! use turbomcp_protocol::types::CreateMessageRequest;
161//!
162//! // v2.0.0
163//! use turbomcp_protocol::{RequestContext, Error, types::CreateMessageRequest};
164//! ```
165//!
166//! All functionality is preserved, just the import path changed!
167//!
168//! ## Architecture
169//!
170//! ```text
171//! turbomcp-protocol/
172//! โ”œโ”€โ”€ error/              # Error types and handling
173//! โ”œโ”€โ”€ message/            # Message types and serialization
174//! โ”œโ”€โ”€ context/            # Request/response context with server capabilities
175//! โ”œโ”€โ”€ types/              # MCP protocol types
176//! โ”œโ”€โ”€ jsonrpc/            # JSON-RPC 2.0 implementation
177//! โ”œโ”€โ”€ validation/         # Schema validation
178//! โ”œโ”€โ”€ session/            # Session management
179//! โ”œโ”€โ”€ registry/           # Component registry
180//! โ””โ”€โ”€ utils/              # Utility functions
181//! ```
182//!
183//! ## Server-to-Client Communication
184//!
185//! The protocol provides a `ServerToClientRequests` trait that enables server-initiated requests
186//! to clients, supporting bidirectional communication patterns like sampling and elicitation:
187//!
188//! ```rust,no_run
189//! use turbomcp_protocol::{RequestContext, types::CreateMessageRequest, ServerToClientRequests};
190//!
191//! // Tools can access server capabilities through the context
192//! async fn my_tool(ctx: RequestContext) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
193//!     if let Some(capabilities) = ctx.clone().server_to_client() {
194//!         // Make a fully-typed sampling request to the client
195//!         let request = CreateMessageRequest {
196//!             messages: vec![/* ... */],
197//!             max_tokens: 100,
198//!             model_preferences: None,
199//!             system_prompt: None,
200//!             include_context: None,
201//!             temperature: None,
202//!             stop_sequences: None,
203//!             _meta: None,
204//!         };
205//!         let response = capabilities.create_message(request, ctx).await?;
206//!     }
207//!     Ok(())
208//! }
209//! ```
210
211#![warn(
212    missing_docs,
213    missing_debug_implementations,
214    rust_2018_idioms,
215    unreachable_pub,
216    clippy::all
217)]
218#![cfg_attr(
219    all(not(feature = "mmap"), not(feature = "lock-free")),
220    deny(unsafe_code)
221)]
222#![cfg_attr(docsrs, feature(doc_cfg))]
223#![allow(
224    clippy::module_name_repetitions,
225    clippy::cast_possible_truncation,  // Intentional in metrics/performance code
226    clippy::cast_possible_wrap,  // Intentional in metrics/performance code
227    clippy::cast_precision_loss,  // Intentional for f64 metrics
228    clippy::cast_sign_loss,  // Intentional for metrics
229    clippy::must_use_candidate,  // Too pedantic for library APIs
230    clippy::return_self_not_must_use,  // Constructor methods don't need must_use
231    clippy::struct_excessive_bools,  // Sometimes bools are the right design
232    clippy::missing_panics_doc,  // Panic docs added where genuinely needed
233    clippy::default_trait_access,  // Default::default() is sometimes clearer
234    clippy::significant_drop_tightening,  // Overly pedantic about drop timing
235    clippy::used_underscore_binding,  // Sometimes underscore bindings are needed
236    clippy::wildcard_imports  // Used in test modules
237)]
238
239// Core abstractions (merged from turbomcp-core in v2.0.0)
240/// Configuration for protocol components.
241pub mod config;
242/// Request/response context, including server-to-client capabilities.
243pub mod context;
244/// An advanced handler registry with metrics and enhanced features.
245pub mod enhanced_registry;
246/// Error types and handling for the protocol.
247pub mod error;
248/// Utilities for creating and working with protocol errors.
249pub mod error_utils;
250/// Traits and types for handling different MCP requests (tools, prompts, etc.).
251pub mod handlers;
252/// Lock-free data structures for high-performance concurrent scenarios.
253#[cfg(feature = "lock-free")]
254pub mod lock_free;
255/// Core message types and serialization logic.
256pub mod message;
257/// Basic handler registration and lookup.
258pub mod registry;
259/// Security-related utilities, such as path validation.
260pub mod security;
261/// Session management for client connections.
262pub mod session;
263/// Utilities for shared, concurrent state management.
264pub mod shared;
265/// State management for the protocol.
266pub mod state;
267/// General utility functions.
268pub mod utils;
269/// Zero-copy data handling utilities for performance-critical operations.
270pub mod zero_copy;
271
272// Protocol-specific modules
273/// Capability negotiation and management.
274pub mod capabilities;
275// Old elicitation module removed - use types::elicitation instead (MCP 2025-06-18 compliant)
276/// JSON-RPC 2.0 protocol implementation.
277pub mod jsonrpc;
278/// All MCP protocol types (requests, responses, and data structures).
279pub mod types;
280/// Schema validation for protocol messages.
281pub mod validation;
282/// Protocol version management and compatibility checking.
283pub mod versioning;
284
285// Test utilities (public to allow downstream crates to use them in tests)
286// Following the pattern from axum and tokio
287/// Public test utilities for use in downstream crates.
288pub mod test_helpers;
289
290// Re-export core types
291pub use context::{
292    BidirectionalContext, ClientCapabilities as ContextClientCapabilities, ClientId,
293    ClientIdExtractor, ClientSession, CommunicationDirection, CommunicationInitiator,
294    CompletionCapabilities, CompletionContext, CompletionOption,
295    CompletionReference as ContextCompletionReference, ConnectionMetrics, ElicitationContext,
296    ElicitationState, PingContext, PingOrigin, RequestContext, RequestContextExt, RequestInfo,
297    ResourceTemplateContext, ResponseContext, ServerInitiatedContext, ServerInitiatedType,
298    ServerToClientRequests, TemplateParameter,
299};
300// Timestamp and ContentType are now in types module
301pub use enhanced_registry::{EnhancedRegistry, HandlerStats};
302pub use error::{Error, ErrorContext, ErrorKind, Result, RetryInfo};
303pub use handlers::{
304    CompletionItem, CompletionProvider, ElicitationHandler, ElicitationResponse,
305    HandlerCapabilities, JsonRpcHandler, PingHandler, PingResponse, ResolvedResource,
306    ResourceTemplate as HandlerResourceTemplate, ResourceTemplateHandler, ServerInfo,
307    ServerInitiatedCapabilities, TemplateParam,
308};
309pub use message::{Message, MessageId, MessageMetadata};
310pub use registry::RegistryError;
311pub use security::{validate_file_extension, validate_path, validate_path_within};
312pub use session::{SessionAnalytics, SessionConfig, SessionManager};
313pub use shared::{ConsumableShared, Shareable, Shared, SharedError};
314pub use state::StateManager;
315
316// Re-export ONLY essential types at root (v2.0 - improved ergonomics)
317// Everything else requires module qualification: turbomcp_protocol::types::*
318pub use types::{
319    // Most common tool operations
320    CallToolRequest,
321    CallToolResult,
322
323    ClientCapabilities,
324    // Macro API types (used by generated code - not typically imported by users)
325    GetPromptRequest,
326    GetPromptResult,
327    // Most common request/response pairs (initialization flow)
328    InitializeRequest,
329    InitializeResult,
330
331    ReadResourceRequest,
332    ReadResourceResult,
333
334    // Capability negotiation (used in every initialize)
335    ServerCapabilities,
336};
337
338// Note: types module is already declared as `pub mod types;` above
339// Users access other types via turbomcp_protocol::types::Tool, etc.
340
341// Allow deprecated on re-export - users importing JsonRpcBatch will still get deprecation warnings
342#[allow(deprecated)]
343pub use jsonrpc::{
344    JsonRpcBatch, JsonRpcError, JsonRpcErrorCode, JsonRpcNotification, JsonRpcRequest,
345    JsonRpcResponse, JsonRpcVersion,
346};
347
348pub use capabilities::{
349    CapabilityMatcher, CapabilityNegotiator, CapabilitySet,
350    builders::{
351        ClientCapabilitiesBuilder, ClientCapabilitiesBuilderState, ServerCapabilitiesBuilder,
352        ServerCapabilitiesBuilderState,
353    },
354};
355
356pub use versioning::{VersionCompatibility, VersionManager, VersionRequirement};
357
358/// Alias for RequestContext for backward compatibility
359pub type Context = RequestContext;
360
361/// Current MCP protocol version supported by this SDK
362pub const PROTOCOL_VERSION: &str = "2025-11-25";
363
364/// Supported protocol versions for compatibility
365pub const SUPPORTED_VERSIONS: &[&str] = &["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
366
367/// Maximum message size in bytes (1MB) - Reduced for security (DoS protection)
368pub const MAX_MESSAGE_SIZE: usize = 1024 * 1024;
369
370/// Default timeout for operations in milliseconds
371pub const DEFAULT_TIMEOUT_MS: u64 = 30_000;
372
373/// SDK version information
374pub const SDK_VERSION: &str = env!("CARGO_PKG_VERSION");
375
376/// SDK name identifier
377pub const SDK_NAME: &str = "turbomcp";
378
379/// Protocol feature flags
380pub mod features {
381    /// Tool calling capability
382    pub const TOOLS: &str = "tools";
383
384    /// Prompt capability
385    pub const PROMPTS: &str = "prompts";
386
387    /// Resource capability
388    pub const RESOURCES: &str = "resources";
389
390    /// Logging capability
391    pub const LOGGING: &str = "logging";
392
393    /// Progress notifications
394    pub const PROGRESS: &str = "progress";
395
396    /// Sampling capability
397    pub const SAMPLING: &str = "sampling";
398
399    /// Roots capability
400    pub const ROOTS: &str = "roots";
401}
402
403/// Protocol method names
404pub mod methods {
405    // Initialization
406    /// Initialize handshake method
407    pub const INITIALIZE: &str = "initialize";
408    /// Initialized notification method
409    pub const INITIALIZED: &str = "notifications/initialized";
410
411    // Tools
412    /// List available tools method
413    pub const LIST_TOOLS: &str = "tools/list";
414    /// Call a specific tool method
415    pub const CALL_TOOL: &str = "tools/call";
416
417    // Prompts
418    /// List available prompts method
419    pub const LIST_PROMPTS: &str = "prompts/list";
420    /// Get a specific prompt method
421    pub const GET_PROMPT: &str = "prompts/get";
422
423    // Resources
424    /// List available resources method
425    pub const LIST_RESOURCES: &str = "resources/list";
426    /// Read a specific resource method
427    pub const READ_RESOURCE: &str = "resources/read";
428    /// Subscribe to resource updates method
429    pub const SUBSCRIBE: &str = "resources/subscribe";
430    /// Unsubscribe from resource updates method
431    pub const UNSUBSCRIBE: &str = "resources/unsubscribe";
432    /// Resource updated notification
433    pub const RESOURCE_UPDATED: &str = "notifications/resources/updated";
434    /// Resource list changed notification
435    pub const RESOURCE_LIST_CHANGED: &str = "notifications/resources/list_changed";
436
437    // Logging
438    /// Set logging level method
439    pub const SET_LEVEL: &str = "logging/setLevel";
440    /// Log message notification
441    pub const LOG_MESSAGE: &str = "notifications/message";
442
443    // Progress
444    /// Progress update notification
445    pub const PROGRESS: &str = "notifications/progress";
446
447    // Sampling
448    /// Create sampling message method
449    pub const CREATE_MESSAGE: &str = "sampling/createMessage";
450
451    // Roots
452    /// List directory roots method
453    pub const LIST_ROOTS: &str = "roots/list";
454    /// Roots list changed notification
455    pub const ROOTS_LIST_CHANGED: &str = "notifications/roots/list_changed";
456}
457
458/// Protocol error codes (JSON-RPC standard + MCP extensions)
459pub mod error_codes {
460    // JSON-RPC standard errors
461    /// Parse error - Invalid JSON was received by the server
462    pub const PARSE_ERROR: i32 = -32700;
463    /// Invalid request - The JSON sent is not a valid Request object
464    pub const INVALID_REQUEST: i32 = -32600;
465    /// Method not found - The method does not exist / is not available
466    pub const METHOD_NOT_FOUND: i32 = -32601;
467    /// Invalid params - Invalid method parameter(s)
468    pub const INVALID_PARAMS: i32 = -32602;
469    /// Internal error - Internal JSON-RPC error
470    pub const INTERNAL_ERROR: i32 = -32603;
471
472    // Implementation-specific JSON-RPC errors (reserved range -32000 to -32099)
473    /// URL elicitation required - Server requires client to provide info via URL elicitation
474    pub const URL_ELICITATION_REQUIRED: i32 = -32042;
475
476    // MCP-specific errors (application-defined range)
477    /// Tool not found error
478    pub const TOOL_NOT_FOUND: i32 = -32001;
479    /// Tool execution error
480    pub const TOOL_EXECUTION_ERROR: i32 = -32002;
481    /// Prompt not found error
482    pub const PROMPT_NOT_FOUND: i32 = -32003;
483    /// Resource not found error
484    pub const RESOURCE_NOT_FOUND: i32 = -32004;
485    /// Resource access denied error
486    pub const RESOURCE_ACCESS_DENIED: i32 = -32005;
487    /// Capability not supported error
488    pub const CAPABILITY_NOT_SUPPORTED: i32 = -32006;
489    /// Protocol version mismatch error
490    pub const PROTOCOL_VERSION_MISMATCH: i32 = -32007;
491    /// Authentication required error
492    pub const AUTHENTICATION_REQUIRED: i32 = -32008;
493    /// Rate limited error
494    pub const RATE_LIMITED: i32 = -32009;
495    /// Server overloaded error
496    pub const SERVER_OVERLOADED: i32 = -32010;
497}
498
499#[cfg(test)]
500mod tests {
501    use super::*;
502
503    #[test]
504    fn test_version_constants() {
505        assert_eq!(PROTOCOL_VERSION, "2025-11-25");
506        assert!(SUPPORTED_VERSIONS.contains(&PROTOCOL_VERSION));
507    }
508
509    #[test]
510    fn test_size_constants() {
511        // Constants are statically verified at compile-time
512        const _: () = assert!(
513            MAX_MESSAGE_SIZE > 1024,
514            "MAX_MESSAGE_SIZE must be larger than 1KB"
515        );
516        const _: () = assert!(
517            MAX_MESSAGE_SIZE == 1024 * 1024,
518            "MAX_MESSAGE_SIZE must be 1MB for security"
519        );
520
521        const _: () = assert!(
522            DEFAULT_TIMEOUT_MS > 1000,
523            "DEFAULT_TIMEOUT_MS must be larger than 1 second"
524        );
525        const _: () = assert!(
526            DEFAULT_TIMEOUT_MS == 30_000,
527            "DEFAULT_TIMEOUT_MS must be 30 seconds"
528        );
529    }
530
531    #[test]
532    fn test_method_names() {
533        assert_eq!(methods::INITIALIZE, "initialize");
534        assert_eq!(methods::LIST_TOOLS, "tools/list");
535        assert_eq!(methods::CALL_TOOL, "tools/call");
536    }
537
538    #[test]
539    fn test_error_codes() {
540        assert_eq!(error_codes::PARSE_ERROR, -32700);
541        assert_eq!(error_codes::TOOL_NOT_FOUND, -32001);
542    }
543}