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