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